kagent-ts 0.1.3 → 0.1.5
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/LICENSE +68 -21
- package/README.md +27 -371
- package/dist/compression/progressive-compressor.d.ts +66 -0
- package/dist/compression/progressive-compressor.d.ts.map +1 -0
- package/dist/compression/progressive-compressor.js +367 -0
- package/dist/compression/progressive-compressor.js.map +1 -0
- package/dist/compression/types.d.ts +1 -5
- package/dist/compression/types.d.ts.map +1 -1
- package/dist/context/context-manager.d.ts +34 -15
- package/dist/context/context-manager.d.ts.map +1 -1
- package/dist/context/context-manager.js +78 -28
- package/dist/context/context-manager.js.map +1 -1
- package/dist/context/types.d.ts +20 -4
- package/dist/context/types.d.ts.map +1 -1
- package/dist/core/agent.d.ts +407 -35
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +685 -70
- package/dist/core/agent.js.map +1 -1
- package/dist/core/fusion-agent.d.ts +207 -0
- package/dist/core/fusion-agent.d.ts.map +1 -0
- package/dist/core/fusion-agent.js +769 -0
- package/dist/core/fusion-agent.js.map +1 -0
- package/dist/core/hooks.d.ts +19 -7
- package/dist/core/hooks.d.ts.map +1 -1
- package/dist/core/plan-solve-agent.d.ts +1 -15
- package/dist/core/plan-solve-agent.d.ts.map +1 -1
- package/dist/core/plan-solve-agent.js +144 -117
- package/dist/core/plan-solve-agent.js.map +1 -1
- package/dist/core/react-agent.d.ts +0 -13
- package/dist/core/react-agent.d.ts.map +1 -1
- package/dist/core/react-agent.js +128 -101
- package/dist/core/react-agent.js.map +1 -1
- package/dist/core/response-schema.d.ts +65 -0
- package/dist/core/response-schema.d.ts.map +1 -1
- package/dist/core/response-schema.js +174 -1
- package/dist/core/response-schema.js.map +1 -1
- package/dist/core/system-prompts.d.ts +27 -0
- package/dist/core/system-prompts.d.ts.map +1 -0
- package/dist/core/system-prompts.js +112 -0
- package/dist/core/system-prompts.js.map +1 -0
- package/dist/eval/benchmark.d.ts +81 -0
- package/dist/eval/benchmark.d.ts.map +1 -0
- package/dist/eval/benchmark.js +292 -0
- package/dist/eval/benchmark.js.map +1 -0
- package/dist/eval/eval-runner.d.ts +79 -0
- package/dist/eval/eval-runner.d.ts.map +1 -0
- package/dist/eval/eval-runner.js +252 -0
- package/dist/eval/eval-runner.js.map +1 -0
- package/dist/eval/index.d.ts +7 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +13 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/eval/tool-call-evaluator.d.ts +72 -0
- package/dist/eval/tool-call-evaluator.d.ts.map +1 -0
- package/dist/eval/tool-call-evaluator.js +265 -0
- package/dist/eval/tool-call-evaluator.js.map +1 -0
- package/dist/eval/types.d.ts +219 -0
- package/dist/eval/types.d.ts.map +1 -0
- package/dist/eval/types.js +3 -0
- package/dist/eval/types.js.map +1 -0
- package/dist/index.d.ts +61 -14
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +121 -8
- package/dist/index.js.map +1 -1
- package/dist/llm/anthropic-provider.d.ts +141 -0
- package/dist/llm/anthropic-provider.d.ts.map +1 -0
- package/dist/llm/anthropic-provider.js +486 -0
- package/dist/llm/anthropic-provider.js.map +1 -0
- package/dist/llm/errors.d.ts +26 -0
- package/dist/llm/errors.d.ts.map +1 -0
- package/dist/llm/errors.js +19 -0
- package/dist/llm/errors.js.map +1 -0
- package/dist/llm/factory.d.ts +73 -0
- package/dist/llm/factory.d.ts.map +1 -0
- package/dist/llm/factory.js +77 -0
- package/dist/llm/factory.js.map +1 -0
- package/dist/llm/fallback-provider.d.ts +47 -0
- package/dist/llm/fallback-provider.d.ts.map +1 -0
- package/dist/llm/fallback-provider.js +91 -0
- package/dist/llm/fallback-provider.js.map +1 -0
- package/dist/llm/interface.d.ts +54 -11
- package/dist/llm/interface.d.ts.map +1 -1
- package/dist/llm/interface.js +34 -0
- package/dist/llm/interface.js.map +1 -1
- package/dist/llm/model-router.d.ts +126 -0
- package/dist/llm/model-router.d.ts.map +1 -0
- package/dist/llm/model-router.js +178 -0
- package/dist/llm/model-router.js.map +1 -0
- package/dist/llm/openai-provider.d.ts +8 -32
- package/dist/llm/openai-provider.d.ts.map +1 -1
- package/dist/llm/openai-provider.js +27 -60
- package/dist/llm/openai-provider.js.map +1 -1
- package/dist/llm/rate-limiter.d.ts +41 -0
- package/dist/llm/rate-limiter.d.ts.map +1 -0
- package/dist/llm/rate-limiter.js +93 -0
- package/dist/llm/rate-limiter.js.map +1 -0
- package/dist/llm/retry.d.ts +26 -0
- package/dist/llm/retry.d.ts.map +1 -0
- package/dist/llm/retry.js +44 -0
- package/dist/llm/retry.js.map +1 -0
- package/dist/llm/token-budget.d.ts +97 -0
- package/dist/llm/token-budget.d.ts.map +1 -0
- package/dist/llm/token-budget.js +115 -0
- package/dist/llm/token-budget.js.map +1 -0
- package/dist/logging/index.d.ts +2 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +7 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/logger.d.ts +38 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +34 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/mcp/index.d.ts +4 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/mcp-client-manager.d.ts +72 -0
- package/dist/mcp/mcp-client-manager.d.ts.map +1 -0
- package/dist/mcp/mcp-client-manager.js +235 -0
- package/dist/mcp/mcp-client-manager.js.map +1 -0
- package/dist/mcp/mcp-types.d.ts +58 -0
- package/dist/mcp/mcp-types.d.ts.map +1 -0
- package/dist/mcp/mcp-types.js +20 -0
- package/dist/mcp/mcp-types.js.map +1 -0
- package/dist/memory/index.d.ts +3 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +6 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/memory-manager.d.ts +119 -0
- package/dist/memory/memory-manager.d.ts.map +1 -0
- package/dist/memory/memory-manager.js +334 -0
- package/dist/memory/memory-manager.js.map +1 -0
- package/dist/messages/types.d.ts +2 -0
- package/dist/messages/types.d.ts.map +1 -1
- package/dist/orchestrator/index.d.ts +5 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/index.js +13 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/json-extractor.d.ts +18 -0
- package/dist/orchestrator/json-extractor.d.ts.map +1 -0
- package/dist/orchestrator/json-extractor.js +111 -0
- package/dist/orchestrator/json-extractor.js.map +1 -0
- package/dist/orchestrator/orchestrator-agent.d.ts +152 -0
- package/dist/orchestrator/orchestrator-agent.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator-agent.js +675 -0
- package/dist/orchestrator/orchestrator-agent.js.map +1 -0
- package/dist/orchestrator/orchestrator-response.d.ts +40 -0
- package/dist/orchestrator/orchestrator-response.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator-response.js +275 -0
- package/dist/orchestrator/orchestrator-response.js.map +1 -0
- package/dist/orchestrator/orchestrator-types.d.ts +116 -0
- package/dist/orchestrator/orchestrator-types.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator-types.js +3 -0
- package/dist/orchestrator/orchestrator-types.js.map +1 -0
- package/dist/preferences/preference-manager.d.ts +8 -3
- package/dist/preferences/preference-manager.d.ts.map +1 -1
- package/dist/preferences/preference-manager.js +17 -4
- package/dist/preferences/preference-manager.js.map +1 -1
- package/dist/rag/chroma-store.d.ts +52 -0
- package/dist/rag/chroma-store.d.ts.map +1 -0
- package/dist/rag/chroma-store.js +110 -0
- package/dist/rag/chroma-store.js.map +1 -0
- package/dist/rag/document-loader.d.ts +21 -0
- package/dist/rag/document-loader.d.ts.map +1 -0
- package/dist/rag/document-loader.js +129 -0
- package/dist/rag/document-loader.js.map +1 -0
- package/dist/rag/embedding-provider.d.ts +36 -0
- package/dist/rag/embedding-provider.d.ts.map +1 -0
- package/dist/rag/embedding-provider.js +74 -0
- package/dist/rag/embedding-provider.js.map +1 -0
- package/dist/rag/index.d.ts +17 -0
- package/dist/rag/index.d.ts.map +1 -0
- package/dist/rag/index.js +27 -0
- package/dist/rag/index.js.map +1 -0
- package/dist/rag/keyword-index.d.ts +53 -0
- package/dist/rag/keyword-index.d.ts.map +1 -0
- package/dist/rag/keyword-index.js +161 -0
- package/dist/rag/keyword-index.js.map +1 -0
- package/dist/rag/llm-reranker.d.ts +36 -0
- package/dist/rag/llm-reranker.d.ts.map +1 -0
- package/dist/rag/llm-reranker.js +95 -0
- package/dist/rag/llm-reranker.js.map +1 -0
- package/dist/rag/rag-manager.d.ts +54 -0
- package/dist/rag/rag-manager.d.ts.map +1 -0
- package/dist/rag/rag-manager.js +179 -0
- package/dist/rag/rag-manager.js.map +1 -0
- package/dist/rag/rag-types.d.ts +143 -0
- package/dist/rag/rag-types.d.ts.map +1 -0
- package/dist/rag/rag-types.js +9 -0
- package/dist/rag/rag-types.js.map +1 -0
- package/dist/rag/rrf.d.ts +47 -0
- package/dist/rag/rrf.d.ts.map +1 -0
- package/dist/rag/rrf.js +70 -0
- package/dist/rag/rrf.js.map +1 -0
- package/dist/rag/search-knowledge.d.ts +24 -0
- package/dist/rag/search-knowledge.d.ts.map +1 -0
- package/dist/rag/search-knowledge.js +86 -0
- package/dist/rag/search-knowledge.js.map +1 -0
- package/dist/rag/text-splitter.d.ts +25 -0
- package/dist/rag/text-splitter.d.ts.map +1 -0
- package/dist/rag/text-splitter.js +136 -0
- package/dist/rag/text-splitter.js.map +1 -0
- package/dist/rag/vector-store.d.ts +34 -0
- package/dist/rag/vector-store.d.ts.map +1 -0
- package/dist/rag/vector-store.js +73 -0
- package/dist/rag/vector-store.js.map +1 -0
- package/dist/reflection/error-notebook.d.ts +125 -0
- package/dist/reflection/error-notebook.d.ts.map +1 -0
- package/dist/reflection/error-notebook.js +368 -0
- package/dist/reflection/error-notebook.js.map +1 -0
- package/dist/reflection/index.d.ts +8 -0
- package/dist/reflection/index.d.ts.map +1 -0
- package/dist/reflection/index.js +12 -0
- package/dist/reflection/index.js.map +1 -0
- package/dist/reflection/memory-reflector.d.ts +97 -0
- package/dist/reflection/memory-reflector.d.ts.map +1 -0
- package/dist/reflection/memory-reflector.js +215 -0
- package/dist/reflection/memory-reflector.js.map +1 -0
- package/dist/reflection/reflection-agent.d.ts +105 -0
- package/dist/reflection/reflection-agent.d.ts.map +1 -0
- package/dist/reflection/reflection-agent.js +234 -0
- package/dist/reflection/reflection-agent.js.map +1 -0
- package/dist/reflection/reflection-hook.d.ts +50 -0
- package/dist/reflection/reflection-hook.d.ts.map +1 -0
- package/dist/reflection/reflection-hook.js +108 -0
- package/dist/reflection/reflection-hook.js.map +1 -0
- package/dist/rules/project-rules.d.ts +47 -0
- package/dist/rules/project-rules.d.ts.map +1 -0
- package/dist/rules/project-rules.js +166 -0
- package/dist/rules/project-rules.js.map +1 -0
- package/dist/security/boundaries.d.ts +81 -0
- package/dist/security/boundaries.d.ts.map +1 -0
- package/dist/security/boundaries.js +158 -0
- package/dist/security/boundaries.js.map +1 -0
- package/dist/security/index.d.ts +2 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/index.js +11 -0
- package/dist/security/index.js.map +1 -0
- package/dist/session/session-types.d.ts +25 -4
- package/dist/session/session-types.d.ts.map +1 -1
- package/dist/skills/file-skill-loader.d.ts +9 -20
- package/dist/skills/file-skill-loader.d.ts.map +1 -1
- package/dist/skills/file-skill-loader.js +35 -164
- package/dist/skills/file-skill-loader.js.map +1 -1
- package/dist/skills/index.d.ts +1 -1
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +1 -2
- package/dist/skills/index.js.map +1 -1
- package/dist/skills/skill-manager.d.ts +22 -29
- package/dist/skills/skill-manager.d.ts.map +1 -1
- package/dist/skills/skill-manager.js +63 -85
- package/dist/skills/skill-manager.js.map +1 -1
- package/dist/skills/types.d.ts +4 -16
- package/dist/skills/types.d.ts.map +1 -1
- package/dist/subagent/index.d.ts +4 -0
- package/dist/subagent/index.d.ts.map +1 -0
- package/dist/subagent/index.js +8 -0
- package/dist/subagent/index.js.map +1 -0
- package/dist/subagent/subagent-loader.d.ts +53 -0
- package/dist/subagent/subagent-loader.d.ts.map +1 -0
- package/dist/subagent/subagent-loader.js +155 -0
- package/dist/subagent/subagent-loader.js.map +1 -0
- package/dist/subagent/subagent-manager.d.ts +161 -0
- package/dist/subagent/subagent-manager.d.ts.map +1 -0
- package/dist/subagent/subagent-manager.js +468 -0
- package/dist/subagent/subagent-manager.js.map +1 -0
- package/dist/subagent/subagent-types.d.ts +77 -0
- package/dist/subagent/subagent-types.d.ts.map +1 -0
- package/dist/subagent/subagent-types.js +3 -0
- package/dist/subagent/subagent-types.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +3 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +87 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/edit-file.d.ts.map +1 -1
- package/dist/tools/builtin/edit-file.js +1 -0
- package/dist/tools/builtin/edit-file.js.map +1 -1
- package/dist/tools/builtin/index.d.ts +14 -0
- package/dist/tools/builtin/index.d.ts.map +1 -1
- package/dist/tools/builtin/index.js +45 -1
- package/dist/tools/builtin/index.js.map +1 -1
- package/dist/tools/builtin/list-errors.d.ts +7 -0
- package/dist/tools/builtin/list-errors.d.ts.map +1 -0
- package/dist/tools/builtin/list-errors.js +64 -0
- package/dist/tools/builtin/list-errors.js.map +1 -0
- package/dist/tools/builtin/list-subagents.d.ts +7 -0
- package/dist/tools/builtin/list-subagents.d.ts.map +1 -0
- package/dist/tools/builtin/list-subagents.js +21 -0
- package/dist/tools/builtin/list-subagents.js.map +1 -0
- package/dist/tools/builtin/recall.d.ts +11 -0
- package/dist/tools/builtin/recall.d.ts.map +1 -0
- package/dist/tools/builtin/recall.js +60 -0
- package/dist/tools/builtin/recall.js.map +1 -0
- package/dist/tools/builtin/remember.d.ts +12 -0
- package/dist/tools/builtin/remember.d.ts.map +1 -0
- package/dist/tools/builtin/remember.js +72 -0
- package/dist/tools/builtin/remember.js.map +1 -0
- package/dist/tools/builtin/skill.d.ts +14 -0
- package/dist/tools/builtin/skill.d.ts.map +1 -0
- package/dist/tools/builtin/skill.js +71 -0
- package/dist/tools/builtin/skill.js.map +1 -0
- package/dist/tools/builtin/spawn-subagent.d.ts +7 -0
- package/dist/tools/builtin/spawn-subagent.d.ts.map +1 -0
- package/dist/tools/builtin/spawn-subagent.js +43 -0
- package/dist/tools/builtin/spawn-subagent.js.map +1 -0
- package/dist/tools/builtin/web-fetch.d.ts +3 -0
- package/dist/tools/builtin/web-fetch.d.ts.map +1 -0
- package/dist/tools/builtin/web-fetch.js +101 -0
- package/dist/tools/builtin/web-fetch.js.map +1 -0
- package/dist/tools/builtin/write-file.d.ts.map +1 -1
- package/dist/tools/builtin/write-file.js +1 -0
- package/dist/tools/builtin/write-file.js.map +1 -1
- package/dist/tools/circuit-breaker.d.ts +19 -10
- package/dist/tools/circuit-breaker.d.ts.map +1 -1
- package/dist/tools/circuit-breaker.js +22 -11
- package/dist/tools/circuit-breaker.js.map +1 -1
- package/dist/tools/error-tracker.d.ts +28 -44
- package/dist/tools/error-tracker.d.ts.map +1 -1
- package/dist/tools/error-tracker.js +39 -156
- package/dist/tools/error-tracker.js.map +1 -1
- package/dist/tools/tool-filter.d.ts +70 -0
- package/dist/tools/tool-filter.d.ts.map +1 -0
- package/dist/tools/tool-filter.js +92 -0
- package/dist/tools/tool-filter.js.map +1 -0
- package/dist/tools/tool-output-truncator.d.ts +36 -0
- package/dist/tools/tool-output-truncator.d.ts.map +1 -0
- package/dist/tools/tool-output-truncator.js +117 -0
- package/dist/tools/tool-output-truncator.js.map +1 -0
- package/dist/tools/tool-registry.d.ts +25 -9
- package/dist/tools/tool-registry.d.ts.map +1 -1
- package/dist/tools/tool-registry.js +77 -28
- package/dist/tools/tool-registry.js.map +1 -1
- package/dist/tools/tool-validator.d.ts +13 -0
- package/dist/tools/tool-validator.d.ts.map +1 -0
- package/dist/tools/tool-validator.js +116 -0
- package/dist/tools/tool-validator.js.map +1 -0
- package/dist/tools/types.d.ts +86 -3
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +51 -2
- package/dist/tools/types.js.map +1 -1
- package/dist/trace/trace-logger.d.ts +30 -4
- package/dist/trace/trace-logger.d.ts.map +1 -1
- package/dist/trace/trace-logger.js +83 -7
- package/dist/trace/trace-logger.js.map +1 -1
- package/package.json +14 -4
- package/dist/compression/sliding-window.d.ts +0 -21
- package/dist/compression/sliding-window.d.ts.map +0 -1
- package/dist/compression/sliding-window.js +0 -44
- package/dist/compression/sliding-window.js.map +0 -1
package/dist/core/agent.js
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Agent = void 0;
|
|
4
|
+
const model_router_1 = require("../llm/model-router");
|
|
5
|
+
const message_1 = require("../messages/message");
|
|
6
|
+
const system_prompts_1 = require("./system-prompts");
|
|
7
|
+
const boundaries_1 = require("../security/boundaries");
|
|
4
8
|
const context_manager_1 = require("../context/context-manager");
|
|
5
9
|
const tool_registry_1 = require("../tools/tool-registry");
|
|
10
|
+
const tool_output_truncator_1 = require("../tools/tool-output-truncator");
|
|
11
|
+
const types_1 = require("../tools/types");
|
|
12
|
+
const tool_validator_1 = require("../tools/tool-validator");
|
|
6
13
|
const skill_manager_1 = require("../skills/skill-manager");
|
|
14
|
+
const memory_manager_1 = require("../memory/memory-manager");
|
|
15
|
+
const project_rules_1 = require("../rules/project-rules");
|
|
7
16
|
const session_manager_1 = require("../session/session-manager");
|
|
17
|
+
const token_counter_1 = require("../utils/token-counter");
|
|
8
18
|
const preference_manager_1 = require("../preferences/preference-manager");
|
|
19
|
+
const mcp_client_manager_1 = require("../mcp/mcp-client-manager");
|
|
20
|
+
const subagent_manager_1 = require("../subagent/subagent-manager");
|
|
21
|
+
const rag_manager_1 = require("../rag/rag-manager");
|
|
22
|
+
const search_knowledge_1 = require("../rag/search-knowledge");
|
|
23
|
+
const list_subagents_1 = require("../tools/builtin/list-subagents");
|
|
24
|
+
const spawn_subagent_1 = require("../tools/builtin/spawn-subagent");
|
|
25
|
+
const list_errors_1 = require("../tools/builtin/list-errors");
|
|
26
|
+
const skill_1 = require("../tools/builtin/skill");
|
|
27
|
+
const remember_1 = require("../tools/builtin/remember");
|
|
28
|
+
const recall_1 = require("../tools/builtin/recall");
|
|
29
|
+
const builtin_1 = require("../tools/builtin");
|
|
30
|
+
const logger_1 = require("../logging/logger");
|
|
31
|
+
const token_budget_1 = require("../llm/token-budget");
|
|
9
32
|
/**
|
|
10
33
|
* Abstract base Agent class.
|
|
11
34
|
*
|
|
@@ -25,6 +48,10 @@ class Agent {
|
|
|
25
48
|
contextManager;
|
|
26
49
|
toolRegistry;
|
|
27
50
|
skillManager;
|
|
51
|
+
/** Long-term memory (rules + project facts) persisted across sessions. */
|
|
52
|
+
memoryManager;
|
|
53
|
+
/** User-defined project rules loaded from disk. */
|
|
54
|
+
projectRules;
|
|
28
55
|
/** The original core system prompt (before skill sections are appended). */
|
|
29
56
|
coreSystemPrompt;
|
|
30
57
|
/** User preferences — plain-text directives injected into the system prompt. */
|
|
@@ -33,10 +60,14 @@ class Agent {
|
|
|
33
60
|
preferenceManager;
|
|
34
61
|
/** Lifecycle hooks for observing agent execution. */
|
|
35
62
|
hooks = [];
|
|
36
|
-
/**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
63
|
+
/** Logger for framework-internal messages. */
|
|
64
|
+
logger;
|
|
65
|
+
/** Token budget for session-level cost control (optional). */
|
|
66
|
+
tokenBudget;
|
|
67
|
+
/** Human-in-the-loop approval callback (from AgentConfig). */
|
|
68
|
+
onToolApproval;
|
|
69
|
+
/** Whether to execute independent tool calls in parallel (default: true). */
|
|
70
|
+
enableParallelToolExecution;
|
|
40
71
|
// ─── Session & Cancellation ─────────────────────────────────────────
|
|
41
72
|
/** Session manager for checkpoint persistence (optional). */
|
|
42
73
|
sessionManager;
|
|
@@ -44,36 +75,64 @@ class Agent {
|
|
|
44
75
|
checkpointingEnabled = false;
|
|
45
76
|
/** Whether the current run has been cancelled by the user. */
|
|
46
77
|
_cancelled = false;
|
|
78
|
+
/** Controller for aborting in-flight LLM requests on cancellation. */
|
|
79
|
+
_abortController;
|
|
80
|
+
// ─── MCP (Model Context Protocol) ─────────────────────────────────────
|
|
81
|
+
/** MCP server configurations (from AgentConfig). */
|
|
82
|
+
mcpServerConfigs;
|
|
83
|
+
/** MCP client manager for dynamic tool discovery (lazily initialized). */
|
|
84
|
+
mcpClientManager;
|
|
85
|
+
/** Guards async init() from running more than once per instance. */
|
|
86
|
+
_mcpInitialized = false;
|
|
87
|
+
// ─── RAG ────────────────────────────────────────────────────────────────
|
|
88
|
+
/** RAG manager (lazily initialized in init()). */
|
|
89
|
+
ragManager;
|
|
90
|
+
/** RAG configuration (from AgentConfig). */
|
|
91
|
+
ragConfig;
|
|
92
|
+
// ─── Sub-Agent ────────────────────────────────────────────────────────
|
|
93
|
+
/** Sub-agent manager (lazily initialized in init()). */
|
|
94
|
+
subAgentManager;
|
|
95
|
+
/** Sub-agent definitions directory (from AgentConfig). */
|
|
96
|
+
subAgentsDir;
|
|
97
|
+
/** LLM provider for sub-agents (defaults to main llm if not set). */
|
|
98
|
+
subAgentLLM;
|
|
99
|
+
/** Skills directory path (from AgentConfig). */
|
|
100
|
+
skillsDir;
|
|
47
101
|
constructor(config) {
|
|
48
102
|
this._cancelled = false;
|
|
49
103
|
this.llm = config.llm;
|
|
50
|
-
this.
|
|
104
|
+
this.logger = config.logger ?? new logger_1.ConsoleLogger();
|
|
105
|
+
this.onToolApproval = config.onToolApproval;
|
|
106
|
+
this.enableParallelToolExecution = config.enableParallelToolExecution ?? true;
|
|
107
|
+
this.contextManager = config.contextManager ?? new context_manager_1.ContextManager(undefined, this.logger);
|
|
51
108
|
// Prefer toolRegistry; fall back to plain tools array
|
|
52
109
|
if (config.toolRegistry) {
|
|
53
110
|
this.toolRegistry = config.toolRegistry;
|
|
54
111
|
}
|
|
55
112
|
else {
|
|
56
|
-
|
|
113
|
+
const truncator = (config.toolOutputMaxBytes && config.toolOutputMaxBytes > 0)
|
|
114
|
+
? new tool_output_truncator_1.ToolOutputTruncator(config.toolOutputMaxBytes)
|
|
115
|
+
: undefined;
|
|
116
|
+
this.toolRegistry = new tool_registry_1.ToolRegistry(config.toolRetryCount, config.toolErrorTracker, truncator);
|
|
57
117
|
if (config.tools && config.tools.length > 0) {
|
|
58
118
|
this.toolRegistry.registerMany(config.tools);
|
|
59
119
|
}
|
|
60
120
|
}
|
|
61
|
-
// Skill manager —
|
|
121
|
+
// Skill manager — file-based progressive disclosure
|
|
62
122
|
if (config.skillManager) {
|
|
63
123
|
this.skillManager = config.skillManager;
|
|
64
124
|
}
|
|
65
125
|
else {
|
|
66
|
-
this.skillManager = new skill_manager_1.SkillManager();
|
|
67
|
-
}
|
|
68
|
-
this.skillManager.bindToolRegistry(this.toolRegistry);
|
|
69
|
-
// Register any skills passed directly
|
|
70
|
-
if (config.skills && config.skills.length > 0) {
|
|
71
|
-
this.skillManager.register(...config.skills);
|
|
126
|
+
this.skillManager = new skill_manager_1.SkillManager(this.logger);
|
|
72
127
|
}
|
|
73
128
|
// Register file-based skills if a directory is configured
|
|
74
129
|
if (config.skillsDir) {
|
|
75
130
|
this.skillManager.registerFromDirectory(config.skillsDir);
|
|
76
131
|
}
|
|
132
|
+
// Memory — long-term facts, rules, and project context
|
|
133
|
+
this.memoryManager = new memory_manager_1.MemoryManager(config.memoryDir);
|
|
134
|
+
// Project rules — user-authored, always injected
|
|
135
|
+
this.projectRules = new project_rules_1.ProjectRules(config.rulesPath);
|
|
77
136
|
// Store core system prompt and set it
|
|
78
137
|
this.coreSystemPrompt = config.systemPrompt ?? "";
|
|
79
138
|
if (this.coreSystemPrompt) {
|
|
@@ -87,6 +146,24 @@ class Agent {
|
|
|
87
146
|
});
|
|
88
147
|
}
|
|
89
148
|
this.checkpointingEnabled = config.enableCheckpointing ?? false;
|
|
149
|
+
this.mcpServerConfigs = config.mcpServers;
|
|
150
|
+
this.subAgentsDir = config.subAgentsDir;
|
|
151
|
+
this.skillsDir = config.skillsDir;
|
|
152
|
+
this.ragConfig = config.rag;
|
|
153
|
+
// Resolve sub-agent LLM:
|
|
154
|
+
// 1. Explicit `subAgentLLM` → use it directly
|
|
155
|
+
// 2. `llm` is a ModelRouter → use router.forSubAgent()
|
|
156
|
+
// 3. Fallback → sub-agents share the main `llm`
|
|
157
|
+
if (config.subAgentLLM) {
|
|
158
|
+
this.subAgentLLM = config.subAgentLLM;
|
|
159
|
+
}
|
|
160
|
+
else if (config.llm instanceof model_router_1.ModelRouter) {
|
|
161
|
+
this.subAgentLLM = config.llm.forSubAgent();
|
|
162
|
+
}
|
|
163
|
+
// Token budget — session-level cost control
|
|
164
|
+
if (config.tokenBudgetConfig) {
|
|
165
|
+
this.tokenBudget = new token_budget_1.TokenBudget(config.tokenBudgetConfig);
|
|
166
|
+
}
|
|
90
167
|
// ── Hooks ──────────────────────────────────────────────────────────────
|
|
91
168
|
const rawHooks = config.hooks ?? [];
|
|
92
169
|
this.hooks = Array.isArray(rawHooks) ? rawHooks : [rawHooks];
|
|
@@ -118,12 +195,6 @@ class Agent {
|
|
|
118
195
|
return this.toolRegistry;
|
|
119
196
|
}
|
|
120
197
|
// ─── Skill Management ────────────────────────────────────────────────
|
|
121
|
-
/**
|
|
122
|
-
* Add skills to the agent's SkillManager.
|
|
123
|
-
*/
|
|
124
|
-
addSkill(...skills) {
|
|
125
|
-
this.skillManager.register(...skills);
|
|
126
|
-
}
|
|
127
198
|
/**
|
|
128
199
|
* Get the SkillManager (for advanced management).
|
|
129
200
|
*/
|
|
@@ -160,42 +231,372 @@ class Agent {
|
|
|
160
231
|
this.hooks.push(hook);
|
|
161
232
|
}
|
|
162
233
|
/**
|
|
163
|
-
* Rebuild the system message
|
|
164
|
-
*
|
|
234
|
+
* Rebuild the system message.
|
|
235
|
+
*
|
|
236
|
+
* Sections are assembled in priority order:
|
|
237
|
+
* 1. Core prompt (agent identity + instructions)
|
|
238
|
+
* 2. Project rules (user-authored, always injected)
|
|
239
|
+
* 3. Preferences (user-set language / verbosity / style)
|
|
240
|
+
* 4. Error recovery rules (tool failure recovery guidance)
|
|
241
|
+
* 5. Long-term memories (index of persisted facts + rules)
|
|
242
|
+
* 6. Available skills (inactive skills the LLM can activate)
|
|
243
|
+
* 7. Active skill content (full instructions for activated skills)
|
|
244
|
+
*
|
|
245
|
+
* Empty sections are silently skipped.
|
|
165
246
|
*/
|
|
247
|
+
/**
|
|
248
|
+
* Build the full system prompt from all sections.
|
|
249
|
+
*
|
|
250
|
+
* Subclasses that need to append extra content (e.g. plan progress)
|
|
251
|
+
* should call this and concatenate, instead of duplicating the assembly.
|
|
252
|
+
*/
|
|
253
|
+
buildSystemPrompt() {
|
|
254
|
+
const sections = [
|
|
255
|
+
this.coreSystemPrompt,
|
|
256
|
+
system_prompts_1.SECURITY_GUIDANCE,
|
|
257
|
+
this.hasSubAgents() ? system_prompts_1.SUB_AGENT_DELEGATION : "",
|
|
258
|
+
this.projectRules.buildPrompt(),
|
|
259
|
+
preference_manager_1.PreferenceManager.toPrompt(this.preferences),
|
|
260
|
+
this.memoryManager.buildPromptHint(),
|
|
261
|
+
this.skillManager.buildAvailableSkillsHint(),
|
|
262
|
+
this.skillManager.buildSkillsPrompt(),
|
|
263
|
+
].filter(Boolean);
|
|
264
|
+
return sections.join("");
|
|
265
|
+
}
|
|
166
266
|
rebuildSystemPrompt() {
|
|
167
|
-
|
|
168
|
-
const skillsHint = this.skillManager.buildAvailableSkillsHint();
|
|
169
|
-
const skillsContent = this.skillManager.buildSkillsPrompt();
|
|
170
|
-
const fullPrompt = this.coreSystemPrompt + prefsPrompt + skillsHint + skillsContent;
|
|
171
|
-
this.contextManager.setSystemMessage(fullPrompt);
|
|
267
|
+
this.contextManager.setSystemMessage(this.buildSystemPrompt());
|
|
172
268
|
}
|
|
173
269
|
/**
|
|
174
|
-
* Pre-iteration maintenance:
|
|
175
|
-
* 1. Compress context window if needed.
|
|
176
|
-
* 2. Auto-reload preferences from disk if the file was manually edited.
|
|
270
|
+
* Pre-iteration maintenance: compress context window if needed.
|
|
177
271
|
*/
|
|
178
|
-
checkAndCompress() {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
272
|
+
async checkAndCompress() {
|
|
273
|
+
await this.contextManager.checkAndCompress(this.llm);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Reload preferences from disk if the file was manually edited.
|
|
277
|
+
* Called once at the start of each run so edits between runs take
|
|
278
|
+
* effect without restarting the agent process — but they won't
|
|
279
|
+
* change mid-run behavior.
|
|
280
|
+
*/
|
|
281
|
+
reloadPreferencesIfChanged() {
|
|
184
282
|
if (this.preferenceManager?.hasFileChanged()) {
|
|
185
283
|
this.preferences = this.preferenceManager.reload();
|
|
186
284
|
this.rebuildSystemPrompt();
|
|
187
|
-
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Re-scan the skills directory for new SKILL.md files added between runs.
|
|
291
|
+
* New skills are registered and become available to the LLM immediately.
|
|
292
|
+
*/
|
|
293
|
+
reloadSkillsFromDirectory() {
|
|
294
|
+
if (!this.skillsDir)
|
|
295
|
+
return false;
|
|
296
|
+
const added = this.skillManager.reloadFromDirectory(this.skillsDir);
|
|
297
|
+
if (added.length > 0) {
|
|
298
|
+
this.rebuildSystemPrompt();
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
return false;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Re-read the MEMORY.md index from disk if it was manually edited
|
|
305
|
+
* between runs. The index is a lightweight list of memory names +
|
|
306
|
+
* descriptions — full content is loaded on demand via the recall tool.
|
|
307
|
+
*/
|
|
308
|
+
reloadMemoryIfChanged() {
|
|
309
|
+
if (this.memoryManager.reloadIfChanged()) {
|
|
310
|
+
this.rebuildSystemPrompt();
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Incrementally connect to MCP servers that were added to the config
|
|
317
|
+
* since the last run. Already-connected servers are left untouched.
|
|
318
|
+
*/
|
|
319
|
+
async reconnectMCPIfNeeded() {
|
|
320
|
+
if (!this.mcpClientManager || !this.mcpServerConfigs)
|
|
321
|
+
return;
|
|
322
|
+
const newServers = {};
|
|
323
|
+
for (const [name, config] of Object.entries(this.mcpServerConfigs)) {
|
|
324
|
+
if (!this.mcpClientManager.hasServer(name)) {
|
|
325
|
+
newServers[name] = config;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
if (Object.keys(newServers).length === 0)
|
|
329
|
+
return;
|
|
330
|
+
const errors = await this.mcpClientManager.connectAll(newServers);
|
|
331
|
+
if (errors.length > 0) {
|
|
332
|
+
this.logger.warn("MCP", `${errors.length} new server(s) failed to connect: ` +
|
|
333
|
+
errors.map((e) => e.serverName).join(", "));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Reload all dynamic resources at the start of a run.
|
|
338
|
+
* Picks up changes made between conversation turns.
|
|
339
|
+
*/
|
|
340
|
+
async reloadDynamicResources() {
|
|
341
|
+
this.reloadPreferencesIfChanged(); // rebuilds internally if changed
|
|
342
|
+
const rulesChanged = this.projectRules.reloadIfChanged();
|
|
343
|
+
this.reloadSkillsFromDirectory(); // rebuilds internally if changed
|
|
344
|
+
this.reloadMemoryIfChanged(); // rebuilds internally if changed
|
|
345
|
+
if (rulesChanged) {
|
|
346
|
+
this.rebuildSystemPrompt();
|
|
347
|
+
}
|
|
348
|
+
await this.reconnectMCPIfNeeded();
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* After a resume, recover results from sub-agents that were cancelled
|
|
352
|
+
* mid-run. Completed results are injected into context so the LLM can
|
|
353
|
+
* see them; still-running sub-agents get a notice.
|
|
354
|
+
*/
|
|
355
|
+
recoverOrphanedSubAgentResults() {
|
|
356
|
+
if (!this.subAgentManager)
|
|
357
|
+
return;
|
|
358
|
+
const orphaned = this.subAgentManager.collectOrphanedResults();
|
|
359
|
+
for (const r of orphaned) {
|
|
360
|
+
const msg = message_1.Message.user(`[Sub-agent "${r.name}" (${r.subAgentId}) — recovered after interruption]\n\n${r.output}`);
|
|
361
|
+
this.contextManager.addMessage(msg.toDict());
|
|
362
|
+
}
|
|
363
|
+
// If some cancelled sub-agents are still running, let the LLM know
|
|
364
|
+
const stillRunning = this.subAgentManager.getActiveCount();
|
|
365
|
+
if (stillRunning > 0) {
|
|
366
|
+
const msg = message_1.Message.user(`[System] ${stillRunning} sub-agent(s) from the previous session are still running. ` +
|
|
367
|
+
`Their results will appear when ready. Do not re-spawn them.`);
|
|
368
|
+
this.contextManager.addMessage(msg.toDict());
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Validate that user input won't overwhelm the context window.
|
|
373
|
+
*
|
|
374
|
+
* Returns a user-facing error string if the input is too large,
|
|
375
|
+
* or `null` if it passes the check.
|
|
376
|
+
*/
|
|
377
|
+
validateInputSize(input) {
|
|
378
|
+
const { maxTokens } = this.contextManager.getState();
|
|
379
|
+
const inputTokens = (0, token_counter_1.countTokens)(input);
|
|
380
|
+
// Reserve ~20% for system prompt + tools + response overhead
|
|
381
|
+
const maxSafeInput = Math.floor(maxTokens * 0.8);
|
|
382
|
+
if (inputTokens > maxSafeInput) {
|
|
383
|
+
return (`Your input is too large (~${inputTokens} tokens). ` +
|
|
384
|
+
`The maximum safe input size is ~${maxSafeInput} tokens ` +
|
|
385
|
+
`(context window: ${maxTokens} tokens, with 20% reserved for system overhead). ` +
|
|
386
|
+
`Please split your request into smaller parts.`);
|
|
387
|
+
}
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Check whether a tool that requires approval should be executed.
|
|
392
|
+
*
|
|
393
|
+
* @returns `true` if approved, `false` if denied (or no callback configured).
|
|
394
|
+
*/
|
|
395
|
+
async checkToolApproval(toolName, args) {
|
|
396
|
+
if (!this.onToolApproval) {
|
|
397
|
+
this.logger.warn("Approval", `Tool "${toolName}" requires approval but no onToolApproval configured — denied.`);
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
try {
|
|
401
|
+
return await this.onToolApproval(toolName, args);
|
|
402
|
+
}
|
|
403
|
+
catch {
|
|
404
|
+
this.logger.warn("Approval", `Approval callback threw for "${toolName}" — denied.`);
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Execute a batch of tool calls from a single LLM response.
|
|
410
|
+
*
|
|
411
|
+
* When `enableParallelToolExecution` is true and all tools in the batch are
|
|
412
|
+
* parallel-safe (`sequential` is not set), tools execute concurrently via
|
|
413
|
+
* `Promise.allSettled`. Otherwise, they execute one at a time (serial).
|
|
414
|
+
*
|
|
415
|
+
* Handles the full lifecycle for each tool call:
|
|
416
|
+
* 1. Parse JSON arguments (malformed args → error result, no execution)
|
|
417
|
+
* 2. HITL approval check for tools marked `requireApproval`
|
|
418
|
+
* 3. Hook notifications (`onToolStart`, `onToolEnd`, `onToolError`)
|
|
419
|
+
* 4. Execution via `ToolRegistry.execute()`
|
|
420
|
+
* 5. Context injection (all results added after execution completes)
|
|
421
|
+
* 6. Post-execution: sub-agent spawn tracking, MCP failure warnings
|
|
422
|
+
*
|
|
423
|
+
* @param toolCalls The tool calls from the LLM response.
|
|
424
|
+
* @param mcpWarnedServers Set tracking which MCP servers have already
|
|
425
|
+
* been warned about in this batch.
|
|
426
|
+
* @returns Whether any tool in the batch failed.
|
|
427
|
+
*/
|
|
428
|
+
async executeToolCallsBatch(toolCalls, mcpWarnedServers) {
|
|
429
|
+
// ── Step 1: Parse & validate all arguments up front ──────────────
|
|
430
|
+
const slots = [];
|
|
431
|
+
for (const tc of toolCalls) {
|
|
432
|
+
// 1a. JSON syntax check
|
|
433
|
+
let args;
|
|
434
|
+
try {
|
|
435
|
+
args = JSON.parse(tc.function.arguments);
|
|
436
|
+
}
|
|
437
|
+
catch {
|
|
438
|
+
const result = (0, types_1.toolError)(types_1.ToolErrorCode.ARGUMENTS_PARSE_ERROR, `[RETRYABLE:ARGUMENTS_PARSE_ERROR] Failed to parse arguments for tool "${tc.function.name}". ` +
|
|
439
|
+
`The raw arguments were: ${tc.function.arguments || "(empty)"}\n\n` +
|
|
440
|
+
`Please re-invoke the tool with correctly formatted JSON arguments.`, "retryable");
|
|
441
|
+
for (const h of this.hooks)
|
|
442
|
+
h.onToolError?.(tc.function.name, result.content, tc.id);
|
|
443
|
+
slots.push({ toolCall: tc, args: {}, result });
|
|
444
|
+
continue;
|
|
445
|
+
}
|
|
446
|
+
// 1b. JSON Schema validation against the tool's parameter definition
|
|
447
|
+
const tool = this.toolRegistry.getTool(tc.function.name);
|
|
448
|
+
if (tool) {
|
|
449
|
+
const validationError = (0, tool_validator_1.validateToolArgs)(tc.function.name, tool.parameters, args);
|
|
450
|
+
if (validationError) {
|
|
451
|
+
for (const h of this.hooks)
|
|
452
|
+
h.onToolError?.(tc.function.name, validationError.content, tc.id);
|
|
453
|
+
slots.push({ toolCall: tc, args, result: validationError });
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
slots.push({ toolCall: tc, args });
|
|
458
|
+
}
|
|
459
|
+
// ── Step 2: HITL approval — check all requiring tools upfront ────
|
|
460
|
+
for (const slot of slots) {
|
|
461
|
+
if (slot.result)
|
|
462
|
+
continue; // already failed at parse stage
|
|
463
|
+
const tool = this.toolRegistry.getTool(slot.toolCall.function.name);
|
|
464
|
+
if (tool?.requireApproval) {
|
|
465
|
+
const approved = await this.checkToolApproval(slot.toolCall.function.name, slot.args);
|
|
466
|
+
if (!approved) {
|
|
467
|
+
slot.result = (0, types_1.toolError)(types_1.ToolErrorCode.APPROVAL_DENIED, `[FATAL:APPROVAL_DENIED] Tool "${slot.toolCall.function.name}" requires approval and was denied. ` +
|
|
468
|
+
`Do NOT retry this tool. Find a different approach.`, "fatal");
|
|
469
|
+
for (const h of this.hooks)
|
|
470
|
+
h.onToolError?.(slot.toolCall.function.name, slot.result.content, slot.toolCall.id);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
// ── Step 3: Decide serial vs parallel ──────────────────────────────
|
|
475
|
+
const executable = slots.filter((s) => !s.result);
|
|
476
|
+
const allParallelSafe = executable.every((s) => {
|
|
477
|
+
const tool = this.toolRegistry.getTool(s.toolCall.function.name);
|
|
478
|
+
return !tool?.sequential;
|
|
479
|
+
});
|
|
480
|
+
const shouldParallelize = this.enableParallelToolExecution &&
|
|
481
|
+
allParallelSafe &&
|
|
482
|
+
executable.length > 1;
|
|
483
|
+
// ── Step 4: Execute ────────────────────────────────────────────────
|
|
484
|
+
if (shouldParallelize) {
|
|
485
|
+
// Fire onToolStart for all executable tools before concurrent execution
|
|
486
|
+
for (const slot of executable) {
|
|
487
|
+
for (const h of this.hooks)
|
|
488
|
+
h.onToolStart?.(slot.toolCall.function.name, slot.args, slot.toolCall.id);
|
|
489
|
+
}
|
|
490
|
+
// Execute all in parallel.
|
|
491
|
+
// Each task fires its own onToolEnd / onToolError hooks so the
|
|
492
|
+
// TraceLogger (and other hook consumers) see events in actual
|
|
493
|
+
// completion order rather than array order.
|
|
494
|
+
await Promise.allSettled(executable.map(async (slot) => {
|
|
495
|
+
const result = await this.toolRegistry.execute(slot.toolCall.function.name, slot.args);
|
|
496
|
+
slot.result = result;
|
|
497
|
+
if (result.success) {
|
|
498
|
+
for (const h of this.hooks)
|
|
499
|
+
h.onToolEnd?.(slot.toolCall.function.name, result.content, slot.toolCall.id);
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
for (const h of this.hooks)
|
|
503
|
+
h.onToolError?.(slot.toolCall.function.name, result.content, slot.toolCall.id);
|
|
504
|
+
}
|
|
505
|
+
}));
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
// Serial path (legacy behaviour or forced by sequential tools)
|
|
509
|
+
for (const slot of executable) {
|
|
510
|
+
for (const h of this.hooks)
|
|
511
|
+
h.onToolStart?.(slot.toolCall.function.name, slot.args, slot.toolCall.id);
|
|
512
|
+
slot.result = await this.toolRegistry.execute(slot.toolCall.function.name, slot.args);
|
|
513
|
+
if (slot.result.success) {
|
|
514
|
+
for (const h of this.hooks)
|
|
515
|
+
h.onToolEnd?.(slot.toolCall.function.name, slot.result.content, slot.toolCall.id);
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
for (const h of this.hooks)
|
|
519
|
+
h.onToolError?.(slot.toolCall.function.name, slot.result.content, slot.toolCall.id);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
// ── Step 5: Inject results into context & post-process ─────────────
|
|
524
|
+
let hadFailure = false;
|
|
525
|
+
for (const slot of slots) {
|
|
526
|
+
const result = slot.result;
|
|
527
|
+
const toolName = slot.toolCall.function.name;
|
|
528
|
+
const toolMessage = message_1.Message.tool((0, boundaries_1.wrapAndScan)(`tool:${toolName}`, result.content), slot.toolCall.id, toolName);
|
|
529
|
+
this.contextManager.addMessage(toolMessage.toDict());
|
|
530
|
+
if (!result.success) {
|
|
531
|
+
hadFailure = true;
|
|
532
|
+
}
|
|
533
|
+
// Sub-agent spawned — purely informational; results arrive
|
|
534
|
+
// asynchronously and will be injected via pollSubAgentResults().
|
|
535
|
+
if (result.success && slot.toolCall.function.name === "spawn_subagent") {
|
|
536
|
+
this.logger.info("SubAgent", `Spawned "${slot.args.name ?? "unknown"}" — ` +
|
|
537
|
+
`result will arrive in a later iteration.`);
|
|
538
|
+
}
|
|
539
|
+
// MCP tool failure — warn about potential connection loss.
|
|
540
|
+
// Only warn once per server per batch to avoid duplicate messages.
|
|
541
|
+
if (!result.success &&
|
|
542
|
+
!builtin_1.BUILTIN_TOOL_NAMES.has(slot.toolCall.function.name)) {
|
|
543
|
+
const serverName = slot.toolCall.function.name.split("_")[0] ?? "unknown";
|
|
544
|
+
if (!mcpWarnedServers.has(serverName)) {
|
|
545
|
+
const isConnErr = result.content.includes("connection") ||
|
|
546
|
+
result.content.includes("not connected") ||
|
|
547
|
+
result.content.includes("ECONNREFUSED") ||
|
|
548
|
+
result.content.includes("ENOTFOUND");
|
|
549
|
+
if (isConnErr) {
|
|
550
|
+
mcpWarnedServers.add(serverName);
|
|
551
|
+
this.logger.info("MCP", `Connection lost to server "${serverName}" — ` +
|
|
552
|
+
`further calls to this server may fail.`);
|
|
553
|
+
const mcpWarn = message_1.Message.system(`MCP server "${serverName}" appears to be disconnected: ${result.content.slice(0, 200)}`);
|
|
554
|
+
this.contextManager.addMessage(mcpWarn.toDict());
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
return { hadFailure };
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Check whether the token budget allows another LLM call.
|
|
563
|
+
*
|
|
564
|
+
* @param estimatedInputTokens Approximate tokens in the upcoming request
|
|
565
|
+
* (system prompt + context messages).
|
|
566
|
+
* @returns A user-facing error string if the budget is exhausted,
|
|
567
|
+
* or `null` if the call can proceed.
|
|
568
|
+
*/
|
|
569
|
+
checkTokenBudget(estimatedInputTokens) {
|
|
570
|
+
if (!this.tokenBudget)
|
|
571
|
+
return null;
|
|
572
|
+
const status = this.tokenBudget.checkBeforeCall(estimatedInputTokens);
|
|
573
|
+
if (status.isExhausted) {
|
|
574
|
+
return (`Token budget exhausted: ${status.totalTokensUsed.toLocaleString()}/${status.maxTotalTokens.toLocaleString()} tokens used ` +
|
|
575
|
+
`across ${status.callCount} LLM calls. ` +
|
|
576
|
+
`Start a new conversation with agent.newTopic() or agent.clearConversation() to reset the budget.`);
|
|
577
|
+
}
|
|
578
|
+
// One-shot warning at 80 %
|
|
579
|
+
if (this.tokenBudget.shouldWarn()) {
|
|
580
|
+
this.logger.warn("TokenBudget", `Warning: ${Math.round(status.totalTokensUsed / status.maxTotalTokens * 100)}% of budget used ` +
|
|
581
|
+
`(${status.totalTokensUsed.toLocaleString()}/${status.maxTotalTokens.toLocaleString()} tokens).`);
|
|
188
582
|
}
|
|
583
|
+
return null;
|
|
189
584
|
}
|
|
190
585
|
// ─── Cancellation ────────────────────────────────────────────────────
|
|
191
586
|
/**
|
|
192
587
|
* Cancel the current run.
|
|
193
588
|
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
589
|
+
* Aborts any in-flight LLM request via the AbortController, sets the
|
|
590
|
+
* cancellation flag, and cancels all running sub-agents. The agent loop
|
|
591
|
+
* will save a "cancelled" checkpoint and exit at its next iteration.
|
|
592
|
+
* The session is preserved on disk and can be resumed later.
|
|
196
593
|
*/
|
|
197
594
|
cancel() {
|
|
595
|
+
// Abort the in-flight LLM request first so the agent doesn't keep
|
|
596
|
+
// waiting for a response that's about to be discarded anyway.
|
|
597
|
+
this._abortController?.abort();
|
|
198
598
|
this._cancelled = true;
|
|
599
|
+
this.subAgentManager?.cancelAll();
|
|
199
600
|
}
|
|
200
601
|
/**
|
|
201
602
|
* Whether the run has been cancelled by the user.
|
|
@@ -269,17 +670,41 @@ class Agent {
|
|
|
269
670
|
};
|
|
270
671
|
}
|
|
271
672
|
/**
|
|
272
|
-
* Save a session checkpoint to disk (if session manager is configured
|
|
273
|
-
* and the run has NOT been cancelled).
|
|
673
|
+
* Save a session checkpoint to disk (if session manager is configured).
|
|
274
674
|
*/
|
|
275
675
|
saveCheckpoint(status = "active") {
|
|
276
676
|
if (!this.sessionManager)
|
|
277
677
|
return;
|
|
278
|
-
if (this.isCancelled)
|
|
279
|
-
return; // Don't save on abort
|
|
280
678
|
const state = this.buildBaseSessionState(status);
|
|
281
679
|
this.sessionManager.saveCheckpoint(state);
|
|
282
680
|
}
|
|
681
|
+
/**
|
|
682
|
+
* Handle an LLMNetworkError: save an interrupted checkpoint if
|
|
683
|
+
* checkpointing is enabled, and return a user-facing message with
|
|
684
|
+
* resume instructions.
|
|
685
|
+
*
|
|
686
|
+
* @param err The network error that occurred.
|
|
687
|
+
* @param iteration The current iteration number (for the log).
|
|
688
|
+
* @param resumeInstruction What the user should type to resume
|
|
689
|
+
* (e.g. "continue with my previous request").
|
|
690
|
+
*/
|
|
691
|
+
handleNetworkError(err, iteration, resumeInstruction = "continue") {
|
|
692
|
+
if (this.checkpointingEnabled) {
|
|
693
|
+
this.saveCheckpoint("interrupted");
|
|
694
|
+
}
|
|
695
|
+
const sid = this.sessionManager?.getSessionId() ?? "unknown";
|
|
696
|
+
this.logger.error("Network Error", `${err.cause}: ${err.message}`);
|
|
697
|
+
if (this.checkpointingEnabled && this.sessionManager) {
|
|
698
|
+
return (`[Network Error] ${err.message}\n\n` +
|
|
699
|
+
`Your session "${sid}" has been saved (iteration ${iteration}).\n` +
|
|
700
|
+
`After your network is restored, resume with:\n` +
|
|
701
|
+
` agent.resume("${sid}", "${resumeInstruction}")\n\n` +
|
|
702
|
+
`Or start a new session by calling agent.run() again with a fresh input.`);
|
|
703
|
+
}
|
|
704
|
+
// Checkpointing not enabled — just report the error
|
|
705
|
+
return (`[Network Error] ${err.message}\n\n` +
|
|
706
|
+
`Please check your network connection and try again.`);
|
|
707
|
+
}
|
|
283
708
|
/**
|
|
284
709
|
* Restore agent state from a previously saved session.
|
|
285
710
|
*
|
|
@@ -303,6 +728,9 @@ class Agent {
|
|
|
303
728
|
throw new Error(`Session "${sessionId}" was created by a ${state.agentType} agent, ` +
|
|
304
729
|
`but this agent is type "${expectedType}". Cannot resume.`);
|
|
305
730
|
}
|
|
731
|
+
// Clear cancellation state — the user explicitly chose to resume
|
|
732
|
+
this._cancelled = false;
|
|
733
|
+
this._abortController = undefined; // will be recreated in run()
|
|
306
734
|
// Sync session manager to the restored session ID so subsequent
|
|
307
735
|
// checkpoints write to the correct file
|
|
308
736
|
this.sessionManager.setSessionId(state.sessionId);
|
|
@@ -326,6 +754,49 @@ class Agent {
|
|
|
326
754
|
*/
|
|
327
755
|
clearConversation() {
|
|
328
756
|
this.contextManager.clear();
|
|
757
|
+
this.tokenBudget?.reset();
|
|
758
|
+
}
|
|
759
|
+
/**
|
|
760
|
+
* Continue the current conversation with a follow-up input.
|
|
761
|
+
*
|
|
762
|
+
* Equivalent to `run()` but conveys the semantics of a multi-turn
|
|
763
|
+
* conversation continuation. Messages from previous calls are preserved
|
|
764
|
+
* in context, so the LLM sees the full conversation history.
|
|
765
|
+
*
|
|
766
|
+
* @param input The follow-up message from the user.
|
|
767
|
+
* @returns The agent's response.
|
|
768
|
+
*/
|
|
769
|
+
async chat(input) {
|
|
770
|
+
return this.run(input);
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* Start a new topic with a fresh conversation.
|
|
774
|
+
*
|
|
775
|
+
* Clears the message history (preserving the system prompt and
|
|
776
|
+
* configuration) and runs the input as the first message of a
|
|
777
|
+
* new conversation. The token budget is also reset.
|
|
778
|
+
*
|
|
779
|
+
* @param input The first message of the new topic.
|
|
780
|
+
* @returns The agent's response.
|
|
781
|
+
*/
|
|
782
|
+
async newTopic(input) {
|
|
783
|
+
this.clearConversation();
|
|
784
|
+
return this.run(input);
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* The number of messages in the current conversation (excluding the
|
|
788
|
+
* system message). Use this to check whether there is an active
|
|
789
|
+
* conversation or to monitor context growth.
|
|
790
|
+
*/
|
|
791
|
+
get conversationLength() {
|
|
792
|
+
return this.contextManager.getMessages().length;
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Get the cumulative token consumption and cost for the current session.
|
|
796
|
+
* Returns null if no `tokenBudgetConfig` was configured.
|
|
797
|
+
*/
|
|
798
|
+
getSessionCost() {
|
|
799
|
+
return this.tokenBudget?.getSessionCost() ?? null;
|
|
329
800
|
}
|
|
330
801
|
/**
|
|
331
802
|
* Reset the agent to its initial state.
|
|
@@ -334,10 +805,13 @@ class Agent {
|
|
|
334
805
|
* After calling reset(), the agent behaves as if newly constructed.
|
|
335
806
|
*/
|
|
336
807
|
reset() {
|
|
808
|
+
this._abortController?.abort();
|
|
809
|
+
this._cancelled = false;
|
|
337
810
|
this.contextManager.clear();
|
|
338
811
|
this.coreSystemPrompt = "";
|
|
339
812
|
this.preferences = {};
|
|
340
|
-
this.
|
|
813
|
+
this.tokenBudget?.reset();
|
|
814
|
+
this.subAgentManager?.cancelAll();
|
|
341
815
|
if (this.sessionManager) {
|
|
342
816
|
this.sessionManager.deleteSession(this.sessionManager.getSessionId());
|
|
343
817
|
}
|
|
@@ -349,6 +823,147 @@ class Agent {
|
|
|
349
823
|
getAgentType() {
|
|
350
824
|
return "react";
|
|
351
825
|
}
|
|
826
|
+
// ─── MCP / Async Initialization ─────────────────────────────────────────
|
|
827
|
+
/**
|
|
828
|
+
* Initialize async resources (MCP connections, tool discovery).
|
|
829
|
+
*
|
|
830
|
+
* Idempotent — safe to call multiple times; the actual work happens
|
|
831
|
+
* only on the first invocation. Subclasses SHOULD call `await this.init()`
|
|
832
|
+
* at the start of `run()`.
|
|
833
|
+
*
|
|
834
|
+
* If MCP servers are configured:
|
|
835
|
+
* 1. Creates an McpClientManager bound to the tool registry.
|
|
836
|
+
* 2. Connects to each server and registers discovered tools.
|
|
837
|
+
* 3. Logs warnings for any servers that fail to connect.
|
|
838
|
+
*/
|
|
839
|
+
async init() {
|
|
840
|
+
if (this._mcpInitialized)
|
|
841
|
+
return;
|
|
842
|
+
this._mcpInitialized = true;
|
|
843
|
+
// ── Error tracking tool ──────────────────────────────────────────
|
|
844
|
+
try {
|
|
845
|
+
this.toolRegistry.register((0, list_errors_1.createListErrorsTool)(this.toolRegistry));
|
|
846
|
+
}
|
|
847
|
+
catch {
|
|
848
|
+
this.logger.debug("Init", `"list_errors" already registered — keeping existing.`);
|
|
849
|
+
}
|
|
850
|
+
// ── MCP connections ──────────────────────────────────────────────
|
|
851
|
+
if (this.mcpServerConfigs && Object.keys(this.mcpServerConfigs).length > 0) {
|
|
852
|
+
this.mcpClientManager = new mcp_client_manager_1.McpClientManager(this.toolRegistry, this.logger);
|
|
853
|
+
const errors = await this.mcpClientManager.connectAll(this.mcpServerConfigs);
|
|
854
|
+
if (errors.length > 0) {
|
|
855
|
+
this.logger.warn("MCP", `${errors.length} of ${Object.keys(this.mcpServerConfigs).length} server(s) failed to connect.`);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
// ── Sub-agent registry ───────────────────────────────────────────
|
|
859
|
+
if (this.subAgentsDir) {
|
|
860
|
+
this.subAgentManager = new subagent_manager_1.SubAgentManager();
|
|
861
|
+
this.subAgentManager.setLogger(this.logger);
|
|
862
|
+
this.subAgentManager.bind(this.llm, this.toolRegistry, this.skillManager, this.skillsDir, undefined, undefined, this.subAgentLLM);
|
|
863
|
+
this.subAgentManager.registerFromDirectory(this.subAgentsDir);
|
|
864
|
+
// Register sub-agent tools into the tool registry
|
|
865
|
+
try {
|
|
866
|
+
this.toolRegistry.register((0, list_subagents_1.createListSubagentsTool)(this.subAgentManager));
|
|
867
|
+
}
|
|
868
|
+
catch {
|
|
869
|
+
this.logger.debug("Init", `"list_subagents" already registered — keeping existing.`);
|
|
870
|
+
}
|
|
871
|
+
try {
|
|
872
|
+
this.toolRegistry.register((0, spawn_subagent_1.createSpawnSubagentTool)(this.subAgentManager));
|
|
873
|
+
}
|
|
874
|
+
catch {
|
|
875
|
+
this.logger.debug("Init", `"spawn_subagent" already registered — keeping existing.`);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
// ── RAG knowledge base ─────────────────────────────────────────────
|
|
879
|
+
if (this.ragConfig) {
|
|
880
|
+
this.ragManager = new rag_manager_1.RAGManager(this.ragConfig, this.logger);
|
|
881
|
+
await this.ragManager.index();
|
|
882
|
+
try {
|
|
883
|
+
this.toolRegistry.register((0, search_knowledge_1.createSearchKnowledgeTool)(this.ragManager));
|
|
884
|
+
}
|
|
885
|
+
catch {
|
|
886
|
+
this.logger.debug("Init", `"search_knowledge" already registered — keeping existing.`);
|
|
887
|
+
}
|
|
888
|
+
try {
|
|
889
|
+
this.toolRegistry.register((0, search_knowledge_1.createListKnowledgeDocumentsTool)(this.ragManager));
|
|
890
|
+
}
|
|
891
|
+
catch {
|
|
892
|
+
this.logger.debug("Init", `"list_knowledge_documents" already registered — keeping existing.`);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
// ── Skill tool (LLM-driven activation) ────────────────────────────
|
|
896
|
+
try {
|
|
897
|
+
this.toolRegistry.register((0, skill_1.createSkillTool)(this.skillManager, () => this.rebuildSystemPrompt()));
|
|
898
|
+
}
|
|
899
|
+
catch {
|
|
900
|
+
this.logger.debug("Init", `"skill" already registered — keeping existing.`);
|
|
901
|
+
}
|
|
902
|
+
// ── Remember / Recall tools (long-term memory) ────────────────────
|
|
903
|
+
try {
|
|
904
|
+
this.toolRegistry.register((0, remember_1.createRememberTool)(this.memoryManager));
|
|
905
|
+
}
|
|
906
|
+
catch {
|
|
907
|
+
this.logger.debug("Init", `"remember" already registered — keeping existing.`);
|
|
908
|
+
}
|
|
909
|
+
try {
|
|
910
|
+
this.toolRegistry.register((0, recall_1.createRecallTool)(this.memoryManager));
|
|
911
|
+
}
|
|
912
|
+
catch {
|
|
913
|
+
this.logger.debug("Init", `"recall" already registered — keeping existing.`);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
/**
|
|
917
|
+
* Gracefully shut down MCP connections.
|
|
918
|
+
*
|
|
919
|
+
* Disconnects all servers and unregisters their tools. Safe to call
|
|
920
|
+
* even if init() was never called or no servers were configured.
|
|
921
|
+
*/
|
|
922
|
+
async shutdown() {
|
|
923
|
+
await this.mcpClientManager?.disconnectAll();
|
|
924
|
+
if (this.subAgentManager) {
|
|
925
|
+
await this.subAgentManager.awaitAll();
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
// ─── Sub-Agent ────────────────────────────────────────────────────────
|
|
929
|
+
/**
|
|
930
|
+
* Check whether sub-agents are available.
|
|
931
|
+
*
|
|
932
|
+
* Used by `buildSystemPrompt()` to decide whether to include sub-agent
|
|
933
|
+
* delegation instructions. Returns true only when a SubAgentManager is
|
|
934
|
+
* configured AND has at least one registered definition.
|
|
935
|
+
*/
|
|
936
|
+
hasSubAgents() {
|
|
937
|
+
return this.subAgentManager?.hasDefinitions() === true;
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Spawn a sub-agent by definition name.
|
|
941
|
+
*
|
|
942
|
+
* The sub-agent runs asynchronously — this method returns immediately.
|
|
943
|
+
* Call `pollSubAgentResults()` at the start of each iteration to
|
|
944
|
+
* collect completed results.
|
|
945
|
+
*
|
|
946
|
+
* @param name The registered sub-agent definition name.
|
|
947
|
+
* @param input The task description for the sub-agent.
|
|
948
|
+
* @returns The unique run ID.
|
|
949
|
+
*/
|
|
950
|
+
spawnSubAgent(name, input) {
|
|
951
|
+
if (!this.subAgentManager) {
|
|
952
|
+
throw new Error("No SubAgentManager configured. Set `subAgentsDir` in AgentConfig.");
|
|
953
|
+
}
|
|
954
|
+
return this.subAgentManager.spawn(name, input);
|
|
955
|
+
}
|
|
956
|
+
/**
|
|
957
|
+
* Poll for completed sub-agent results.
|
|
958
|
+
*
|
|
959
|
+
* Should be called at the start of each ReAct iteration to inject
|
|
960
|
+
* sub-agent outputs into the main agent's context.
|
|
961
|
+
*/
|
|
962
|
+
async pollSubAgentResults() {
|
|
963
|
+
if (!this.subAgentManager)
|
|
964
|
+
return [];
|
|
965
|
+
return this.subAgentManager.pollCompleted();
|
|
966
|
+
}
|
|
352
967
|
// ─── Error Trace & Analysis ──────────────────────────────────────────
|
|
353
968
|
/**
|
|
354
969
|
* Get the error tracker (if configured via the ToolRegistry).
|
|
@@ -357,38 +972,38 @@ class Agent {
|
|
|
357
972
|
return this.toolRegistry.getErrorTracker();
|
|
358
973
|
}
|
|
359
974
|
/**
|
|
360
|
-
* Call after a tool returns
|
|
361
|
-
*
|
|
362
|
-
*
|
|
975
|
+
* Call after a tool returns a result — checks if the result indicates
|
|
976
|
+
* a tool failure (retryable or fatal) and saves the trace ID so the
|
|
977
|
+
* next LLM analysis thought can be captured.
|
|
363
978
|
*
|
|
364
|
-
* @param toolName The name of the tool that
|
|
365
|
-
* @param result The
|
|
979
|
+
* @param toolName The name of the tool that was executed.
|
|
980
|
+
* @param result The structured ToolResult returned by ToolRegistry.execute().
|
|
366
981
|
*/
|
|
367
|
-
trackToolErrorForAnalysis(toolName, result) {
|
|
368
|
-
const tracker = this.errorTracker;
|
|
369
|
-
if (!tracker)
|
|
370
|
-
return;
|
|
371
|
-
// Check if the result contains retry guidance (indicating a failure)
|
|
372
|
-
if (result.includes("[Retry Guidance]") || result.includes("has been automatically disabled")) {
|
|
373
|
-
const activeTraceId = tracker.getActiveTraceId(toolName);
|
|
374
|
-
if (activeTraceId) {
|
|
375
|
-
this.pendingErrorTraceId = activeTraceId;
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
982
|
/**
|
|
380
|
-
*
|
|
381
|
-
*
|
|
983
|
+
* Capture the LLM's reasoning as error analysis for any active tool error traces.
|
|
984
|
+
*
|
|
985
|
+
* Call this after parsing the LLM's `thought` from each response. If any tools
|
|
986
|
+
* have an open failure chain (active trace), the thought is recorded as the
|
|
987
|
+
* LLM's analysis of what went wrong and how to proceed.
|
|
988
|
+
*
|
|
989
|
+
* This feeds the error→analysis pipeline:
|
|
990
|
+
* 1. Tool fails → recordFailure() creates an active trace
|
|
991
|
+
* 2. LLM sees error → its next thought IS the analysis
|
|
992
|
+
* 3. Analysis → recordAnalysis() attaches the LLM's reasoning to the trace
|
|
382
993
|
*
|
|
383
|
-
*
|
|
994
|
+
* For cross-session learning, use ErrorNotebook (错题本) via ReflectionHook.
|
|
995
|
+
*
|
|
996
|
+
* @param thought The LLM's reasoning (from parsed.thought).
|
|
384
997
|
*/
|
|
385
|
-
|
|
386
|
-
if (
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
998
|
+
captureErrorAnalysis(thought) {
|
|
999
|
+
if (!thought)
|
|
1000
|
+
return;
|
|
1001
|
+
const tracker = this.toolRegistry.getErrorTracker();
|
|
1002
|
+
if (!tracker)
|
|
1003
|
+
return;
|
|
1004
|
+
const activeTraces = tracker.getActiveTraces();
|
|
1005
|
+
for (const { traceId } of activeTraces) {
|
|
1006
|
+
tracker.recordAnalysis(traceId, thought);
|
|
392
1007
|
}
|
|
393
1008
|
}
|
|
394
1009
|
/**
|