mirror of
https://github.com/tiddly-gittly/TidGi-Desktop.git
synced 2026-04-27 15:50:57 -07:00
feat: typing defaultAgent
This commit is contained in:
parent
02e5be68cc
commit
c11f2a0cd6
6 changed files with 589 additions and 94 deletions
|
|
@ -88,6 +88,7 @@
|
|||
"winston-daily-rotate-file": "5.0.0",
|
||||
"winston-transport": "4.9.0",
|
||||
"wouter": "^3.6.0",
|
||||
"zod": "^3.24.3",
|
||||
"zustand": "^5.0.3",
|
||||
"zx": "8.3.1"
|
||||
},
|
||||
|
|
|
|||
119
pnpm-lock.yaml
generated
119
pnpm-lock.yaml
generated
|
|
@ -15,19 +15,19 @@ importers:
|
|||
dependencies:
|
||||
'@ai-sdk/anthropic':
|
||||
specifier: ^1.2.6
|
||||
version: 1.2.6(zod@3.23.8)
|
||||
version: 1.2.6(zod@3.24.3)
|
||||
'@ai-sdk/deepseek':
|
||||
specifier: ^0.2.6
|
||||
version: 0.2.6(zod@3.23.8)
|
||||
version: 0.2.6(zod@3.24.3)
|
||||
'@ai-sdk/openai':
|
||||
specifier: ^1.3.7
|
||||
version: 1.3.7(zod@3.23.8)
|
||||
version: 1.3.7(zod@3.24.3)
|
||||
'@ai-sdk/openai-compatible':
|
||||
specifier: ^0.2.6
|
||||
version: 0.2.6(zod@3.23.8)
|
||||
version: 0.2.6(zod@3.24.3)
|
||||
ai:
|
||||
specifier: ^4.3.2
|
||||
version: 4.3.2(react@19.0.0)(zod@3.23.8)
|
||||
version: 4.3.2(react@19.0.0)(zod@3.24.3)
|
||||
ansi-to-html:
|
||||
specifier: ^0.7.2
|
||||
version: 0.7.2
|
||||
|
|
@ -126,7 +126,7 @@ importers:
|
|||
version: 3.3.2
|
||||
ollama-ai-provider:
|
||||
specifier: ^1.2.0
|
||||
version: 1.2.0(zod@3.23.8)
|
||||
version: 1.2.0(zod@3.24.3)
|
||||
reablocks:
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1(@emotion/is-prop-valid@1.2.2)(@types/react@19.0.8)(prop-types@15.8.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||
|
|
@ -184,6 +184,9 @@ importers:
|
|||
wouter:
|
||||
specifier: ^3.6.0
|
||||
version: 3.6.0(react@19.0.0)
|
||||
zod:
|
||||
specifier: ^3.24.3
|
||||
version: 3.24.3
|
||||
zustand:
|
||||
specifier: ^5.0.3
|
||||
version: 5.0.3(@types/react@19.0.8)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.5.0(react@19.0.0))
|
||||
|
|
@ -7383,8 +7386,8 @@ packages:
|
|||
peerDependencies:
|
||||
zod: ^3.24.1
|
||||
|
||||
zod@3.23.8:
|
||||
resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
|
||||
zod@3.24.3:
|
||||
resolution: {integrity: sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==}
|
||||
|
||||
zustand@5.0.3:
|
||||
resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==}
|
||||
|
|
@ -7415,58 +7418,58 @@ snapshots:
|
|||
|
||||
'@aashutoshrathi/word-wrap@1.2.6': {}
|
||||
|
||||
'@ai-sdk/anthropic@1.2.6(zod@3.23.8)':
|
||||
'@ai-sdk/anthropic@1.2.6(zod@3.24.3)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 1.1.0
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.23.8)
|
||||
zod: 3.23.8
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.24.3)
|
||||
zod: 3.24.3
|
||||
|
||||
'@ai-sdk/deepseek@0.2.6(zod@3.23.8)':
|
||||
'@ai-sdk/deepseek@0.2.6(zod@3.24.3)':
|
||||
dependencies:
|
||||
'@ai-sdk/openai-compatible': 0.2.6(zod@3.23.8)
|
||||
'@ai-sdk/openai-compatible': 0.2.6(zod@3.24.3)
|
||||
'@ai-sdk/provider': 1.1.0
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.23.8)
|
||||
zod: 3.23.8
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.24.3)
|
||||
zod: 3.24.3
|
||||
|
||||
'@ai-sdk/openai-compatible@0.2.6(zod@3.23.8)':
|
||||
'@ai-sdk/openai-compatible@0.2.6(zod@3.24.3)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 1.1.0
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.23.8)
|
||||
zod: 3.23.8
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.24.3)
|
||||
zod: 3.24.3
|
||||
|
||||
'@ai-sdk/openai@1.3.7(zod@3.23.8)':
|
||||
'@ai-sdk/openai@1.3.7(zod@3.24.3)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 1.1.0
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.23.8)
|
||||
zod: 3.23.8
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.24.3)
|
||||
zod: 3.24.3
|
||||
|
||||
'@ai-sdk/provider-utils@2.2.4(zod@3.23.8)':
|
||||
'@ai-sdk/provider-utils@2.2.4(zod@3.24.3)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 1.1.0
|
||||
nanoid: 3.3.11
|
||||
secure-json-parse: 2.7.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@ai-sdk/provider@1.1.0':
|
||||
dependencies:
|
||||
json-schema: 0.4.0
|
||||
|
||||
'@ai-sdk/react@1.2.6(react@19.0.0)(zod@3.23.8)':
|
||||
'@ai-sdk/react@1.2.6(react@19.0.0)(zod@3.24.3)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.23.8)
|
||||
'@ai-sdk/ui-utils': 1.2.5(zod@3.23.8)
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.24.3)
|
||||
'@ai-sdk/ui-utils': 1.2.5(zod@3.24.3)
|
||||
react: 19.0.0
|
||||
swr: 2.3.3(react@19.0.0)
|
||||
throttleit: 2.1.0
|
||||
optionalDependencies:
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@ai-sdk/ui-utils@1.2.5(zod@3.23.8)':
|
||||
'@ai-sdk/ui-utils@1.2.5(zod@3.24.3)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 1.1.0
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.23.8)
|
||||
zod: 3.23.8
|
||||
zod-to-json-schema: 3.24.5(zod@3.23.8)
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.24.3)
|
||||
zod: 3.24.3
|
||||
zod-to-json-schema: 3.24.5(zod@3.24.3)
|
||||
|
||||
'@aws-crypto/sha256-browser@5.2.0':
|
||||
dependencies:
|
||||
|
|
@ -8525,7 +8528,7 @@ snapshots:
|
|||
dependencies:
|
||||
'@jimp/types': 1.6.0
|
||||
'@jimp/utils': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-blur@1.6.0':
|
||||
dependencies:
|
||||
|
|
@ -8535,7 +8538,7 @@ snapshots:
|
|||
'@jimp/plugin-circle@1.6.0':
|
||||
dependencies:
|
||||
'@jimp/types': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-color@1.6.0':
|
||||
dependencies:
|
||||
|
|
@ -8543,7 +8546,7 @@ snapshots:
|
|||
'@jimp/types': 1.6.0
|
||||
'@jimp/utils': 1.6.0
|
||||
tinycolor2: 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-contain@1.6.0':
|
||||
dependencies:
|
||||
|
|
@ -8552,7 +8555,7 @@ snapshots:
|
|||
'@jimp/plugin-resize': 1.6.0
|
||||
'@jimp/types': 1.6.0
|
||||
'@jimp/utils': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-cover@1.6.0':
|
||||
dependencies:
|
||||
|
|
@ -8560,20 +8563,20 @@ snapshots:
|
|||
'@jimp/plugin-crop': 1.6.0
|
||||
'@jimp/plugin-resize': 1.6.0
|
||||
'@jimp/types': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-crop@1.6.0':
|
||||
dependencies:
|
||||
'@jimp/core': 1.6.0
|
||||
'@jimp/types': 1.6.0
|
||||
'@jimp/utils': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-displace@1.6.0':
|
||||
dependencies:
|
||||
'@jimp/types': 1.6.0
|
||||
'@jimp/utils': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-dither@1.6.0':
|
||||
dependencies:
|
||||
|
|
@ -8583,12 +8586,12 @@ snapshots:
|
|||
dependencies:
|
||||
'@jimp/types': 1.6.0
|
||||
'@jimp/utils': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-flip@1.6.0':
|
||||
dependencies:
|
||||
'@jimp/types': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-hash@1.6.0':
|
||||
dependencies:
|
||||
|
|
@ -8606,7 +8609,7 @@ snapshots:
|
|||
'@jimp/plugin-mask@1.6.0':
|
||||
dependencies:
|
||||
'@jimp/types': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-print@1.6.0':
|
||||
dependencies:
|
||||
|
|
@ -8619,18 +8622,18 @@ snapshots:
|
|||
parse-bmfont-binary: 1.0.6
|
||||
parse-bmfont-xml: 1.1.6
|
||||
simple-xml-to-json: 1.2.3
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-quantize@1.6.0':
|
||||
dependencies:
|
||||
image-q: 4.0.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-resize@1.6.0':
|
||||
dependencies:
|
||||
'@jimp/core': 1.6.0
|
||||
'@jimp/types': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-rotate@1.6.0':
|
||||
dependencies:
|
||||
|
|
@ -8639,7 +8642,7 @@ snapshots:
|
|||
'@jimp/plugin-resize': 1.6.0
|
||||
'@jimp/types': 1.6.0
|
||||
'@jimp/utils': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/plugin-threshold@1.6.0':
|
||||
dependencies:
|
||||
|
|
@ -8648,11 +8651,11 @@ snapshots:
|
|||
'@jimp/plugin-hash': 1.6.0
|
||||
'@jimp/types': 1.6.0
|
||||
'@jimp/utils': 1.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/types@1.6.0':
|
||||
dependencies:
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
'@jimp/utils@1.6.0':
|
||||
dependencies:
|
||||
|
|
@ -9752,15 +9755,15 @@ snapshots:
|
|||
clean-stack: 2.2.0
|
||||
indent-string: 4.0.0
|
||||
|
||||
ai@4.3.2(react@19.0.0)(zod@3.23.8):
|
||||
ai@4.3.2(react@19.0.0)(zod@3.24.3):
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 1.1.0
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.23.8)
|
||||
'@ai-sdk/react': 1.2.6(react@19.0.0)(zod@3.23.8)
|
||||
'@ai-sdk/ui-utils': 1.2.5(zod@3.23.8)
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.24.3)
|
||||
'@ai-sdk/react': 1.2.6(react@19.0.0)(zod@3.24.3)
|
||||
'@ai-sdk/ui-utils': 1.2.5(zod@3.24.3)
|
||||
'@opentelemetry/api': 1.9.0
|
||||
jsondiffpatch: 0.6.0
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
optionalDependencies:
|
||||
react: 19.0.0
|
||||
|
||||
|
|
@ -13291,13 +13294,13 @@ snapshots:
|
|||
|
||||
obuf@1.1.2: {}
|
||||
|
||||
ollama-ai-provider@1.2.0(zod@3.23.8):
|
||||
ollama-ai-provider@1.2.0(zod@3.24.3):
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 1.1.0
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.23.8)
|
||||
'@ai-sdk/provider-utils': 2.2.4(zod@3.24.3)
|
||||
partial-json: 0.1.7
|
||||
optionalDependencies:
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
omggif@1.0.10: {}
|
||||
|
||||
|
|
@ -15384,11 +15387,11 @@ snapshots:
|
|||
toposort: 2.0.2
|
||||
type-fest: 2.19.0
|
||||
|
||||
zod-to-json-schema@3.24.5(zod@3.23.8):
|
||||
zod-to-json-schema@3.24.5(zod@3.24.3):
|
||||
dependencies:
|
||||
zod: 3.23.8
|
||||
zod: 3.24.3
|
||||
|
||||
zod@3.23.8: {}
|
||||
zod@3.24.3: {}
|
||||
|
||||
zustand@5.0.3(@types/react@19.0.8)(immer@10.1.1)(react@19.0.0)(use-sync-external-store@1.5.0(react@19.0.0)):
|
||||
optionalDependencies:
|
||||
|
|
|
|||
265
src/services/agent/defaultAgents/defaultAgentsSchema.ts
Normal file
265
src/services/agent/defaultAgents/defaultAgentsSchema.ts
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
* 代表提示词部分的接口定义
|
||||
*/
|
||||
export interface IPromptPart {
|
||||
id: string;
|
||||
text?: string;
|
||||
tags?: string[];
|
||||
caption?: string;
|
||||
content?: string;
|
||||
name?: string;
|
||||
children?: IPromptPart[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Schema for a prompt part in the agent configuration
|
||||
*/
|
||||
// 使用前置声明解决递归类型引用问题,并使用具体的接口而不是 any
|
||||
const PromptPartSchema: z.ZodType<IPromptPart> = z.lazy(() =>
|
||||
z.object({
|
||||
id: z.string().describe('唯一标识符'),
|
||||
text: z.string().optional().describe('提示词文本内容'),
|
||||
tags: z.array(z.string()).optional().describe('标签列表,用于分类和引用'),
|
||||
caption: z.string().optional().describe('提示词的简短描述'),
|
||||
content: z.string().optional().describe('提示词内容,通常用于动态修改的情况'),
|
||||
name: z.string().optional().describe('名称,用于特定场景的引用'),
|
||||
children: z.array(PromptPartSchema).optional().describe('子提示词列表')
|
||||
}).describe('表示提示词的一部分,可以是文本或嵌套结构')
|
||||
);
|
||||
|
||||
/**
|
||||
* 提示词配置
|
||||
*/
|
||||
export const PromptSchema = z.object({
|
||||
id: z.string().describe('提示词配置的唯一标识符'),
|
||||
caption: z.string().describe('简短描述'),
|
||||
enabled: z.boolean().optional().default(true).describe('是否启用'),
|
||||
promptType: z.enum(['system', 'user']).optional().describe('提示词类型'),
|
||||
tags: z.array(z.string()).optional().describe('标签列表'),
|
||||
text: z.string().optional().describe('提示词内容'),
|
||||
children: z.array(PromptPartSchema).optional().describe('子提示词列表'),
|
||||
}).describe('完整的提示词配置,包含类型和内容');
|
||||
|
||||
/**
|
||||
* 模型参数配置
|
||||
*/
|
||||
export const ModelParametersSchema = z.object({
|
||||
temperature: z.number().min(0).max(2).optional().describe('控制输出随机性,越高越随机'),
|
||||
frequency_penalty: z.number().optional().describe('频率惩罚,避免重复'),
|
||||
presence_penalty: z.number().optional().describe('存在惩罚,鼓励多样性'),
|
||||
top_p: z.number().optional().describe('Top-p 采样'),
|
||||
top_k: z.number().optional().describe('Top-k 采样'),
|
||||
top_a: z.number().optional().describe('Top-a 采样'),
|
||||
min_p: z.number().optional().describe('Min-p 采样'),
|
||||
repetition_penalty: z.number().optional().describe('重复惩罚'),
|
||||
max_context: z.number().optional().describe('最大上下文长度'),
|
||||
max_tokens: z.number().optional().describe('最大生成 token 数'),
|
||||
stream: z.boolean().optional().default(true).describe('是否使用流式输出'),
|
||||
function_calling: z.boolean().optional().describe('是否支持函数调用'),
|
||||
show_thoughts: z.boolean().optional().describe('是否展示思考过程'),
|
||||
reasoning_effort: z.enum(['low', 'medium', 'high']).optional().describe('推理努力程度'),
|
||||
seed: z.number().optional().describe('随机种子,-1 表示随机'),
|
||||
}).describe('模型生成参数配置');
|
||||
|
||||
/**
|
||||
* Wiki 参数配置
|
||||
*/
|
||||
const WikiParameterSchema = z.object({
|
||||
workspaceName: z.string().describe('工作区名称'),
|
||||
filter: z.string().describe('筛选条件'),
|
||||
}).describe('Wiki 参数配置');
|
||||
|
||||
/**
|
||||
* 触发条件配置
|
||||
*/
|
||||
const TriggerSchema = z.object({
|
||||
search: z.string().optional().describe('搜索关键词'),
|
||||
randomChance: z.number().min(0).max(1).optional().describe('随机触发概率'),
|
||||
filter: z.string().optional().describe('筛选条件'),
|
||||
model: z.object({
|
||||
preset: z.string().optional().describe('预设模型'),
|
||||
system: z.string().optional().describe('系统提示词'),
|
||||
user: z.string().optional().describe('用户提示词'),
|
||||
}).optional().describe('基于模型判断的触发条件'),
|
||||
}).describe('触发条件配置');
|
||||
|
||||
/**
|
||||
* 位置参数配置
|
||||
*/
|
||||
const PositionParameterSchema = z.object({
|
||||
position: z.enum(['relative', 'absolute', 'before', 'after']).describe('位置类型'),
|
||||
targetId: z.string().describe('目标元素ID'),
|
||||
bottom: z.number().optional().describe('底部偏移'),
|
||||
}).describe('位置参数配置');
|
||||
|
||||
/**
|
||||
* 完全替换参数配置
|
||||
*/
|
||||
const FullReplacementParameterSchema = z.object({
|
||||
targetId: z.string().describe('目标元素ID'),
|
||||
sourceType: z.enum(['historyOfSession', 'llmResponse']).describe('源类型'),
|
||||
}).describe('完全替换参数配置');
|
||||
|
||||
/**
|
||||
* 动态位置参数配置
|
||||
*/
|
||||
const DynamicPositionParameterSchema = PositionParameterSchema.extend({}).describe('动态位置参数配置');
|
||||
|
||||
/**
|
||||
* 检索增强生成参数配置
|
||||
*/
|
||||
const RetrievalAugmentedGenerationParameterSchema = PositionParameterSchema.extend({
|
||||
sourceType: z.enum(['wiki']).describe('源类型'),
|
||||
wikiParam: WikiParameterSchema.optional().describe('Wiki 参数'),
|
||||
trigger: TriggerSchema.optional().describe('触发条件'),
|
||||
removal: z.object({
|
||||
expireAfterChatRound: z.number().optional().describe('多少轮对话后过期'),
|
||||
coolDownChatRoundAfterLastShown: z.number().optional().describe('上次展示后冷却轮数'),
|
||||
}).optional().describe('移除条件'),
|
||||
}).describe('检索增强生成参数配置');
|
||||
|
||||
/**
|
||||
* 函数参数配置
|
||||
*/
|
||||
const FunctionParameterSchema = PositionParameterSchema.extend({
|
||||
functionId: z.string().describe('函数ID'),
|
||||
timeoutSecond: z.number().optional().describe('超时时间(秒)'),
|
||||
timeoutMessage: z.string().optional().describe('超时消息'),
|
||||
trigger: TriggerSchema.optional().describe('触发条件'),
|
||||
}).describe('函数参数配置');
|
||||
|
||||
/**
|
||||
* JavaScript 工具参数配置
|
||||
*/
|
||||
const JavascriptToolParameterSchema = PositionParameterSchema.extend({
|
||||
uri: z.string().describe('JavaScript 工具 URI'),
|
||||
}).describe('JavaScript 工具参数配置');
|
||||
|
||||
/**
|
||||
* 模型上下文协议参数配置
|
||||
*/
|
||||
const ModelContextProtocolParameterSchema = PositionParameterSchema.extend({
|
||||
id: z.string().describe('MCP 服务器 ID'),
|
||||
timeoutSecond: z.number().optional().describe('超时时间(秒)'),
|
||||
timeoutMessage: z.string().optional().describe('超时消息'),
|
||||
responseProcessing: z.object({
|
||||
id: z.array(z.string()).describe('响应处理器 ID'),
|
||||
}).optional().describe('响应处理配置'),
|
||||
trigger: TriggerSchema.optional().describe('触发条件'),
|
||||
}).describe('模型上下文协议参数配置');
|
||||
|
||||
/**
|
||||
* 工具调用参数配置
|
||||
*/
|
||||
const ToolCallingParameterSchema = z.object({
|
||||
targetId: z.string().describe('目标元素ID'),
|
||||
match: z.string().describe('匹配模式'),
|
||||
}).describe('工具调用参数配置');
|
||||
|
||||
/**
|
||||
* 自动重新生成参数配置
|
||||
*/
|
||||
const AutoRerollParameterSchema = z.object({
|
||||
targetId: z.string().describe('目标元素ID'),
|
||||
search: z.string().describe('搜索关键词'),
|
||||
maxRetry: z.number().describe('最大重试次数'),
|
||||
}).describe('自动重新生成参数配置');
|
||||
|
||||
/**
|
||||
* 自动回复参数配置
|
||||
*/
|
||||
const AutoReplyParameterSchema = z.object({
|
||||
targetId: z.string().describe('目标元素ID'),
|
||||
text: z.string().describe('回复文本'),
|
||||
trigger: TriggerSchema.describe('触发条件'),
|
||||
maxAutoReply: z.number().describe('最大自动回复次数'),
|
||||
}).describe('自动回复参数配置');
|
||||
|
||||
/**
|
||||
* 提示词动态修改配置
|
||||
*/
|
||||
export const PromptDynamicModificationSchema = z.object({
|
||||
id: z.string().describe('唯一标识符'),
|
||||
caption: z.string().describe('简短描述'),
|
||||
description: z.string().optional().describe('详细描述'),
|
||||
content: z.string().optional().describe('内容'),
|
||||
forbidOverrides: z.boolean().optional().default(false).describe('是否禁止覆盖'),
|
||||
|
||||
// 动态修改类型
|
||||
dynamicModificationType: z.enum([
|
||||
'fullReplacement',
|
||||
'dynamicPosition',
|
||||
'retrievalAugmentedGeneration',
|
||||
'function',
|
||||
'javascriptTool',
|
||||
'modelContextProtocol',
|
||||
]).describe('动态修改类型'),
|
||||
|
||||
// 各种参数配置
|
||||
fullReplacementParam: FullReplacementParameterSchema.optional().describe('完全替换参数'),
|
||||
dynamicPositionParam: DynamicPositionParameterSchema.optional().describe('动态位置参数'),
|
||||
retrievalAugmentedGenerationParam: RetrievalAugmentedGenerationParameterSchema.optional().describe('检索增强生成参数'),
|
||||
functionParam: FunctionParameterSchema.optional().describe('函数参数'),
|
||||
javascriptToolParam: JavascriptToolParameterSchema.optional().describe('JavaScript 工具参数'),
|
||||
modelContextProtocolParam: ModelContextProtocolParameterSchema.optional().describe('模型上下文协议参数'),
|
||||
}).describe('提示词动态修改配置');
|
||||
|
||||
/**
|
||||
* 响应动态修改配置
|
||||
*/
|
||||
export const ResponseDynamicModificationSchema = z.object({
|
||||
id: z.string().describe('唯一标识符'),
|
||||
caption: z.string().optional().describe('简短描述'),
|
||||
dynamicModificationType: z.enum(['fullReplacement']).optional().describe('动态修改类型'),
|
||||
fullReplacementParam: FullReplacementParameterSchema.optional().describe('完全替换参数'),
|
||||
forbidOverrides: z.boolean().optional().default(false).describe('是否禁止覆盖'),
|
||||
|
||||
// 响应处理类型
|
||||
responseProcessingType: z.enum(['toolCalling', 'autoReroll']).optional().describe('响应处理类型'),
|
||||
toolCallingParam: ToolCallingParameterSchema.optional().describe('工具调用参数'),
|
||||
autoRerollParam: AutoRerollParameterSchema.optional().describe('自动重新生成参数'),
|
||||
|
||||
// 响应类型
|
||||
responseType: z.enum(['autoReply']).optional().describe('响应类型'),
|
||||
autoReplyParam: AutoReplyParameterSchema.optional().describe('自动回复参数'),
|
||||
}).describe('响应动态修改配置');
|
||||
|
||||
/**
|
||||
* 响应配置
|
||||
*/
|
||||
export const ResponseSchema = z.object({
|
||||
id: z.string().describe('唯一标识符'),
|
||||
caption: z.string().describe('简短描述'),
|
||||
}).describe('响应配置');
|
||||
|
||||
/**
|
||||
* 代理配置
|
||||
*/
|
||||
export const AgentSchema = z.object({
|
||||
id: z.string().describe('代理唯一标识符'),
|
||||
provider: z.string().describe('提供商'),
|
||||
model: z.string().describe('使用的模型'),
|
||||
modelParameters: ModelParametersSchema.describe('模型参数配置'),
|
||||
prompts: z.array(PromptSchema).describe('提示词配置列表'),
|
||||
promptDynamicModification: z.array(PromptDynamicModificationSchema).describe('提示词动态修改配置列表'),
|
||||
response: z.array(ResponseSchema).describe('响应配置列表'),
|
||||
responseDynamicModification: z.array(ResponseDynamicModificationSchema).describe('响应动态修改配置列表'),
|
||||
}).describe('代理配置');
|
||||
|
||||
/**
|
||||
* 默认代理列表
|
||||
*/
|
||||
export const DefaultAgentsSchema = z.array(AgentSchema).describe('默认代理配置列表');
|
||||
|
||||
/**
|
||||
* 默认代理配置类型
|
||||
*/
|
||||
export type DefaultAgents = z.infer<typeof DefaultAgentsSchema>;
|
||||
export type AgentPromptDescription = z.infer<typeof AgentSchema>;
|
||||
export type ModelParameters = z.infer<typeof ModelParametersSchema>;
|
||||
export type Prompt = z.infer<typeof PromptSchema>;
|
||||
export type PromptDynamicModification = z.infer<typeof PromptDynamicModificationSchema>;
|
||||
export type Response = z.infer<typeof ResponseSchema>;
|
||||
export type ResponseDynamicModification = z.infer<typeof ResponseDynamicModificationSchema>;
|
||||
|
|
@ -82,9 +82,6 @@ export async function* echoHandler(context: TaskContext) {
|
|||
{ text: `You said: ${userText}` },
|
||||
];
|
||||
|
||||
// DEBUG: console response.errorDetail
|
||||
console.log(`response.errorDetail`, response.errorDetail);
|
||||
|
||||
// If we have structured error details, add them as an error part
|
||||
if (response.errorDetail) {
|
||||
parts.push({
|
||||
|
|
|
|||
218
src/services/agent/defaultAgents/exampleAgent.ts
Normal file
218
src/services/agent/defaultAgents/exampleAgent.ts
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
import { container } from '@services/container';
|
||||
import { IExternalAPIService } from '@services/externalAPI/interface';
|
||||
import serviceIdentifier from '@services/serviceIdentifier';
|
||||
import * as fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import { TaskContext, TaskYieldUpdate } from '../server';
|
||||
import * as schema from '../server/schema';
|
||||
import { AgentPromptDescription, DefaultAgentsSchema } from './defaultAgentsSchema';
|
||||
|
||||
/**
|
||||
* 示例代理处理器
|
||||
* 根据 defaultAgents.json 中的配置来处理用户消息并生成响应
|
||||
*
|
||||
* @param context - 任务上下文,包含用户消息和任务信息
|
||||
*/
|
||||
export async function* exampleAgentHandler(context: TaskContext) {
|
||||
// 发送工作中状态
|
||||
yield {
|
||||
state: 'working',
|
||||
message: {
|
||||
role: 'agent',
|
||||
parts: [{ text: '正在处理您的消息...' }],
|
||||
},
|
||||
} as TaskYieldUpdate;
|
||||
|
||||
// 获取 AI API 服务
|
||||
const externalAPIService = container.get<IExternalAPIService>(serviceIdentifier.ExternalAPI);
|
||||
|
||||
// 检查是否被取消
|
||||
if (context.isCancelled()) {
|
||||
yield { state: 'canceled' } as TaskYieldUpdate;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 读取默认代理配置文件
|
||||
const agentsConfigPath = path.join(__dirname, '../defaultAgents.json');
|
||||
const agentsConfigContent = await fs.readFile(agentsConfigPath, 'utf-8');
|
||||
|
||||
// 解析配置文件
|
||||
const agentsConfig = DefaultAgentsSchema.parse(JSON.parse(agentsConfigContent));
|
||||
|
||||
// 查找示例代理配置
|
||||
const exampleAgent = agentsConfig.find(agent => agent.id === 'example-agent');
|
||||
|
||||
if (!exampleAgent) {
|
||||
throw new Error('找不到示例代理配置');
|
||||
}
|
||||
|
||||
// 获取用户消息文本
|
||||
const userText = (context.userMessage.parts as schema.TextPart[])
|
||||
.filter((part) => part.text)
|
||||
.map((part) => part.text)
|
||||
.join(' ');
|
||||
|
||||
// 提供初步反馈
|
||||
yield {
|
||||
state: 'working',
|
||||
message: {
|
||||
role: 'agent',
|
||||
parts: [{ text: `您说: ${userText}\n\n正在使用 ${exampleAgent.provider} 的 ${exampleAgent.model} 模型生成回复...` }],
|
||||
},
|
||||
} as TaskYieldUpdate;
|
||||
|
||||
// 构建提示词
|
||||
const systemPrompt = generateSystemPrompt(exampleAgent);
|
||||
|
||||
// 获取 AI 配置
|
||||
const aiConfig = await externalAPIService.getAIConfig({
|
||||
provider: exampleAgent.provider,
|
||||
model: exampleAgent.model,
|
||||
modelParameters: {
|
||||
temperature: exampleAgent.modelParameters.temperature,
|
||||
maxTokens: exampleAgent.modelParameters.max_tokens,
|
||||
topP: exampleAgent.modelParameters.top_p,
|
||||
},
|
||||
});
|
||||
|
||||
// 跟踪当前请求 ID 用于可能的取消
|
||||
let currentRequestId: string | null = null;
|
||||
|
||||
try {
|
||||
// 使用 AI 服务生成回复
|
||||
for await (
|
||||
const response of externalAPIService.generateFromAI(
|
||||
[
|
||||
{ role: 'system', content: systemPrompt },
|
||||
{ role: 'user', content: userText },
|
||||
],
|
||||
aiConfig,
|
||||
)
|
||||
) {
|
||||
// 存储请求 ID 用于潜在的取消
|
||||
if (!currentRequestId && response.requestId) {
|
||||
currentRequestId = response.requestId;
|
||||
}
|
||||
|
||||
// 检查取消
|
||||
if (context.isCancelled()) {
|
||||
if (currentRequestId) {
|
||||
await externalAPIService.cancelAIRequest(currentRequestId);
|
||||
}
|
||||
yield { state: 'canceled' } as TaskYieldUpdate;
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理不同的响应状态
|
||||
if (response.status === 'update' || response.status === 'done') {
|
||||
yield {
|
||||
state: response.status === 'done' ? 'completed' : 'working',
|
||||
message: {
|
||||
role: 'agent',
|
||||
parts: [{ text: response.content }],
|
||||
},
|
||||
} as TaskYieldUpdate;
|
||||
} else if (response.status === 'error') {
|
||||
// 处理错误响应
|
||||
const parts: schema.Part[] = [
|
||||
{ text: `遇到错误: ${response.errorDetail?.message || '未知错误'}` },
|
||||
];
|
||||
|
||||
// 如果有结构化错误详情,添加它们
|
||||
if (response.errorDetail) {
|
||||
parts.push({
|
||||
type: 'error',
|
||||
error: {
|
||||
name: response.errorDetail.name,
|
||||
code: response.errorDetail.code,
|
||||
provider: response.errorDetail.provider,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
yield {
|
||||
state: 'failed',
|
||||
message: {
|
||||
role: 'agent',
|
||||
parts,
|
||||
},
|
||||
} as TaskYieldUpdate;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// 处理未预期的错误
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
|
||||
yield {
|
||||
state: 'failed',
|
||||
message: {
|
||||
role: 'agent',
|
||||
parts: [{ text: `处理时遇到意外错误: ${errorMessage}` }],
|
||||
},
|
||||
} as TaskYieldUpdate;
|
||||
} finally {
|
||||
// 确保在需要时取消请求
|
||||
if (context.isCancelled() && currentRequestId) {
|
||||
await externalAPIService.cancelAIRequest(currentRequestId);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// 处理配置文件处理错误
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
|
||||
yield {
|
||||
state: 'failed',
|
||||
message: {
|
||||
role: 'agent',
|
||||
parts: [{ text: `配置处理错误: ${errorMessage}` }],
|
||||
},
|
||||
} as TaskYieldUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据代理配置生成系统提示词
|
||||
*
|
||||
* @param agent - 代理配置
|
||||
* @returns 构建好的系统提示词
|
||||
*/
|
||||
function generateSystemPrompt(agent: AgentPromptDescription): string {
|
||||
// 查找系统提示词
|
||||
const systemPrompt = agent.prompts.find(prompt => prompt.id === 'system');
|
||||
if (!systemPrompt || !systemPrompt.children) {
|
||||
return '你是一个AI助手,请回答用户的问题。';
|
||||
}
|
||||
|
||||
// 构建提示词
|
||||
let finalPrompt = '';
|
||||
|
||||
// 添加主要提示词
|
||||
const mainPrompt = systemPrompt.children.find(child => child.id === 'default-main');
|
||||
if (mainPrompt && mainPrompt.text) {
|
||||
finalPrompt = `${mainPrompt.text}\n\n`;
|
||||
}
|
||||
|
||||
// 添加其他标记为 SystemPrompt 的提示词
|
||||
systemPrompt.children
|
||||
.filter(child => child.tags?.includes('SystemPrompt') && child.id !== 'default-main')
|
||||
.forEach(prompt => {
|
||||
if (prompt.text) {
|
||||
finalPrompt = `${finalPrompt}${prompt.text}\n\n`;
|
||||
}
|
||||
});
|
||||
|
||||
// 添加工具提示词,如果存在
|
||||
const toolsPrompt = systemPrompt.children.find(child => child.id === 'default-tools');
|
||||
if (toolsPrompt && toolsPrompt.children) {
|
||||
const beforeTool = toolsPrompt.children.find(child => child.id === 'default-before-tool');
|
||||
const postTool = toolsPrompt.children.find(child => child.id === 'default-post-tool');
|
||||
|
||||
if (beforeTool && beforeTool.text && postTool && postTool.text) {
|
||||
finalPrompt = `${finalPrompt}${beforeTool.text}\n\n${postTool.text}\n\n`;
|
||||
}
|
||||
}
|
||||
|
||||
return finalPrompt.trim();
|
||||
}
|
||||
|
|
@ -1,56 +1,67 @@
|
|||
import * as schema from './schema';
|
||||
import { TaskStore } from './store';
|
||||
// Import TaskStore
|
||||
|
||||
/**
|
||||
* Update yielded by a session handler.
|
||||
* Context object provided to the TaskHandler.
|
||||
*/
|
||||
export type SessionYieldUpdate =
|
||||
| Omit<schema.TaskStatus, 'timestamp'>
|
||||
| schema.Artifact;
|
||||
|
||||
// 保持与 A2A 协议兼容
|
||||
export type TaskYieldUpdate = SessionYieldUpdate;
|
||||
|
||||
/**
|
||||
* Context provided to session handlers for processing messages
|
||||
*/
|
||||
export interface SessionContext {
|
||||
export interface TaskContext {
|
||||
/**
|
||||
* The current session object (kept as 'task' for handler API compatibility)
|
||||
* The current state of the task when the handler is invoked or resumed.
|
||||
* Note: This is a snapshot. For the absolute latest state during async operations,
|
||||
* the handler might need to reload the task via the store.
|
||||
*/
|
||||
task: schema.Task;
|
||||
|
||||
/**
|
||||
* The most recent message from the user
|
||||
* The specific user message that triggered this handler invocation or resumption.
|
||||
*/
|
||||
userMessage: schema.Message;
|
||||
|
||||
/**
|
||||
* Full history of the conversation
|
||||
* Function to check if cancellation has been requested for this task.
|
||||
* Handlers should ideally check this periodically during long-running operations.
|
||||
* @returns {boolean} True if cancellation has been requested, false otherwise.
|
||||
*/
|
||||
history: schema.Message[];
|
||||
isCancelled(): boolean;
|
||||
|
||||
/**
|
||||
* Check if the session has been cancelled
|
||||
* The message history associated with the task up to the point the handler is invoked.
|
||||
* Optional, as history might not always be available or relevant.
|
||||
*/
|
||||
isCancelled: () => boolean;
|
||||
history?: schema.Message[];
|
||||
|
||||
/**
|
||||
* Optional session store for persistence (rarely needed by handlers)
|
||||
*/
|
||||
taskStore?: TaskStore;
|
||||
// taskStore is removed as the server now handles loading/saving directly.
|
||||
// If a handler specifically needs history, it would need to be passed differently
|
||||
// or the handler pattern might need adjustment based on use case.
|
||||
|
||||
// Potential future additions:
|
||||
// - logger instance
|
||||
// - AbortSignal linked to cancellation
|
||||
}
|
||||
|
||||
// Keep TaskContext type for backward compatibility
|
||||
export type TaskContext = SessionContext;
|
||||
/**
|
||||
* Represents the possible types of updates a TaskHandler can yield.
|
||||
* It's either a partial TaskStatus (without the server-managed timestamp)
|
||||
* or a complete Artifact object.
|
||||
*/
|
||||
export type TaskYieldUpdate =
|
||||
| Omit<schema.TaskStatus, 'timestamp'>
|
||||
| schema.Artifact;
|
||||
|
||||
/**
|
||||
* Session handler function type
|
||||
* Takes a session context and returns an async generator of updates
|
||||
* Defines the signature for a task handler function.
|
||||
*
|
||||
* Handlers are implemented as async generators. They receive context about the
|
||||
* task and the triggering message. They can perform work and `yield` status
|
||||
* or artifact updates (`TaskYieldUpdate`). The server consumes these yields,
|
||||
* updates the task state in the store, and streams events if applicable.
|
||||
*
|
||||
* @param context - The TaskContext object containing task details, cancellation status, and store access.
|
||||
* @yields {TaskYieldUpdate} - Updates to the task's status or artifacts.
|
||||
* @returns {Promise<schema.Task | void>} - Optionally returns the final complete Task object
|
||||
* (needed for non-streaming 'tasks/send'). If void is returned, the server uses the
|
||||
* last known state from the store after processing all yields.
|
||||
*/
|
||||
export type SessionHandler = (
|
||||
context: SessionContext
|
||||
) => AsyncGenerator<SessionYieldUpdate>;
|
||||
|
||||
// Keep TaskHandler type for backward compatibility with A2A protocol
|
||||
export type TaskHandler = SessionHandler;
|
||||
export type TaskHandler = (
|
||||
context: TaskContext,
|
||||
) => AsyncGenerator<TaskYieldUpdate, schema.Task | void, unknown>;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue