@gt-fe/eap-runtime 0.0.12 → 0.0.14
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 +3 -1
- package/dist/api/handlers/invoke.handler.d.ts +1 -1
- package/dist/api/handlers/invoke.handler.js +3 -0
- package/dist/api/handlers/stream.handler.d.ts +1 -1
- package/dist/api/handlers/stream.handler.js +4 -1
- package/dist/api/routes/agent.routes.d.ts +2 -2
- package/dist/common/index.d.ts +1 -0
- package/dist/common/index.js +1 -0
- package/dist/common/logger.d.ts +16 -4
- package/dist/common/logger.js +82 -16
- package/dist/common/runtime-package-version.d.ts +2 -0
- package/dist/common/runtime-package-version.js +5 -0
- package/dist/common/types.d.ts +5 -5
- package/dist/common/types.js +2 -2
- package/dist/contracts/permission-checker.d.ts +1 -1
- package/dist/debug/llm-turn-log.d.ts +12 -0
- package/dist/debug/llm-turn-log.js +1 -0
- package/dist/governance/governance-client.d.ts +1 -1
- package/dist/governance/index.d.ts +1 -1
- package/dist/governance/permission-guard.d.ts +1 -1
- package/dist/graph/adapters/langgraph.adapter.d.ts +3 -1
- package/dist/graph/adapters/langgraph.adapter.js +67 -14
- package/dist/graph/adapters/subgraph-compiler.js +5 -2
- package/dist/graph/contracts/executable-graph.d.ts +19 -8
- package/dist/graph/contracts/executable-graph.js +1 -1
- package/dist/graph/nodes/llm-node.d.ts +3 -0
- package/dist/graph/nodes/llm-node.js +8 -0
- package/dist/graph/nodes/skill-bind-node.d.ts +3 -4
- package/dist/graph/nodes/skill-bind-node.js +1 -20
- package/dist/graph/nodes/tool-node.d.ts +2 -0
- package/dist/graph/nodes/tool-node.js +20 -14
- package/dist/index.d.ts +1 -1
- package/dist/memory/compression/index.d.ts +1 -1
- package/dist/memory/compression/index.js +1 -1
- package/dist/memory/compression/sliding-window.compression.js +7 -7
- package/dist/memory/index.d.ts +1 -1
- package/dist/memory/index.js +1 -1
- package/dist/memory/message-compression.service.d.ts +12 -1
- package/dist/memory/message-compression.service.js +29 -1
- package/dist/providers/http-llm-provider.d.ts +1 -0
- package/dist/providers/http-llm-provider.js +4 -1
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +1 -1
- package/dist/providers/local-llm-provider.d.ts +4 -1
- package/dist/providers/local-llm-provider.js +15 -3
- package/dist/providers/routing-llm-provider.js +13 -4
- package/dist/registry/agent-models.d.ts +1 -1
- package/dist/registry/agent-models.js +1 -1
- package/dist/registry/agent-registry-client.d.ts +1 -1
- package/dist/registry/deployment-snapshot.js +19 -17
- package/dist/registry/graph-loader.d.ts +11 -1
- package/dist/registry/graph-loader.js +115 -56
- package/dist/registry/preload-errors.d.ts +1 -1
- package/dist/registry/preload-errors.js +1 -1
- package/dist/registry/skill-io-guard.js +1 -1
- package/dist/registry/skill-tree.js +1 -1
- package/dist/runtime/agent-runtime.d.ts +3 -3
- package/dist/runtime/agent-runtime.js +14 -4
- package/dist/runtime/dev-runtime.d.ts +2 -0
- package/dist/runtime/dev-runtime.js +2 -0
- package/dist/runtime/types.d.ts +4 -4
- package/dist/server.js +1 -1
- package/dist/session/compression-middleware.d.ts +2 -1
- package/dist/session/compression-middleware.js +7 -4
- package/dist/sse/events/skill-events.d.ts +1 -1
- package/dist/sse/events/skill-events.js +1 -1
- package/dist/sse/events/stats-events.d.ts +9 -0
- package/dist/token/compression-budget-integration.d.ts +1 -1
- package/dist/token/compression-budget-integration.js +18 -10
- package/dist/token/context-window.d.ts +42 -0
- package/dist/token/context-window.js +73 -0
- package/dist/token/index.d.ts +1 -0
- package/dist/token/index.js +1 -0
- package/dist/tool/create-tool-executor.d.ts +1 -1
- package/dist/tool/dev-http-executor.d.ts +2 -1
- package/dist/tool/dev-http-executor.js +14 -2
- package/dist/tool/dev-mcp-executor.d.ts +11 -1
- package/dist/tool/dev-mcp-executor.js +27 -1
- package/dist/tool/dev-tool-executor.d.ts +2 -1
- package/dist/tool/dev-tool-executor.js +6 -0
- package/dist/tool/harness-command.js +1 -1
- package/dist/tool/harness-primitives.d.ts +7 -0
- package/dist/tool/harness-primitives.js +57 -6
- package/dist/tool/http-tool-executor.js +1 -1
- package/dist/tool/index.d.ts +2 -1
- package/dist/tool/index.js +1 -0
- package/dist/tool/local-mcp-client.d.ts +5 -2
- package/dist/tool/local-mcp-client.js +130 -3
- package/dist/tool/local-tool-executor.d.ts +3 -2
- package/dist/tool/local-tool-executor.js +16 -1
- package/dist/tool/mcp-list.d.ts +53 -0
- package/dist/tool/mcp-list.js +199 -0
- package/dist/tool/mcp-tool-executor.d.ts +6 -1
- package/dist/tool/mcp-tool-executor.js +53 -1
- package/dist/tool/skill-dir-infer.d.ts +17 -0
- package/dist/tool/skill-dir-infer.js +81 -0
- package/dist/tool/skill-script-refs.d.ts +1 -8
- package/dist/tool/skill-script-refs.js +32 -20
- package/dist/tool/system-prompt-builder.d.ts +35 -16
- package/dist/tool/system-prompt-builder.js +30 -58
- package/dist/tool/timeout.d.ts +2 -2
- package/dist/tool/timeout.js +6 -3
- package/dist/tool/tool-execution-router.d.ts +3 -2
- package/dist/tool/tool-execution-router.js +8 -1
- package/dist/tool/tool-executor.interface.d.ts +11 -0
- package/dist/tool/tool-orchestrator.d.ts +1 -1
- package/dist/tool/tool-orchestrator.js +1 -1
- package/dist/utils/format-error.d.ts +2 -2
- package/dist/utils/format-error.js +2 -2
- package/dist/utils/http-error.d.ts +2 -2
- package/dist/utils/http-error.js +2 -2
- package/package.json +6 -33
|
@@ -18,17 +18,35 @@ import { ToolResultInjector } from '../../tool/tool-result-injector.js';
|
|
|
18
18
|
import { fileArtifactFromToolOutput } from '../../tool/file-artifact.js';
|
|
19
19
|
import { EchoLLMProvider } from '../../providers/echo-llm-provider.js';
|
|
20
20
|
import { ConditionEvaluator } from '../condition-evaluator.js';
|
|
21
|
-
import { SystemPromptBuilder, buildToolCatalog, loadedToolsToApiTools } from '../../tool/system-prompt-builder.js';
|
|
21
|
+
import { SystemPromptBuilder, buildToolCatalog, loadedToolsToApiTools, resolveLlmPromptInputs } from '../../tool/system-prompt-builder.js';
|
|
22
22
|
import { resolveJailFromState, resolveJailRoots } from '../../tool/harness-primitives.js';
|
|
23
23
|
import os from 'node:os';
|
|
24
24
|
import { bindSelectedSkill } from '../nodes/skill-bind-node.js';
|
|
25
25
|
import { resolveGraphPrompt } from '../resolve-graph-prompt.js';
|
|
26
|
+
import { hydrateMcpTools, MCP_LIST_TOOL_NAME } from '../../tool/mcp-list.js';
|
|
26
27
|
import { SkillAuditRecorder } from '../skill-audit-recorder.js';
|
|
27
28
|
import { preloadSkillNotFound } from '../../registry/preload-errors.js';
|
|
28
|
-
import { AppError, ErrorCodes } from '@
|
|
29
|
+
import { AppError, ErrorCodes } from '@eap/contracts';
|
|
30
|
+
import { pickContextFields } from '../../token/context-window.js';
|
|
29
31
|
import { isHitlDecision, lastAssistantHasUnansweredToolCalls } from '../hitl/hitl-handler.js';
|
|
30
32
|
import { classifySkillRead } from './skill-read.js';
|
|
31
33
|
import { withGraphSpan } from '../trace-span.js';
|
|
34
|
+
/** 图未写 `config.maxIterations` 时的 recursionLimit。`agent ⇄ tools` 一圈约 2,50 ≈ 24 次工具往返。 */
|
|
35
|
+
export const DEFAULT_GRAPH_RECURSION_LIMIT = 50;
|
|
36
|
+
/**
|
|
37
|
+
* LangGraph `recursionLimit` 计 superstep(每进一个节点 +1),不是 ReAct 圈数。
|
|
38
|
+
* 图上 `config.maxIterations` 优先;缺省 {@link DEFAULT_GRAPH_RECURSION_LIMIT}。
|
|
39
|
+
*/
|
|
40
|
+
function langGraphRunOptions(dsl, extra) {
|
|
41
|
+
const raw = dsl.config?.maxIterations;
|
|
42
|
+
const recursionLimit = typeof raw === 'number' && Number.isFinite(raw) && raw > 0
|
|
43
|
+
? Math.trunc(raw)
|
|
44
|
+
: DEFAULT_GRAPH_RECURSION_LIMIT;
|
|
45
|
+
return {
|
|
46
|
+
...extra,
|
|
47
|
+
recursionLimit,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
32
50
|
// ─────────────────────────────────────────────
|
|
33
51
|
// LangGraphAdapter
|
|
34
52
|
// ─────────────────────────────────────────────
|
|
@@ -196,6 +214,7 @@ export class LangGraphAdapter {
|
|
|
196
214
|
payload: {
|
|
197
215
|
toolCallId: progress.toolCallId,
|
|
198
216
|
toolName: progress.toolName,
|
|
217
|
+
...(progress.toolset ? { toolset: progress.toolset } : {}),
|
|
199
218
|
arguments: progress.arguments ?? {},
|
|
200
219
|
...loc,
|
|
201
220
|
},
|
|
@@ -217,6 +236,7 @@ export class LangGraphAdapter {
|
|
|
217
236
|
payload: {
|
|
218
237
|
toolCallId: progress.toolCallId,
|
|
219
238
|
toolName: progress.toolName,
|
|
239
|
+
...(progress.toolset ? { toolset: progress.toolset } : {}),
|
|
220
240
|
content: progress.content,
|
|
221
241
|
success: true,
|
|
222
242
|
...loc,
|
|
@@ -232,6 +252,7 @@ export class LangGraphAdapter {
|
|
|
232
252
|
payload: {
|
|
233
253
|
toolCallId: progress.toolCallId,
|
|
234
254
|
toolName: progress.toolName,
|
|
255
|
+
...(progress.toolset ? { toolset: progress.toolset } : {}),
|
|
235
256
|
error: progress.error ?? 'Unknown error',
|
|
236
257
|
willRetry: false,
|
|
237
258
|
...loc,
|
|
@@ -300,7 +321,7 @@ export class LangGraphAdapter {
|
|
|
300
321
|
loadedSkills: ephemeral(undefined),
|
|
301
322
|
skillDefinitions: ephemeral(undefined),
|
|
302
323
|
skillInput: ephemeral(undefined),
|
|
303
|
-
|
|
324
|
+
agentSystemPrompt: ephemeral(undefined),
|
|
304
325
|
activatedSkill: ephemeral(undefined),
|
|
305
326
|
skillRoute: ephemeral(undefined),
|
|
306
327
|
silentOutput: ephemeral(undefined),
|
|
@@ -421,7 +442,7 @@ export class LangGraphAdapter {
|
|
|
421
442
|
this.streamedTextThisTurn = false;
|
|
422
443
|
const producer = (async () => {
|
|
423
444
|
try {
|
|
424
|
-
const streamIterator = await ref.compiled.stream(input, {
|
|
445
|
+
const streamIterator = await ref.compiled.stream(input, langGraphRunOptions(ref.dsl, {
|
|
425
446
|
configurable: {
|
|
426
447
|
thread_id: resolveCheckpointThreadId({
|
|
427
448
|
sessionId: typeof state.sessionId === 'string' ? state.sessionId : undefined,
|
|
@@ -430,7 +451,7 @@ export class LangGraphAdapter {
|
|
|
430
451
|
}),
|
|
431
452
|
},
|
|
432
453
|
streamMode: 'updates',
|
|
433
|
-
});
|
|
454
|
+
}));
|
|
434
455
|
for await (const update of streamIterator) {
|
|
435
456
|
for (const event of this.convertUpdatesToEvents(update, graph.id, () => this.streamChunkIndex++, ref.silentNodeIds, ref.subgraphNodeIds)) {
|
|
436
457
|
enqueue(event);
|
|
@@ -467,7 +488,7 @@ export class LangGraphAdapter {
|
|
|
467
488
|
const ref = this.getCompiledRef(graph);
|
|
468
489
|
const input = this.graphStateToLangGraphInput(state);
|
|
469
490
|
const startTime = Date.now();
|
|
470
|
-
const result = await ref.compiled.invoke(input, {
|
|
491
|
+
const result = await ref.compiled.invoke(input, langGraphRunOptions(ref.dsl, {
|
|
471
492
|
configurable: {
|
|
472
493
|
thread_id: resolveCheckpointThreadId({
|
|
473
494
|
sessionId: typeof state.sessionId === 'string' ? state.sessionId : undefined,
|
|
@@ -475,7 +496,7 @@ export class LangGraphAdapter {
|
|
|
475
496
|
graphId: graph.id,
|
|
476
497
|
}),
|
|
477
498
|
},
|
|
478
|
-
});
|
|
499
|
+
}));
|
|
479
500
|
const duration = Date.now() - startTime;
|
|
480
501
|
const messages = Array.isArray(result['messages']) ? result['messages'] : [];
|
|
481
502
|
const lastMessage = messages[messages.length - 1];
|
|
@@ -492,6 +513,7 @@ export class LangGraphAdapter {
|
|
|
492
513
|
model: u.model ?? 'unknown',
|
|
493
514
|
inputTokens: u.inputTokens ?? 0,
|
|
494
515
|
outputTokens: u.outputTokens ?? 0,
|
|
516
|
+
...pickContextFields(u),
|
|
495
517
|
}));
|
|
496
518
|
const inputTokens = perNode.reduce((s, u) => s + u.inputTokens, 0);
|
|
497
519
|
const outputTokens = perNode.reduce((s, u) => s + u.outputTokens, 0);
|
|
@@ -655,7 +677,6 @@ export class LangGraphAdapter {
|
|
|
655
677
|
currentNode: node.id,
|
|
656
678
|
skillRoute: patch.skillRoute,
|
|
657
679
|
activatedSkill: patch.activatedSkill,
|
|
658
|
-
activeSkillPrompt: patch.activeSkillPrompt,
|
|
659
680
|
skillInput: patch.skillInput,
|
|
660
681
|
messages: { __set: patch.messages },
|
|
661
682
|
};
|
|
@@ -788,9 +809,34 @@ export class LangGraphAdapter {
|
|
|
788
809
|
return withGraphSpan(state, { name: node.id, type: 'llm' }, async () => {
|
|
789
810
|
const promptRoots = Array.isArray(state['promptRoots']) ? state['promptRoots'] : [];
|
|
790
811
|
const resolvedPrompt = resolveGraphPrompt(baseConfig.systemPrompt, promptRoots);
|
|
791
|
-
const
|
|
812
|
+
const loadedToolsBase = state['loadedTools'];
|
|
792
813
|
const agentCode = typeof state['agentCode'] === 'string' ? state['agentCode'] : undefined;
|
|
793
814
|
const skillDefs = state['skillDefinitions'];
|
|
815
|
+
const execCtx = state['executionContext'];
|
|
816
|
+
const userId = (typeof execCtx?.userId === 'string' && execCtx.userId) || state['userId'];
|
|
817
|
+
const loadedTools = disableTools
|
|
818
|
+
? loadedToolsBase
|
|
819
|
+
: await hydrateMcpTools(loadedToolsBase, this.toolExecutor, {
|
|
820
|
+
authContext: {
|
|
821
|
+
userId: String(userId ?? ''),
|
|
822
|
+
delegationToken: String(execCtx?.delegationToken ?? state['delegationToken'] ?? ''),
|
|
823
|
+
agentCode: String(agentCode ?? ''),
|
|
824
|
+
},
|
|
825
|
+
correlationId: typeof state['correlationId'] === 'string' ? state['correlationId'] : undefined,
|
|
826
|
+
taskId: typeof state['taskId'] === 'string' ? state['taskId'] : undefined,
|
|
827
|
+
onListFailure: ({ toolset, error }) => {
|
|
828
|
+
this.emitToolExecutionEvents({
|
|
829
|
+
toolCallId: `mcp-list:${toolset}`,
|
|
830
|
+
toolName: MCP_LIST_TOOL_NAME,
|
|
831
|
+
toolset,
|
|
832
|
+
status: 'error',
|
|
833
|
+
error,
|
|
834
|
+
});
|
|
835
|
+
},
|
|
836
|
+
});
|
|
837
|
+
if (loadedTools && loadedTools !== loadedToolsBase) {
|
|
838
|
+
state['loadedTools'] = loadedTools;
|
|
839
|
+
}
|
|
794
840
|
// [DEBUG] 打印 loadedTools 实际状态
|
|
795
841
|
if (process.env.EAP_LLM_DEBUG === '1') {
|
|
796
842
|
const toolNames = loadedTools ? Object.keys(loadedTools) : [];
|
|
@@ -798,8 +844,6 @@ export class LangGraphAdapter {
|
|
|
798
844
|
}
|
|
799
845
|
const catalog = includeSkillCatalog ? this.buildSkillCatalog(skillDefs) : undefined;
|
|
800
846
|
const toolCatalog = disableTools ? undefined : buildToolCatalog(loadedTools);
|
|
801
|
-
const execCtx = state['executionContext'];
|
|
802
|
-
const userId = (typeof execCtx?.userId === 'string' && execCtx.userId) || state['userId'];
|
|
803
847
|
const jail = resolveJailFromState({
|
|
804
848
|
agentDir: state['agentDir'],
|
|
805
849
|
userId,
|
|
@@ -816,8 +860,14 @@ export class LangGraphAdapter {
|
|
|
816
860
|
bundlePath: skill.bundlePath,
|
|
817
861
|
entryFile: skill.entryFile,
|
|
818
862
|
}));
|
|
863
|
+
const promptInputs = resolveLlmPromptInputs({
|
|
864
|
+
silent,
|
|
865
|
+
agentSystemPrompt: state['agentSystemPrompt'],
|
|
866
|
+
nodePrompt: resolvedPrompt,
|
|
867
|
+
});
|
|
819
868
|
const assembled = this.systemPromptBuilder.build({
|
|
820
|
-
|
|
869
|
+
agentPrompt: promptInputs.agentPrompt,
|
|
870
|
+
nodePrompt: promptInputs.nodePrompt,
|
|
821
871
|
skillCatalog: catalog,
|
|
822
872
|
toolCatalog,
|
|
823
873
|
agentCode,
|
|
@@ -880,8 +930,9 @@ export class LangGraphAdapter {
|
|
|
880
930
|
}
|
|
881
931
|
: undefined);
|
|
882
932
|
const next = await llmNode.execute(state);
|
|
933
|
+
const hydratedUpdate = loadedTools && loadedTools !== loadedToolsBase ? { loadedTools } : {};
|
|
883
934
|
if (!silent)
|
|
884
|
-
return next;
|
|
935
|
+
return { ...next, ...hydratedUpdate };
|
|
885
936
|
const added = Array.isArray(next.messages) ? next.messages[0] : undefined;
|
|
886
937
|
const raw = added && typeof added === 'object' && typeof added.content === 'string'
|
|
887
938
|
? added.content
|
|
@@ -890,13 +941,14 @@ export class LangGraphAdapter {
|
|
|
890
941
|
...next,
|
|
891
942
|
messages: [],
|
|
892
943
|
silentOutput: raw,
|
|
944
|
+
...hydratedUpdate,
|
|
893
945
|
};
|
|
894
946
|
});
|
|
895
947
|
};
|
|
896
948
|
}
|
|
897
949
|
/**
|
|
898
950
|
* 子图节点:优先 config.subgraphDsl;否则按 skillId 从 state.skillDefinitions.workflow 解析。
|
|
899
|
-
*
|
|
951
|
+
* 技能正文用短目录 + read_file,不灌 system。
|
|
900
952
|
*/
|
|
901
953
|
createSubGraphNodeFunction(node) {
|
|
902
954
|
const embeddedDsl = node.config?.['subgraphDsl'];
|
|
@@ -1199,6 +1251,7 @@ export class LangGraphAdapter {
|
|
|
1199
1251
|
costEstimate: Number(u['costEstimate'] ?? 0),
|
|
1200
1252
|
durationMs: typeof u['durationMs'] === 'number' ? u['durationMs'] : undefined,
|
|
1201
1253
|
graphId,
|
|
1254
|
+
...pickContextFields(u),
|
|
1202
1255
|
},
|
|
1203
1256
|
};
|
|
1204
1257
|
}
|
|
@@ -12,6 +12,7 @@ import { LangGraphAdapter } from './langgraph.adapter.js';
|
|
|
12
12
|
import { resolveTraceId } from '../../common/trace-id.js';
|
|
13
13
|
import { filterLoadedToolsForSkill, } from '../../tool/system-prompt-builder.js';
|
|
14
14
|
import { unwrapHitlPaused } from '../hitl/hitl-handler.js';
|
|
15
|
+
import { pickContextFields } from '../../token/context-window.js';
|
|
15
16
|
import { assertSkillIoIfEnabled, coerceSkillInputFromMessages, } from '../../registry/skill-io-guard.js';
|
|
16
17
|
/**
|
|
17
18
|
* SubGraphCompiler — 子图编译器
|
|
@@ -99,7 +100,6 @@ export class SubGraphCompiler {
|
|
|
99
100
|
const agentCode = state['agentCode'] ?? state['agentId'];
|
|
100
101
|
const defs = state['skillDefinitions'];
|
|
101
102
|
const skillInfo = resolvedSkillId ? defs?.[resolvedSkillId] : undefined;
|
|
102
|
-
const skillPrompt = skillInfo?.prompt;
|
|
103
103
|
const parentTools = state['loadedTools'];
|
|
104
104
|
const scopedTools = filterLoadedToolsForSkill(parentTools, skillInfo);
|
|
105
105
|
const skillInput = skillInfo
|
|
@@ -132,7 +132,9 @@ export class SubGraphCompiler {
|
|
|
132
132
|
loadedTools: scopedTools,
|
|
133
133
|
loadedSkills: state['loadedSkills'],
|
|
134
134
|
skillDefinitions: defs,
|
|
135
|
-
|
|
135
|
+
agentSystemPrompt: typeof state['agentSystemPrompt'] === 'string'
|
|
136
|
+
? state['agentSystemPrompt']
|
|
137
|
+
: undefined,
|
|
136
138
|
activatedSkill: resolvedSkillId || undefined,
|
|
137
139
|
skillInput,
|
|
138
140
|
traceId,
|
|
@@ -200,6 +202,7 @@ export class SubGraphCompiler {
|
|
|
200
202
|
model: u.model,
|
|
201
203
|
inputTokens: u.inputTokens,
|
|
202
204
|
outputTokens: u.outputTokens,
|
|
205
|
+
...pickContextFields(u),
|
|
203
206
|
})),
|
|
204
207
|
}
|
|
205
208
|
: {}),
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
* Executable Graph 类型定义
|
|
3
3
|
*
|
|
4
4
|
* 定义 Graph 引擎核心的可执行图、DSL、节点、边等类型。
|
|
5
|
-
* 与 @
|
|
5
|
+
* 与 @eap/contracts 的 GraphDSL 基础类型互补,在 Runtime 层提供更丰富的类型支持。
|
|
6
6
|
*
|
|
7
7
|
* @see design.md §1.4 StateGraph Contract
|
|
8
8
|
* @see requirements.md Requirement 1 AC1-AC2
|
|
9
9
|
*/
|
|
10
|
-
import type { GraphDSL as BaseGraphDSL, GraphNode as BaseGraphNode, GraphEdge as BaseGraphEdge, GraphNodeType, GraphConfig } from '@
|
|
10
|
+
import type { GraphDSL as BaseGraphDSL, GraphNode as BaseGraphNode, GraphEdge as BaseGraphEdge, GraphNodeType, GraphConfig } from '@eap/contracts';
|
|
11
11
|
export type { GraphNodeType, GraphConfig };
|
|
12
12
|
/**
|
|
13
13
|
* RuntimeGraphConfig — Runtime 层扩展的 Graph 配置
|
|
14
14
|
*
|
|
15
|
-
* 在 @
|
|
15
|
+
* 在 @eap/contracts GraphConfig 基础上增加 Runtime 执行所需的 maxRetries。
|
|
16
16
|
*/
|
|
17
17
|
export interface RuntimeGraphConfig extends GraphConfig {
|
|
18
18
|
/** Graph 级默认重试次数(节点级 retry 可覆盖) */
|
|
@@ -21,7 +21,7 @@ export interface RuntimeGraphConfig extends GraphConfig {
|
|
|
21
21
|
/**
|
|
22
22
|
* GraphNode — Runtime 层扩展的节点定义
|
|
23
23
|
*
|
|
24
|
-
* 继承 @
|
|
24
|
+
* 继承 @eap/contracts 基础 GraphNode,增加 Runtime 执行所需的字段:
|
|
25
25
|
* - 重试配置(节点级 maxRetries + 退避策略)
|
|
26
26
|
* - HITL 标记(interrupt_before / interrupt_after)
|
|
27
27
|
* - 描述信息(调试/Trace 用)
|
|
@@ -79,7 +79,7 @@ export interface ConditionalBranch {
|
|
|
79
79
|
/**
|
|
80
80
|
* GraphDSL — Runtime 层扩展的声明式工作流定义
|
|
81
81
|
*
|
|
82
|
-
* 扩展 @
|
|
82
|
+
* 扩展 @eap/contracts 的 BaseGraphDSL,增加条件路由、入口/终止节点等。
|
|
83
83
|
*/
|
|
84
84
|
export interface GraphDSL extends Omit<BaseGraphDSL, 'config' | 'nodes' | 'edges'> {
|
|
85
85
|
/** 覆盖节点类型为 Runtime 扩展版本 */
|
|
@@ -163,7 +163,7 @@ export interface ExecutableGraph {
|
|
|
163
163
|
/** 底层引擎内部实例引用(opaque,由 adapter 管理) */
|
|
164
164
|
_engineInstance?: unknown;
|
|
165
165
|
}
|
|
166
|
-
import type { ExecutionContext as PlatformExecutionContext } from '@
|
|
166
|
+
import type { ExecutionContext as PlatformExecutionContext } from '@eap/contracts';
|
|
167
167
|
/**
|
|
168
168
|
* GraphState — 传入 stream/invoke 的上下文数据
|
|
169
169
|
*/
|
|
@@ -189,14 +189,18 @@ export interface GraphState {
|
|
|
189
189
|
loadedSkills?: import('../../tool/system-prompt-builder.js').LoadedSkillInfo[];
|
|
190
190
|
/** GraphLoader 注入:skillId → 完整定义(子图解析 / prompt) */
|
|
191
191
|
skillDefinitions?: import('../../tool/system-prompt-builder.js').LoadedSkillMap;
|
|
192
|
-
/**
|
|
193
|
-
|
|
192
|
+
/**
|
|
193
|
+
* Agent 基线系统提示词(manifest.prompts.system)。
|
|
194
|
+
* execute/stream 每轮注入;非 silent LLM 拼入 system 的 agent 段。
|
|
195
|
+
*/
|
|
196
|
+
agentSystemPrompt?: string;
|
|
194
197
|
/** silent LLM 的原始输出;不入对话 messages */
|
|
195
198
|
silentOutput?: string;
|
|
196
199
|
/** 解析 graph 内 ./prompts/*.md 的根目录(agentDir + 工程根) */
|
|
197
200
|
promptRoots?: string[];
|
|
198
201
|
/** 预装 Agent 包目录:`{EAP_PREINSTALL_ROOT}/agents/<code>/<ver>` */
|
|
199
202
|
agentDir?: string;
|
|
203
|
+
/** bind / 子图选中的技能;harness 路径解析不写此字段 */
|
|
200
204
|
activatedSkill?: string | null;
|
|
201
205
|
skillRoute?: string;
|
|
202
206
|
/** bind / invoke 解析出的 Skill 入参;子图 IO 校验读取 */
|
|
@@ -331,6 +335,13 @@ export interface GraphTokenUsage {
|
|
|
331
335
|
model: string;
|
|
332
336
|
inputTokens: number;
|
|
333
337
|
outputTokens: number;
|
|
338
|
+
used?: number;
|
|
339
|
+
window?: number;
|
|
340
|
+
parts?: {
|
|
341
|
+
system: number;
|
|
342
|
+
messages: number;
|
|
343
|
+
tools: number;
|
|
344
|
+
};
|
|
334
345
|
}>;
|
|
335
346
|
/** 当前会话跨请求累计消耗(可选;由 session 层服务填充) */
|
|
336
347
|
conversationTotal?: {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Executable Graph 类型定义
|
|
3
3
|
*
|
|
4
4
|
* 定义 Graph 引擎核心的可执行图、DSL、节点、边等类型。
|
|
5
|
-
* 与 @
|
|
5
|
+
* 与 @eap/contracts 的 GraphDSL 基础类型互补,在 Runtime 层提供更丰富的类型支持。
|
|
6
6
|
*
|
|
7
7
|
* @see design.md §1.4 StateGraph Contract
|
|
8
8
|
* @see requirements.md Requirement 1 AC1-AC2
|
|
@@ -58,6 +58,8 @@ export interface LLMNodeConfig {
|
|
|
58
58
|
agentCode?: string;
|
|
59
59
|
correlationId?: string;
|
|
60
60
|
};
|
|
61
|
+
/** ModelRecord.capabilities.maxContextTokens;缺省则不写 used/window */
|
|
62
|
+
maxContextTokens?: number;
|
|
61
63
|
}
|
|
62
64
|
/**
|
|
63
65
|
* LLMResponse — LLM 完整响应
|
|
@@ -178,6 +180,7 @@ export declare class LLMNode {
|
|
|
178
180
|
*
|
|
179
181
|
* 根据 streaming 配置选择 invoke 或 stream 模式。
|
|
180
182
|
* 失败时按 backoff 策略重试,最多重试 maxRetries 次。
|
|
183
|
+
* AbortError / 「This operation was aborted」(含 LLM HTTP 超时包装)立即失败,不重试。
|
|
181
184
|
*/
|
|
182
185
|
private invokeWithRetry;
|
|
183
186
|
/**
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* @see requirements.md Requirement 1 AC6, Requirement 9
|
|
11
11
|
*/
|
|
12
12
|
import { formatUnknownError } from '../../utils/format-error.js';
|
|
13
|
+
import { buildContextUsage, turnSectionChars } from '../../token/context-window.js';
|
|
14
|
+
import { isAbortError } from '../../tool/timeout.js';
|
|
13
15
|
// ─────────────────────────────────────────────
|
|
14
16
|
// Default retry config
|
|
15
17
|
// ─────────────────────────────────────────────
|
|
@@ -94,6 +96,7 @@ export class LLMNode {
|
|
|
94
96
|
// (即 user 消息重复的根因)。
|
|
95
97
|
//
|
|
96
98
|
// __llmTokenUsage channel 同样是 **数组累加器 reducer**,每次追加一条使用明细。
|
|
99
|
+
const context = buildContextUsage(response.inputTokens, this.config.maxContextTokens, turnSectionChars(this.config, messages));
|
|
97
100
|
return {
|
|
98
101
|
messages: [assistantMessage],
|
|
99
102
|
currentNode: this.nodeId,
|
|
@@ -104,6 +107,7 @@ export class LLMNode {
|
|
|
104
107
|
inputTokens: response.inputTokens,
|
|
105
108
|
outputTokens: response.outputTokens,
|
|
106
109
|
durationMs,
|
|
110
|
+
...(context ?? {}),
|
|
107
111
|
},
|
|
108
112
|
],
|
|
109
113
|
};
|
|
@@ -183,6 +187,7 @@ export class LLMNode {
|
|
|
183
187
|
*
|
|
184
188
|
* 根据 streaming 配置选择 invoke 或 stream 模式。
|
|
185
189
|
* 失败时按 backoff 策略重试,最多重试 maxRetries 次。
|
|
190
|
+
* AbortError / 「This operation was aborted」(含 LLM HTTP 超时包装)立即失败,不重试。
|
|
186
191
|
*/
|
|
187
192
|
async invokeWithRetry(messages) {
|
|
188
193
|
let lastError;
|
|
@@ -195,6 +200,9 @@ export class LLMNode {
|
|
|
195
200
|
}
|
|
196
201
|
catch (error) {
|
|
197
202
|
lastError = error instanceof Error ? error : new Error(formatUnknownError(error));
|
|
203
|
+
if (isAbortError(error) || isAbortError(lastError)) {
|
|
204
|
+
throw lastError;
|
|
205
|
+
}
|
|
198
206
|
// 最后一次尝试不需要等待
|
|
199
207
|
if (attempt < this.retryConfig.maxRetries) {
|
|
200
208
|
const delay = this.calculateBackoffDelay(attempt);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 可选图胶水:把 silent LLM 的结构化输出写成
|
|
3
|
-
* 不是 Graph
|
|
2
|
+
* 可选图胶水:把 silent LLM 的结构化输出写成 skillRoute / activatedSkill。
|
|
3
|
+
* 不是 Graph 节点类型。技能正文走短目录 + read_file,不灌 system。
|
|
4
4
|
*/
|
|
5
5
|
import type { LoadedSkillInfo, LoadedSkillMap } from '../../tool/system-prompt-builder.js';
|
|
6
6
|
export type SkillRoute = 'skill' | 'clarify' | 'none';
|
|
@@ -9,7 +9,6 @@ export interface SkillBindPatch {
|
|
|
9
9
|
activatedSkill: string | null;
|
|
10
10
|
/** 展示名;未选中时为空 */
|
|
11
11
|
skillName?: string;
|
|
12
|
-
activeSkillPrompt?: string;
|
|
13
12
|
skillInput?: Record<string, unknown>;
|
|
14
13
|
messages: Array<Record<string, unknown>>;
|
|
15
14
|
/** 用户写了 skill 名但清单里没有,才算 unmatched */
|
|
@@ -25,7 +24,7 @@ interface SkillSelectPayload {
|
|
|
25
24
|
export declare function extractJsonObject(text: string): SkillSelectPayload | null;
|
|
26
25
|
export declare function resolveSkillDefinition(defs: LoadedSkillMap | undefined, rawName: string): LoadedSkillInfo | undefined;
|
|
27
26
|
/**
|
|
28
|
-
* 消费选择节点刚写出的 assistant JSON
|
|
27
|
+
* 消费选择节点刚写出的 assistant JSON,改写为路由。
|
|
29
28
|
* 返回的 messages 是**整段替换**(调用方须覆盖 messages channel 时改用 replace 语义)。
|
|
30
29
|
*/
|
|
31
30
|
export declare function bindSelectedSkill(state: Record<string, unknown>): SkillBindPatch;
|
|
@@ -38,26 +38,8 @@ export function resolveSkillDefinition(defs, rawName) {
|
|
|
38
38
|
(skill.name && skill.name.toLowerCase() === needle));
|
|
39
39
|
});
|
|
40
40
|
}
|
|
41
|
-
function formatParams(params) {
|
|
42
|
-
return Object.entries(params)
|
|
43
|
-
.map(([key, value]) => `- ${key}: ${JSON.stringify(value)}`)
|
|
44
|
-
.join('\n');
|
|
45
|
-
}
|
|
46
|
-
function buildSkillPrompt(skill, params) {
|
|
47
|
-
const parts = [`# 技能:${skill.name || skill.skillId}`];
|
|
48
|
-
if (skill.description) {
|
|
49
|
-
parts.push(skill.description);
|
|
50
|
-
}
|
|
51
|
-
if (params && Object.keys(params).length > 0) {
|
|
52
|
-
parts.push(`# 提取的参数\n${formatParams(params)}`);
|
|
53
|
-
}
|
|
54
|
-
if (skill.prompt?.trim()) {
|
|
55
|
-
parts.push(skill.prompt.trim());
|
|
56
|
-
}
|
|
57
|
-
return parts.join('\n\n');
|
|
58
|
-
}
|
|
59
41
|
/**
|
|
60
|
-
* 消费选择节点刚写出的 assistant JSON
|
|
42
|
+
* 消费选择节点刚写出的 assistant JSON,改写为路由。
|
|
61
43
|
* 返回的 messages 是**整段替换**(调用方须覆盖 messages channel 时改用 replace 语义)。
|
|
62
44
|
*/
|
|
63
45
|
export function bindSelectedSkill(state) {
|
|
@@ -108,7 +90,6 @@ export function bindSelectedSkill(state) {
|
|
|
108
90
|
skillRoute: 'skill',
|
|
109
91
|
activatedSkill: skill.skillId,
|
|
110
92
|
skillName: skill.name || skill.skillId,
|
|
111
|
-
activeSkillPrompt: buildSkillPrompt(skill, params),
|
|
112
93
|
skillInput: params,
|
|
113
94
|
messages: nextMessages(),
|
|
114
95
|
};
|
|
@@ -33,6 +33,8 @@ type LangGraphState = Record<string, unknown>;
|
|
|
33
33
|
export interface ToolNodeProgress {
|
|
34
34
|
toolCallId: string;
|
|
35
35
|
toolName: string;
|
|
36
|
+
/** 工具集编码;与 toolName 一起给 UI 显示 `toolset/toolName` */
|
|
37
|
+
toolset?: string;
|
|
36
38
|
status: 'started' | 'completed' | 'error';
|
|
37
39
|
arguments?: Record<string, unknown>;
|
|
38
40
|
content?: string;
|
|
@@ -10,29 +10,18 @@
|
|
|
10
10
|
* @see requirements.md Requirement 8 AC1, AC3, AC5
|
|
11
11
|
*/
|
|
12
12
|
import { resolveJailFromState } from '../../tool/harness-primitives.js';
|
|
13
|
+
import { inferHarnessSkillDir } from '../../tool/skill-dir-infer.js';
|
|
13
14
|
import { isHitlDecision, unwrapHitlPaused } from '../hitl/hitl-handler.js';
|
|
14
15
|
import { ToolConfirmationInterceptor } from '../../tool/tool-confirmation.js';
|
|
15
16
|
import { resolveCheckpointThreadId } from '../../session/persist-turn-messages.js';
|
|
16
17
|
import { resolveTraceId } from '../../common/trace-id.js';
|
|
18
|
+
import { toolsetCodeFromLoaded } from '../../tool/mcp-list.js';
|
|
17
19
|
function skillDirsFromState(state) {
|
|
18
20
|
const defs = state['skillDefinitions'];
|
|
19
21
|
return Object.values(defs ?? {})
|
|
20
22
|
.filter((skill) => Boolean(skill.bundlePath))
|
|
21
23
|
.map((skill) => ({ skillId: skill.skillId, bundlePath: skill.bundlePath }));
|
|
22
24
|
}
|
|
23
|
-
function resolveActiveSkillDir(state) {
|
|
24
|
-
const defs = state['skillDefinitions'];
|
|
25
|
-
if (!defs)
|
|
26
|
-
return undefined;
|
|
27
|
-
const activated = state['activatedSkill'];
|
|
28
|
-
if (typeof activated === 'string' && defs[activated]?.bundlePath) {
|
|
29
|
-
return defs[activated].bundlePath;
|
|
30
|
-
}
|
|
31
|
-
const paths = Object.values(defs)
|
|
32
|
-
.map((skill) => skill.bundlePath)
|
|
33
|
-
.filter((p) => Boolean(p));
|
|
34
|
-
return paths.length === 1 ? paths[0] : undefined;
|
|
35
|
-
}
|
|
36
25
|
export class ToolNode {
|
|
37
26
|
orchestrator;
|
|
38
27
|
injector;
|
|
@@ -75,12 +64,24 @@ export class ToolNode {
|
|
|
75
64
|
skillDefinitions: state['skillDefinitions'],
|
|
76
65
|
});
|
|
77
66
|
const jailExtraRoots = jail.extraRoots ?? [];
|
|
78
|
-
const
|
|
67
|
+
const batchCalls = lastAssistantMessage.toolCalls.map((tc) => ({
|
|
68
|
+
name: tc.name,
|
|
69
|
+
arguments: tc.arguments,
|
|
70
|
+
}));
|
|
71
|
+
const boundSkill = typeof state['activatedSkill'] === 'string' ? state['activatedSkill'] : undefined;
|
|
79
72
|
// 4. 转换为 ToolCallRequest[](附带 manifest 路由字段)
|
|
80
73
|
const requests = lastAssistantMessage.toolCalls.map((tc) => {
|
|
81
74
|
const loaded = loadedTools?.[tc.name];
|
|
82
75
|
const correlationId = String(state['correlationId'] ?? tc.id);
|
|
83
76
|
const taskId = String(state['taskId'] ?? state['correlationId'] ?? tc.id);
|
|
77
|
+
const command = typeof tc.arguments?.command === 'string' ? tc.arguments.command : undefined;
|
|
78
|
+
const skillDir = inferHarnessSkillDir({
|
|
79
|
+
command,
|
|
80
|
+
toolCalls: batchCalls,
|
|
81
|
+
messages,
|
|
82
|
+
skillDirs,
|
|
83
|
+
activatedSkill: boundSkill,
|
|
84
|
+
});
|
|
84
85
|
return {
|
|
85
86
|
toolCallId: tc.id,
|
|
86
87
|
toolName: tc.name,
|
|
@@ -153,11 +154,13 @@ export class ToolNode {
|
|
|
153
154
|
const needsHitl = Boolean(this.hitlHandler) &&
|
|
154
155
|
requests.some((req) => confirmationTools.has(req.toolName));
|
|
155
156
|
const runOne = async (req, i) => {
|
|
157
|
+
const toolset = toolsetCodeFromLoaded(loadedTools?.[req.toolName]);
|
|
156
158
|
const resumingHitl = isHitlDecision(state['hitlChoice']);
|
|
157
159
|
if (!resumingHitl) {
|
|
158
160
|
emitProgress({
|
|
159
161
|
toolCallId: req.toolCallId,
|
|
160
162
|
toolName: req.toolName,
|
|
163
|
+
...(toolset ? { toolset } : {}),
|
|
161
164
|
status: 'started',
|
|
162
165
|
arguments: req.arguments,
|
|
163
166
|
});
|
|
@@ -197,6 +200,7 @@ export class ToolNode {
|
|
|
197
200
|
emitProgress({
|
|
198
201
|
toolCallId: result.toolCallId,
|
|
199
202
|
toolName: result.toolName,
|
|
203
|
+
...(toolset ? { toolset } : {}),
|
|
200
204
|
status: 'completed',
|
|
201
205
|
arguments: req.arguments,
|
|
202
206
|
content: result.content,
|
|
@@ -207,6 +211,7 @@ export class ToolNode {
|
|
|
207
211
|
emitProgress({
|
|
208
212
|
toolCallId: result.toolCallId,
|
|
209
213
|
toolName: result.toolName,
|
|
214
|
+
...(toolset ? { toolset } : {}),
|
|
210
215
|
status: 'error',
|
|
211
216
|
arguments: req.arguments,
|
|
212
217
|
error: result.error ?? 'unknown error',
|
|
@@ -243,6 +248,7 @@ export class ToolNode {
|
|
|
243
248
|
emitProgress({
|
|
244
249
|
toolCallId: req.toolCallId,
|
|
245
250
|
toolName: req.toolName,
|
|
251
|
+
...(toolset ? { toolset } : {}),
|
|
246
252
|
status: 'error',
|
|
247
253
|
arguments: req.arguments,
|
|
248
254
|
error: message,
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export * from './common/index.js';
|
|
|
16
16
|
export * from './registry/index.js';
|
|
17
17
|
export * from './providers/index.js';
|
|
18
18
|
export type { ITraceCollector, TraceEvent, TraceSession, ExecutionFlowEvent, ExecutionNodeEvent, TraceLinkEvent, TraceLinkNodeEvent, } from './contracts/trace-collector.js';
|
|
19
|
-
export type { ExecutionContext, CallerType, GovernancePermissionCheckParams, GovernancePermissionCheckResult, PermissionDenyReason, } from '@
|
|
19
|
+
export type { ExecutionContext, CallerType, GovernancePermissionCheckParams, GovernancePermissionCheckResult, PermissionDenyReason, } from '@eap/contracts';
|
|
20
20
|
export { HttpGovernanceClient, AllowAllGovernanceClient, resolveExecutionContext, assertToolPermission, assertSkillPermission, permissionMessage, PermissionDeniedError, GovernanceUnavailableError, } from './governance/index.js';
|
|
21
21
|
export type { IGovernanceClient } from './governance/index.js';
|
|
22
22
|
export { FileLlmTurnLog, InMemoryLlmTurnLog, createFileLlmTurnLogFromEnv, maskApiKey, resolveLlmTurnDir, } from './debug/llm-turn-log.js';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 提供多种压缩策略用于处理长对话历史。
|
|
5
5
|
*/
|
|
6
|
-
export { type CompressionConfig, type CompressionResult, type CompressionRecord, type CompressionStrategy, type CompressionReason, type IMessageCompressionService, DEFAULT_COMPRESSION_CONFIG, estimateTokenCount, estimateMessagesTokens, countRounds, } from '../message-compression.service.js';
|
|
6
|
+
export { type CompressionConfig, type CompressionResult, type CompressionRecord, type CompressionStrategy, type CompressionReason, type IMessageCompressionService, DEFAULT_COMPRESSION_CONFIG, COMPRESSION_WINDOW_FACTOR, COMPRESSION_MAX_TOKENS_FALLBACK, resolveCompressionMaxTokens, mergeCompressionConfig, estimateTokenCount, estimateMessagesTokens, countRounds, } from '../message-compression.service.js';
|
|
7
7
|
export { SlidingWindowCompression, TruncateCompression, type SummarizeFunction, } from './sliding-window.compression.js';
|
|
8
8
|
export { createLLMSummarize, createSimpleSummarize, type LLMCallFunction, } from './llm-summarize.js';
|
|
9
9
|
export { PostgresCompressionRepository, InMemoryCompressionRepository, type ICompressionRepository, } from './compression.repository.js';
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 提供多种压缩策略用于处理长对话历史。
|
|
5
5
|
*/
|
|
6
6
|
// 压缩接口和工具函数
|
|
7
|
-
export { DEFAULT_COMPRESSION_CONFIG, estimateTokenCount, estimateMessagesTokens, countRounds, } from '../message-compression.service.js';
|
|
7
|
+
export { DEFAULT_COMPRESSION_CONFIG, COMPRESSION_WINDOW_FACTOR, COMPRESSION_MAX_TOKENS_FALLBACK, resolveCompressionMaxTokens, mergeCompressionConfig, estimateTokenCount, estimateMessagesTokens, countRounds, } from '../message-compression.service.js';
|
|
8
8
|
// 滑动窗口压缩策略
|
|
9
9
|
export { SlidingWindowCompression, TruncateCompression, } from './sliding-window.compression.js';
|
|
10
10
|
// LLM 摘要函数
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @see message-compression.service.ts 压缩接口定义
|
|
10
10
|
* @see requirements.md Requirement 4.3
|
|
11
11
|
*/
|
|
12
|
-
import { DEFAULT_COMPRESSION_CONFIG, estimateMessagesTokens, countRounds, } from '../message-compression.service.js';
|
|
12
|
+
import { DEFAULT_COMPRESSION_CONFIG, estimateMessagesTokens, countRounds, mergeCompressionConfig, } from '../message-compression.service.js';
|
|
13
13
|
/**
|
|
14
14
|
* 默认摘要函数(占位)
|
|
15
15
|
*
|
|
@@ -30,14 +30,14 @@ export class SlidingWindowCompression {
|
|
|
30
30
|
config;
|
|
31
31
|
summarize;
|
|
32
32
|
constructor(config, summarize) {
|
|
33
|
-
this.config =
|
|
33
|
+
this.config = mergeCompressionConfig(DEFAULT_COMPRESSION_CONFIG, config);
|
|
34
34
|
this.summarize = summarize ?? defaultSummarize;
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* 检查是否需要压缩
|
|
38
38
|
*/
|
|
39
39
|
checkCompression(messages, config) {
|
|
40
|
-
const mergedConfig =
|
|
40
|
+
const mergedConfig = mergeCompressionConfig(this.config, config);
|
|
41
41
|
const currentTokens = this.estimateTokens(messages);
|
|
42
42
|
const currentRounds = countRounds(messages);
|
|
43
43
|
// 检查 Token 数是否超限
|
|
@@ -73,7 +73,7 @@ export class SlidingWindowCompression {
|
|
|
73
73
|
* 3. 用摘要 + 最近 N 轮替换原始消息
|
|
74
74
|
*/
|
|
75
75
|
async compress(messages, config) {
|
|
76
|
-
const mergedConfig =
|
|
76
|
+
const mergedConfig = mergeCompressionConfig(this.config, config);
|
|
77
77
|
// 1. 找到最近 N 轮的起始位置
|
|
78
78
|
const splitIndex = this.findSplitIndex(messages, mergedConfig.preserveRecentRounds);
|
|
79
79
|
// 如果消息太少,不需要压缩
|
|
@@ -134,10 +134,10 @@ export class SlidingWindowCompression {
|
|
|
134
134
|
export class TruncateCompression {
|
|
135
135
|
config;
|
|
136
136
|
constructor(config) {
|
|
137
|
-
this.config =
|
|
137
|
+
this.config = mergeCompressionConfig(DEFAULT_COMPRESSION_CONFIG, config);
|
|
138
138
|
}
|
|
139
139
|
checkCompression(messages, config) {
|
|
140
|
-
const mergedConfig =
|
|
140
|
+
const mergedConfig = mergeCompressionConfig(this.config, config);
|
|
141
141
|
const currentTokens = this.estimateTokens(messages);
|
|
142
142
|
const currentRounds = countRounds(messages);
|
|
143
143
|
if (currentTokens > mergedConfig.maxTokens || currentRounds > mergedConfig.maxRounds) {
|
|
@@ -155,7 +155,7 @@ export class TruncateCompression {
|
|
|
155
155
|
};
|
|
156
156
|
}
|
|
157
157
|
async compress(messages, config) {
|
|
158
|
-
const mergedConfig =
|
|
158
|
+
const mergedConfig = mergeCompressionConfig(this.config, config);
|
|
159
159
|
const preserveCount = mergedConfig.preserveRecentRounds * 2; // 每轮 2 条消息
|
|
160
160
|
if (messages.length <= preserveCount) {
|
|
161
161
|
return messages;
|