diff --git a/web/app/src/modules/agent-bot/agent-bot.ts b/web/app/src/modules/agent-bot/agent-bot.ts index e3a8baa3..185a5620 100644 --- a/web/app/src/modules/agent-bot/agent-bot.ts +++ b/web/app/src/modules/agent-bot/agent-bot.ts @@ -1,12 +1,11 @@ import { inject, prop, transient } from '@difizen/mana-app'; -import qs from 'query-string'; import { AsyncModel } from '../../common/async-model.js'; import { AxiosClient } from '../axios-client/index.js'; -import { UserManager } from '../user/index.js'; import { AgentConfigManager } from './agent-config-manager.js'; import type { AgentConfig } from './agent-config.js'; +import type { AgentConfigOption } from './protocol.js'; import { AgentBotOption, AgentBotType } from './protocol.js'; @transient() @@ -24,9 +23,7 @@ export class AgentBot extends AsyncModel { @prop() draft?: AgentConfig; - draftConfigId?: number; - - option: any; + option: AgentBotOption; constructor( @inject(AgentBotOption) option: AgentBotOption, @@ -40,32 +37,29 @@ export class AgentBot extends AsyncModel { this.id = option.id; this.initialize(option); - this.ensureDraft(); + this.ensureDraft(option); } shouldInitFromMeta(option: AgentBotOption): boolean { return AgentBotType.isFullOption(option); } - async ensureDraft(): Promise { + async ensureDraft(option: AgentBotOption): Promise { await this.ready; - let config: AgentConfig; - if (this.draftConfigId) { - config = await this.configManager.getDraft({ id: this.draftConfigId }); - } else { - config = await this.configManager.create(); - this.draftConfigId = config.id; - await this.save(); + let draftConfig = option.draft; + if (!this.option.draft) { + draftConfig = await this.fetchDraftInfo(option); + } + if (draftConfig) { + this.draft = this.configManager.create(draftConfig); } - this.draft = config; - return config; + return this.draft; } protected override fromMeta(option: AgentBotOption) { this.id = option.id; this.name = option.name!; this.avatar = option.avatar!; - this.draftConfigId = option.draft; super.fromMeta(option); } @@ -78,10 +72,19 @@ export class AgentBot extends AsyncModel { } } + async fetchDraftInfo(option: AgentBotOption) { + const res = await this.axios.get( + `api/v1/agent/bots/${option.id}/draft`, + ); + if (res.status === 200) { + return res.data; + } + return undefined; + } + toMeta(): AgentBotOption { return { id: this.id, - draft: this.draftConfigId, name: this.name, avatar: this.avatar, }; diff --git a/web/app/src/modules/agent-bot/agent-config-manager.ts b/web/app/src/modules/agent-bot/agent-config-manager.ts index 330c8473..6af0e4d0 100644 --- a/web/app/src/modules/agent-bot/agent-config-manager.ts +++ b/web/app/src/modules/agent-bot/agent-config-manager.ts @@ -15,11 +15,7 @@ export class AgentConfigManager { return this.configFactory(option); }; - create = async (): Promise => { - const res = await this.axios.post(`api/v1/agent/configs`); - if (res.status !== 200) { - throw new Error('failed to create agent config'); - } - return this.configFactory(res.data); + create = (option: AgentConfigOption): AgentConfig => { + return this.configFactory(option); }; } diff --git a/web/app/src/modules/agent-bot/agent-config.ts b/web/app/src/modules/agent-bot/agent-config.ts index 4690b5d8..2e61d352 100644 --- a/web/app/src/modules/agent-bot/agent-config.ts +++ b/web/app/src/modules/agent-bot/agent-config.ts @@ -1,15 +1,9 @@ import { inject, prop, transient } from '@difizen/mana-app'; -import qs from 'query-string'; import { AsyncModel } from '../../common/async-model.js'; import { AxiosClient } from '../axios-client/index.js'; -import { UserManager } from '../user/index.js'; -import type { - AgentConfigMeta, - AgentConfigModelMeta, - AgentConfigStatus, -} from './protocol.js'; +import type { AgentConfigInfo, AgentConfigModelMeta } from './protocol.js'; import { AgentConfigOption, AgentConfigType } from './protocol.js'; @transient() @@ -17,7 +11,9 @@ export class AgentConfig extends AsyncModel { protected axios: AxiosClient; id: number; - status: AgentConfigStatus = 'draft'; + bot_id: number; + + is_draft = true; @prop() persona?: string; @@ -26,7 +22,7 @@ export class AgentConfig extends AsyncModel { model?: AgentConfigModelMeta; @prop() - config?: AgentConfigMeta; + config?: AgentConfigInfo; option?: AgentConfigOption; @@ -48,7 +44,8 @@ export class AgentConfig extends AsyncModel { protected override fromMeta(option: AgentConfigOption): void { this.id = option.id; - this.status = option.status || 'draft'; + this.bot_id = option.bot_id; + this.is_draft = option.is_draft || true; this.persona = option.config?.persona; this.model = option.config?.model; // TODO: tools & datasets @@ -69,7 +66,8 @@ export class AgentConfig extends AsyncModel { toMeta(): AgentConfigOption { return { id: this.id, - status: this.status, + bot_id: this.bot_id, + is_draft: this.is_draft, config: { ...(this.config || {}), persona: this.persona, diff --git a/web/app/src/modules/agent-bot/protocol.ts b/web/app/src/modules/agent-bot/protocol.ts index 81749ffd..b4b80ad5 100644 --- a/web/app/src/modules/agent-bot/protocol.ts +++ b/web/app/src/modules/agent-bot/protocol.ts @@ -15,7 +15,7 @@ export interface AgentConfigModelMeta { key: string; [key: string]: any; } -export interface AgentConfigMeta { +export interface AgentConfigInfo { persona: string; tools: AgentConfigToolMeta[]; datasets: AgentConfigDatasetMeta[]; @@ -31,8 +31,9 @@ export const AgentConfigOption = Syringe.defineToken('AgentConfigOption', { export interface AgentConfigOption { id: number; - status?: AgentConfigStatus; - config?: Partial; + bot_id: number; + is_draft?: boolean; + config?: Partial; } export type AgentConfigFactory = (options: AgentConfigOption) => AgentConfig; @@ -45,7 +46,7 @@ export const AgentConfigType = { return !!(data && 'id' in data); }, isFullOption(data?: Record): boolean { - return AgentBotType.isOption(data) && 'config' in data; + return AgentBotType.isOption(data) && 'bot_id' in data && 'config' in data; }, }; @@ -58,7 +59,7 @@ export interface AgentBotMeta { export interface AgentBotOption extends Partial { id: number; - draft?: number; + draft?: AgentConfigOption | null; } export const AgentBotOption = Syringe.defineToken('AgentBotOption', { @@ -78,5 +79,3 @@ export const AgentBotType = { return AgentBotType.isOption(data) && 'name' in data && 'avatar' in data; }, }; - -export type AgentConfigStatus = 'draft' | 'publish'; diff --git a/web/app/src/modules/axios-client/client.ts b/web/app/src/modules/axios-client/client.ts index 740012de..b8bc2397 100644 --- a/web/app/src/modules/axios-client/client.ts +++ b/web/app/src/modules/axios-client/client.ts @@ -2,6 +2,7 @@ import type { Syringe } from '@difizen/mana-app'; import axios from 'axios'; +import qs from 'query-string'; import { UserManager } from '../user/user-manager.js'; @@ -10,13 +11,14 @@ export const getContextClient = (ctx: Syringe.Context) => { axios.interceptors.request.use(async function (config) { // TODO: change to jwt token if (config.url) { - const url = new URL(config.url); - if (!url.searchParams.has('user_id')) { + const parsed = qs.parseUrl(config.url); + const query = parsed.query; + if (!query['user_id']) { const userManager = ctx.container.get(UserManager); await userManager.initialized; if (userManager.current) { - url.searchParams.append('user_id', userManager.current.id); - config.url = url.toString(); + query['user_id'] = userManager.current.id; + config.url = qs.stringifyUrl(parsed); } } } diff --git a/web/app/src/modules/model/built-in-model-meta.ts b/web/app/src/modules/model/built-in-model-meta.ts index bde6d947..e499acfd 100644 --- a/web/app/src/modules/model/built-in-model-meta.ts +++ b/web/app/src/modules/model/built-in-model-meta.ts @@ -1,4 +1,4 @@ -import type { ModelMeta } from './protocol'; +import type { ModelMeta } from './protocol.js'; const gpt4: ModelMeta = { key: 'gpt-4', diff --git a/web/app/src/modules/model/model.ts b/web/app/src/modules/model/model.ts index 84f71936..c29fffb1 100644 --- a/web/app/src/modules/model/model.ts +++ b/web/app/src/modules/model/model.ts @@ -1,6 +1,6 @@ import { inject, prop, transient } from '@difizen/mana-app'; -import { ModelOption, type ModelConfigMeta, type ModelMeta } from './protocol'; +import { ModelOption, type ModelConfigMeta, type ModelMeta } from './protocol.js'; @transient() export class Model { diff --git a/web/app/src/modules/model/protocol.ts b/web/app/src/modules/model/protocol.ts index 27c43a2b..5731edff 100644 --- a/web/app/src/modules/model/protocol.ts +++ b/web/app/src/modules/model/protocol.ts @@ -1,6 +1,6 @@ import { Syringe } from '@difizen/mana-app'; -import type { Model } from './model'; +import type { Model } from './model.js'; export interface ModelMeta { key: string;