@zhin.js/core 1.0.36 → 1.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/README.md +57 -3
- package/lib/adapter.d.ts +11 -0
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +61 -0
- package/lib/adapter.js.map +1 -1
- package/lib/ai/index.d.ts +3 -39
- package/lib/ai/index.d.ts.map +1 -1
- package/lib/ai/index.js +2 -44
- package/lib/ai/index.js.map +1 -1
- package/lib/ai/types.d.ts +4 -3
- package/lib/ai/types.d.ts.map +1 -1
- package/lib/built/ai-trigger.js.map +1 -1
- package/lib/built/common-adapter-tools.d.ts +55 -0
- package/lib/built/common-adapter-tools.d.ts.map +1 -0
- package/lib/built/common-adapter-tools.js +158 -0
- package/lib/built/common-adapter-tools.js.map +1 -0
- package/lib/built/dispatcher.d.ts.map +1 -1
- package/lib/built/dispatcher.js +50 -46
- package/lib/built/dispatcher.js.map +1 -1
- package/lib/built/skill.d.ts.map +1 -1
- package/lib/built/skill.js +0 -1
- package/lib/built/skill.js.map +1 -1
- package/lib/built/tool.d.ts +3 -3
- package/lib/built/tool.d.ts.map +1 -1
- package/lib/built/tool.js.map +1 -1
- package/lib/feature.d.ts +16 -1
- package/lib/feature.d.ts.map +1 -1
- package/lib/feature.js +41 -2
- package/lib/feature.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/plugin.d.ts +38 -1
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +73 -22
- package/lib/plugin.js.map +1 -1
- package/lib/scheduler/scheduler.js +1 -1
- package/lib/scheduler/scheduler.js.map +1 -1
- package/lib/types.d.ts +43 -28
- package/lib/types.d.ts.map +1 -1
- package/lib/utils.d.ts +12 -3
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +64 -54
- package/lib/utils.js.map +1 -1
- package/package.json +5 -5
- package/src/adapter.ts +85 -5
- package/src/ai/index.ts +8 -186
- package/src/ai/types.ts +5 -4
- package/src/built/ai-trigger.ts +2 -2
- package/src/built/common-adapter-tools.ts +207 -0
- package/src/built/dispatcher.ts +51 -52
- package/src/built/skill.ts +3 -4
- package/src/built/tool.ts +3 -3
- package/src/feature.ts +45 -2
- package/src/index.ts +2 -0
- package/src/plugin.ts +92 -31
- package/src/scheduler/scheduler.ts +1 -1
- package/src/types.ts +39 -28
- package/src/utils.ts +63 -52
- package/tests/ai/setup.ts +2 -2
- package/tests/utils.test.ts +1 -3
- package/lib/ai/agent.d.ts +0 -130
- package/lib/ai/agent.d.ts.map +0 -1
- package/lib/ai/agent.js +0 -684
- package/lib/ai/agent.js.map +0 -1
- package/lib/ai/bootstrap.d.ts +0 -91
- package/lib/ai/bootstrap.d.ts.map +0 -1
- package/lib/ai/bootstrap.js +0 -243
- package/lib/ai/bootstrap.js.map +0 -1
- package/lib/ai/builtin-tools.d.ts +0 -59
- package/lib/ai/builtin-tools.d.ts.map +0 -1
- package/lib/ai/builtin-tools.js +0 -777
- package/lib/ai/builtin-tools.js.map +0 -1
- package/lib/ai/compaction.d.ts +0 -132
- package/lib/ai/compaction.d.ts.map +0 -1
- package/lib/ai/compaction.js +0 -370
- package/lib/ai/compaction.js.map +0 -1
- package/lib/ai/context-manager.d.ts +0 -213
- package/lib/ai/context-manager.d.ts.map +0 -1
- package/lib/ai/context-manager.js +0 -313
- package/lib/ai/context-manager.js.map +0 -1
- package/lib/ai/conversation-memory.d.ts +0 -181
- package/lib/ai/conversation-memory.d.ts.map +0 -1
- package/lib/ai/conversation-memory.js +0 -581
- package/lib/ai/conversation-memory.js.map +0 -1
- package/lib/ai/cron-engine.d.ts +0 -92
- package/lib/ai/cron-engine.d.ts.map +0 -1
- package/lib/ai/cron-engine.js +0 -278
- package/lib/ai/cron-engine.js.map +0 -1
- package/lib/ai/follow-up.d.ts +0 -131
- package/lib/ai/follow-up.d.ts.map +0 -1
- package/lib/ai/follow-up.js +0 -265
- package/lib/ai/follow-up.js.map +0 -1
- package/lib/ai/hooks.d.ts +0 -143
- package/lib/ai/hooks.d.ts.map +0 -1
- package/lib/ai/hooks.js +0 -108
- package/lib/ai/hooks.js.map +0 -1
- package/lib/ai/init.d.ts +0 -30
- package/lib/ai/init.d.ts.map +0 -1
- package/lib/ai/init.js +0 -686
- package/lib/ai/init.js.map +0 -1
- package/lib/ai/output.d.ts +0 -93
- package/lib/ai/output.d.ts.map +0 -1
- package/lib/ai/output.js +0 -176
- package/lib/ai/output.js.map +0 -1
- package/lib/ai/rate-limiter.d.ts +0 -38
- package/lib/ai/rate-limiter.d.ts.map +0 -1
- package/lib/ai/rate-limiter.js +0 -86
- package/lib/ai/rate-limiter.js.map +0 -1
- package/lib/ai/service.d.ts +0 -88
- package/lib/ai/service.d.ts.map +0 -1
- package/lib/ai/service.js +0 -285
- package/lib/ai/service.js.map +0 -1
- package/lib/ai/session.d.ts +0 -186
- package/lib/ai/session.d.ts.map +0 -1
- package/lib/ai/session.js +0 -443
- package/lib/ai/session.js.map +0 -1
- package/lib/ai/subagent.d.ts +0 -50
- package/lib/ai/subagent.d.ts.map +0 -1
- package/lib/ai/subagent.js +0 -144
- package/lib/ai/subagent.js.map +0 -1
- package/lib/ai/tone-detector.d.ts +0 -19
- package/lib/ai/tone-detector.d.ts.map +0 -1
- package/lib/ai/tone-detector.js +0 -72
- package/lib/ai/tone-detector.js.map +0 -1
- package/lib/ai/tools.d.ts +0 -45
- package/lib/ai/tools.d.ts.map +0 -1
- package/lib/ai/tools.js +0 -206
- package/lib/ai/tools.js.map +0 -1
- package/lib/ai/user-profile.d.ts +0 -56
- package/lib/ai/user-profile.d.ts.map +0 -1
- package/lib/ai/user-profile.js +0 -130
- package/lib/ai/user-profile.js.map +0 -1
- package/lib/ai/zhin-agent/builtin-tools.d.ts +0 -17
- package/lib/ai/zhin-agent/builtin-tools.d.ts.map +0 -1
- package/lib/ai/zhin-agent/builtin-tools.js +0 -220
- package/lib/ai/zhin-agent/builtin-tools.js.map +0 -1
- package/lib/ai/zhin-agent/config.d.ts +0 -54
- package/lib/ai/zhin-agent/config.d.ts.map +0 -1
- package/lib/ai/zhin-agent/config.js +0 -76
- package/lib/ai/zhin-agent/config.js.map +0 -1
- package/lib/ai/zhin-agent/exec-policy.d.ts +0 -20
- package/lib/ai/zhin-agent/exec-policy.d.ts.map +0 -1
- package/lib/ai/zhin-agent/exec-policy.js +0 -71
- package/lib/ai/zhin-agent/exec-policy.js.map +0 -1
- package/lib/ai/zhin-agent/index.d.ts +0 -70
- package/lib/ai/zhin-agent/index.d.ts.map +0 -1
- package/lib/ai/zhin-agent/index.js +0 -404
- package/lib/ai/zhin-agent/index.js.map +0 -1
- package/lib/ai/zhin-agent/prompt.d.ts +0 -21
- package/lib/ai/zhin-agent/prompt.d.ts.map +0 -1
- package/lib/ai/zhin-agent/prompt.js +0 -111
- package/lib/ai/zhin-agent/prompt.js.map +0 -1
- package/lib/ai/zhin-agent/tool-collector.d.ts +0 -22
- package/lib/ai/zhin-agent/tool-collector.d.ts.map +0 -1
- package/lib/ai/zhin-agent/tool-collector.js +0 -218
- package/lib/ai/zhin-agent/tool-collector.js.map +0 -1
- package/src/ai/agent.ts +0 -812
- package/src/ai/bootstrap.ts +0 -309
- package/src/ai/builtin-tools.ts +0 -849
- package/src/ai/compaction.ts +0 -529
- package/src/ai/context-manager.ts +0 -440
- package/src/ai/conversation-memory.ts +0 -774
- package/src/ai/cron-engine.ts +0 -337
- package/src/ai/follow-up.ts +0 -357
- package/src/ai/hooks.ts +0 -223
- package/src/ai/init.ts +0 -762
- package/src/ai/output.ts +0 -261
- package/src/ai/rate-limiter.ts +0 -129
- package/src/ai/service.ts +0 -331
- package/src/ai/session.ts +0 -544
- package/src/ai/subagent.ts +0 -209
- package/src/ai/tone-detector.ts +0 -89
- package/src/ai/tools.ts +0 -218
- package/src/ai/user-profile.ts +0 -181
- package/src/ai/zhin-agent/builtin-tools.ts +0 -247
- package/src/ai/zhin-agent/config.ts +0 -113
- package/src/ai/zhin-agent/exec-policy.ts +0 -78
- package/src/ai/zhin-agent/index.ts +0 -512
- package/src/ai/zhin-agent/prompt.ts +0 -131
- package/src/ai/zhin-agent/tool-collector.ts +0 -243
- package/tests/ai/agent.test.ts +0 -614
- package/tests/ai/context-manager.test.ts +0 -413
- package/tests/ai/conversation-memory.test.ts +0 -128
- package/tests/ai/follow-up.test.ts +0 -175
- package/tests/ai/integration.test.ts +0 -584
- package/tests/ai/output.test.ts +0 -128
- package/tests/ai/rate-limiter.test.ts +0 -108
- package/tests/ai/session.test.ts +0 -375
- package/tests/ai/subagent.test.ts +0 -270
- package/tests/ai/tone-detector.test.ts +0 -80
- package/tests/ai/tools-builtin.test.ts +0 -346
- package/tests/ai/user-profile.test.ts +0 -73
- package/tests/ai/zhin-agent.test.ts +0 -177
package/src/types.ts
CHANGED
|
@@ -14,7 +14,7 @@ export interface Models extends Record<string,object>{
|
|
|
14
14
|
SystemLog: SystemLog
|
|
15
15
|
User: User,
|
|
16
16
|
}
|
|
17
|
-
export type MaybePromise<T> = T extends Promise<infer U> ? T|U : T|Promise<T>;
|
|
17
|
+
export type MaybePromise<T> = [T] extends [Promise<infer U>] ? T|U : T|Promise<T>;
|
|
18
18
|
export interface RegisteredAdapters {
|
|
19
19
|
process: ProcessAdapter;
|
|
20
20
|
}
|
|
@@ -71,6 +71,8 @@ export interface MessageSender{
|
|
|
71
71
|
id: string;
|
|
72
72
|
name?: string;
|
|
73
73
|
permissions?:string[]
|
|
74
|
+
/** 平台侧角色标识(owner / admin / member 等) */
|
|
75
|
+
role?: string;
|
|
74
76
|
}
|
|
75
77
|
/**
|
|
76
78
|
* 通用字典类型
|
|
@@ -305,25 +307,52 @@ export type ToolScope = 'private' | 'group' | 'channel';
|
|
|
305
307
|
*/
|
|
306
308
|
export type ToolPermissionLevel = 'user' | 'group_admin' | 'group_owner' | 'bot_admin' | 'owner';
|
|
307
309
|
|
|
308
|
-
|
|
310
|
+
/**
|
|
311
|
+
* 标准化工具返回类型。
|
|
312
|
+
* execute 可返回以下任一形式:
|
|
313
|
+
* - string: 直接作为文本回复
|
|
314
|
+
* - { text: string }: 结构化文本
|
|
315
|
+
* - { data: unknown; format?: string }: 结构化数据
|
|
316
|
+
* - void/null/undefined: 无回复
|
|
317
|
+
* - Record / Array: 自动 JSON.stringify
|
|
318
|
+
*/
|
|
319
|
+
export type ToolResult = string | void | null | undefined | { text: string } | { data: unknown; format?: string } | Record<string, unknown> | unknown[];
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* 统一的 Tool 定义(支持泛型参数类型推断)。
|
|
323
|
+
*
|
|
324
|
+
* @template TArgs 参数类型,默认 Record<string, any>
|
|
325
|
+
*
|
|
326
|
+
* @example
|
|
327
|
+
* ```typescript
|
|
328
|
+
* // 无泛型 — 兼容旧代码
|
|
329
|
+
* const tool: Tool = { name: 'ping', ... };
|
|
330
|
+
*
|
|
331
|
+
* // 有泛型 — 通过 defineTool 获得类型安全
|
|
332
|
+
* const tool = defineTool<{ city: string }>({
|
|
333
|
+
* name: 'weather',
|
|
334
|
+
* parameters: { type: 'object', properties: { city: { type: 'string', description: '城市' } }, required: ['city'] },
|
|
335
|
+
* execute: async (args) => args.city, // args.city 有类型提示
|
|
336
|
+
* });
|
|
337
|
+
* ```
|
|
338
|
+
*/
|
|
339
|
+
export interface Tool<TArgs extends Record<string, any> = Record<string, any>> {
|
|
309
340
|
/** 工具名称(唯一标识,建议使用 snake_case) */
|
|
310
341
|
name: string;
|
|
311
342
|
|
|
312
343
|
/** 工具描述(供 AI 和帮助系统使用) */
|
|
313
344
|
description: string;
|
|
314
345
|
|
|
315
|
-
/**
|
|
316
|
-
|
|
317
|
-
*/
|
|
318
|
-
parameters: ToolParametersSchema;
|
|
346
|
+
/** 参数定义(JSON Schema 格式) */
|
|
347
|
+
parameters: ToolParametersSchema<TArgs>;
|
|
319
348
|
|
|
320
349
|
/**
|
|
321
350
|
* 工具执行函数
|
|
322
351
|
* @param args 解析后的参数
|
|
323
352
|
* @param context 执行上下文(包含消息、发送者等信息)
|
|
324
|
-
* @returns
|
|
353
|
+
* @returns 执行结果
|
|
325
354
|
*/
|
|
326
|
-
execute: (args:
|
|
355
|
+
execute: (args: TArgs, context?: ToolContext) => MaybePromise<ToolResult>;
|
|
327
356
|
|
|
328
357
|
/** 工具来源标识(自动填充:adapter:xxx / plugin:xxx) */
|
|
329
358
|
source?: string;
|
|
@@ -386,27 +415,9 @@ export interface Tool {
|
|
|
386
415
|
}
|
|
387
416
|
|
|
388
417
|
/**
|
|
389
|
-
*
|
|
390
|
-
* 提供泛型参数以获得 execute 函数的类型推断
|
|
418
|
+
* @deprecated 使用 `Tool<TArgs>` 替代。Tool 已原生支持泛型。
|
|
391
419
|
*/
|
|
392
|
-
export
|
|
393
|
-
name: string;
|
|
394
|
-
description: string;
|
|
395
|
-
parameters: ToolParametersSchema<TArgs>;
|
|
396
|
-
execute: (args: TArgs, context?: ToolContext) => MaybePromise<any>;
|
|
397
|
-
source?: string;
|
|
398
|
-
tags?: string[];
|
|
399
|
-
keywords?: string[];
|
|
400
|
-
command?: Tool.CommandConfig | false;
|
|
401
|
-
permissions?: string[];
|
|
402
|
-
/** 支持的平台列表(不填则支持所有平台) */
|
|
403
|
-
platforms?: string[];
|
|
404
|
-
/** 支持的场景列表(不填则支持所有场景) */
|
|
405
|
-
scopes?: ToolScope[];
|
|
406
|
-
/** 调用所需的最低权限级别(默认 'user') */
|
|
407
|
-
permissionLevel?: ToolPermissionLevel;
|
|
408
|
-
hidden?: boolean;
|
|
409
|
-
}
|
|
420
|
+
export type ToolDefinition<TArgs extends Record<string, any> = Record<string, any>> = Tool<TArgs>;
|
|
410
421
|
|
|
411
422
|
export namespace Tool {
|
|
412
423
|
/**
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as path from "path";
|
|
2
2
|
import * as fs from "fs";
|
|
3
|
+
import * as vm from "vm";
|
|
3
4
|
import {
|
|
4
5
|
AdapterMessage,
|
|
5
6
|
Dict,
|
|
@@ -11,15 +12,21 @@ import {
|
|
|
11
12
|
import { Message } from "./message.js";
|
|
12
13
|
|
|
13
14
|
export function getValueWithRuntime(template: string, ctx: Dict) {
|
|
14
|
-
|
|
15
|
-
if (result === `return(${template})`) return undefined;
|
|
16
|
-
return result;
|
|
15
|
+
return evaluate(template, ctx);
|
|
17
16
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Evaluate a single expression in a sandboxed vm context.
|
|
19
|
+
* Unlike `execute`, does NOT wrap in IIFE — the expression value is returned directly.
|
|
20
|
+
*/
|
|
21
|
+
export const evaluate = <S extends Record<string, unknown>, T = unknown>(exp: string, context: S): T | undefined => {
|
|
22
|
+
const script = getOrCompileScript(exp);
|
|
23
|
+
if (!script) return undefined;
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
return script.runInNewContext(buildSandbox(context), { timeout: 200 }) as T;
|
|
27
|
+
} catch {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
23
30
|
};
|
|
24
31
|
/**
|
|
25
32
|
* 组合中间件,洋葱模型
|
|
@@ -74,25 +81,28 @@ export function compose<P extends RegisteredAdapter=RegisteredAdapter>(
|
|
|
74
81
|
return dispatch(0);
|
|
75
82
|
};
|
|
76
83
|
}
|
|
77
|
-
//
|
|
84
|
+
// LRU cache for compiled vm.Script instances
|
|
78
85
|
const MAX_EVAL_CACHE_SIZE = 1000;
|
|
79
|
-
const
|
|
80
|
-
const evalCacheKeys: string[] = [];
|
|
86
|
+
const scriptCache = new Map<string, vm.Script>();
|
|
81
87
|
|
|
82
|
-
|
|
83
|
-
let
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
delete evalCache[oldest];
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
fn = evalCache[exp] = toFunction(exp);
|
|
93
|
-
evalCacheKeys.push(exp);
|
|
88
|
+
function getOrCompileScript(code: string): vm.Script | null {
|
|
89
|
+
let script = scriptCache.get(code);
|
|
90
|
+
if (script) return script;
|
|
91
|
+
try {
|
|
92
|
+
script = new vm.Script(code);
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
94
95
|
}
|
|
95
|
-
|
|
96
|
+
if (scriptCache.size >= MAX_EVAL_CACHE_SIZE) {
|
|
97
|
+
const oldest = scriptCache.keys().next().value;
|
|
98
|
+
if (oldest !== undefined) scriptCache.delete(oldest);
|
|
99
|
+
}
|
|
100
|
+
scriptCache.set(code, script);
|
|
101
|
+
return script;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function buildSandbox<S extends Record<string, unknown>>(context: S): Record<string, unknown> {
|
|
105
|
+
return {
|
|
96
106
|
...context,
|
|
97
107
|
process: {
|
|
98
108
|
version: process.version,
|
|
@@ -106,48 +116,48 @@ export const execute = <S, T = any>(exp: string, context: S): T => {
|
|
|
106
116
|
pid: process.pid,
|
|
107
117
|
ppid: process.ppid,
|
|
108
118
|
},
|
|
109
|
-
Bun: "你想干嘛",
|
|
110
119
|
global: undefined,
|
|
120
|
+
globalThis: undefined,
|
|
111
121
|
Buffer: undefined,
|
|
112
122
|
crypto: undefined,
|
|
123
|
+
require: undefined,
|
|
124
|
+
import: undefined,
|
|
125
|
+
__dirname: undefined,
|
|
126
|
+
__filename: undefined,
|
|
127
|
+
Bun: undefined,
|
|
128
|
+
Deno: undefined,
|
|
113
129
|
};
|
|
114
|
-
|
|
115
|
-
return fn.apply(context, [context]);
|
|
116
|
-
} catch {
|
|
117
|
-
return exp as T;
|
|
118
|
-
}
|
|
119
|
-
};
|
|
130
|
+
}
|
|
120
131
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Execute a code block in a sandboxed vm context.
|
|
134
|
+
* Supports `return` statements by wrapping in an IIFE.
|
|
135
|
+
* Throws on compilation or runtime errors.
|
|
136
|
+
*/
|
|
137
|
+
export const execute = <S extends Record<string, unknown>, T = unknown>(code: string, context: S): T => {
|
|
138
|
+
const wrapped = `(function(){${code}})()`;
|
|
139
|
+
const script = getOrCompileScript(wrapped);
|
|
140
|
+
if (!script) throw new SyntaxError(`Failed to compile: ${code.slice(0, 80)}`);
|
|
141
|
+
|
|
142
|
+
return script.runInNewContext(buildSandbox(context), { timeout: 200 }) as T;
|
|
127
143
|
};
|
|
128
144
|
|
|
129
|
-
// 清理 evalCache(用于内存调试)
|
|
130
145
|
export function clearEvalCache(): void {
|
|
131
|
-
|
|
132
|
-
delete evalCache[key];
|
|
133
|
-
});
|
|
134
|
-
evalCacheKeys.length = 0;
|
|
146
|
+
scriptCache.clear();
|
|
135
147
|
}
|
|
136
148
|
|
|
137
|
-
// 获取 evalCache 统计信息(用于内存调试)
|
|
138
149
|
export function getEvalCacheStats(): { size: number; maxSize: number } {
|
|
139
150
|
return {
|
|
140
|
-
size:
|
|
141
|
-
maxSize: MAX_EVAL_CACHE_SIZE
|
|
151
|
+
size: scriptCache.size,
|
|
152
|
+
maxSize: MAX_EVAL_CACHE_SIZE,
|
|
142
153
|
};
|
|
143
154
|
}
|
|
144
155
|
export function compiler(template: string, ctx: Dict) {
|
|
145
156
|
const matched = [...template.matchAll(/\${([^}]*?)}/g)];
|
|
146
157
|
for (const item of matched) {
|
|
147
158
|
const tpl = item[1];
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
if (typeof value !== "string") value = JSON.stringify(value, null, 2);
|
|
159
|
+
const raw = getValueWithRuntime(tpl, ctx);
|
|
160
|
+
const value = typeof raw === 'string' ? raw : (raw == null ? 'undefined' : JSON.stringify(raw, null, 2));
|
|
151
161
|
template = template.replace(`\${${item[1]}}`, value);
|
|
152
162
|
}
|
|
153
163
|
return template;
|
|
@@ -394,14 +404,15 @@ export namespace Time {
|
|
|
394
404
|
|
|
395
405
|
export function parseDate(date: string) {
|
|
396
406
|
const parsed = parseTime(date);
|
|
407
|
+
let dateInput: string | number = date;
|
|
397
408
|
if (parsed) {
|
|
398
|
-
|
|
409
|
+
dateInput = Date.now() + parsed;
|
|
399
410
|
} else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) {
|
|
400
|
-
|
|
411
|
+
dateInput = `${new Date().toLocaleDateString()}-${date}`;
|
|
401
412
|
} else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) {
|
|
402
|
-
|
|
413
|
+
dateInput = `${new Date().getFullYear()}-${date}`;
|
|
403
414
|
}
|
|
404
|
-
return
|
|
415
|
+
return dateInput ? new Date(dateInput) : new Date();
|
|
405
416
|
}
|
|
406
417
|
|
|
407
418
|
export function formatTimeShort(ms: number) {
|
package/tests/ai/setup.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { vi } from 'vitest';
|
|
10
10
|
import type { Message, MessageElement, Tool, ToolContext } from '@zhin.js/core';
|
|
11
|
-
import type { AIConfig,
|
|
11
|
+
import type { AIConfig, ChatMessage } from '@zhin.js/core';
|
|
12
12
|
|
|
13
13
|
// ============================================================================
|
|
14
14
|
// Logger Mock
|
|
@@ -226,7 +226,7 @@ export const createMockAIConfig = (overrides: Partial<AIConfig> = {}): AIConfig
|
|
|
226
226
|
defaultProvider: 'mock',
|
|
227
227
|
sessions: {
|
|
228
228
|
maxHistory: 10,
|
|
229
|
-
|
|
229
|
+
expireMs: 300000,
|
|
230
230
|
},
|
|
231
231
|
context: {
|
|
232
232
|
enabled: false,
|
package/tests/utils.test.ts
CHANGED
|
@@ -140,9 +140,7 @@ describe('evaluate and execute', () => {
|
|
|
140
140
|
})
|
|
141
141
|
|
|
142
142
|
it('should handle invalid expressions gracefully', () => {
|
|
143
|
-
|
|
144
|
-
// 无效表达式会被 try-catch 捕获,返回 undefined
|
|
145
|
-
expect(result).toBeUndefined()
|
|
143
|
+
expect(() => execute('invalid syntax here !!!', {})).toThrow()
|
|
146
144
|
})
|
|
147
145
|
|
|
148
146
|
it('should provide safe process context', () => {
|
package/lib/ai/agent.d.ts
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @zhin.js/ai - Agent System
|
|
3
|
-
* AI Agent 实现,支持工具调用和多轮对话
|
|
4
|
-
*/
|
|
5
|
-
import type { AIProvider, AgentConfig, AgentTool, AgentResult, ChatMessage, ToolFilterOptions, Usage } from './types.js';
|
|
6
|
-
/**
|
|
7
|
-
* 根据工具名和参数生成简短标题(用于日志、TOOLS.md 等)
|
|
8
|
-
*/
|
|
9
|
-
export declare function formatToolTitle(name: string, args?: Record<string, any>): string;
|
|
10
|
-
/**
|
|
11
|
-
* Agent 执行状态
|
|
12
|
-
*/
|
|
13
|
-
export interface AgentState {
|
|
14
|
-
messages: ChatMessage[];
|
|
15
|
-
toolCalls: {
|
|
16
|
-
tool: string;
|
|
17
|
-
args: Record<string, any>;
|
|
18
|
-
result: any;
|
|
19
|
-
}[];
|
|
20
|
-
usage: Usage;
|
|
21
|
-
iterations: number;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Agent 事件
|
|
25
|
-
*/
|
|
26
|
-
export interface AgentEvents {
|
|
27
|
-
'thinking': (message: string) => void;
|
|
28
|
-
'tool_call': (tool: string, args: Record<string, any>) => void;
|
|
29
|
-
'tool_result': (tool: string, result: any) => void;
|
|
30
|
-
'streaming': (content: string) => void;
|
|
31
|
-
'complete': (result: AgentResult) => void;
|
|
32
|
-
'error': (error: Error) => void;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* AI Agent 类
|
|
36
|
-
* 支持工具调用、多轮对话、流式输出
|
|
37
|
-
*/
|
|
38
|
-
export declare class Agent {
|
|
39
|
-
private provider;
|
|
40
|
-
private config;
|
|
41
|
-
private tools;
|
|
42
|
-
private eventHandlers;
|
|
43
|
-
constructor(provider: AIProvider, config: AgentConfig);
|
|
44
|
-
/**
|
|
45
|
-
* 默认系统提示词
|
|
46
|
-
*/
|
|
47
|
-
private getDefaultSystemPrompt;
|
|
48
|
-
/**
|
|
49
|
-
* 注册事件处理器
|
|
50
|
-
*/
|
|
51
|
-
on<K extends keyof AgentEvents>(event: K, handler: AgentEvents[K]): () => void;
|
|
52
|
-
/**
|
|
53
|
-
* 触发事件
|
|
54
|
-
*/
|
|
55
|
-
private emit;
|
|
56
|
-
/**
|
|
57
|
-
* 添加工具
|
|
58
|
-
*/
|
|
59
|
-
addTool(tool: AgentTool): void;
|
|
60
|
-
/**
|
|
61
|
-
* 移除工具
|
|
62
|
-
*/
|
|
63
|
-
removeTool(name: string): void;
|
|
64
|
-
/**
|
|
65
|
-
* 获取工具定义(缓存在第一次调用后保持不变)
|
|
66
|
-
*/
|
|
67
|
-
private getToolDefinitions;
|
|
68
|
-
/**
|
|
69
|
-
* 生成工具调用的去重 key
|
|
70
|
-
*/
|
|
71
|
-
private static toolCallKey;
|
|
72
|
-
/**
|
|
73
|
-
* 安全解析 JSON,失败则返回原始字符串
|
|
74
|
-
*/
|
|
75
|
-
private static safeParse;
|
|
76
|
-
/**
|
|
77
|
-
* 程序化工具过滤 —— 替代 AI 意图分析的高效方案
|
|
78
|
-
*
|
|
79
|
-
* 评分规则(按权重从高到低):
|
|
80
|
-
* 1. keywords 精确匹配: +1.0 per hit —— 工具声明的触发关键词
|
|
81
|
-
* 2. tags 匹配: +0.5 per hit —— 工具分类标签
|
|
82
|
-
* 3. 工具名 token 匹配: +0.3 per hit —— 工具名按 `.` `_` `-` 拆词
|
|
83
|
-
* 4. description 关键词: +0.15 per hit —— 描述中的词/短语
|
|
84
|
-
*
|
|
85
|
-
* 权限过滤发生在评分之前,直接跳过无权使用的工具。
|
|
86
|
-
*
|
|
87
|
-
* @param message 用户消息原文
|
|
88
|
-
* @param tools 候选工具列表
|
|
89
|
-
* @param options 过滤选项
|
|
90
|
-
* @returns 按相关性降序排列的工具子集
|
|
91
|
-
*/
|
|
92
|
-
static filterTools(message: string, tools: AgentTool[], options?: ToolFilterOptions): AgentTool[];
|
|
93
|
-
/**
|
|
94
|
-
* 执行单个工具调用(带超时保护)
|
|
95
|
-
*/
|
|
96
|
-
private executeToolCall;
|
|
97
|
-
/**
|
|
98
|
-
* 并行执行多个工具调用(跳过重复的)
|
|
99
|
-
* @returns 新执行的工具调用结果列表;如果全部重复则返回空数组
|
|
100
|
-
*/
|
|
101
|
-
private executeToolCalls;
|
|
102
|
-
/**
|
|
103
|
-
* 累加 token 用量
|
|
104
|
-
*/
|
|
105
|
-
private static addUsage;
|
|
106
|
-
/**
|
|
107
|
-
* 运行 Agent
|
|
108
|
-
*
|
|
109
|
-
* @param userMessage 用户消息
|
|
110
|
-
* @param context 对话上下文
|
|
111
|
-
* @param filterOptions 工具过滤选项 —— 启用后在 AI 调用之前程序化筛选工具,省去额外的 AI 意图分析往返
|
|
112
|
-
*/
|
|
113
|
-
run(userMessage: string, context?: ChatMessage[], filterOptions?: ToolFilterOptions): Promise<AgentResult>;
|
|
114
|
-
/**
|
|
115
|
-
* 流式运行 Agent
|
|
116
|
-
*
|
|
117
|
-
* @param userMessage 用户消息
|
|
118
|
-
* @param context 对话上下文
|
|
119
|
-
* @param filterOptions 工具过滤选项 —— 启用后在 AI 调用之前程序化筛选工具
|
|
120
|
-
*/
|
|
121
|
-
runStream(userMessage: string, context?: ChatMessage[], filterOptions?: ToolFilterOptions): AsyncIterable<{
|
|
122
|
-
type: 'content' | 'tool_call' | 'tool_result' | 'done';
|
|
123
|
-
data: any;
|
|
124
|
-
}>;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* 创建 Agent 实例
|
|
128
|
-
*/
|
|
129
|
-
export declare function createAgent(provider: AIProvider, config: Omit<AgentConfig, 'provider'>): Agent;
|
|
130
|
-
//# sourceMappingURL=agent.d.ts.map
|
package/lib/ai/agent.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/ai/agent.ts"],"names":[],"mappings":"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"}
|