@zhin.js/agent 0.1.14 → 0.1.16
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/README.md +80 -43
- package/lib/builtin/activate-skill-tool.d.ts +21 -0
- package/lib/builtin/activate-skill-tool.d.ts.map +1 -0
- package/lib/builtin/activate-skill-tool.js +57 -0
- package/lib/builtin/activate-skill-tool.js.map +1 -0
- package/lib/builtin/ask-user-tool.d.ts +28 -0
- package/lib/builtin/ask-user-tool.d.ts.map +1 -0
- package/lib/builtin/ask-user-tool.js +182 -0
- package/lib/builtin/ask-user-tool.js.map +1 -0
- package/lib/builtin/bash-tool.d.ts +23 -0
- package/lib/builtin/bash-tool.d.ts.map +1 -0
- package/lib/builtin/bash-tool.js +64 -0
- package/lib/builtin/bash-tool.js.map +1 -0
- package/lib/builtin/bing-search-html.d.ts +37 -0
- package/lib/builtin/bing-search-html.d.ts.map +1 -0
- package/lib/builtin/bing-search-html.js +116 -0
- package/lib/builtin/bing-search-html.js.map +1 -0
- package/lib/builtin/builtin-base-tool.d.ts +25 -0
- package/lib/builtin/builtin-base-tool.d.ts.map +1 -0
- package/lib/builtin/builtin-base-tool.js +30 -0
- package/lib/builtin/builtin-base-tool.js.map +1 -0
- package/lib/builtin/edit-file-tool.d.ts +13 -0
- package/lib/builtin/edit-file-tool.d.ts.map +1 -0
- package/lib/builtin/edit-file-tool.js +81 -0
- package/lib/builtin/edit-file-tool.js.map +1 -0
- package/lib/builtin/file-edit-quote-utils.d.ts +24 -0
- package/lib/builtin/file-edit-quote-utils.d.ts.map +1 -0
- package/lib/builtin/file-edit-quote-utils.js +81 -0
- package/lib/builtin/file-edit-quote-utils.js.map +1 -0
- package/lib/builtin/glob-tool.d.ts +23 -0
- package/lib/builtin/glob-tool.d.ts.map +1 -0
- package/lib/builtin/glob-tool.js +54 -0
- package/lib/builtin/glob-tool.js.map +1 -0
- package/lib/builtin/grep-tool.d.ts +23 -0
- package/lib/builtin/grep-tool.d.ts.map +1 -0
- package/lib/builtin/grep-tool.js +118 -0
- package/lib/builtin/grep-tool.js.map +1 -0
- package/lib/builtin/install-skill-tool.d.ts +24 -0
- package/lib/builtin/install-skill-tool.d.ts.map +1 -0
- package/lib/builtin/install-skill-tool.js +76 -0
- package/lib/builtin/install-skill-tool.js.map +1 -0
- package/lib/builtin/list-dir-tool.d.ts +13 -0
- package/lib/builtin/list-dir-tool.d.ts.map +1 -0
- package/lib/builtin/list-dir-tool.js +59 -0
- package/lib/builtin/list-dir-tool.js.map +1 -0
- package/lib/builtin/read-file-tool.d.ts +14 -0
- package/lib/builtin/read-file-tool.d.ts.map +1 -0
- package/lib/builtin/read-file-tool.js +77 -0
- package/lib/builtin/read-file-tool.js.map +1 -0
- package/lib/builtin/read-memory-tool.d.ts +14 -0
- package/lib/builtin/read-memory-tool.d.ts.map +1 -0
- package/lib/builtin/read-memory-tool.js +49 -0
- package/lib/builtin/read-memory-tool.js.map +1 -0
- package/lib/builtin/spawn-task-tool.d.ts +20 -0
- package/lib/builtin/spawn-task-tool.d.ts.map +1 -0
- package/lib/builtin/spawn-task-tool.js +57 -0
- package/lib/builtin/spawn-task-tool.js.map +1 -0
- package/lib/builtin/todo-read-tool.d.ts +14 -0
- package/lib/builtin/todo-read-tool.d.ts.map +1 -0
- package/lib/builtin/todo-read-tool.js +56 -0
- package/lib/builtin/todo-read-tool.js.map +1 -0
- package/lib/builtin/todo-write-tool.d.ts +14 -0
- package/lib/builtin/todo-write-tool.d.ts.map +1 -0
- package/lib/builtin/todo-write-tool.js +54 -0
- package/lib/builtin/todo-write-tool.js.map +1 -0
- package/lib/builtin/web-fetch-tool.d.ts +19 -0
- package/lib/builtin/web-fetch-tool.d.ts.map +1 -0
- package/lib/builtin/web-fetch-tool.js +89 -0
- package/lib/builtin/web-fetch-tool.js.map +1 -0
- package/lib/builtin/web-search-locale.d.ts +16 -0
- package/lib/builtin/web-search-locale.d.ts.map +1 -0
- package/lib/builtin/web-search-locale.js +73 -0
- package/lib/builtin/web-search-locale.js.map +1 -0
- package/lib/builtin/web-search-tool.d.ts +20 -0
- package/lib/builtin/web-search-tool.d.ts.map +1 -0
- package/lib/builtin/web-search-tool.js +105 -0
- package/lib/builtin/web-search-tool.js.map +1 -0
- package/lib/builtin/web-tool-utils.d.ts +4 -0
- package/lib/builtin/web-tool-utils.d.ts.map +1 -0
- package/lib/builtin/web-tool-utils.js +4 -0
- package/lib/builtin/web-tool-utils.js.map +1 -0
- package/lib/builtin/write-file-tool.d.ts +13 -0
- package/lib/builtin/write-file-tool.d.ts.map +1 -0
- package/lib/builtin/write-file-tool.js +51 -0
- package/lib/builtin/write-file-tool.js.map +1 -0
- package/lib/builtin/write-memory-tool.d.ts +14 -0
- package/lib/builtin/write-memory-tool.d.ts.map +1 -0
- package/lib/builtin/write-memory-tool.js +50 -0
- package/lib/builtin/write-memory-tool.js.map +1 -0
- package/lib/builtin-tools.d.ts +10 -11
- package/lib/builtin-tools.d.ts.map +1 -1
- package/lib/builtin-tools.js +44 -862
- package/lib/builtin-tools.js.map +1 -1
- package/lib/defaults/tools.d.ts +3 -6
- package/lib/defaults/tools.d.ts.map +1 -1
- package/lib/defaults/tools.js +3 -11
- package/lib/defaults/tools.js.map +1 -1
- package/lib/index.d.ts +25 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +24 -3
- package/lib/index.js.map +1 -1
- package/lib/init/create-zhin-agent.d.ts.map +1 -1
- package/lib/init/create-zhin-agent.js +4 -3
- package/lib/init/create-zhin-agent.js.map +1 -1
- package/lib/init/message-media.d.ts +8 -0
- package/lib/init/message-media.d.ts.map +1 -0
- package/lib/init/message-media.js +75 -0
- package/lib/init/message-media.js.map +1 -0
- package/lib/init/output-renderer.d.ts +3 -0
- package/lib/init/output-renderer.d.ts.map +1 -0
- package/lib/init/output-renderer.js +38 -0
- package/lib/init/output-renderer.js.map +1 -0
- package/lib/init/register-ai-trigger.d.ts +1 -1
- package/lib/init/register-ai-trigger.d.ts.map +1 -1
- package/lib/init/register-ai-trigger.js +35 -159
- package/lib/init/register-ai-trigger.js.map +1 -1
- package/lib/init/register-builtin-tools.d.ts.map +1 -1
- package/lib/init/register-builtin-tools.js +9 -5
- package/lib/init/register-builtin-tools.js.map +1 -1
- package/lib/orchestrator/index.d.ts +2 -0
- package/lib/orchestrator/index.d.ts.map +1 -1
- package/lib/orchestrator/index.js +1 -0
- package/lib/orchestrator/index.js.map +1 -1
- package/lib/orchestrator/resource-registry.d.ts +1 -0
- package/lib/orchestrator/resource-registry.d.ts.map +1 -1
- package/lib/orchestrator/resource-registry.js +6 -0
- package/lib/orchestrator/resource-registry.js.map +1 -1
- package/lib/orchestrator/tool-registry.d.ts +5 -11
- package/lib/orchestrator/tool-registry.d.ts.map +1 -1
- package/lib/orchestrator/tool-registry.js +30 -75
- package/lib/orchestrator/tool-registry.js.map +1 -1
- package/lib/orchestrator/tool-selection.d.ts +39 -0
- package/lib/orchestrator/tool-selection.d.ts.map +1 -0
- package/lib/orchestrator/tool-selection.js +319 -0
- package/lib/orchestrator/tool-selection.js.map +1 -0
- package/lib/orchestrator/types.d.ts +2 -0
- package/lib/orchestrator/types.d.ts.map +1 -1
- package/lib/reserved-tools.d.ts +3 -0
- package/lib/reserved-tools.d.ts.map +1 -0
- package/lib/reserved-tools.js +30 -0
- package/lib/reserved-tools.js.map +1 -0
- package/lib/service.d.ts +9 -5
- package/lib/service.d.ts.map +1 -1
- package/lib/service.js +42 -36
- package/lib/service.js.map +1 -1
- package/lib/subagent.d.ts +6 -0
- package/lib/subagent.d.ts.map +1 -1
- package/lib/subagent.js +33 -15
- package/lib/subagent.js.map +1 -1
- package/lib/task-executor.d.ts +1 -0
- package/lib/task-executor.d.ts.map +1 -1
- package/lib/task-executor.js +15 -8
- package/lib/task-executor.js.map +1 -1
- package/lib/zhin-agent/builtin-tools.d.ts +1 -3
- package/lib/zhin-agent/builtin-tools.d.ts.map +1 -1
- package/lib/zhin-agent/builtin-tools.js +4 -41
- package/lib/zhin-agent/builtin-tools.js.map +1 -1
- package/lib/zhin-agent/config.d.ts +7 -0
- package/lib/zhin-agent/config.d.ts.map +1 -1
- package/lib/zhin-agent/config.js +12 -7
- package/lib/zhin-agent/config.js.map +1 -1
- package/lib/zhin-agent/context-budget.d.ts +27 -0
- package/lib/zhin-agent/context-budget.d.ts.map +1 -0
- package/lib/zhin-agent/context-budget.js +50 -0
- package/lib/zhin-agent/context-budget.js.map +1 -0
- package/lib/zhin-agent/index.d.ts +10 -0
- package/lib/zhin-agent/index.d.ts.map +1 -1
- package/lib/zhin-agent/index.js +120 -84
- package/lib/zhin-agent/index.js.map +1 -1
- package/lib/zhin-agent/model-harness.d.ts +29 -0
- package/lib/zhin-agent/model-harness.d.ts.map +1 -0
- package/lib/zhin-agent/model-harness.js +67 -0
- package/lib/zhin-agent/model-harness.js.map +1 -0
- package/lib/zhin-agent/pre-exec.d.ts +7 -0
- package/lib/zhin-agent/pre-exec.d.ts.map +1 -0
- package/lib/zhin-agent/pre-exec.js +25 -0
- package/lib/zhin-agent/pre-exec.js.map +1 -0
- package/lib/zhin-agent/prompt.d.ts +10 -8
- package/lib/zhin-agent/prompt.d.ts.map +1 -1
- package/lib/zhin-agent/prompt.js +37 -30
- package/lib/zhin-agent/prompt.js.map +1 -1
- package/lib/zhin-agent/text-sanitize.d.ts +8 -0
- package/lib/zhin-agent/text-sanitize.d.ts.map +1 -0
- package/lib/zhin-agent/text-sanitize.js +19 -0
- package/lib/zhin-agent/text-sanitize.js.map +1 -0
- package/lib/zhin-agent/tool-runtime.d.ts +31 -0
- package/lib/zhin-agent/tool-runtime.d.ts.map +1 -0
- package/lib/zhin-agent/tool-runtime.js +49 -0
- package/lib/zhin-agent/tool-runtime.js.map +1 -0
- package/package.json +8 -6
- package/lib/tools.d.ts +0 -45
- package/lib/tools.d.ts.map +0 -1
- package/lib/tools.js +0 -205
- package/lib/tools.js.map +0 -1
- package/lib/zhin-agent/tool-collector.d.ts +0 -22
- package/lib/zhin-agent/tool-collector.d.ts.map +0 -1
- package/lib/zhin-agent/tool-collector.js +0 -225
- package/lib/zhin-agent/tool-collector.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/zhin-agent/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAKzD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAI/D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,aAAa,CAGpG;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQ5G;AAED,eAAO,MAAM,WAAW,gBAAgB,CAAC;AACzC,eAAO,MAAM,sBAAsB,wDAAwD,CAAC;AAC5F,eAAO,MAAM,sBAAsB,wCAAwC,CAAC;AAE5E,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/zhin-agent/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;AAKzD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,aAAa,CAI/D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,aAAa,CAGpG;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQ5G;AAED,eAAO,MAAM,WAAW,gBAAgB,CAAC;AACzC,eAAO,MAAM,sBAAsB,wDAAwD,CAAC;AAC5F,eAAO,MAAM,sBAAsB,wCAAwC,CAAC;AAE5E,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAA6B,CAAC;AAE1E,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAGpE,wBAAwB;AACxB,eAAO,MAAM,gBAAgB;;;;CAInB,CAAC;AAEX,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IAC7C,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,GAAG,aAAa,GAAG,QAAQ,CAAC;IAC/D,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,qCAAqC;IACrC,aAAa,CAAC,EAAE,EAAE,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IAClD,sCAAsC;IACtC,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,iDAAiD;IACjD,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,yDAAyD;IACzD,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,eAAO,MAAM,cAAc,EAAE,QAAQ,CAAC,eAAe,CA6BpD,CAAC;AAEF,8CAA8C;AAC9C,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAIpH"}
|
package/lib/zhin-agent/config.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* ZhinAgent 配置、常量、类型定义
|
|
3
3
|
*/
|
|
4
4
|
import { DEFAULT_CONTEXT_TOKENS } from '@zhin.js/ai';
|
|
5
|
+
import { PERMISSION_LEVEL_PRIORITY } from '../orchestrator/tool-selection.js';
|
|
5
6
|
const SMALL_MODEL_RE = /[:\-_](0\.5|1\.?[58]?|[3-8])b\b/i;
|
|
6
7
|
const MEDIUM_MODEL_RE = /[:\-_](14|[12][0-9]|32)b\b/i;
|
|
7
8
|
/**
|
|
@@ -40,13 +41,8 @@ export function resolveSkillInstructionMaxChars(config, modelName) {
|
|
|
40
41
|
export const SECTION_SEP = '\n\n---\n\n';
|
|
41
42
|
export const HISTORY_CONTEXT_MARKER = '[Chat messages since your last reply - for context]';
|
|
42
43
|
export const CURRENT_MESSAGE_MARKER = '[Current message - respond to this]';
|
|
43
|
-
export const PERM_MAP =
|
|
44
|
-
|
|
45
|
-
group_admin: 1,
|
|
46
|
-
group_owner: 2,
|
|
47
|
-
bot_admin: 3,
|
|
48
|
-
owner: 4,
|
|
49
|
-
};
|
|
44
|
+
export const PERM_MAP = PERMISSION_LEVEL_PRIORITY;
|
|
45
|
+
const TRUE_VALUES = new Set(['1', 'true', 'yes', 'on']);
|
|
50
46
|
/** 上下文感知内置工具的关键词触发正则 */
|
|
51
47
|
export const KEYWORD_TRIGGERS = {
|
|
52
48
|
chatHistory: /之前|上次|历史|回忆|聊过|记录|还记得|曾经/i,
|
|
@@ -80,5 +76,14 @@ export const DEFAULT_CONFIG = {
|
|
|
80
76
|
subagentTools: [],
|
|
81
77
|
modelSizeHint: '',
|
|
82
78
|
skillInstructionMaxChars: 0,
|
|
79
|
+
modelHarness: {},
|
|
80
|
+
phaseTrace: false,
|
|
83
81
|
};
|
|
82
|
+
/** `env` 参数主要用于测试注入,运行时默认读取 `process.env`。 */
|
|
83
|
+
export function isPhaseTraceEnabled(config, env = process.env) {
|
|
84
|
+
if (config.phaseTrace)
|
|
85
|
+
return true;
|
|
86
|
+
const raw = env.ZHIN_AGENT_PHASE_TRACE?.trim().toLowerCase();
|
|
87
|
+
return !!raw && TRUE_VALUES.has(raw);
|
|
88
|
+
}
|
|
84
89
|
//# sourceMappingURL=config.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/zhin-agent/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/zhin-agent/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { AIProvider, ChatMessage, PruneResult } from '@zhin.js/ai';
|
|
2
|
+
import type { ModelRegistry } from '@zhin.js/ai';
|
|
3
|
+
import type { ZhinAgentConfig } from './config.js';
|
|
4
|
+
export interface ResolvedContextBudget {
|
|
5
|
+
contextWindow: number;
|
|
6
|
+
maxHistoryShare: number;
|
|
7
|
+
source: 'config' | 'model-registry' | 'provider' | 'default';
|
|
8
|
+
}
|
|
9
|
+
export interface PrunedHistory {
|
|
10
|
+
messages: ChatMessage[];
|
|
11
|
+
result: PruneResult;
|
|
12
|
+
budget: ResolvedContextBudget;
|
|
13
|
+
}
|
|
14
|
+
export declare function resolveContextBudget(params: {
|
|
15
|
+
config: Required<ZhinAgentConfig>;
|
|
16
|
+
provider: AIProvider;
|
|
17
|
+
modelRegistry?: ModelRegistry | null;
|
|
18
|
+
model?: string;
|
|
19
|
+
}): ResolvedContextBudget;
|
|
20
|
+
export declare function pruneHistoryWithBudget(params: {
|
|
21
|
+
messages: ChatMessage[];
|
|
22
|
+
config: Required<ZhinAgentConfig>;
|
|
23
|
+
provider: AIProvider;
|
|
24
|
+
modelRegistry?: ModelRegistry | null;
|
|
25
|
+
model?: string;
|
|
26
|
+
}): PrunedHistory;
|
|
27
|
+
//# sourceMappingURL=context-budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-budget.d.ts","sourceRoot":"","sources":["../../src/zhin-agent/context-budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAKxE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,qBAAqB;IACpC,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,QAAQ,GAAG,gBAAgB,GAAG,UAAU,GAAG,SAAS,CAAC;CAC9D;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,qBAAqB,CAAC;CAC/B;AAWD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE;IAC3C,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IAClC,QAAQ,EAAE,UAAU,CAAC;IACrB,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,qBAAqB,CAgCxB;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,CAAC;IAClC,QAAQ,EAAE,UAAU,CAAC;IACrB,aAAa,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,aAAa,CAYhB"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { DEFAULT_CONTEXT_TOKENS, pruneHistoryForContext, } from '@zhin.js/ai';
|
|
2
|
+
function resolveRegistryWindow(registry, provider, model) {
|
|
3
|
+
if (!registry || !model)
|
|
4
|
+
return undefined;
|
|
5
|
+
return registry.getModel(provider.name, model)?.contextWindow;
|
|
6
|
+
}
|
|
7
|
+
export function resolveContextBudget(params) {
|
|
8
|
+
const configured = params.config.contextTokens;
|
|
9
|
+
if (configured && configured > 0 && configured !== DEFAULT_CONTEXT_TOKENS) {
|
|
10
|
+
return {
|
|
11
|
+
contextWindow: configured,
|
|
12
|
+
maxHistoryShare: params.config.maxHistoryShare ?? 0.5,
|
|
13
|
+
source: 'config',
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const registryWindow = resolveRegistryWindow(params.modelRegistry, params.provider, params.model);
|
|
17
|
+
if (registryWindow && registryWindow > 0) {
|
|
18
|
+
return {
|
|
19
|
+
contextWindow: registryWindow,
|
|
20
|
+
maxHistoryShare: params.config.maxHistoryShare ?? 0.5,
|
|
21
|
+
source: 'model-registry',
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (params.provider.contextWindow && params.provider.contextWindow > 0) {
|
|
25
|
+
return {
|
|
26
|
+
contextWindow: params.provider.contextWindow,
|
|
27
|
+
maxHistoryShare: params.config.maxHistoryShare ?? 0.5,
|
|
28
|
+
source: 'provider',
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
contextWindow: configured || DEFAULT_CONTEXT_TOKENS,
|
|
33
|
+
maxHistoryShare: params.config.maxHistoryShare ?? 0.5,
|
|
34
|
+
source: 'default',
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function pruneHistoryWithBudget(params) {
|
|
38
|
+
const budget = resolveContextBudget(params);
|
|
39
|
+
const result = pruneHistoryForContext({
|
|
40
|
+
messages: params.messages,
|
|
41
|
+
maxContextTokens: budget.contextWindow,
|
|
42
|
+
maxHistoryShare: budget.maxHistoryShare,
|
|
43
|
+
});
|
|
44
|
+
return {
|
|
45
|
+
messages: result.messages,
|
|
46
|
+
result,
|
|
47
|
+
budget,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=context-budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-budget.js","sourceRoot":"","sources":["../../src/zhin-agent/context-budget.ts"],"names":[],"mappings":"AACA,OAAO,EACL,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAgBrB,SAAS,qBAAqB,CAC5B,QAA0C,EAC1C,QAAoB,EACpB,KAAc;IAEd,IAAI,CAAC,QAAQ,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,aAAa,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAKpC;IACC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;IAC/C,IAAI,UAAU,IAAI,UAAU,GAAG,CAAC,IAAI,UAAU,KAAK,sBAAsB,EAAE,CAAC;QAC1E,OAAO;YACL,aAAa,EAAE,UAAU;YACzB,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,eAAe,IAAI,GAAG;YACrD,MAAM,EAAE,QAAQ;SACjB,CAAC;IACJ,CAAC;IAED,MAAM,cAAc,GAAG,qBAAqB,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IAClG,IAAI,cAAc,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACzC,OAAO;YACL,aAAa,EAAE,cAAc;YAC7B,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,eAAe,IAAI,GAAG;YACrD,MAAM,EAAE,gBAAgB;SACzB,CAAC;IACJ,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,IAAI,MAAM,CAAC,QAAQ,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;QACvE,OAAO;YACL,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,aAAa;YAC5C,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,eAAe,IAAI,GAAG;YACrD,MAAM,EAAE,UAAU;SACnB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,aAAa,EAAE,UAAU,IAAI,sBAAsB;QACnD,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,eAAe,IAAI,GAAG;QACrD,MAAM,EAAE,SAAS;KAClB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAMtC;IACC,MAAM,MAAM,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,sBAAsB,CAAC;QACpC,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,gBAAgB,EAAE,MAAM,CAAC,aAAa;QACtC,eAAe,EAAE,MAAM,CAAC,eAAe;KACxC,CAAC,CAAC;IACH,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,MAAM;QACN,MAAM;KACP,CAAC;AACJ,CAAC"}
|
|
@@ -41,6 +41,7 @@ export declare class ZhinAgent {
|
|
|
41
41
|
private activeSkillsContext;
|
|
42
42
|
private skillsSummaryXML;
|
|
43
43
|
private modelRegistry;
|
|
44
|
+
private phaseTraceEnabled;
|
|
44
45
|
constructor(provider: AIProvider, config?: ZhinAgentConfig);
|
|
45
46
|
setSkillRegistry(registry: SkillRegistry): void;
|
|
46
47
|
setSessionManager(manager: SessionManager): void;
|
|
@@ -64,7 +65,16 @@ export declare class ZhinAgent {
|
|
|
64
65
|
setActiveSkillsContext(content: string): void;
|
|
65
66
|
setSkillsSummaryXML(xml: string): void;
|
|
66
67
|
process(content: string, context: ToolContext, externalTools?: Tool[], onChunk?: OnChunkCallback): Promise<OutputElement[]>;
|
|
68
|
+
private buildDisciplinedPrompt;
|
|
69
|
+
private logPhase;
|
|
67
70
|
processMultimodal(parts: ContentPart[], context: ToolContext, onChunk?: OnChunkCallback): Promise<OutputElement[]>;
|
|
71
|
+
/**
|
|
72
|
+
* 为内置工具注入 `extra.web_search_locale`:
|
|
73
|
+
* - 若调用方已在 `context.extra.web_search_locale` 中设置,则规范化后沿用;
|
|
74
|
+
* - 否则读取用户档案 `preferred_language` / `language`;
|
|
75
|
+
* - 均未设置时不在 extra 中写入,web_search 默认使用中文市场。
|
|
76
|
+
*/
|
|
77
|
+
private attachWebSearchLocale;
|
|
68
78
|
private buildHistoryMessages;
|
|
69
79
|
private streamChatWithHistory;
|
|
70
80
|
private saveToSession;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/zhin-agent/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAe,WAAW,EAAE,MAAM,aAAa,CAAC;AACnF,OAAO,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE,OAAO,EAAE,cAAc,EAA8B,MAAM,aAAa,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/zhin-agent/index.ts"],"names":[],"mappings":"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"}
|
package/lib/zhin-agent/index.js
CHANGED
|
@@ -21,40 +21,22 @@ import { SessionManager, createMemorySessionManager } from '@zhin.js/ai';
|
|
|
21
21
|
import { ConversationMemory } from '@zhin.js/ai';
|
|
22
22
|
import { parseOutput } from '@zhin.js/ai';
|
|
23
23
|
import { UserProfileStore } from '../user-profile.js';
|
|
24
|
+
import { WEB_SEARCH_LOCALE_EXTRA_KEY, normalizeWebSearchLocaleHint, } from '../builtin/web-search-locale.js';
|
|
24
25
|
import { RateLimiter } from '@zhin.js/ai';
|
|
25
26
|
import { detectTone } from '@zhin.js/ai';
|
|
26
27
|
import { SubagentManager } from '../subagent.js';
|
|
27
|
-
import { pruneHistoryForContext, DEFAULT_CONTEXT_TOKENS, } from '@zhin.js/ai';
|
|
28
28
|
import { triggerAIHook, createAIHookEvent } from '../hooks.js';
|
|
29
29
|
// ── Sub-modules ─────────────────────────────────────────────────────
|
|
30
|
-
import { DEFAULT_CONFIG,
|
|
30
|
+
import { DEFAULT_CONFIG, isPhaseTraceEnabled, } from './config.js';
|
|
31
31
|
import { applyExecPolicyToTools } from '../security/exec-policy.js';
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
32
|
+
import { buildEnhancedPersona, buildContextHint, buildRichSystemPrompt, buildUserMessageWithHistory, FIXED_DISCIPLINE_RULES, } from './prompt.js';
|
|
33
|
+
import { buildPreExecFastPathPrompt, collectRuntimeTools, planToolRun, } from './tool-runtime.js';
|
|
34
|
+
import { stripHallucinatedToolCalls, stripThinkBlocks } from './text-sanitize.js';
|
|
35
|
+
import { pruneHistoryWithBudget } from './context-budget.js';
|
|
36
|
+
import { resolveModelHarness } from './model-harness.js';
|
|
37
|
+
import { RESERVED_TOOL_NAMES, RESERVED_TOOL_NAME_PREFIXES } from '../reserved-tools.js';
|
|
35
38
|
const logger = new Logger(null, 'ZhinAgent');
|
|
36
39
|
const now = () => performance.now();
|
|
37
|
-
/** Strip `<think>…</think>` blocks that some reasoning models embed in content. */
|
|
38
|
-
function stripThinkBlocks(text) {
|
|
39
|
-
return text.replace(/<think>[\s\S]*?<\/think>\s*/g, '').trim();
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Strip hallucinated tool-call markup that some models emit as plain text
|
|
43
|
-
* (e.g. `<tool_call …/>`, `<function=xxx>…</function>`, `<|plugin|>…`).
|
|
44
|
-
* Only removes the markup; any surrounding real text is preserved.
|
|
45
|
-
*/
|
|
46
|
-
function stripHallucinatedToolCalls(text) {
|
|
47
|
-
let cleaned = text;
|
|
48
|
-
// <tool_call …/> or <tool_call …>…</tool_call>
|
|
49
|
-
cleaned = cleaned.replace(/<tool_call\b[\s\S]*?(?:\/>|<\/tool_call>)/gi, '');
|
|
50
|
-
// <function=name>…</function>
|
|
51
|
-
cleaned = cleaned.replace(/<function=[^>]*>[\s\S]*?<\/function>/gi, '');
|
|
52
|
-
// <|plugin|>…<|/plugin|> (some Chinese models)
|
|
53
|
-
cleaned = cleaned.replace(/<\|plugin\|>[\s\S]*?<\|\/plugin\|>/gi, '');
|
|
54
|
-
// <<<tool_call>>> … <<<end>>> style
|
|
55
|
-
cleaned = cleaned.replace(/<<<tool_call>>>[\s\S]*?<<<end>>>/gi, '');
|
|
56
|
-
return cleaned.trim();
|
|
57
|
-
}
|
|
58
40
|
// ============================================================================
|
|
59
41
|
// ZhinAgent
|
|
60
42
|
// ============================================================================
|
|
@@ -73,9 +55,11 @@ export class ZhinAgent {
|
|
|
73
55
|
activeSkillsContext = '';
|
|
74
56
|
skillsSummaryXML = '';
|
|
75
57
|
modelRegistry = null;
|
|
58
|
+
phaseTraceEnabled;
|
|
76
59
|
constructor(provider, config) {
|
|
77
60
|
this.provider = provider;
|
|
78
61
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
62
|
+
this.phaseTraceEnabled = isPhaseTraceEnabled(this.config);
|
|
79
63
|
this.sessions = createMemorySessionManager();
|
|
80
64
|
this.memory = new ConversationMemory({
|
|
81
65
|
minTopicRounds: this.config.minTopicRounds,
|
|
@@ -101,6 +85,7 @@ export class ZhinAgent {
|
|
|
101
85
|
}
|
|
102
86
|
setModelRegistry(registry) {
|
|
103
87
|
this.modelRegistry = registry;
|
|
88
|
+
this.subagentManager?.setModelRegistry(registry);
|
|
104
89
|
}
|
|
105
90
|
upgradeMemoryToDatabase(msgModel, sumModel) {
|
|
106
91
|
this.memory.upgradeToDatabase(msgModel, sumModel);
|
|
@@ -113,8 +98,10 @@ export class ZhinAgent {
|
|
|
113
98
|
provider: this.provider,
|
|
114
99
|
workspace: process.cwd(),
|
|
115
100
|
createTools,
|
|
101
|
+
subagentTools: this.config.subagentTools,
|
|
116
102
|
maxIterations: this.config.maxSubagentIterations,
|
|
117
103
|
execPolicyConfig: this.config,
|
|
104
|
+
modelRegistry: this.modelRegistry,
|
|
118
105
|
});
|
|
119
106
|
logger.debug('SubagentManager initialized');
|
|
120
107
|
}
|
|
@@ -181,12 +168,19 @@ export class ZhinAgent {
|
|
|
181
168
|
const { senderId, sceneId, platform } = context;
|
|
182
169
|
const sessionId = SessionManager.generateId(platform || '', senderId || '', sceneId);
|
|
183
170
|
const userId = senderId || 'unknown';
|
|
171
|
+
this.logPhase('turn.start', sessionId, {
|
|
172
|
+
mode: 'text',
|
|
173
|
+
provider: this.provider.name,
|
|
174
|
+
});
|
|
184
175
|
// 0. Rate limit
|
|
185
176
|
const rateCheck = this.rateLimiter.check(userId);
|
|
186
177
|
if (!rateCheck.allowed) {
|
|
178
|
+
this.logPhase('turn.rate_limited', sessionId, { userId });
|
|
187
179
|
logger.debug(`[速率限制] 用户 ${userId} 被限制: ${rateCheck.message}`);
|
|
188
180
|
return parseOutput(rateCheck.message || '请稍后再试');
|
|
189
181
|
}
|
|
182
|
+
// 0.5 工具上下文:web_search 语言(档案 preferred_language / language,否则默认中文)
|
|
183
|
+
const contextForTools = await this.attachWebSearchLocale(context, userId);
|
|
190
184
|
triggerAIHook(createAIHookEvent('message', 'received', sessionId, {
|
|
191
185
|
userId,
|
|
192
186
|
content,
|
|
@@ -194,22 +188,21 @@ export class ZhinAgent {
|
|
|
194
188
|
})).catch(() => { });
|
|
195
189
|
// 1. Collect tools
|
|
196
190
|
const tFilter = now();
|
|
197
|
-
const allTools =
|
|
191
|
+
const allTools = collectRuntimeTools({
|
|
192
|
+
content,
|
|
193
|
+
context: contextForTools,
|
|
194
|
+
externalTools,
|
|
198
195
|
config: this.config,
|
|
199
196
|
skillRegistry: this.skillRegistry,
|
|
200
197
|
externalRegistered: this.externalTools,
|
|
198
|
+
sessionId,
|
|
199
|
+
userId,
|
|
200
|
+
memory: this.memory,
|
|
201
|
+
userProfiles: this.userProfiles,
|
|
202
|
+
subagentManager: this.subagentManager,
|
|
201
203
|
});
|
|
202
|
-
// Inject context-aware built-in tools on keyword match
|
|
203
|
-
if (KEYWORD_TRIGGERS.chatHistory.test(content)) {
|
|
204
|
-
allTools.push(createChatHistoryTool(sessionId, this.memory));
|
|
205
|
-
}
|
|
206
|
-
if (KEYWORD_TRIGGERS.userProfile.test(content)) {
|
|
207
|
-
allTools.push(createUserProfileTool(userId, this.userProfiles));
|
|
208
|
-
}
|
|
209
|
-
if (this.subagentManager && KEYWORD_TRIGGERS.spawnTask.test(content)) {
|
|
210
|
-
allTools.push(createSpawnTaskTool(context, this.subagentManager));
|
|
211
|
-
}
|
|
212
204
|
const filterMs = (now() - tFilter).toFixed(0);
|
|
205
|
+
this.logPhase('tools.collected', sessionId, { count: allTools.length });
|
|
213
206
|
logger.info(`[工具过滤] ${allTools.length} 个工具: ${allTools.map(t => t.name).join(', ') || '(无)'}`);
|
|
214
207
|
// 2. History + profile (parallel)
|
|
215
208
|
const tMem = now();
|
|
@@ -217,82 +210,71 @@ export class ZhinAgent {
|
|
|
217
210
|
this.buildHistoryMessages(sessionId),
|
|
218
211
|
this.userProfiles.buildProfileSummary(userId),
|
|
219
212
|
]);
|
|
220
|
-
const
|
|
221
|
-
const
|
|
222
|
-
const pruneResult = pruneHistoryForContext({
|
|
213
|
+
const chatCandidates = this.resolveModelCandidates('chat');
|
|
214
|
+
const { messages: historyMessages, result: pruneResult, budget: contextBudget, } = pruneHistoryWithBudget({
|
|
223
215
|
messages: rawHistoryMessages,
|
|
224
|
-
|
|
225
|
-
|
|
216
|
+
config: this.config,
|
|
217
|
+
provider: this.provider,
|
|
218
|
+
modelRegistry: this.modelRegistry,
|
|
219
|
+
model: chatCandidates[0],
|
|
226
220
|
});
|
|
227
|
-
let historyMessages = pruneResult.messages;
|
|
228
221
|
if (pruneResult.droppedCount > 0) {
|
|
229
222
|
logger.debug(`[上下文窗口] 丢弃 ${pruneResult.droppedCount} 条历史消息 (${pruneResult.droppedTokens} tokens)`);
|
|
230
223
|
}
|
|
231
224
|
const memMs = (now() - tMem).toFixed(0);
|
|
225
|
+
this.logPhase('context.ready', sessionId, { historyCount: historyMessages.length });
|
|
232
226
|
// 2.5 Tone + persona
|
|
233
227
|
const toneHint = this.config.toneAwareness ? detectTone(content).hint : '';
|
|
234
228
|
const personaEnhanced = buildEnhancedPersona(this.config, profileSummary, toneHint);
|
|
235
229
|
// 3. No tools → chat path (prefer per-session model, then lightweight model)
|
|
236
230
|
if (allTools.length === 0) {
|
|
231
|
+
this.logPhase('path.chat', sessionId, { toolCount: 0 });
|
|
237
232
|
const liteModel = this.config.chatLiteModel || undefined;
|
|
238
|
-
|
|
233
|
+
const chatSystemPrompt = this.buildDisciplinedPrompt(personaEnhanced);
|
|
234
|
+
logger.info(`[System Prompt] chat-path: ${chatSystemPrompt.length} chars${liteModel ? `, model=${liteModel}` : ''}`);
|
|
239
235
|
logger.debug(`[闲聊路径] 过滤=${filterMs}ms, 记忆=${memMs}ms (${historyMessages.length}条), 0 工具`);
|
|
240
236
|
const tLLM = now();
|
|
241
|
-
|
|
237
|
+
this.logPhase('chat.llm.start', sessionId, { model: liteModel || chatCandidates[0] || '' });
|
|
238
|
+
let reply = await this.streamChatWithHistory(content, chatSystemPrompt, historyMessages, onChunk, liteModel);
|
|
242
239
|
reply = stripHallucinatedToolCalls(reply);
|
|
243
240
|
const llmMs = (now() - tLLM).toFixed(0);
|
|
241
|
+
this.logPhase('chat.llm.end', sessionId, { durationMs: Number(llmMs) });
|
|
244
242
|
logger.info(`[闲聊路径] 过滤=${filterMs}ms, 记忆=${memMs}ms, LLM=${llmMs}ms, 总=${(now() - t0).toFixed(0)}ms`);
|
|
245
243
|
await this.saveToSession(sessionId, content, reply, sceneId);
|
|
244
|
+
this.logPhase('turn.end', sessionId, { path: 'chat' });
|
|
246
245
|
return parseOutput(reply);
|
|
247
246
|
}
|
|
248
247
|
logger.debug(`[工具路径] 过滤=${filterMs}ms, 记忆=${memMs}ms, ${allTools.length} 工具 (${allTools.map(t => t.name).join(', ')})`);
|
|
249
248
|
// 4. Pre-executable tools
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
249
|
+
const preExecCandidates = allTools.filter(tool => tool.preExecutable);
|
|
250
|
+
const tPre = preExecCandidates.length > 0 ? now() : 0;
|
|
251
|
+
if (preExecCandidates.length > 0) {
|
|
252
|
+
logger.debug(`预执行: ${preExecCandidates.map(t => t.name).join(', ')}`);
|
|
254
253
|
}
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
tool.execute({}),
|
|
263
|
-
new Promise((_, rej) => setTimeout(() => rej(new Error('超时')), this.config.preExecTimeout)),
|
|
264
|
-
]);
|
|
265
|
-
return { name: tool.name, result };
|
|
266
|
-
}));
|
|
267
|
-
for (const r of results) {
|
|
268
|
-
if (r.status === 'fulfilled') {
|
|
269
|
-
let s = typeof r.value.result === 'string' ? r.value.result : JSON.stringify(r.value.result);
|
|
270
|
-
if (s.length > 500) {
|
|
271
|
-
s = s.slice(0, 500) + `\n... (truncated, ${s.length} chars total)`;
|
|
272
|
-
}
|
|
273
|
-
preData += `\n【${r.value.name}】${s}`;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
254
|
+
const toolRun = await planToolRun(allTools, this.config.preExecTimeout);
|
|
255
|
+
this.logPhase('preexec.done', sessionId, {
|
|
256
|
+
mode: toolRun.mode,
|
|
257
|
+
preExecutedTools: toolRun.preExecution.tools.length,
|
|
258
|
+
});
|
|
259
|
+
const preData = toolRun.preExecution.data;
|
|
260
|
+
if (tPre > 0) {
|
|
276
261
|
logger.debug(`预执行耗时: ${(now() - tPre).toFixed(0)}ms`);
|
|
277
262
|
}
|
|
278
263
|
// 6. Path selection
|
|
279
264
|
let reply;
|
|
280
|
-
|
|
281
|
-
|
|
265
|
+
if (toolRun.mode === 'pre-exec-fast-path') {
|
|
266
|
+
this.logPhase('path.pre_exec_fast', sessionId, { toolCount: allTools.length });
|
|
282
267
|
// Fast path
|
|
283
268
|
const tLLM = now();
|
|
284
|
-
const prompt =
|
|
285
|
-
|
|
286
|
-
Pre-fetched data (from user's question):
|
|
287
|
-
${preData}
|
|
288
|
-
|
|
289
|
-
Answer the user's question based on the data above. Be clear and concise; use emoji when appropriate.`;
|
|
269
|
+
const prompt = this.buildDisciplinedPrompt(buildPreExecFastPathPrompt(personaEnhanced, preData));
|
|
290
270
|
logger.info(`[System Prompt] fast-path: ${prompt.length} chars`);
|
|
271
|
+
this.logPhase('fast.llm.start', sessionId, { model: chatCandidates[0] || '' });
|
|
291
272
|
reply = await this.streamChatWithHistory(content, prompt, historyMessages, onChunk);
|
|
273
|
+
this.logPhase('fast.llm.end', sessionId, { durationMs: Math.round(now() - tLLM) });
|
|
292
274
|
logger.info(`[快速路径] 过滤=${filterMs}ms, 记忆=${memMs}ms, LLM=${(now() - tLLM).toFixed(0)}ms, 总=${(now() - t0).toFixed(0)}ms`);
|
|
293
275
|
}
|
|
294
276
|
else {
|
|
295
|
-
|
|
277
|
+
this.logPhase('path.agent', sessionId, { toolCount: allTools.length });
|
|
296
278
|
const tAgent = now();
|
|
297
279
|
logger.debug(`Agent 路径: ${allTools.length} 个工具`);
|
|
298
280
|
const contextHint = buildContextHint(context, content);
|
|
@@ -312,10 +294,16 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
312
294
|
// Adaptive maxIterations: boost when skills are active (multi-step skill flows)
|
|
313
295
|
const SKILL_ITERATION_BOOST = 3;
|
|
314
296
|
const hasSkillActivation = agentTools.some(t => t.name === 'activate_skill' || t.name === 'install_skill');
|
|
297
|
+
const harness = resolveModelHarness(this.provider.name, chatCandidates[0] || '', this.config.modelHarness);
|
|
298
|
+
const baseIterations = harness.maxIterations ?? this.config.maxIterations;
|
|
315
299
|
const effectiveMaxIterations = hasSkillActivation
|
|
316
|
-
?
|
|
317
|
-
:
|
|
318
|
-
|
|
300
|
+
? baseIterations + SKILL_ITERATION_BOOST
|
|
301
|
+
: baseIterations;
|
|
302
|
+
this.logPhase('harness.resolved', sessionId, {
|
|
303
|
+
model: chatCandidates[0] || '',
|
|
304
|
+
harnessMaxIterations: harness.maxIterations ?? null,
|
|
305
|
+
effectiveMaxIterations,
|
|
306
|
+
});
|
|
319
307
|
const agent = createAgent(this.provider, {
|
|
320
308
|
model: chatCandidates[0],
|
|
321
309
|
modelFallbacks: chatCandidates.slice(1),
|
|
@@ -323,11 +311,16 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
323
311
|
tools: agentTools,
|
|
324
312
|
maxIterations: effectiveMaxIterations,
|
|
325
313
|
turnTimeout: this.config.timeout,
|
|
314
|
+
contextWindow: contextBudget.contextWindow,
|
|
315
|
+
reservedToolNames: RESERVED_TOOL_NAMES,
|
|
316
|
+
reservedToolNamePrefixes: RESERVED_TOOL_NAME_PREFIXES,
|
|
326
317
|
});
|
|
327
318
|
const userMessageWithHistory = buildUserMessageWithHistory(historyMessages, content);
|
|
328
319
|
let result;
|
|
329
320
|
try {
|
|
321
|
+
this.logPhase('agent.run.start', sessionId, { model: chatCandidates[0] || '' });
|
|
330
322
|
result = await agent.run(userMessageWithHistory, []);
|
|
323
|
+
this.logPhase('agent.run.end', sessionId, { iterations: result.iterations });
|
|
331
324
|
}
|
|
332
325
|
finally {
|
|
333
326
|
agent.dispose();
|
|
@@ -341,8 +334,18 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
341
334
|
content: reply,
|
|
342
335
|
platform: platform || '',
|
|
343
336
|
})).catch(() => { });
|
|
337
|
+
this.logPhase('turn.end', sessionId, { path: toolRun.mode === 'pre-exec-fast-path' ? 'fast' : 'agent' });
|
|
344
338
|
return parseOutput(reply);
|
|
345
339
|
}
|
|
340
|
+
buildDisciplinedPrompt(basePrompt) {
|
|
341
|
+
const discipline = `# Discipline\n${FIXED_DISCIPLINE_RULES.map(rule => `- ${rule}`).join('\n')}`;
|
|
342
|
+
return `${discipline}\n\n${basePrompt}`;
|
|
343
|
+
}
|
|
344
|
+
logPhase(phase, sessionId, extra = {}) {
|
|
345
|
+
if (!this.phaseTraceEnabled)
|
|
346
|
+
return;
|
|
347
|
+
logger.info({ phase, sessionId, ...extra }, '[AGENT_PHASE]');
|
|
348
|
+
}
|
|
346
349
|
async processMultimodal(parts, context, onChunk) {
|
|
347
350
|
const { senderId, sceneId, platform } = context;
|
|
348
351
|
const sessionId = SessionManager.generateId(platform || '', senderId || '', sceneId);
|
|
@@ -351,9 +354,9 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
351
354
|
if (!rateCheck.allowed) {
|
|
352
355
|
return parseOutput(rateCheck.message || '请稍后再试');
|
|
353
356
|
}
|
|
354
|
-
const
|
|
357
|
+
const rawHistoryMessages = await this.buildHistoryMessages(sessionId);
|
|
355
358
|
const profileSummary = await this.userProfiles.buildProfileSummary(userId);
|
|
356
|
-
const personaEnhanced = buildEnhancedPersona(this.config, profileSummary, '');
|
|
359
|
+
const personaEnhanced = this.buildDisciplinedPrompt(buildEnhancedPersona(this.config, profileSummary, ''));
|
|
357
360
|
// Build text summary describing the multimodal content
|
|
358
361
|
const textFragments = [];
|
|
359
362
|
const llmParts = [];
|
|
@@ -384,6 +387,16 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
384
387
|
}
|
|
385
388
|
const textContent = textFragments.join(' ') || '[多模态消息]';
|
|
386
389
|
const visionCandidates = this.resolveModelCandidates('vision');
|
|
390
|
+
const { messages: historyMessages, result: pruneResult } = pruneHistoryWithBudget({
|
|
391
|
+
messages: rawHistoryMessages,
|
|
392
|
+
config: this.config,
|
|
393
|
+
provider: this.provider,
|
|
394
|
+
modelRegistry: this.modelRegistry,
|
|
395
|
+
model: visionCandidates[0],
|
|
396
|
+
});
|
|
397
|
+
if (pruneResult.droppedCount > 0) {
|
|
398
|
+
logger.debug(`[多模态上下文窗口] 丢弃 ${pruneResult.droppedCount} 条历史消息 (${pruneResult.droppedTokens} tokens)`);
|
|
399
|
+
}
|
|
387
400
|
const messages = [
|
|
388
401
|
{ role: 'system', content: personaEnhanced },
|
|
389
402
|
...historyMessages,
|
|
@@ -437,6 +450,29 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
437
450
|
return parseOutput(reply);
|
|
438
451
|
}
|
|
439
452
|
// ── Internal helpers ────────────────────────────────────────────────
|
|
453
|
+
/**
|
|
454
|
+
* 为内置工具注入 `extra.web_search_locale`:
|
|
455
|
+
* - 若调用方已在 `context.extra.web_search_locale` 中设置,则规范化后沿用;
|
|
456
|
+
* - 否则读取用户档案 `preferred_language` / `language`;
|
|
457
|
+
* - 均未设置时不在 extra 中写入,web_search 默认使用中文市场。
|
|
458
|
+
*/
|
|
459
|
+
async attachWebSearchLocale(context, userId) {
|
|
460
|
+
const extra = { ...(context.extra ?? {}) };
|
|
461
|
+
const existing = extra[WEB_SEARCH_LOCALE_EXTRA_KEY];
|
|
462
|
+
if (typeof existing === 'string' && existing.trim()) {
|
|
463
|
+
extra[WEB_SEARCH_LOCALE_EXTRA_KEY] = normalizeWebSearchLocaleHint(existing);
|
|
464
|
+
return { ...context, extra };
|
|
465
|
+
}
|
|
466
|
+
const [preferred, language] = await Promise.all([
|
|
467
|
+
this.userProfiles.get(userId, 'preferred_language'),
|
|
468
|
+
this.userProfiles.get(userId, 'language'),
|
|
469
|
+
]);
|
|
470
|
+
const hint = (preferred ?? language)?.trim();
|
|
471
|
+
if (hint) {
|
|
472
|
+
extra[WEB_SEARCH_LOCALE_EXTRA_KEY] = normalizeWebSearchLocaleHint(hint);
|
|
473
|
+
}
|
|
474
|
+
return { ...context, extra };
|
|
475
|
+
}
|
|
440
476
|
async buildHistoryMessages(sessionId) {
|
|
441
477
|
return this.memory.buildContext(sessionId);
|
|
442
478
|
}
|