further rename

This commit is contained in:
lin onetwo 2025-11-27 01:29:21 +08:00
parent d0bcc684ef
commit 02124bad1a
39 changed files with 275 additions and 271 deletions

View file

@ -46,7 +46,7 @@ Object.defineProperty(window, 'observables', {
userInfo$: new BehaviorSubject(undefined).asObservable(),
},
agentInstance: {
concatPrompt: vi.fn((promptDescription: Pick<AgentPromptDescription, 'handlerConfig'>, messages: AgentInstanceMessage[]) => {
concatPrompt: vi.fn((promptDescription: Pick<AgentPromptDescription, 'agentFrameworkConfig'>, messages: AgentInstanceMessage[]) => {
const agentInstanceService = container.get<AgentInstanceService>(serviceIdentifier.AgentInstance);
// Initialize handlers (plugins and built-in handlers) before calling concatPrompt
// We need to wrap this in an Observable since concatPrompt returns an Observable

View file

@ -4,7 +4,7 @@ import { Box, Button, Container, Step, StepLabel, Stepper, TextField, Typography
import { styled } from '@mui/material/styles';
import type { RJSFSchema } from '@rjsf/utils';
import type { AgentDefinition } from '@services/agentDefinition/interface';
import { HandlerConfig } from '@services/agentInstance/promptConcat/promptConcatSchema';
import { AgentFrameworkConfig } from '@services/agentInstance/promptConcat/promptConcatSchema';
import useDebouncedCallback from 'beautiful-react-hooks/useDebouncedCallback';
import { nanoid } from 'nanoid';
import React, { useEffect, useState } from 'react';
@ -99,19 +99,19 @@ export const CreateNewAgentContent: React.FC<CreateNewAgentContentProps> = ({ ta
// Load schema when temporaryAgentDefinition is available
useEffect(() => {
const loadSchema = async () => {
if (temporaryAgentDefinition?.handlerID) {
if (temporaryAgentDefinition?.agentFrameworkID) {
try {
const schema = await window.service.agentInstance.getFrameworkConfigSchema(temporaryAgentDefinition.handlerID);
const schema = await window.service.agentInstance.getFrameworkConfigSchema(temporaryAgentDefinition.agentFrameworkID);
setPromptSchema(schema as RJSFSchema);
} catch (error) {
console.error('Failed to load handler config schema:', error);
console.error('Failed to load framework config schema:', error);
setPromptSchema(null);
}
}
};
void loadSchema();
}, [temporaryAgentDefinition?.handlerID]);
}, [temporaryAgentDefinition?.agentFrameworkID]);
// Create preview agent when entering step 3
useEffect(() => {
@ -374,11 +374,11 @@ export const CreateNewAgentContent: React.FC<CreateNewAgentContentProps> = ({ ta
<Box sx={{ mt: 2, height: 400, overflow: 'auto' }}>
<PromptConfigForm
schema={promptSchema}
formData={(temporaryAgentDefinition.handlerConfig || {}) as HandlerConfig}
formData={(temporaryAgentDefinition.agentFrameworkConfig || {}) as AgentFrameworkConfig}
onChange={(updatedConfig) => {
void handleAgentDefinitionChange({
...temporaryAgentDefinition,
handlerConfig: updatedConfig as Record<string, unknown>,
agentFrameworkConfig: updatedConfig as Record<string, unknown>,
});
}}
loading={false}

View file

@ -2,7 +2,7 @@ import { Box, Button, CircularProgress, Container, Divider, TextField, Typograph
import { styled } from '@mui/material/styles';
import type { RJSFSchema } from '@rjsf/utils';
import type { AgentDefinition } from '@services/agentDefinition/interface';
import { HandlerConfig } from '@services/agentInstance/promptConcat/promptConcatSchema';
import { AgentFrameworkConfig } from '@services/agentInstance/promptConcat/promptConcatSchema';
import useDebouncedCallback from 'beautiful-react-hooks/useDebouncedCallback';
import React, { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
@ -94,30 +94,30 @@ export const EditAgentDefinitionContent: React.FC<EditAgentDefinitionContentProp
void loadAgentDefinition();
}, [tab.agentDefId]);
// Load handler config schema
// Load framework config schema
useEffect(() => {
const loadSchema = async () => {
if (!agentDefinition?.handlerID) {
// No handlerID found
if (!agentDefinition?.agentFrameworkID) {
// No agentFrameworkID found
return;
}
try {
// Loading framework config schema
const schema = await window.service.agentInstance.getFrameworkConfigSchema(agentDefinition.handlerID);
const schema = await window.service.agentInstance.getFrameworkConfigSchema(agentDefinition.agentFrameworkID);
// Schema loaded successfully
setPromptSchema(schema);
} catch (error) {
void window.service.native.log('error', 'EditAgentDefinitionContent: Failed to load handler config schema', {
void window.service.native.log('error', 'EditAgentDefinitionContent: Failed to load framework config schema', {
error,
handlerID: agentDefinition.handlerID,
agentFrameworkID: agentDefinition.agentFrameworkID,
});
console.error('Failed to load handler config schema:', error);
console.error('Failed to load framework config schema:', error);
}
};
void loadSchema();
}, [agentDefinition?.handlerID]);
}, [agentDefinition?.agentFrameworkID]);
// Auto-save to backend whenever agentDefinition changes (debounced)
const saveToBackendDebounced = useDebouncedCallback(
@ -235,7 +235,7 @@ export const EditAgentDefinitionContent: React.FC<EditAgentDefinitionContentProp
return {
...previous,
handlerConfig: formData as Record<string, unknown>,
agentFrameworkConfig: formData as Record<string, unknown>,
};
},
);
@ -356,7 +356,7 @@ export const EditAgentDefinitionContent: React.FC<EditAgentDefinitionContentProp
<Box sx={{ mt: 2 }} data-testid='edit-agent-prompt-form'>
<PromptConfigForm
schema={promptSchema}
formData={agentDefinition.handlerConfig as HandlerConfig}
formData={agentDefinition.agentFrameworkConfig as AgentFrameworkConfig}
onChange={handlePromptConfigChange}
/>
</Box>

View file

@ -157,7 +157,7 @@ describe('CreateNewAgentContent', () => {
id: 'template-1',
name: 'Test Template',
description: 'Test Description',
handlerConfig: { systemPrompt: 'Test prompt' },
agentFrameworkConfig: { systemPrompt: 'Test prompt' },
};
mockCreateAgentDef.mockResolvedValue({
@ -258,8 +258,8 @@ describe('CreateNewAgentContent', () => {
const mockAgentDefinition = {
id: 'temp-123',
name: 'Test Agent',
handlerID: 'test-handler',
handlerConfig: { prompts: [{ text: 'Original prompt', role: 'system' }] },
agentFrameworkID: 'test-handler',
agentFrameworkConfig: { prompts: [{ text: 'Original prompt', role: 'system' }] },
};
mockGetAgentDef.mockResolvedValue(mockAgentDefinition);
@ -285,13 +285,13 @@ describe('CreateNewAgentContent', () => {
expect(mockUpdateAgentDef).not.toHaveBeenCalled();
});
it('should trigger schema loading when temporaryAgentDefinition has handlerID', async () => {
// Mock agent definition with handlerID that will be restored
it('should trigger schema loading when temporaryAgentDefinition has agentFrameworkID', async () => {
// Mock agent definition with agentFrameworkID that will be restored
const mockAgentDefinition = {
id: 'temp-123',
name: 'Test Agent',
handlerID: 'test-handler',
handlerConfig: { prompts: [{ text: 'Test prompt', role: 'system' }] },
agentFrameworkID: 'test-handler',
agentFrameworkConfig: { prompts: [{ text: 'Test prompt', role: 'system' }] },
};
mockGetAgentDef.mockResolvedValue(mockAgentDefinition);
@ -313,7 +313,7 @@ describe('CreateNewAgentContent', () => {
expect(mockGetAgentDef).toHaveBeenCalledWith('temp-123');
}, { timeout: 1000 });
// After restoration, the component should have the handlerID and trigger schema loading
// After restoration, the component should have the agentFrameworkID and trigger schema loading
await waitFor(() => {
expect(mockGetFrameworkConfigSchema).toHaveBeenCalledWith('test-handler');
}, { timeout: 2000 });
@ -341,8 +341,8 @@ describe('CreateNewAgentContent', () => {
const mockTemplate = {
id: 'template-1',
name: 'Test Template',
handlerID: 'test-handler',
handlerConfig: { prompts: [{ text: 'Test prompt', role: 'system' }] },
agentFrameworkID: 'test-handler',
agentFrameworkConfig: { prompts: [{ text: 'Test prompt', role: 'system' }] },
};
const mockCreatedDefinition = {
@ -378,8 +378,8 @@ describe('CreateNewAgentContent', () => {
const mockTemplate = {
id: 'template-1',
name: 'Test Template',
handlerID: 'test-handler',
handlerConfig: { prompts: [{ text: 'Original prompt' }] },
agentFrameworkID: 'test-handler',
agentFrameworkConfig: { prompts: [{ text: 'Original prompt' }] },
};
const mockCreatedDefinition = {
@ -443,7 +443,7 @@ describe('CreateNewAgentContent', () => {
expect(mockCreateAgentDef).toHaveBeenCalledWith(
expect.objectContaining({
name: 'My Agent',
handlerID: 'test-handler',
agentFrameworkID: 'test-handler',
}),
);
});
@ -459,7 +459,7 @@ describe('CreateNewAgentContent', () => {
expect(mockUpdateAgentDef).toHaveBeenCalledWith(
expect.objectContaining({
id: expect.stringContaining('temp-'),
handlerID: 'test-handler',
agentFrameworkID: 'test-handler',
}),
);
}, { timeout: 500 });
@ -470,8 +470,8 @@ describe('CreateNewAgentContent', () => {
const mockTemplate = {
id: 'task-agent',
name: 'Example Agent',
handlerID: 'basicPromptConcatHandler',
handlerConfig: {
agentFrameworkID: 'basicPromptConcatHandler',
agentFrameworkConfig: {
prompts: [
{
id: 'system',
@ -503,7 +503,7 @@ describe('CreateNewAgentContent', () => {
// Step 1: Create agent definition (simulates template selection)
const createdDef = await window.service.agentDefinition.createAgentDef(mockCreatedDefinition);
expect(createdDef).toBeDefined();
const prompts = (createdDef.handlerConfig).prompts as Array<{
const prompts = (createdDef.agentFrameworkConfig).prompts as Array<{
children?: Array<{ text?: string }>;
}>;
expect((prompts as Array<{ children?: Array<{ text?: string }> }>)[0]?.children?.[0]?.text).toBe('You are a helpful assistant for Tiddlywiki user.');
@ -511,14 +511,14 @@ describe('CreateNewAgentContent', () => {
// Step 2: Update system prompt in nested structure
const updatedDefinition = {
...mockCreatedDefinition,
handlerConfig: {
...mockCreatedDefinition.handlerConfig,
agentFrameworkConfig: {
...mockCreatedDefinition.agentFrameworkConfig,
prompts: [
{
...mockCreatedDefinition.handlerConfig.prompts[0],
...mockCreatedDefinition.agentFrameworkConfig.prompts[0],
children: [
{
...mockCreatedDefinition.handlerConfig.prompts[0].children[0],
...mockCreatedDefinition.agentFrameworkConfig.prompts[0].children[0],
text: '你是一个专业的代码助手,请用中文回答编程问题。',
},
],
@ -532,7 +532,7 @@ describe('CreateNewAgentContent', () => {
// Verify the correct nested structure is updated
expect(mockUpdateAgentDef).toHaveBeenCalledWith(
expect.objectContaining({
handlerConfig: expect.objectContaining({
agentFrameworkConfig: expect.objectContaining({
prompts: expect.arrayContaining([
expect.objectContaining({
role: 'system',

View file

@ -49,7 +49,7 @@ const mockAgentDefinition = {
id: 'test-agent-def-id',
name: 'Test Agent',
description: 'A test agent for editing',
handlerID: 'testHandler',
agentFrameworkID: 'testHandler',
config: {},
};

View file

@ -302,35 +302,35 @@ export const agentActions = (
}
},
getHandlerId: async () => {
getAgentFrameworkId: async () => {
try {
const { agent, agentDef } = get();
if (agentDef?.handlerID) {
return agentDef.handlerID;
if (agentDef?.agentFrameworkID) {
return agentDef.agentFrameworkID;
}
if (agent?.agentDefId) {
const fetchedAgentDefinition = await window.service.agentDefinition.getAgentDef(agent.agentDefId);
if (fetchedAgentDefinition?.handlerID) {
return fetchedAgentDefinition.handlerID;
if (fetchedAgentDefinition?.agentFrameworkID) {
return fetchedAgentDefinition.agentFrameworkID;
}
}
throw new Error('No active agent in store or handler ID not found');
throw new Error('No active agent in store or agent framework ID not found');
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
const finalError = new Error(`Failed to get handler ID: ${errorMessage}`);
const finalError = new Error(`Failed to get agent framework ID: ${errorMessage}`);
set({ error: finalError });
throw finalError;
}
},
/**
* Get handler configuration schema for current handler
* Get framework configuration schema for current framework
*/
getFrameworkConfigSchema: async () => {
try {
const handlerId = await get().getHandlerId();
return await window.service.agentInstance.getFrameworkConfigSchema(handlerId);
const agentFrameworkId = await get().getAgentFrameworkId();
return await window.service.agentInstance.getFrameworkConfigSchema(agentFrameworkId);
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
const finalError = new Error(`Failed to get handler schema: ${errorMessage}`);

View file

@ -70,14 +70,14 @@ export const previewActionsMiddleware: StateCreator<AgentChatStoreType, [], [],
getPreviewPromptResult: async (
inputText: string,
handlerConfig: AgentPromptDescription['handlerConfig'],
agentFrameworkConfig: AgentPromptDescription['agentFrameworkConfig'],
) => {
try {
set({ previewLoading: true });
const messages = Array.from(get().messages.values());
// Safety check - if handlerConfig is empty, fail early
if (Object.keys(handlerConfig).length === 0) {
// Safety check - if agentFrameworkConfig is empty, fail early
if (!agentFrameworkConfig || Object.keys(agentFrameworkConfig).length === 0) {
set({ previewLoading: false, previewResult: null });
return null;
}
@ -93,7 +93,7 @@ export const previewActionsMiddleware: StateCreator<AgentChatStoreType, [], [],
}
// Use the streaming API with progress updates
const concatStream = window.observables.agentInstance.concatPrompt({ handlerConfig }, messages);
const concatStream = window.observables.agentInstance.concatPrompt({ agentFrameworkConfig }, messages);
// Initialize progress
set({

View file

@ -90,7 +90,7 @@ export interface BasicActions {
cancelAgent: () => Promise<void>;
/** Get the handler ID for the current agent */
getHandlerId: () => Promise<string>;
getAgentFrameworkId: () => Promise<string>;
/** Get the configuration schema for the current handler */
getFrameworkConfigSchema: () => Promise<Record<string, unknown>>;
@ -188,12 +188,12 @@ export interface PreviewActions {
/**
* Generates a preview of prompts for the current agent state
* @param inputText Input text to include in the preview
* @param handlerConfig Prompt configuration to use for preview
* @param agentFrameworkConfig Framework configuration to use for preview
* @returns Promise that resolves when preview is generated and state is updated
*/
getPreviewPromptResult: (
inputText: string,
handlerConfig: AgentPromptDescription['handlerConfig'],
agentFrameworkConfig: AgentPromptDescription['agentFrameworkConfig'],
) => Promise<
{
flatPrompts: ModelMessage[];

View file

@ -1,4 +1,4 @@
import { useHandlerConfigManagement } from '@/windows/Preferences/sections/ExternalAPI/useHandlerConfigManagement';
import { useAgentFrameworkConfigManagement } from '@/windows/Preferences/sections/ExternalAPI/useAgentFrameworkConfigManagement';
import MonacoEditor from '@monaco-editor/react';
import { Box, styled } from '@mui/material';
import Tab from '@mui/material/Tab';
@ -9,7 +9,7 @@ import React, { FC, SyntheticEvent, useCallback, useEffect, useState } from 'rea
import { useTranslation } from 'react-i18next';
import { useShallow } from 'zustand/react/shallow';
import { HandlerConfig } from '@services/agentInstance/promptConcat/promptConcatSchema';
import { agentFrameworkConfig } from '@services/agentInstance/promptConcat/promptConcatSchema';
import { useAgentChatStore } from '../../../Agent/store/agentChatStore/index';
import { PromptConfigForm } from './PromptConfigForm';
@ -40,11 +40,11 @@ export const EditView: FC<EditViewProps> = ({
);
const {
loading: handlerConfigLoading,
config: handlerConfig,
loading: agentFrameworkConfigLoading,
config: agentFrameworkConfig,
schema: handlerSchema,
handleConfigChange,
} = useHandlerConfigManagement({
} = useAgentFrameworkConfigManagement({
agentDefId: agent?.agentDefId,
agentId: agent?.id,
});
@ -98,7 +98,7 @@ export const EditView: FC<EditViewProps> = ({
);
const handleFormChange = useDebouncedCallback(
async (updatedConfig: HandlerConfig) => {
async (updatedConfig: agentFrameworkConfig) => {
try {
// Ensure the config change is fully persisted before proceeding
await handleConfigChange(updatedConfig);
@ -121,7 +121,7 @@ export const EditView: FC<EditViewProps> = ({
const handleEditorChange = useCallback((value: string | undefined) => {
if (!value) return;
try {
const parsedConfig = JSON.parse(value) as HandlerConfig;
const parsedConfig = JSON.parse(value) as agentFrameworkConfig;
void handleFormChange(parsedConfig);
} catch (error) {
void window.service.native.log('error', 'EditView: Invalid JSON in code editor:', { error });
@ -163,16 +163,16 @@ export const EditView: FC<EditViewProps> = ({
{editorMode === 'form' && (
<PromptConfigForm
schema={handlerSchema ?? {}}
formData={handlerConfig}
formData={agentFrameworkConfig}
onChange={handleFormChange}
loading={handlerConfigLoading}
loading={agentFrameworkConfigLoading}
/>
)}
{editorMode === 'code' && (
<MonacoEditor
height='100%'
defaultLanguage='json'
value={handlerConfig ? JSON.stringify(handlerConfig, null, 2) : '{}'}
value={agentFrameworkConfig ? JSON.stringify(agentFrameworkConfig, null, 2) : '{}'}
onChange={handleEditorChange}
options={{
minimap: { enabled: true },

View file

@ -3,7 +3,7 @@ import { IChangeEvent } from '@rjsf/core';
import Form from '@rjsf/mui';
import { ObjectFieldTemplateProps, RJSFSchema, RJSFValidationError } from '@rjsf/utils';
import validator from '@rjsf/validator-ajv8';
import { HandlerConfig } from '@services/agentInstance/promptConcat/promptConcatSchema';
import { agentFrameworkConfig } from '@services/agentInstance/promptConcat/promptConcatSchema';
import React, { useCallback, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { ErrorDisplay } from './components/ErrorDisplay';
@ -37,9 +37,9 @@ interface PromptConfigFormProps {
/** UI schema for layout customization */
uiSchema?: Record<string, unknown>;
/** Initial form data */
formData?: HandlerConfig;
formData?: agentFrameworkConfig;
/** Change handler for form data */
onChange?: (formData: HandlerConfig) => void;
onChange?: (formData: agentFrameworkConfig) => void;
/** Error handler for form validation errors */
onError?: (errors: RJSFValidationError[]) => void;
/** Whether the form is disabled */
@ -87,7 +87,7 @@ export const PromptConfigForm: React.FC<PromptConfigFormProps> = ({
onError?.(errors);
}, [onError]);
const handleChange = useCallback((changeEvent: IChangeEvent<HandlerConfig>) => {
const handleChange = useCallback((changeEvent: IChangeEvent<agentFrameworkConfig>) => {
const formData = changeEvent.formData;
if (formData) {
onChange?.(formData);

View file

@ -15,10 +15,10 @@ import { ModelMessage } from 'ai';
import { PromptPreviewDialog } from '../index';
// Mock handler config management hook
vi.mock('@/windows/Preferences/sections/ExternalAPI/useHandlerConfigManagement', () => ({
useHandlerConfigManagement: vi.fn(() => ({
vi.mock('@/windows/Preferences/sections/ExternalAPI/useAgentFrameworkConfigManagement', () => ({
useAgentFrameworkConfigManagement: vi.fn(() => ({
loading: false,
config: defaultAgents[0].handlerConfig,
config: defaultAgents[0].agentFrameworkConfig,
handleConfigChange: vi.fn(),
})),
}));
@ -64,7 +64,7 @@ describe('PromptPreviewDialog - Tool Information Rendering', () => {
expect(globalThis.window?.observables?.agentInstance?.concatPrompt).toBeDefined();
// Create test data matching taskAgents.json - cast to avoid type issues in test
const handlerConfig = defaultAgents[0].handlerConfig as never;
const agentFrameworkConfig = defaultAgents[0].agentFrameworkConfig as never;
const messages = [{
id: 'test-message-1',
agentId: 'test-agent',
@ -74,7 +74,7 @@ describe('PromptPreviewDialog - Tool Information Rendering', () => {
// Call the real concatPrompt implementation
const observable = globalThis.window.observables.agentInstance.concatPrompt(
{ handlerConfig },
{ agentFrameworkConfig },
messages,
);
@ -118,11 +118,11 @@ describe('PromptPreviewDialog - Tool Information Rendering', () => {
it('should render workspaces and tools info from real concatPrompt execution', async () => {
// First execute real concatPrompt to get the structured data
const handlerConfig = defaultAgents[0].handlerConfig;
const agentFrameworkConfig = defaultAgents[0].agentFrameworkConfig;
const messages = [{ id: 'test', role: 'user' as const, content: 'Hello world', created: new Date(), modified: new Date(), agentId: 'test' }];
// Pass handlerConfig wrapped (same shape used elsewhere)
const observable = window.observables.agentInstance.concatPrompt({ handlerConfig } as never, messages);
// Pass agentFrameworkConfig wrapped (same shape used elsewhere)
const observable = window.observables.agentInstance.concatPrompt({ agentFrameworkConfig } as never, messages);
const results: unknown[] = [];
let finalResult: { flatPrompts: ModelMessage[]; processedPrompts: IPrompt[] } | undefined;

View file

@ -13,10 +13,10 @@ import defaultAgents from '@services/agentInstance/agentFrameworks/taskAgents.js
import { PromptPreviewDialog } from '../index';
// Mock handler config management hook
vi.mock('@/windows/Preferences/sections/ExternalAPI/useHandlerConfigManagement', () => ({
useHandlerConfigManagement: vi.fn(() => ({
vi.mock('@/windows/Preferences/sections/ExternalAPI/useAgentFrameworkConfigManagement', () => ({
useAgentFrameworkConfigManagement: vi.fn(() => ({
loading: false,
config: defaultAgents[0].handlerConfig,
config: defaultAgents[0].agentFrameworkConfig,
handleConfigChange: vi.fn(),
})),
}));

View file

@ -1,4 +1,4 @@
import { useHandlerConfigManagement } from '@/windows/Preferences/sections/ExternalAPI/useHandlerConfigManagement';
import { useAgentFrameworkConfigManagement } from '@/windows/Preferences/sections/ExternalAPI/useAgentFrameworkConfigManagement';
import CloseIcon from '@mui/icons-material/Close';
import EditIcon from '@mui/icons-material/Edit';
import FullscreenIcon from '@mui/icons-material/Fullscreen';
@ -36,9 +36,9 @@ export const PromptPreviewDialog: React.FC<PromptPreviewDialogProps> = ({
const [isEditMode, setIsEditMode] = useState(false);
const {
loading: handlerConfigLoading,
config: handlerConfig,
} = useHandlerConfigManagement({
loading: agentFrameworkConfigLoading,
config: agentFrameworkConfig,
} = useAgentFrameworkConfigManagement({
agentDefId: agent?.agentDefId,
agentId: agent?.id,
});
@ -54,17 +54,17 @@ export const PromptPreviewDialog: React.FC<PromptPreviewDialogProps> = ({
);
useEffect(() => {
const fetchInitialPreview = async () => {
if (!agent?.agentDefId || handlerConfigLoading || !handlerConfig || !open) {
if (!agent?.agentDefId || agentFrameworkConfigLoading || !agentFrameworkConfig || !open) {
return;
}
try {
await getPreviewPromptResult(inputText, handlerConfig);
await getPreviewPromptResult(inputText, agentFrameworkConfig);
} catch (error) {
console.error('PromptPreviewDialog: Error fetching initial preview:', error);
}
};
void fetchInitialPreview();
}, [agent?.agentDefId, handlerConfig, handlerConfigLoading, inputText, open]); // 移除 getPreviewPromptResult
}, [agent?.agentDefId, agentFrameworkConfig, agentFrameworkConfigLoading, inputText, open]); // 移除 getPreviewPromptResult
const handleToggleFullScreen = useCallback((): void => {
setIsFullScreen(previous => !previous);

View file

@ -90,12 +90,13 @@ describe('AgentDefinitionService getAgentDefs integration', () => {
const defs = await freshService.getAgentDefs();
expect(defs.length).toBeGreaterThan(0);
const exampleAgent = defs.find(d => d.id === (defaultAgents as AgentDefinition[])[0].id);
// Fixed
const exampleAgent = defs.find(d => d.id === (defaultAgents as unknown as AgentDefinition[])[0].id);
expect(exampleAgent).toBeDefined();
expect(exampleAgent!.name).toBeDefined();
expect(exampleAgent!.handlerID).toBeDefined();
expect(exampleAgent!.handlerConfig).toBeDefined();
expect(typeof exampleAgent!.handlerConfig).toBe('object');
expect(exampleAgent!.agentFrameworkID).toBeDefined();
expect(exampleAgent!.agentFrameworkConfig).toBeDefined();
expect(typeof exampleAgent!.agentFrameworkConfig).toBe('object');
});
it('should return only database data without fallback to defaultAgents', async () => {
@ -105,7 +106,7 @@ describe('AgentDefinitionService getAgentDefs integration', () => {
const agentDefRepo = realDataSource.getRepository(AgentDefinitionEntity);
// Save only minimal record (id only) to test new behavior
const example = (defaultAgents as AgentDefinition[])[0];
const example = (defaultAgents as unknown as AgentDefinition[])[0];
await agentDefRepo.save({
id: example.id,
});
@ -116,11 +117,11 @@ describe('AgentDefinitionService getAgentDefs integration', () => {
expect(found).toBeDefined();
// With new behavior, only id should be present, other fields should be undefined or empty
expect(found!.id).toBe(example.id);
expect(found!.handlerID).toBeUndefined();
expect(found!.agentFrameworkID).toBeUndefined();
expect(found!.name).toBeUndefined();
expect(found!.description).toBeUndefined();
expect(found!.avatarUrl).toBeUndefined();
expect(found!.handlerConfig).toEqual({});
expect(found!.agentFrameworkConfig).toEqual({});
expect(found!.aiApiConfig).toBeUndefined();
expect(found!.agentTools).toBeUndefined();
});
@ -132,7 +133,7 @@ describe('AgentDefinitionService getAgentDefs integration', () => {
const agentDefRepo = realDataSource.getRepository(AgentDefinitionEntity);
// Save only minimal record (id only) as per new behavior
const example = (defaultAgents as AgentDefinition[])[0];
const example = (defaultAgents as unknown as AgentDefinition[])[0];
await agentDefRepo.save({
id: example.id,
});
@ -148,8 +149,8 @@ describe('AgentDefinitionService getAgentDefs integration', () => {
expect(entity!.name).toBeNull();
expect(entity!.description).toBeNull();
expect(entity!.avatarUrl).toBeNull();
expect(entity!.handlerID).toBeNull();
expect(entity!.handlerConfig).toBeNull();
expect(entity!.agentFrameworkID).toBeNull();
expect(entity!.agentFrameworkConfig).toBeNull();
expect(entity!.aiApiConfig).toBeNull();
expect(entity!.agentTools).toBeNull();
});
@ -158,15 +159,15 @@ describe('AgentDefinitionService getAgentDefs integration', () => {
const templates = await agentDefinitionService.getAgentTemplates();
// Should include all default agents
expect(templates.length).toBe((defaultAgents as AgentDefinition[]).length);
expect(templates.length).toBe((defaultAgents as unknown as AgentDefinition[]).length);
// Check that template has complete data from taskAgents.json
const exampleTemplate = templates.find(t => t.id === (defaultAgents as AgentDefinition[])[0].id);
const exampleTemplate = templates.find(t => t.id === (defaultAgents as unknown as AgentDefinition[])[0].id);
expect(exampleTemplate).toBeDefined();
expect(exampleTemplate!.name).toBeDefined();
expect(exampleTemplate!.handlerID).toBeDefined();
expect(exampleTemplate!.handlerConfig).toBeDefined();
expect(typeof exampleTemplate!.handlerConfig).toBe('object');
expect(exampleTemplate!.agentFrameworkID).toBeDefined();
expect(exampleTemplate!.agentFrameworkConfig).toBeDefined();
expect(typeof exampleTemplate!.agentFrameworkConfig).toBe('object');
});
it('should not throw when searchName filtering is requested (client-side filtering expected)', async () => {
@ -185,6 +186,6 @@ describe('AgentDefinitionService getAgentDefs integration', () => {
// Should still return default agents and not throw
const templates = await agentDefinitionService.getAgentTemplates();
expect(templates.length).toBe((defaultAgents as AgentDefinition[]).length);
expect(templates.length).toBe((defaultAgents as unknown as AgentDefinition[]).length);
});
});

View file

@ -116,21 +116,21 @@ export function validateAndConvertWikiTiddlerToAgentTemplate(
};
// Try to parse the tiddler text as JSON for agent configuration
let handlerConfig: Record<string, unknown>;
let agentFrameworkConfig: Record<string, unknown>;
try {
const textContent = typeof tiddler.text === 'string' ? tiddler.text : JSON.stringify(tiddler.text || '{}');
const parsed = JSON.parse(textContent) as unknown;
// Ensure handlerConfig is a valid object
// Ensure agentFrameworkConfig is a valid object
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
logger.warn('Invalid handlerConfig in tiddler', {
logger.warn('Invalid agentFrameworkConfig in tiddler', {
function: 'validateAndConvertWikiTiddlerToAgentTemplate',
title: getStringField(tiddler.title),
reason: 'not an object',
});
return null;
}
handlerConfig = parsed as Record<string, unknown>;
agentFrameworkConfig = parsed as Record<string, unknown>;
} catch (parseError) {
logger.warn('Failed to parse agent template from tiddler', {
function: 'validateAndConvertWikiTiddlerToAgentTemplate',
@ -146,8 +146,8 @@ export function validateAndConvertWikiTiddlerToAgentTemplate(
name: getStringField(tiddler.caption) || getStringField(tiddler.title),
description: getStringField(tiddler.description) || `Agent template from ${workspaceName || 'wiki'}`,
avatarUrl: getStringField(tiddler.avatar_url) || undefined,
handlerID: getStringField(tiddler.handler_id) || 'basicPromptConcatHandler',
handlerConfig,
agentFrameworkID: getStringField(tiddler.agentFrameworkID) || 'basicPromptConcatHandler',
agentFrameworkConfig,
aiApiConfig: parseAiApiConfig(tiddler.ai_api_config),
agentTools: parseAgentTools(tiddler.agent_tools),
};

View file

@ -78,8 +78,8 @@ export class AgentDefinitionService implements IAgentDefinitionService {
name: defaultAgent.name,
description: defaultAgent.description,
avatarUrl: defaultAgent.avatarUrl,
handlerID: defaultAgent.handlerID,
handlerConfig: defaultAgent.handlerConfig,
agentFrameworkID: defaultAgent.agentFrameworkID,
agentFrameworkConfig: defaultAgent.agentFrameworkConfig,
aiApiConfig: defaultAgent.aiApiConfig,
agentTools: defaultAgent.agentTools,
})
@ -143,7 +143,7 @@ export class AgentDefinitionService implements IAgentDefinitionService {
throw new Error(`Agent definition not found: ${agent.id}`);
}
const pickedProperties = pick(agent, ['name', 'description', 'avatarUrl', 'handlerID', 'handlerConfig', 'aiApiConfig']);
const pickedProperties = pick(agent, ['name', 'description', 'avatarUrl', 'agentFrameworkID', 'agentFrameworkConfig', 'aiApiConfig']);
Object.assign(existingAgent, pickedProperties);
await this.agentDefRepository!.save(existingAgent);
@ -171,8 +171,8 @@ export class AgentDefinitionService implements IAgentDefinitionService {
name: entity.name || undefined,
description: entity.description || undefined,
avatarUrl: entity.avatarUrl || undefined,
handlerID: entity.handlerID || undefined,
handlerConfig: entity.handlerConfig || {},
agentFrameworkID: entity.agentFrameworkID || undefined,
agentFrameworkConfig: entity.agentFrameworkConfig || {},
aiApiConfig: entity.aiApiConfig || undefined,
agentTools: entity.agentTools || undefined,
}));
@ -212,8 +212,8 @@ export class AgentDefinitionService implements IAgentDefinitionService {
name: entity.name || undefined,
description: entity.description || undefined,
avatarUrl: entity.avatarUrl || undefined,
handlerID: entity.handlerID || undefined,
handlerConfig: entity.handlerConfig || {},
agentFrameworkID: entity.agentFrameworkID || undefined,
agentFrameworkConfig: entity.agentFrameworkConfig || {},
aiApiConfig: entity.aiApiConfig || undefined,
agentTools: entity.agentTools || undefined,
};

View file

@ -42,10 +42,10 @@ export interface AgentDefinition {
description?: string;
/** Agent icon or avatar URL */
avatarUrl?: string;
/** Agent handler function's id, we will find function by this id */
handlerID?: string;
/** Agent handler's config, specific to the handler. This is required to ensure agent has valid configuration. */
handlerConfig: Record<string, unknown>;
/** Agent framework function's id, we will find function by this id */
agentFrameworkID?: string;
/** Agent framework's config, specific to the framework. This is required to ensure agent has valid configuration. */
agentFrameworkConfig: Record<string, unknown>;
/**
* Overwrite the default AI configuration for this agent.
* Priority is higher than the global default agent config.

View file

@ -78,7 +78,7 @@ describe('AgentInstance failure path - external API logs on error', () => {
agentDef: {
id: 'def-1',
name: 'Def 1',
handlerConfig: {},
agentFrameworkConfig: {},
aiApiConfig: { api: { provider: 'test-provider', model: 'test-model' }, modelParameters: { temperature: 0.7, systemPrompt: '', topP: 0.95 } },
},
isCancelled: () => false,

View file

@ -73,7 +73,7 @@ describe('AgentInstanceService Streaming Behavior', () => {
// Mock agent definition service to return our test agent definition
mockAgentDefinitionService.getAgentDef = vi.fn().mockResolvedValue({
...exampleAgent,
handlerID: 'basicPromptConcatHandler',
agentFrameworkID: 'basicPromptConcatHandler',
});
// Mock the getAgent method to return our test instance
vi.spyOn(agentInstanceService, 'getAgent').mockResolvedValue(testAgentInstance);

View file

@ -2,11 +2,11 @@ import { describe, expect, it } from 'vitest';
import { createAgentInstanceData } from '../utilities';
describe('createAgentInstanceData', () => {
it('should create agent instance with undefined handlerConfig (fallback to definition)', () => {
it('should create agent instance with undefined agentFrameworkConfig (fallback to definition)', () => {
const agentDefinition = {
id: 'test-agent-def',
name: 'Test Agent',
handlerConfig: {
agentFrameworkConfig: {
prompts: [
{
text: 'You are a helpful assistant.',
@ -14,29 +14,29 @@ describe('createAgentInstanceData', () => {
},
],
},
handlerID: 'basicPromptConcatHandler',
agentFrameworkID: 'basicPromptConcatHandler',
};
const { instanceData } = createAgentInstanceData(agentDefinition);
expect(instanceData.handlerConfig).toBeUndefined();
expect(instanceData.agentFrameworkConfig).toBeUndefined();
expect(instanceData.agentDefId).toBe('test-agent-def');
expect(instanceData.handlerID).toBe('basicPromptConcatHandler');
expect(instanceData.agentFrameworkID).toBe('basicPromptConcatHandler');
expect(instanceData.name).toContain('Test Agent');
});
it('should create agent instance with undefined handlerConfig even when definition has required handlerConfig', () => {
it('should create agent instance with undefined agentFrameworkConfig even when definition has required agentFrameworkConfig', () => {
const agentDefinition = {
id: 'test-agent-def-no-config',
name: 'Test Agent No Config',
handlerID: 'basicPromptConcatHandler',
handlerConfig: {}, // Required by AgentDefinition interface
agentFrameworkID: 'basicPromptConcatHandler',
agentFrameworkConfig: {}, // Required by AgentDefinition interface
};
const { instanceData } = createAgentInstanceData(agentDefinition);
expect(instanceData.handlerConfig).toBeUndefined();
expect(instanceData.agentFrameworkConfig).toBeUndefined();
expect(instanceData.agentDefId).toBe('test-agent-def-no-config');
expect(instanceData.handlerID).toBe('basicPromptConcatHandler');
expect(instanceData.agentFrameworkID).toBe('basicPromptConcatHandler');
});
});

View file

@ -33,7 +33,7 @@ function makeContext(agentId: string, agentDefId: string, messages: AgentInstanc
agentDef: {
id: agentDefId,
name: 'Test Agent',
handlerConfig: {},
agentFrameworkConfig: {},
aiApiConfig: { api: { provider: 'test-provider', model: 'test-model' }, modelParameters: { temperature: 0.7, systemPrompt: '', topP: 0.95 } } as AiAPIConfig,
},
isCancelled: () => false,
@ -94,8 +94,8 @@ describe('basicPromptConcatHandler - failure path persists error message and log
vi.spyOn(agentDefSvc, 'getAgentDef').mockResolvedValue({
id: 'def-1',
name: 'Def 1',
handlerID: 'basicPromptConcatHandler',
handlerConfig: {
agentFrameworkID: 'basicPromptConcatHandler',
agentFrameworkConfig: {
plugins: [
{ toolId: 'wikiOperation', wikiOperationParam: {} },
],

View file

@ -1,4 +1,4 @@
/**
/**
* Integration tests for promptConcatStream with wikiSearch plugin
* Tests the complete workflow: tool list injection -> AI response -> tool execution -> next round
* Includes yieldNextRoundTo mechanism testing with basicPromptConcatHandler
@ -90,14 +90,14 @@ describe('WikiSearch Plugin Integration & YieldNextRound Mechanism', () => {
it('should complete full wiki search workflow: tool list -> tool execution -> response', async () => {
// Use real agent config from taskAgents.json
const exampleAgent = defaultAgents[0];
const handlerConfig = exampleAgent.handlerConfig;
const agentFrameworkConfig = exampleAgent.agentFrameworkConfig;
// Get the wiki search tool configuration
const wikiPlugin = handlerConfig.plugins.find(p => p.toolId === 'wikiSearch');
const wikiPlugin = agentFrameworkConfig.plugins.find(p => p.toolId === 'wikiSearch');
expect(wikiPlugin).toBeDefined();
if (!wikiPlugin) throw new Error('wikiPlugin not found');
const prompts = JSON.parse(JSON.stringify(handlerConfig.prompts));
const prompts = JSON.parse(JSON.stringify(agentFrameworkConfig.prompts));
// Phase 1: Tool List Injection
const promptConcatHookContext: PromptConcatHookContext = {
@ -108,9 +108,9 @@ describe('WikiSearch Plugin Integration & YieldNextRound Mechanism', () => {
agentDefId: exampleAgent.id,
status: { state: 'working' as const, modified: new Date() },
created: new Date(),
handlerConfig: {},
agentFrameworkConfig: {},
},
agentDef: { id: exampleAgent.id, name: exampleAgent.name, handlerConfig: exampleAgent.handlerConfig },
agentDef: { id: exampleAgent.id, name: exampleAgent.name, agentFrameworkConfig: exampleAgent.agentFrameworkConfig },
isCancelled: () => false,
},
toolConfig: wikiPlugin as IPromptConcatTool,
@ -127,10 +127,10 @@ describe('WikiSearch Plugin Integration & YieldNextRound Mechanism', () => {
],
};
// Create hooks and register tools as defined in handlerConfig
const { hooks: promptHooks } = await createHooksWithTools(handlerConfig);
// Create hooks and register tools as defined in agentFrameworkConfig
const { hooks: promptHooks } = await createHooksWithTools(agentFrameworkConfig);
// First run workspacesList tool to inject available workspaces (if present)
const workspacesPlugin = handlerConfig.plugins?.find(p => p.toolId === 'workspacesList');
const workspacesPlugin = agentFrameworkConfig.plugins?.find(p => p.toolId === 'workspacesList');
if (workspacesPlugin) {
const workspacesContext = { ...promptConcatHookContext, toolConfig: workspacesPlugin } as unknown as PromptConcatHookContext;
await promptHooks.processPrompts.promise(workspacesContext);
@ -179,9 +179,9 @@ describe('WikiSearch Plugin Integration & YieldNextRound Mechanism', () => {
},
created: new Date(),
messages: [],
handlerConfig: {},
agentFrameworkConfig: {},
},
agentDef: { id: 'test-agent-def', name: 'test-agent-def', handlerConfig: {} } as AgentDefinition,
agentDef: { id: 'test-agent-def', name: 'test-agent-def', agentFrameworkConfig: {} } as unknown as AgentDefinition,
isCancelled: () => false,
},
response: {
@ -199,8 +199,8 @@ describe('WikiSearch Plugin Integration & YieldNextRound Mechanism', () => {
actions: {} as unknown as Record<string, unknown>,
};
// Use hooks registered with all plugins from handlerConfig
const { hooks: responseHooks } = await createHooksWithTools(handlerConfig);
// Use hooks registered with all plugins from agentFrameworkConfig
const { hooks: responseHooks } = await createHooksWithTools(agentFrameworkConfig);
// Execute the response complete hook
await responseHooks.responseComplete.promise(responseContext);
// reuse containerForAssert from above assertions
@ -224,10 +224,10 @@ describe('WikiSearch Plugin Integration & YieldNextRound Mechanism', () => {
it('should handle errors in wiki search gracefully', async () => {
// Use real agent config from taskAgents.json
const exampleAgent = defaultAgents[0];
const handlerConfig = exampleAgent.handlerConfig;
const agentFrameworkConfig = exampleAgent.agentFrameworkConfig;
// Get the wiki search tool configuration
const wikiPlugin = handlerConfig.plugins.find(p => p.toolId === 'wikiSearch');
const wikiPlugin = agentFrameworkConfig.plugins.find(p => p.toolId === 'wikiSearch');
expect(wikiPlugin).toBeDefined();
// Mock tool calling with invalid workspace
@ -243,9 +243,9 @@ describe('WikiSearch Plugin Integration & YieldNextRound Mechanism', () => {
},
created: new Date(),
messages: [],
handlerConfig: {},
agentFrameworkConfig: {},
},
agentDef: { id: 'test-agent-def', name: 'test-agent-def', handlerConfig: {} } as AgentDefinition,
agentDef: { id: 'test-agent-def', name: 'test-agent-def', agentFrameworkConfig: {} } as unknown as AgentDefinition,
isCancelled: () => false,
},
response: {
@ -315,7 +315,7 @@ describe('WikiSearch Plugin Integration & YieldNextRound Mechanism', () => {
agentDef: {
id: exampleAgent.id,
name: exampleAgent.name,
handlerConfig: exampleAgent.handlerConfig,
agentFrameworkConfig: exampleAgent.agentFrameworkConfig,
},
isCancelled: () => false,
};

View file

@ -4,7 +4,7 @@ import { logger } from '@services/libs/log';
import serviceIdentifier from '@services/serviceIdentifier';
import { merge } from 'lodash';
import type { AgentInstanceLatestStatus, AgentInstanceMessage, IAgentInstanceService } from '../interface';
import { AgentPromptDescription, AiAPIConfig, HandlerConfig } from '../promptConcat/promptConcatSchema';
import { AgentFrameworkConfig, AgentPromptDescription, AiAPIConfig } from '../promptConcat/promptConcatSchema';
import type { IPromptConcatTool } from '../promptConcat/promptConcatSchema/plugin';
import { responseConcat } from '../promptConcat/responseConcat';
import { getFinalPromptResult } from '../promptConcat/utilities';
@ -31,15 +31,15 @@ export async function* basicPromptConcatHandler(context: AgentFrameworkContext)
// Initialize variables for request tracking
let currentRequestId: string | undefined;
const lastUserMessage: AgentInstanceMessage | undefined = context.agent.messages[context.agent.messages.length - 1];
// Create and register handler hooks based on handler config
const { hooks: agentFrameworkHooks, toolConfigs } = await createHooksWithTools(context.agentDef.handlerConfig || {});
// Create and register handler hooks based on framework config
const { hooks: agentFrameworkHooks, toolConfigs } = await createHooksWithTools(context.agentDef.agentFrameworkConfig || {});
// Log the start of handler execution with context information
logger.debug('Starting prompt handler execution', {
method: 'basicPromptConcatHandler',
agentId: context.agent.id,
defId: context.agentDef.id,
handlerId: context.agentDef.handlerID,
agentFrameworkId: context.agentDef.agentFrameworkID,
messageCount: context.agent.messages.length,
});
// Check if there's a new user message to process - trigger user message received hook
@ -94,12 +94,12 @@ export async function* basicPromptConcatHandler(context: AgentFrameworkContext)
// Process prompts using common handler function
try {
const handlerConfig: HandlerConfig = context.agentDef.handlerConfig as HandlerConfig;
const agentFrameworkConfig = context.agentDef.agentFrameworkConfig as AgentFrameworkConfig;
const agentPromptDescription: AgentPromptDescription = {
id: context.agentDef.id,
api: aiApiConfig.api,
modelParameters: aiApiConfig.modelParameters,
handlerConfig,
agentFrameworkConfig,
};
const agentInstanceService = container.get<IAgentInstanceService>(serviceIdentifier.AgentInstance);
@ -169,7 +169,7 @@ export async function* basicPromptConcatHandler(context: AgentFrameworkContext)
requestId: currentRequestId,
isFinal: true,
toolConfig: (toolConfigs.length > 0 ? toolConfigs[0] : {}) as IPromptConcatTool, // First config for compatibility
agentFrameworkConfig: context.agentDef.handlerConfig, // Pass complete config for tool access
agentFrameworkConfig: context.agentDef.agentFrameworkConfig, // Pass complete config for tool access
actions: undefined as { yieldNextRoundTo?: 'self' | 'human'; newUserMessage?: string } | undefined,
};

View file

@ -4,8 +4,8 @@
"name": "Task Agent",
"description": "Example agent with prompt processing",
"avatarUrl": "https://example.com/task-agent.png",
"handlerID": "basicPromptConcatHandler",
"handlerConfig": {
"agentFrameworkID": "basicPromptConcatHandler",
"agentFrameworkConfig": {
"prompts": [
{
"id": "system",

View file

@ -9,7 +9,7 @@ import { basicPromptConcatHandler } from '@services/agentInstance/agentFramework
import type { AgentFramework, AgentFrameworkContext } from '@services/agentInstance/agentFrameworks/utilities/type';
import { promptConcatStream, PromptConcatStreamState } from '@services/agentInstance/promptConcat/promptConcat';
import type { AgentPromptDescription } from '@services/agentInstance/promptConcat/promptConcatSchema';
import { getPromptConcatHandlerConfigJsonSchema } from '@services/agentInstance/promptConcat/promptConcatSchema/jsonSchema';
import { getPromptConcatAgentFrameworkConfigJsonSchema } from '@services/agentInstance/promptConcat/promptConcatSchema/jsonSchema';
import { createHooksWithTools, initializeToolSystem } from '@services/agentInstance/tools';
import type { IDatabaseService } from '@services/database/interface';
import { AgentInstanceEntity, AgentInstanceMessageEntity } from '@services/database/schema/agent';
@ -80,7 +80,7 @@ export class AgentInstanceService implements IAgentInstanceService {
public registerBuiltinFrameworks(): void {
// Tools are already registered in initialize(), so we only register frameworks here
// Register basic prompt concatenation framework with its schema
this.registerFramework('basicPromptConcatHandler', basicPromptConcatHandler, getPromptConcatHandlerConfigJsonSchema());
this.registerFramework('basicPromptConcatHandler', basicPromptConcatHandler, getPromptConcatAgentFrameworkConfigJsonSchema());
}
/**
@ -216,7 +216,7 @@ export class AgentInstanceService implements IAgentInstanceService {
}
// Update fields using pick + Object.assign for consistency with updateAgentDef
const pickedProperties = pick(data, ['name', 'status', 'avatarUrl', 'aiApiConfig', 'closed', 'handlerConfig']);
const pickedProperties = pick(data, ['name', 'status', 'avatarUrl', 'aiApiConfig', 'closed', 'agentFrameworkConfig']);
Object.assign(instanceEntity, pickedProperties);
// Save instance updates
@ -354,13 +354,13 @@ export class AgentInstanceService implements IAgentInstanceService {
}
// Get appropriate framework
const handlerId = agentDefinition.handlerID;
if (!handlerId) {
throw new Error(`Handler ID not found in agent definition: ${agentDefinition.id}`);
const agentFrameworkId = agentDefinition.agentFrameworkID;
if (!agentFrameworkId) {
throw new Error(`Agent framework ID not found in agent definition: ${agentDefinition.id}`);
}
const framework = this.agentFrameworks.get(handlerId);
const framework = this.agentFrameworks.get(agentFrameworkId);
if (!framework) {
throw new Error(`Framework not found: ${handlerId}`);
throw new Error(`Framework not found: ${agentFrameworkId}`);
}
// Create framework context with temporary message added for processing
@ -380,7 +380,7 @@ export class AgentInstanceService implements IAgentInstanceService {
};
// Create fresh hooks for this framework execution and register tools based on frameworkConfig
const { hooks: frameworkHooks } = await createHooksWithTools(agentDefinition.handlerConfig || {});
const { hooks: frameworkHooks } = await createHooksWithTools(agentDefinition.agentFrameworkConfig || {});
// Trigger userMessageReceived hook with the configured tools
await frameworkHooks.userMessageReceived.promise({
@ -848,10 +848,10 @@ export class AgentInstanceService implements IAgentInstanceService {
}
}
public concatPrompt(promptDescription: Pick<AgentPromptDescription, 'handlerConfig'>, messages: AgentInstanceMessage[]): Observable<PromptConcatStreamState> {
public concatPrompt(promptDescription: Pick<AgentPromptDescription, 'agentFrameworkConfig'>, messages: AgentInstanceMessage[]): Observable<PromptConcatStreamState> {
logger.debug('AgentInstanceService.concatPrompt called', {
hasPromptConfig: !!promptDescription.handlerConfig,
promptConfigKeys: Object.keys(promptDescription.handlerConfig),
hasPromptConfig: !!promptDescription.agentFrameworkConfig,
promptConfigKeys: Object.keys(promptDescription.agentFrameworkConfig || {}),
messagesCount: messages.length,
});
@ -866,9 +866,9 @@ export class AgentInstanceService implements IAgentInstanceService {
agentDefId: 'temp',
status: { state: 'working' as const, modified: new Date() },
created: new Date(),
handlerConfig: {},
agentFrameworkConfig: {},
},
agentDef: { id: 'temp', name: 'temp', handlerConfig: promptDescription.handlerConfig },
agentDef: { id: 'temp', name: 'temp', agentFrameworkConfig: promptDescription.agentFrameworkConfig || {} },
isCancelled: () => false,
};

View file

@ -8,16 +8,16 @@ import { AgentPromptDescription } from '@services/agentInstance/promptConcat/pro
/**
* Content of a session instance that user chat with an agent.
* Inherits from AgentDefinition but makes handlerConfig optional to allow fallback.
* Inherits from AgentDefinition but makes agentFrameworkConfig optional to allow fallback.
* The instance can override the definition's configuration, or fall back to using it.
*/
export interface AgentInstance extends Omit<AgentDefinition, 'name' | 'handlerConfig'> {
export interface AgentInstance extends Omit<AgentDefinition, 'name' | 'agentFrameworkConfig'> {
/** Agent description ID that generates this instance */
agentDefId: string;
/** Session name, optional in instance unlike definition */
name?: string;
/** Agent handler's config - optional, falls back to AgentDefinition.handlerConfig if not set */
handlerConfig?: Record<string, unknown>;
/** Agent framework's config - optional, falls back to AgentDefinition.agentFrameworkConfig if not set */
agentFrameworkConfig?: Record<string, unknown>;
/**
* Message history.
* latest on top, so it's easy to get first one as user's latest input, and rest as history.
@ -196,12 +196,12 @@ export interface IAgentInstanceService {
* @param messages Messages to be included in prompt generation
* @returns Observable stream of processing states, with final state containing complete results
*/
concatPrompt(promptDescription: Pick<AgentPromptDescription, 'handlerConfig'>, messages: AgentInstanceMessage[]): Observable<PromptConcatStreamState>;
concatPrompt(promptDescription: Pick<AgentPromptDescription, 'agentFrameworkConfig'>, messages: AgentInstanceMessage[]): Observable<PromptConcatStreamState>;
/**
* Get JSON Schema for handler configuration
* This allows frontend to generate a form based on the schema for a specific handler
* @param handlerId Handler ID to get schema for
* @param agentFrameworkID Handler ID to get schema for
* @returns JSON Schema for handler configuration
*/
getFrameworkConfigSchema(frameworkId: string): Record<string, unknown>;

View file

@ -203,13 +203,13 @@ export interface PromptConcatStreamState {
* Yields intermediate results for real-time UI updates
*/
export async function* promptConcatStream(
agentConfig: Pick<AgentPromptDescription, 'handlerConfig'>,
agentConfig: Pick<AgentPromptDescription, 'agentFrameworkConfig'>,
messages: AgentInstanceMessage[],
agentFrameworkContext: AgentFrameworkContext,
): AsyncGenerator<PromptConcatStreamState, PromptConcatStreamState, unknown> {
const agentFrameworkConfig = agentConfig.handlerConfig;
const promptConfigs = Array.isArray(agentFrameworkConfig.prompts) ? agentFrameworkConfig.prompts : [];
const toolConfigs = (Array.isArray(agentFrameworkConfig.plugins) ? agentFrameworkConfig.plugins : []) as IPromptConcatTool[];
const agentFrameworkConfig = agentConfig.agentFrameworkConfig;
const promptConfigs = Array.isArray(agentFrameworkConfig?.prompts) ? agentFrameworkConfig.prompts : [];
const toolConfigs = (Array.isArray(agentFrameworkConfig?.plugins) ? agentFrameworkConfig.plugins : []) as IPromptConcatTool[];
const promptsCopy = cloneDeep(promptConfigs);
const sourcePaths = generateSourcePaths(promptsCopy, toolConfigs);
@ -342,7 +342,7 @@ export async function* promptConcatStream(
* @returns Processed prompt array and original prompt tree
*/
export async function promptConcat(
agentConfig: Pick<AgentPromptDescription, 'handlerConfig'>,
agentConfig: Pick<AgentPromptDescription, 'agentFrameworkConfig'>,
messages: AgentInstanceMessage[],
agentFrameworkContext: AgentFrameworkContext,
): Promise<{

View file

@ -72,7 +72,7 @@ export function getFrameworkConfigSchema() {
* "model": "Qwen/Qwen2.5-7B-Instruct"
* },
* "modelParameters": { ... },
* "handlerConfig": {
* "agentFrameworkConfig": {
* "prompts": [ ... ],
* "response": [ ... ],
* "plugins": [ ... ],
@ -88,7 +88,7 @@ export function getAgentConfigSchema() {
title: t('Schema.AgentConfig.IdTitle'),
description: t('Schema.AgentConfig.Id'),
}),
handlerConfig: dynamicFrameworkConfigSchema,
agentFrameworkConfig: dynamicFrameworkConfigSchema,
}).meta({
title: t('Schema.AgentConfig.Title'),
description: t('Schema.AgentConfig.Description'),
@ -110,7 +110,9 @@ export function getDefaultAgentsSchema() {
export type DefaultAgents = z.infer<ReturnType<typeof getDefaultAgentsSchema>>;
export type AgentPromptDescription = z.infer<ReturnType<typeof getAgentConfigSchema>>;
export type AiAPIConfig = z.infer<typeof AIConfigSchema>;
export type HandlerConfig = z.infer<ReturnType<typeof getFrameworkConfigSchema>>;
export type AgentFrameworkConfig = z.infer<ReturnType<typeof getFrameworkConfigSchema>>;
// Backward compat alias
export type agentFrameworkConfig = AgentFrameworkConfig;
// Re-export all schemas and types
export * from './modelParameters';

View file

@ -11,7 +11,7 @@ import { getFrameworkConfigSchema } from './index';
*
* Description field is i18n key, use i18nAlly extension to see it on VSCode. And use react-i18next to translate it on frontend.
*/
export function getPromptConcatHandlerConfigJsonSchema() {
export function getPromptConcatAgentFrameworkConfigJsonSchema() {
const dynamicFrameworkConfigSchema = getFrameworkConfigSchema();
return z.toJSONSchema(dynamicFrameworkConfigSchema, { target: 'draft-7' });
}

View file

@ -11,7 +11,7 @@ import { AgentInstanceMessage } from '../interface';
import { builtInTools, createAgentFrameworkHooks } from '../tools';
import { AgentResponse, PostProcessContext, YieldNextRoundTarget } from '../tools/types';
import type { IPromptConcatTool } from './promptConcatSchema';
import { AgentPromptDescription, HandlerConfig } from './promptConcatSchema';
import { AgentFrameworkConfig, AgentPromptDescription } from './promptConcatSchema';
/**
* Process response configuration, apply plugins, and return final response
@ -38,9 +38,8 @@ export async function responseConcat(
responseLength: llmResponse.length,
});
const { handlerConfig } = agentConfig;
const agentFrameworkConfig = handlerConfig;
const responses: HandlerConfig['response'] = Array.isArray(agentFrameworkConfig.response) ? agentFrameworkConfig.response : [];
const { agentFrameworkConfig } = agentConfig;
const responses: AgentFrameworkConfig['response'] = Array.isArray(agentFrameworkConfig?.response) ? (agentFrameworkConfig?.response || []) : [];
const toolConfigs = (Array.isArray(agentFrameworkConfig.plugins) ? agentFrameworkConfig.plugins : []) as IPromptConcatTool[];
let modifiedResponses = cloneDeep(responses) as AgentResponse[];

View file

@ -1,4 +1,4 @@
/**
/**
* Tests for Full Replacement plugin duration mechanism
* Tests that expired messages (with duration) are filtered out from AI context
* Based on real configuration from taskAgents.json
@ -15,7 +15,7 @@ import { fullReplacementTool } from '../prompt';
// Use the real agent config
const exampleAgent = defaultAgents[0];
const realhandlerConfig = exampleAgent.handlerConfig;
const realagentFrameworkConfig = exampleAgent.agentFrameworkConfig;
describe('Full Replacement Plugin - Duration Mechanism', () => {
beforeEach(() => {
@ -25,14 +25,14 @@ describe('Full Replacement Plugin - Duration Mechanism', () => {
describe('History Source Type with Duration Filtering', () => {
it('should filter out expired messages (duration=1) from historyOfSession', async () => {
// Find the real fullReplacement plugin for history from taskAgents.json
const historyPlugin = realhandlerConfig.plugins.find(
const historyPlugin = realagentFrameworkConfig.plugins.find(
p => p.toolId === 'fullReplacement' && p.fullReplacementParam?.sourceType === 'historyOfSession',
);
expect(historyPlugin).toBeDefined();
expect(historyPlugin!.fullReplacementParam!.targetId).toBe('default-history'); // Real target ID
// Use real prompts structure from taskAgents.json
const testPrompts = cloneDeep(realhandlerConfig.prompts) as IPrompt[];
const testPrompts = cloneDeep(realagentFrameworkConfig.prompts) as IPrompt[];
const messages: AgentInstanceMessage[] = [
// Message 0: User message, no duration - should be included
@ -104,7 +104,7 @@ describe('Full Replacement Plugin - Duration Mechanism', () => {
status: { state: 'working' as const, modified: new Date() },
created: new Date(),
},
agentDef: { id: 'test-agent-def', name: 'test', handlerConfig: {} },
agentDef: { id: 'test-agent-def', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
},
toolConfig: historyPlugin! as unknown as IPromptConcatTool, // Type cast due to JSON import limitations
@ -147,7 +147,7 @@ describe('Full Replacement Plugin - Duration Mechanism', () => {
});
it('should include messages with duration=0 (visible in current round)', async () => {
const historyPlugin = realhandlerConfig.plugins.find(
const historyPlugin = realagentFrameworkConfig.plugins.find(
p => p.toolId === 'fullReplacement' && p.fullReplacementParam?.sourceType === 'historyOfSession',
);
@ -181,7 +181,7 @@ describe('Full Replacement Plugin - Duration Mechanism', () => {
},
];
const testPrompts = cloneDeep(realhandlerConfig.prompts) as IPrompt[];
const testPrompts = cloneDeep(realagentFrameworkConfig.prompts) as IPrompt[];
const context: PromptConcatHookContext = {
agentFrameworkContext: {
@ -192,7 +192,7 @@ describe('Full Replacement Plugin - Duration Mechanism', () => {
status: { state: 'working' as const, modified: new Date() },
created: new Date(),
},
agentDef: { id: 'test-agent-def', name: 'test', handlerConfig: {} },
agentDef: { id: 'test-agent-def', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
},
toolConfig: historyPlugin! as unknown as IPromptConcatTool, // Type cast for JSON import
@ -220,7 +220,7 @@ describe('Full Replacement Plugin - Duration Mechanism', () => {
});
it('should handle mixed duration values correctly', async () => {
const historyPlugin = realhandlerConfig.plugins.find(
const historyPlugin = realagentFrameworkConfig.plugins.find(
p => p.toolId === 'fullReplacement' && p.fullReplacementParam?.sourceType === 'historyOfSession',
);
@ -263,7 +263,7 @@ describe('Full Replacement Plugin - Duration Mechanism', () => {
},
];
const testPrompts = cloneDeep(realhandlerConfig.prompts) as IPrompt[];
const testPrompts = cloneDeep(realagentFrameworkConfig.prompts) as IPrompt[];
const context: PromptConcatHookContext = {
agentFrameworkContext: {
@ -274,7 +274,7 @@ describe('Full Replacement Plugin - Duration Mechanism', () => {
status: { state: 'working' as const, modified: new Date() },
created: new Date(),
},
agentDef: { id: 'test-agent-def', name: 'test', handlerConfig: {} },
agentDef: { id: 'test-agent-def', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
},
toolConfig: historyPlugin! as unknown as IPromptConcatTool, // Type cast for JSON import
@ -308,7 +308,7 @@ describe('Full Replacement Plugin - Duration Mechanism', () => {
describe('LLM Response Source Type', () => {
it('should verify LLM response replacement config exists', () => {
// Verify the real config has LLM response replacement
const llmResponsePlugin = realhandlerConfig.plugins.find(
const llmResponsePlugin = realagentFrameworkConfig.plugins.find(
p => p.toolId === 'fullReplacement' && p.fullReplacementParam?.sourceType === 'llmResponse',
);
expect(llmResponsePlugin).toBeDefined();

View file

@ -1,4 +1,4 @@
/**
/**
* Deep integration tests for messageManagementTool with real SQLite database
* Tests actual message persistence scenarios using taskAgents.json configuration
*/
@ -90,7 +90,7 @@ describe('Message Management Plugin - Real Database Integration', () => {
name: exampleAgent.name,
version: '1.0.0',
capabilities: [],
handlerConfig: exampleAgent.handlerConfig,
agentFrameworkConfig: exampleAgent.agentFrameworkConfig,
},
isCancelled: () => false,
});

View file

@ -1,4 +1,4 @@
/**
/**
* Tests for wikiOperationTool
*/
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
@ -59,7 +59,7 @@ const makeagentFrameworkContext = (agentId = 'test-agent'): AgentFrameworkContex
status: { state: 'working', modified: new Date() },
created: new Date(),
} as unknown as AgentInstance,
agentDef: { id: 'test-agent-def', name: 'test-agent-def', handlerConfig: {} } as unknown as { id: string; name: string; handlerConfig: Record<string, unknown> },
agentDef: { id: 'test-agent-def', name: 'test-agent-def', agentFrameworkConfig: {} } as unknown as { id: string; name: string; agentFrameworkConfig: Record<string, unknown> },
isCancelled: () => false,
});
@ -90,7 +90,7 @@ describe('wikiOperationTool', () => {
const workspacesContext: PromptConcatHookContext = {
agentFrameworkContext: {
agent: { id: 'test-agent', messages: [], agentDefId: 'test', status: { state: 'working' as const, modified: new Date() }, created: new Date() },
agentDef: { id: 'test', name: 'test', handlerConfig: {} },
agentDef: { id: 'test', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
},
messages: [],

View file

@ -1,4 +1,4 @@
/**
/**
* Comprehensive tests for Wiki Search plugin
* Covers tool list injection, tool execution, duration mechanism, message persistence, and integration scenarios
*/
@ -53,7 +53,7 @@ vi.mock('@services/libs/i18n', () => ({
// Use the real agent config
const exampleAgent = defaultAgents[0];
const handlerConfig = exampleAgent.handlerConfig as AgentPromptDescription['handlerConfig'];
const agentFrameworkConfig = (exampleAgent.agentFrameworkConfig || {}) as AgentPromptDescription['agentFrameworkConfig'];
// Services will be retrieved from container on demand inside each test/describe
@ -77,7 +77,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
it('should inject wiki tools into prompts when configured', async () => {
// Find the wiki search plugin config, make sure our default config
const wikiPlugin = handlerConfig.plugins.find((p: unknown): p is IPromptConcatTool => (p as IPromptConcatTool).toolId === 'wikiSearch');
const wikiPlugin = agentFrameworkConfig.plugins.find((p: unknown): p is IPromptConcatTool => (p as IPromptConcatTool).toolId === 'wikiSearch');
expect(wikiPlugin).toBeDefined();
if (!wikiPlugin) {
// throw error to keep ts believe the plugin exists
@ -89,7 +89,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
expect(wikiPlugin.wikiSearchParam?.toolListPosition).toBeDefined();
// Create a copy of prompts to test modification
const prompts = cloneDeep(handlerConfig.prompts);
const prompts = cloneDeep(agentFrameworkConfig.prompts);
const messages = [
{
id: 'user-1',
@ -104,7 +104,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
const context: PromptConcatHookContext = {
agentFrameworkContext: {
agent: { id: 'test', messages: [], agentDefId: 'test', status: { state: 'working' as const, modified: new Date() }, created: new Date() },
agentDef: { id: 'test', name: 'test', handlerConfig: {} },
agentDef: { id: 'test', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
},
toolConfig: wikiPlugin,
@ -144,7 +144,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
},
};
const prompts = cloneDeep(defaultAgents[0].handlerConfig.prompts);
const prompts = cloneDeep(defaultAgents[0].agentFrameworkConfig.prompts);
const originalPromptsText = JSON.stringify(prompts);
const context = {
@ -173,7 +173,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
status: { state: 'working' as const, modified: new Date() },
created: new Date(),
} as AgentInstance,
agentDef: { id: 'test', name: 'test', handlerConfig: {} } as AgentDefinition,
agentDef: { id: 'test', name: 'test', agentFrameworkConfig: {} } as AgentDefinition,
isCancelled: () => false,
};
const hookContext: PromptConcatHookContext = {
@ -222,7 +222,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
it('should execute wiki search with correct duration=1 and trigger next round', async () => {
// Find the real wikiSearch plugin config from taskAgents.json
const wikiPlugin = handlerConfig.plugins.find((p: unknown): p is IPromptConcatTool => (p as IPromptConcatTool).toolId === 'wikiSearch');
const wikiPlugin = agentFrameworkConfig.plugins.find((p: unknown): p is IPromptConcatTool => (p as IPromptConcatTool).toolId === 'wikiSearch');
expect(wikiPlugin).toBeDefined();
expect(wikiPlugin!.wikiSearchParam).toBeDefined();
@ -258,7 +258,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
},
],
},
agentDef: { id: 'test-agent-def', name: 'test', handlerConfig: {} },
agentDef: { id: 'test-agent-def', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
};
@ -352,7 +352,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
},
],
},
agentDef: { id: 'test-agent-def', name: 'test', handlerConfig: {} },
agentDef: { id: 'test-agent-def', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
};
@ -450,7 +450,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
},
],
},
agentDef: { id: 'test-agent-def', name: 'test', handlerConfig: {} },
agentDef: { id: 'test-agent-def', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
};
@ -507,7 +507,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
status: { state: 'working' as const, modified: new Date() },
created: new Date(),
} as AgentInstance,
agentDef: { id: 'test-agent-def', name: 'test', handlerConfig: {} } as AgentDefinition,
agentDef: { id: 'test-agent-def', name: 'test', agentFrameworkConfig: {} } as AgentDefinition,
isCancelled: () => false,
};
@ -627,7 +627,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
},
],
},
agentDef: { id: 'test-agent-def', name: 'test', handlerConfig: {} },
agentDef: { id: 'test-agent-def', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
};
@ -724,7 +724,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
},
],
},
agentDef: { id: 'test-agent-def', name: 'test', handlerConfig: {} },
agentDef: { id: 'test-agent-def', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
};
@ -795,7 +795,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
},
],
},
agentDef: { id: 'test-agent-def', name: 'test', handlerConfig: {} },
agentDef: { id: 'test-agent-def', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
};
@ -859,7 +859,7 @@ describe('Wiki Search Plugin - Comprehensive Tests', () => {
},
],
},
agentDef: { id: 'test-agent-def', name: 'test', handlerConfig: {} },
agentDef: { id: 'test-agent-def', name: 'test', agentFrameworkConfig: {} },
isCancelled: () => false,
};

View file

@ -1,4 +1,4 @@
/**
/**
* Tests for workspacesListTool
*/
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

View file

@ -1,4 +1,4 @@
/**
/**
* Wiki Search plugin
* Handles wiki search tool list injection, tool calling detection and response processing
*/

View file

@ -14,8 +14,8 @@ export function createAgentInstanceData(agentDefinition: {
name: string;
avatarUrl?: string;
aiApiConfig?: Record<string, unknown>;
handlerConfig?: Record<string, unknown>;
handlerID?: string;
agentFrameworkConfig?: Record<string, unknown>;
agentFrameworkID?: string;
}): {
instanceData: Omit<AgentInstance, 'created' | 'modified'>;
instanceId: string;
@ -31,7 +31,7 @@ export function createAgentInstanceData(agentDefinition: {
};
// Extract necessary fields from agent definition
const { avatarUrl, aiApiConfig, handlerID } = agentDefinition;
const { avatarUrl, aiApiConfig, agentFrameworkID } = agentDefinition;
const instanceData = {
id: instanceId,
@ -40,9 +40,9 @@ export function createAgentInstanceData(agentDefinition: {
status: initialStatus,
avatarUrl,
aiApiConfig,
// Don't copy handlerConfig to instance - it should fallback to definition
handlerConfig: undefined,
handlerID,
// Don't copy agentFrameworkConfig to instance - it should fallback to definition
agentFrameworkConfig: undefined,
agentFrameworkID,
messages: [],
closed: false,
};
@ -119,6 +119,6 @@ export const AGENT_INSTANCE_FIELDS = [
'modified',
'avatarUrl',
'aiApiConfig',
'handlerConfig',
'agentFrameworkConfig',
'closed',
] as const;

View file

@ -29,11 +29,11 @@ export class AgentDefinitionEntity implements Partial<AgentDefinition> {
/** Agent handler function ID, nullable indicates using default handler */
@Column({ nullable: true })
handlerID?: string;
agentFrameworkID?: string;
/** Agent handler configuration parameters, stored as JSON */
@Column({ type: 'simple-json', nullable: true })
handlerConfig?: Record<string, unknown>;
agentFrameworkConfig?: Record<string, unknown>;
/** Agent's AI API configuration, can override global default config */
@Column({ type: 'simple-json', nullable: true })
@ -88,7 +88,7 @@ export class AgentInstanceEntity implements Partial<AgentInstance> {
/** Agent handler configuration parameters, inherited from AgentDefinition */
@Column({ type: 'simple-json', nullable: true })
handlerConfig?: Record<string, unknown>;
agentFrameworkConfig?: Record<string, unknown>;
@Column({ default: false })
closed: boolean = false;

View file

@ -1,29 +1,29 @@
import { HandlerConfig } from '@services/agentInstance/promptConcat/promptConcatSchema';
import { agentFrameworkConfig } from '@services/agentInstance/promptConcat/promptConcatSchema';
import { useCallback, useEffect, useState } from 'react';
interface UseHandlerConfigManagementProps {
interface useAgentFrameworkConfigManagementProps {
agentDefId?: string;
agentId?: string;
}
interface UseHandlerConfigManagementResult {
interface useAgentFrameworkConfigManagementResult {
loading: boolean;
config: HandlerConfig | undefined;
config: agentFrameworkConfig | undefined;
schema?: Record<string, unknown>;
handleConfigChange: (newConfig: HandlerConfig) => Promise<void>;
handleConfigChange: (newConfig: agentFrameworkConfig) => Promise<void>;
}
export const useHandlerConfigManagement = ({ agentDefId, agentId }: UseHandlerConfigManagementProps = {}): UseHandlerConfigManagementResult => {
export const useAgentFrameworkConfigManagement = ({ agentDefId, agentId }: useAgentFrameworkConfigManagementProps = {}): useAgentFrameworkConfigManagementResult => {
const [loading, setLoading] = useState(true);
const [config, setConfig] = useState<HandlerConfig | undefined>(undefined);
const [config, setConfig] = useState<agentFrameworkConfig | undefined>(undefined);
const [schema, setSchema] = useState<Record<string, unknown> | undefined>(undefined);
useEffect(() => {
const fetchConfig = async () => {
try {
setLoading(true);
let finalConfig: HandlerConfig | undefined;
let handlerID: string | undefined;
let finalConfig: agentFrameworkConfig | undefined;
let agentFrameworkID: string | undefined;
if (agentId) {
const agentInstance = await window.service.agentInstance.getAgent(agentId);
@ -32,34 +32,34 @@ export const useHandlerConfigManagement = ({ agentDefId, agentId }: UseHandlerCo
agentDefinition = await window.service.agentDefinition.getAgentDef(agentInstance.agentDefId);
}
// Use instance config if available, otherwise fallback to definition config
if (agentInstance?.handlerConfig && Object.keys(agentInstance.handlerConfig).length > 0) {
finalConfig = agentInstance.handlerConfig as HandlerConfig;
} else if (agentDefinition?.handlerConfig) {
finalConfig = agentDefinition.handlerConfig as HandlerConfig;
if (agentInstance?.agentFrameworkConfig && Object.keys(agentInstance.agentFrameworkConfig).length > 0) {
finalConfig = agentInstance.agentFrameworkConfig as agentFrameworkConfig;
} else if (agentDefinition?.agentFrameworkConfig) {
finalConfig = agentDefinition.agentFrameworkConfig as agentFrameworkConfig;
}
// Use handlerID from instance, fallback to definition
handlerID = agentInstance?.handlerID || agentDefinition?.handlerID;
// Use agentFrameworkID from instance, fallback to definition
agentFrameworkID = agentInstance?.agentFrameworkID || agentDefinition?.agentFrameworkID;
} else if (agentDefId) {
const agentDefinition = await window.service.agentDefinition.getAgentDef(agentDefId);
if (agentDefinition?.handlerConfig) {
finalConfig = agentDefinition.handlerConfig as HandlerConfig;
if (agentDefinition?.agentFrameworkConfig) {
finalConfig = agentDefinition.agentFrameworkConfig as agentFrameworkConfig;
}
handlerID = agentDefinition?.handlerID;
agentFrameworkID = agentDefinition?.agentFrameworkID;
}
if (handlerID) {
if (agentFrameworkID) {
try {
const frameworkSchema = await window.service.agentInstance.getFrameworkConfigSchema(handlerID);
const frameworkSchema = await window.service.agentInstance.getFrameworkConfigSchema(agentFrameworkID);
setSchema(frameworkSchema);
} catch (error) {
void window.service.native.log('error', 'Failed to load handler schema', { function: 'useHandlerConfigManagement.fetchConfig', error });
void window.service.native.log('error', 'Failed to load handler schema', { function: 'useAgentFrameworkConfigManagement.fetchConfig', error });
}
}
setConfig(finalConfig);
setLoading(false);
} catch (error) {
void window.service.native.log('error', 'Failed to load handler configuration', { function: 'useHandlerConfigManagement.fetchConfig', error });
void window.service.native.log('error', 'Failed to load handler configuration', { function: 'useAgentFrameworkConfigManagement.fetchConfig', error });
setLoading(false);
}
};
@ -67,27 +67,29 @@ export const useHandlerConfigManagement = ({ agentDefId, agentId }: UseHandlerCo
void fetchConfig();
}, [agentDefId, agentId]);
const handleConfigChange = useCallback(async (newConfig: HandlerConfig) => {
const handleConfigChange = useCallback(async (newConfig: agentFrameworkConfig) => {
try {
setConfig(newConfig);
if (agentId) {
await window.service.agentInstance.updateAgent(agentId, {
handlerConfig: newConfig,
agentFrameworkConfig: newConfig,
});
} else if (agentDefId) {
const agentDefinition = await window.service.agentDefinition.getAgentDef(agentDefId);
if (agentDefinition) {
await window.service.agentDefinition.updateAgentDef({
...agentDefinition,
handlerConfig: newConfig,
agentFrameworkConfig: newConfig,
});
}
} else {
void window.service.native.log('error', 'No agent ID or definition ID provided for updating handler config', { function: 'useHandlerConfigManagement.handleConfigChange' });
void window.service.native.log('error', 'No agent ID or definition ID provided for updating handler config', {
function: 'useAgentFrameworkConfigManagement.handleConfigChange',
});
}
} catch (error) {
void window.service.native.log('error', 'Failed to update handler configuration', { function: 'useHandlerConfigManagement.handleConfigChange', error });
void window.service.native.log('error', 'Failed to update handler configuration', { function: 'useAgentFrameworkConfigManagement.handleConfigChange', error });
}
}, [agentId, agentDefId]);