@zhin.js/agent 0.1.15 → 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 -88
- 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,44 +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
|
-
// <tool_result …/> or <tool_result …>…</tool_result>
|
|
51
|
-
cleaned = cleaned.replace(/<tool_result\b[\s\S]*?(?:\/>|<\/tool_result>)/gi, '');
|
|
52
|
-
// <function=name>…</function>
|
|
53
|
-
cleaned = cleaned.replace(/<function=[^>]*>[\s\S]*?<\/function>/gi, '');
|
|
54
|
-
// {tool_result} / {tool_call} bare placeholders
|
|
55
|
-
cleaned = cleaned.replace(/\{tool_(?:result|call)\}/gi, '');
|
|
56
|
-
// <|plugin|>…<|/plugin|> (some Chinese models)
|
|
57
|
-
cleaned = cleaned.replace(/<\|plugin\|>[\s\S]*?<\|\/plugin\|>/gi, '');
|
|
58
|
-
// <<<tool_call>>> … <<<end>>> style
|
|
59
|
-
cleaned = cleaned.replace(/<<<tool_call>>>[\s\S]*?<<<end>>>/gi, '');
|
|
60
|
-
return cleaned.trim();
|
|
61
|
-
}
|
|
62
40
|
// ============================================================================
|
|
63
41
|
// ZhinAgent
|
|
64
42
|
// ============================================================================
|
|
@@ -77,9 +55,11 @@ export class ZhinAgent {
|
|
|
77
55
|
activeSkillsContext = '';
|
|
78
56
|
skillsSummaryXML = '';
|
|
79
57
|
modelRegistry = null;
|
|
58
|
+
phaseTraceEnabled;
|
|
80
59
|
constructor(provider, config) {
|
|
81
60
|
this.provider = provider;
|
|
82
61
|
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
62
|
+
this.phaseTraceEnabled = isPhaseTraceEnabled(this.config);
|
|
83
63
|
this.sessions = createMemorySessionManager();
|
|
84
64
|
this.memory = new ConversationMemory({
|
|
85
65
|
minTopicRounds: this.config.minTopicRounds,
|
|
@@ -105,6 +85,7 @@ export class ZhinAgent {
|
|
|
105
85
|
}
|
|
106
86
|
setModelRegistry(registry) {
|
|
107
87
|
this.modelRegistry = registry;
|
|
88
|
+
this.subagentManager?.setModelRegistry(registry);
|
|
108
89
|
}
|
|
109
90
|
upgradeMemoryToDatabase(msgModel, sumModel) {
|
|
110
91
|
this.memory.upgradeToDatabase(msgModel, sumModel);
|
|
@@ -117,8 +98,10 @@ export class ZhinAgent {
|
|
|
117
98
|
provider: this.provider,
|
|
118
99
|
workspace: process.cwd(),
|
|
119
100
|
createTools,
|
|
101
|
+
subagentTools: this.config.subagentTools,
|
|
120
102
|
maxIterations: this.config.maxSubagentIterations,
|
|
121
103
|
execPolicyConfig: this.config,
|
|
104
|
+
modelRegistry: this.modelRegistry,
|
|
122
105
|
});
|
|
123
106
|
logger.debug('SubagentManager initialized');
|
|
124
107
|
}
|
|
@@ -185,12 +168,19 @@ export class ZhinAgent {
|
|
|
185
168
|
const { senderId, sceneId, platform } = context;
|
|
186
169
|
const sessionId = SessionManager.generateId(platform || '', senderId || '', sceneId);
|
|
187
170
|
const userId = senderId || 'unknown';
|
|
171
|
+
this.logPhase('turn.start', sessionId, {
|
|
172
|
+
mode: 'text',
|
|
173
|
+
provider: this.provider.name,
|
|
174
|
+
});
|
|
188
175
|
// 0. Rate limit
|
|
189
176
|
const rateCheck = this.rateLimiter.check(userId);
|
|
190
177
|
if (!rateCheck.allowed) {
|
|
178
|
+
this.logPhase('turn.rate_limited', sessionId, { userId });
|
|
191
179
|
logger.debug(`[速率限制] 用户 ${userId} 被限制: ${rateCheck.message}`);
|
|
192
180
|
return parseOutput(rateCheck.message || '请稍后再试');
|
|
193
181
|
}
|
|
182
|
+
// 0.5 工具上下文:web_search 语言(档案 preferred_language / language,否则默认中文)
|
|
183
|
+
const contextForTools = await this.attachWebSearchLocale(context, userId);
|
|
194
184
|
triggerAIHook(createAIHookEvent('message', 'received', sessionId, {
|
|
195
185
|
userId,
|
|
196
186
|
content,
|
|
@@ -198,22 +188,21 @@ export class ZhinAgent {
|
|
|
198
188
|
})).catch(() => { });
|
|
199
189
|
// 1. Collect tools
|
|
200
190
|
const tFilter = now();
|
|
201
|
-
const allTools =
|
|
191
|
+
const allTools = collectRuntimeTools({
|
|
192
|
+
content,
|
|
193
|
+
context: contextForTools,
|
|
194
|
+
externalTools,
|
|
202
195
|
config: this.config,
|
|
203
196
|
skillRegistry: this.skillRegistry,
|
|
204
197
|
externalRegistered: this.externalTools,
|
|
198
|
+
sessionId,
|
|
199
|
+
userId,
|
|
200
|
+
memory: this.memory,
|
|
201
|
+
userProfiles: this.userProfiles,
|
|
202
|
+
subagentManager: this.subagentManager,
|
|
205
203
|
});
|
|
206
|
-
// Inject context-aware built-in tools on keyword match
|
|
207
|
-
if (KEYWORD_TRIGGERS.chatHistory.test(content)) {
|
|
208
|
-
allTools.push(createChatHistoryTool(sessionId, this.memory));
|
|
209
|
-
}
|
|
210
|
-
if (KEYWORD_TRIGGERS.userProfile.test(content)) {
|
|
211
|
-
allTools.push(createUserProfileTool(userId, this.userProfiles));
|
|
212
|
-
}
|
|
213
|
-
if (this.subagentManager && KEYWORD_TRIGGERS.spawnTask.test(content)) {
|
|
214
|
-
allTools.push(createSpawnTaskTool(context, this.subagentManager));
|
|
215
|
-
}
|
|
216
204
|
const filterMs = (now() - tFilter).toFixed(0);
|
|
205
|
+
this.logPhase('tools.collected', sessionId, { count: allTools.length });
|
|
217
206
|
logger.info(`[工具过滤] ${allTools.length} 个工具: ${allTools.map(t => t.name).join(', ') || '(无)'}`);
|
|
218
207
|
// 2. History + profile (parallel)
|
|
219
208
|
const tMem = now();
|
|
@@ -221,82 +210,71 @@ export class ZhinAgent {
|
|
|
221
210
|
this.buildHistoryMessages(sessionId),
|
|
222
211
|
this.userProfiles.buildProfileSummary(userId),
|
|
223
212
|
]);
|
|
224
|
-
const
|
|
225
|
-
const
|
|
226
|
-
const pruneResult = pruneHistoryForContext({
|
|
213
|
+
const chatCandidates = this.resolveModelCandidates('chat');
|
|
214
|
+
const { messages: historyMessages, result: pruneResult, budget: contextBudget, } = pruneHistoryWithBudget({
|
|
227
215
|
messages: rawHistoryMessages,
|
|
228
|
-
|
|
229
|
-
|
|
216
|
+
config: this.config,
|
|
217
|
+
provider: this.provider,
|
|
218
|
+
modelRegistry: this.modelRegistry,
|
|
219
|
+
model: chatCandidates[0],
|
|
230
220
|
});
|
|
231
|
-
let historyMessages = pruneResult.messages;
|
|
232
221
|
if (pruneResult.droppedCount > 0) {
|
|
233
222
|
logger.debug(`[上下文窗口] 丢弃 ${pruneResult.droppedCount} 条历史消息 (${pruneResult.droppedTokens} tokens)`);
|
|
234
223
|
}
|
|
235
224
|
const memMs = (now() - tMem).toFixed(0);
|
|
225
|
+
this.logPhase('context.ready', sessionId, { historyCount: historyMessages.length });
|
|
236
226
|
// 2.5 Tone + persona
|
|
237
227
|
const toneHint = this.config.toneAwareness ? detectTone(content).hint : '';
|
|
238
228
|
const personaEnhanced = buildEnhancedPersona(this.config, profileSummary, toneHint);
|
|
239
229
|
// 3. No tools → chat path (prefer per-session model, then lightweight model)
|
|
240
230
|
if (allTools.length === 0) {
|
|
231
|
+
this.logPhase('path.chat', sessionId, { toolCount: 0 });
|
|
241
232
|
const liteModel = this.config.chatLiteModel || undefined;
|
|
242
|
-
|
|
233
|
+
const chatSystemPrompt = this.buildDisciplinedPrompt(personaEnhanced);
|
|
234
|
+
logger.info(`[System Prompt] chat-path: ${chatSystemPrompt.length} chars${liteModel ? `, model=${liteModel}` : ''}`);
|
|
243
235
|
logger.debug(`[闲聊路径] 过滤=${filterMs}ms, 记忆=${memMs}ms (${historyMessages.length}条), 0 工具`);
|
|
244
236
|
const tLLM = now();
|
|
245
|
-
|
|
237
|
+
this.logPhase('chat.llm.start', sessionId, { model: liteModel || chatCandidates[0] || '' });
|
|
238
|
+
let reply = await this.streamChatWithHistory(content, chatSystemPrompt, historyMessages, onChunk, liteModel);
|
|
246
239
|
reply = stripHallucinatedToolCalls(reply);
|
|
247
240
|
const llmMs = (now() - tLLM).toFixed(0);
|
|
241
|
+
this.logPhase('chat.llm.end', sessionId, { durationMs: Number(llmMs) });
|
|
248
242
|
logger.info(`[闲聊路径] 过滤=${filterMs}ms, 记忆=${memMs}ms, LLM=${llmMs}ms, 总=${(now() - t0).toFixed(0)}ms`);
|
|
249
243
|
await this.saveToSession(sessionId, content, reply, sceneId);
|
|
244
|
+
this.logPhase('turn.end', sessionId, { path: 'chat' });
|
|
250
245
|
return parseOutput(reply);
|
|
251
246
|
}
|
|
252
247
|
logger.debug(`[工具路径] 过滤=${filterMs}ms, 记忆=${memMs}ms, ${allTools.length} 工具 (${allTools.map(t => t.name).join(', ')})`);
|
|
253
248
|
// 4. Pre-executable tools
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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(', ')}`);
|
|
258
253
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
tool.execute({}),
|
|
267
|
-
new Promise((_, rej) => setTimeout(() => rej(new Error('超时')), this.config.preExecTimeout)),
|
|
268
|
-
]);
|
|
269
|
-
return { name: tool.name, result };
|
|
270
|
-
}));
|
|
271
|
-
for (const r of results) {
|
|
272
|
-
if (r.status === 'fulfilled') {
|
|
273
|
-
let s = typeof r.value.result === 'string' ? r.value.result : JSON.stringify(r.value.result);
|
|
274
|
-
if (s.length > 500) {
|
|
275
|
-
s = s.slice(0, 500) + `\n... (truncated, ${s.length} chars total)`;
|
|
276
|
-
}
|
|
277
|
-
preData += `\n【${r.value.name}】${s}`;
|
|
278
|
-
}
|
|
279
|
-
}
|
|
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) {
|
|
280
261
|
logger.debug(`预执行耗时: ${(now() - tPre).toFixed(0)}ms`);
|
|
281
262
|
}
|
|
282
263
|
// 6. Path selection
|
|
283
264
|
let reply;
|
|
284
|
-
|
|
285
|
-
|
|
265
|
+
if (toolRun.mode === 'pre-exec-fast-path') {
|
|
266
|
+
this.logPhase('path.pre_exec_fast', sessionId, { toolCount: allTools.length });
|
|
286
267
|
// Fast path
|
|
287
268
|
const tLLM = now();
|
|
288
|
-
const prompt =
|
|
289
|
-
|
|
290
|
-
Pre-fetched data (from user's question):
|
|
291
|
-
${preData}
|
|
292
|
-
|
|
293
|
-
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));
|
|
294
270
|
logger.info(`[System Prompt] fast-path: ${prompt.length} chars`);
|
|
271
|
+
this.logPhase('fast.llm.start', sessionId, { model: chatCandidates[0] || '' });
|
|
295
272
|
reply = await this.streamChatWithHistory(content, prompt, historyMessages, onChunk);
|
|
273
|
+
this.logPhase('fast.llm.end', sessionId, { durationMs: Math.round(now() - tLLM) });
|
|
296
274
|
logger.info(`[快速路径] 过滤=${filterMs}ms, 记忆=${memMs}ms, LLM=${(now() - tLLM).toFixed(0)}ms, 总=${(now() - t0).toFixed(0)}ms`);
|
|
297
275
|
}
|
|
298
276
|
else {
|
|
299
|
-
|
|
277
|
+
this.logPhase('path.agent', sessionId, { toolCount: allTools.length });
|
|
300
278
|
const tAgent = now();
|
|
301
279
|
logger.debug(`Agent 路径: ${allTools.length} 个工具`);
|
|
302
280
|
const contextHint = buildContextHint(context, content);
|
|
@@ -316,10 +294,16 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
316
294
|
// Adaptive maxIterations: boost when skills are active (multi-step skill flows)
|
|
317
295
|
const SKILL_ITERATION_BOOST = 3;
|
|
318
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;
|
|
319
299
|
const effectiveMaxIterations = hasSkillActivation
|
|
320
|
-
?
|
|
321
|
-
:
|
|
322
|
-
|
|
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
|
+
});
|
|
323
307
|
const agent = createAgent(this.provider, {
|
|
324
308
|
model: chatCandidates[0],
|
|
325
309
|
modelFallbacks: chatCandidates.slice(1),
|
|
@@ -327,11 +311,16 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
327
311
|
tools: agentTools,
|
|
328
312
|
maxIterations: effectiveMaxIterations,
|
|
329
313
|
turnTimeout: this.config.timeout,
|
|
314
|
+
contextWindow: contextBudget.contextWindow,
|
|
315
|
+
reservedToolNames: RESERVED_TOOL_NAMES,
|
|
316
|
+
reservedToolNamePrefixes: RESERVED_TOOL_NAME_PREFIXES,
|
|
330
317
|
});
|
|
331
318
|
const userMessageWithHistory = buildUserMessageWithHistory(historyMessages, content);
|
|
332
319
|
let result;
|
|
333
320
|
try {
|
|
321
|
+
this.logPhase('agent.run.start', sessionId, { model: chatCandidates[0] || '' });
|
|
334
322
|
result = await agent.run(userMessageWithHistory, []);
|
|
323
|
+
this.logPhase('agent.run.end', sessionId, { iterations: result.iterations });
|
|
335
324
|
}
|
|
336
325
|
finally {
|
|
337
326
|
agent.dispose();
|
|
@@ -345,8 +334,18 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
345
334
|
content: reply,
|
|
346
335
|
platform: platform || '',
|
|
347
336
|
})).catch(() => { });
|
|
337
|
+
this.logPhase('turn.end', sessionId, { path: toolRun.mode === 'pre-exec-fast-path' ? 'fast' : 'agent' });
|
|
348
338
|
return parseOutput(reply);
|
|
349
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
|
+
}
|
|
350
349
|
async processMultimodal(parts, context, onChunk) {
|
|
351
350
|
const { senderId, sceneId, platform } = context;
|
|
352
351
|
const sessionId = SessionManager.generateId(platform || '', senderId || '', sceneId);
|
|
@@ -355,9 +354,9 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
355
354
|
if (!rateCheck.allowed) {
|
|
356
355
|
return parseOutput(rateCheck.message || '请稍后再试');
|
|
357
356
|
}
|
|
358
|
-
const
|
|
357
|
+
const rawHistoryMessages = await this.buildHistoryMessages(sessionId);
|
|
359
358
|
const profileSummary = await this.userProfiles.buildProfileSummary(userId);
|
|
360
|
-
const personaEnhanced = buildEnhancedPersona(this.config, profileSummary, '');
|
|
359
|
+
const personaEnhanced = this.buildDisciplinedPrompt(buildEnhancedPersona(this.config, profileSummary, ''));
|
|
361
360
|
// Build text summary describing the multimodal content
|
|
362
361
|
const textFragments = [];
|
|
363
362
|
const llmParts = [];
|
|
@@ -388,6 +387,16 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
388
387
|
}
|
|
389
388
|
const textContent = textFragments.join(' ') || '[多模态消息]';
|
|
390
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
|
+
}
|
|
391
400
|
const messages = [
|
|
392
401
|
{ role: 'system', content: personaEnhanced },
|
|
393
402
|
...historyMessages,
|
|
@@ -441,6 +450,29 @@ ${preData ? `\nPre-fetched data:\n${preData}\n` : ''}`;
|
|
|
441
450
|
return parseOutput(reply);
|
|
442
451
|
}
|
|
443
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
|
+
}
|
|
444
476
|
async buildHistoryMessages(sessionId) {
|
|
445
477
|
return this.memory.buildContext(sessionId);
|
|
446
478
|
}
|