Skip to content

Commit

Permalink
fix: moving utility methods out of the Studio API implementation
Browse files Browse the repository at this point in the history
Signed-off-by: axel7083 <[email protected]>
  • Loading branch information
axel7083 committed Jan 19, 2024
1 parent aacece4 commit 52fce1b
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 41 deletions.
54 changes: 54 additions & 0 deletions packages/backend/src/managers/catalogManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { Catalog } from '@shared/src/models/ICatalog';
import path from 'node:path';
import fs from 'node:fs';
import defaultCatalog from '../ai.json';
import { Category } from '@shared/src/models/ICategory';

Check failure on line 5 in packages/backend/src/managers/catalogManager.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / windows-2022

All imports in the declaration are only used as types. Use `import type`

Check failure on line 5 in packages/backend/src/managers/catalogManager.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / ubuntu-22.04

All imports in the declaration are only used as types. Use `import type`

Check failure on line 5 in packages/backend/src/managers/catalogManager.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / macos-12

All imports in the declaration are only used as types. Use `import type`
import { Recipe } from '@shared/src/models/IRecipe';

Check failure on line 6 in packages/backend/src/managers/catalogManager.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / windows-2022

All imports in the declaration are only used as types. Use `import type`

Check failure on line 6 in packages/backend/src/managers/catalogManager.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / ubuntu-22.04

All imports in the declaration are only used as types. Use `import type`

Check failure on line 6 in packages/backend/src/managers/catalogManager.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / macos-12

All imports in the declaration are only used as types. Use `import type`
import { ModelInfo } from '@shared/src/models/IModelInfo';

Check failure on line 7 in packages/backend/src/managers/catalogManager.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / windows-2022

All imports in the declaration are only used as types. Use `import type`

Check failure on line 7 in packages/backend/src/managers/catalogManager.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / ubuntu-22.04

All imports in the declaration are only used as types. Use `import type`

Check failure on line 7 in packages/backend/src/managers/catalogManager.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / macos-12

All imports in the declaration are only used as types. Use `import type`

export class CatalogManager {
private catalog: Catalog;

constructor(private appUserDirectory: string) {
// We start with an empty catalog, for the methods to work before the catalog is loaded
this.catalog = {
categories: [],
models: [],
recipes: [],
};
}

public getCategories(): Category[] {
return this.catalog.categories;
}

public getModels(): ModelInfo[] {
return this.catalog.models;
}
public getRecipes(): Recipe[] {
return this.catalog.recipes;
}


async loadCatalog() {
const catalogPath = path.resolve(this.appUserDirectory, 'catalog.json');
try {
if (!fs.existsSync(catalogPath)) {
this.setCatalog(defaultCatalog);
return;
}
// TODO(feloy): watch catalog file and update catalog with new content
const data = await fs.promises.readFile(catalogPath, 'utf-8');
const cat = JSON.parse(data) as Catalog;
this.setCatalog(cat);
} catch (err: unknown) {
console.error('unable to read catalog file, reverting to default catalog', err);
this.setCatalog(defaultCatalog);
}
}

setCatalog(newCatalog: Catalog) {
// TODO(feloy): send message to frontend with new catalog
this.catalog = newCatalog;
}
}
54 changes: 15 additions & 39 deletions packages/backend/src/studio-api-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,47 +15,19 @@ import type { Catalog } from '@shared/src/models/ICatalog';

import * as path from 'node:path';
import * as fs from 'node:fs';

Check failure on line 17 in packages/backend/src/studio-api-impl.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / windows-2022

'fs' is defined but never used

Check failure on line 17 in packages/backend/src/studio-api-impl.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / ubuntu-22.04

'fs' is defined but never used

Check failure on line 17 in packages/backend/src/studio-api-impl.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / macos-12

'fs' is defined but never used
import { CatalogManager } from './managers/catalogManager';

Check failure on line 18 in packages/backend/src/studio-api-impl.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / windows-2022

All imports in the declaration are only used as types. Use `import type`

Check failure on line 18 in packages/backend/src/studio-api-impl.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / ubuntu-22.04

All imports in the declaration are only used as types. Use `import type`

Check failure on line 18 in packages/backend/src/studio-api-impl.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / macos-12

All imports in the declaration are only used as types. Use `import type`

export const RECENT_CATEGORY_ID = 'recent-category';

export class StudioApiImpl implements StudioAPI {
private catalog: Catalog;

constructor(
private applicationManager: ApplicationManager,
private recipeStatusRegistry: RecipeStatusRegistry,
private taskRegistry: TaskRegistry,
private playgroundManager: PlayGroundManager,
) {
// We start with an empty catalog, for the methods to work before the catalog is loaded
this.catalog = {
categories: [],
models: [],
recipes: [],
};
}

async loadCatalog() {
const catalogPath = path.resolve(this.applicationManager.appUserDirectory, 'catalog.json');
try {
if (!fs.existsSync(catalogPath)) {
this.setCatalog(defaultCatalog);
return;
}
// TODO(feloy): watch catalog file and update catalog with new content
const data = await fs.promises.readFile(catalogPath, 'utf-8');
const cat = JSON.parse(data) as Catalog;
this.setCatalog(cat);
} catch (err: unknown) {
console.error('unable to read catalog file, reverting to default catalog', err);
this.setCatalog(defaultCatalog);
}
}

setCatalog(newCatalog: Catalog) {
// TODO(feloy): send message to frontend with new catalog
this.catalog = newCatalog;
}
private catalogManager: CatalogManager,
) {}

async openURL(url: string): Promise<boolean> {
return await podmanDesktopApi.env.openExternal(podmanDesktopApi.Uri.parse(url));
Expand All @@ -74,31 +46,35 @@ export class StudioApiImpl implements StudioAPI {
}

async getCategories(): Promise<Category[]> {
return this.catalog.categories;
return this.catalogManager.getCategories();
}

async getRecipesByCategory(categoryId: string): Promise<Recipe[]> {
if (categoryId === RECENT_CATEGORY_ID) return this.getRecentRecipes();

return this.catalog.recipes.filter(recipe => recipe.categories.includes(categoryId));
// TODO: move logic to catalog manager
return this.catalogManager.getRecipes().filter(recipe => recipe.categories.includes(categoryId));
}

async getRecipeById(recipeId: string): Promise<Recipe> {
const recipe = (this.catalog.recipes as Recipe[]).find(recipe => recipe.id === recipeId);
// TODO: move logic to catalog manager
const recipe = this.catalogManager.getRecipes().find(recipe => recipe.id === recipeId);
if (recipe) return recipe;
throw new Error('Not found');
}

async getModelById(modelId: string): Promise<ModelInfo> {
const model = this.catalog.models.find(m => modelId === m.id);
// TODO: move logic to catalog manager
const model = this.catalogManager.getModels().find(m => modelId === m.id);
if (!model) {
throw new Error(`No model found having id ${modelId}`);
}
return model;
}

async getModelsByIds(ids: string[]): Promise<ModelInfo[]> {
return this.catalog.models.filter(m => ids.includes(m.id)) ?? [];
// TODO: move logic to catalog manager
return this.catalogManager.getModels().filter(m => ids.includes(m.id)) ?? [];
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -107,9 +83,7 @@ export class StudioApiImpl implements StudioAPI {
}

async pullApplication(recipeId: string): Promise<void> {
console.log('StudioApiImpl pullApplication', recipeId);
const recipe: Recipe = await this.getRecipeById(recipeId);
console.log('StudioApiImpl recipe', recipe);

// the user should have selected one model, we use the first one for the moment
const modelId = recipe.models[0];
Expand All @@ -122,9 +96,10 @@ export class StudioApiImpl implements StudioAPI {
}

async getLocalModels(): Promise<ModelInfo[]> {
// TODO: move logic to catalog manager
const local = this.applicationManager.getLocalModels();
const localIds = local.map(l => l.id);
return this.catalog.models.filter(m => localIds.includes(m.id));
return this.catalogManager.getModels().filter(m => localIds.includes(m.id));
}

async getTasksByLabel(label: string): Promise<Task[]> {
Expand All @@ -143,6 +118,7 @@ export class StudioApiImpl implements StudioAPI {
}

askPlayground(modelId: string, prompt: string): Promise<number> {

const localModelInfo = this.applicationManager.getLocalModels().filter(m => m.id === modelId);
if (localModelInfo.length !== 1) {
throw new Error('model not found');
Expand Down
15 changes: 13 additions & 2 deletions packages/backend/src/studio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { RecipeStatusRegistry } from './registries/RecipeStatusRegistry';
import * as fs from 'node:fs';
import { TaskRegistry } from './registries/TaskRegistry';
import { PlayGroundManager } from './managers/playground';
import { CatalogManager } from './managers/catalogManager';

export class Studio {
readonly #extensionContext: ExtensionContext;
Expand All @@ -36,6 +37,7 @@ export class Studio {
rpcExtension: RpcExtension;
studioApi: StudioApiImpl;
playgroundManager: PlayGroundManager;
catalogManager: CatalogManager;

constructor(readonly extensionContext: ExtensionContext) {
this.#extensionContext = extensionContext;
Expand Down Expand Up @@ -93,8 +95,17 @@ export class Studio {
const recipeStatusRegistry = new RecipeStatusRegistry(taskRegistry);
const applicationManager = new ApplicationManager(gitManager, recipeStatusRegistry, this.#extensionContext);
this.playgroundManager = new PlayGroundManager(this.#panel.webview);
this.studioApi = new StudioApiImpl(applicationManager, recipeStatusRegistry, taskRegistry, this.playgroundManager);
await this.studioApi.loadCatalog();
this.catalogManager = new CatalogManager(applicationManager.appUserDirectory);
this.studioApi = new StudioApiImpl(
applicationManager,
recipeStatusRegistry,
taskRegistry,
this.playgroundManager,
this.catalogManager

Check warning on line 104 in packages/backend/src/studio.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / windows-2022

Missing trailing comma

Check warning on line 104 in packages/backend/src/studio.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / ubuntu-22.04

Missing trailing comma

Check warning on line 104 in packages/backend/src/studio.ts

View workflow job for this annotation

GitHub Actions / linter, formatters and unit tests / macos-12

Missing trailing comma
);

await this.catalogManager.loadCatalog();

// Register the instance
this.rpcExtension.registerInstance<StudioApiImpl>(StudioApiImpl, this.studioApi);
}
Expand Down

0 comments on commit 52fce1b

Please sign in to comment.