agent-world 0.13.0 → 0.15.0
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 +90 -17
- package/dist/cli/commands.d.ts +7 -1
- package/dist/cli/commands.js +27 -10
- package/dist/cli/hitl.d.ts +4 -1
- package/dist/cli/hitl.js +55 -20
- package/dist/cli/index.js +249 -97
- package/dist/cli/system-events.d.ts +27 -0
- package/dist/cli/system-events.js +63 -0
- package/dist/core/activity-tracker.d.ts +26 -0
- package/dist/core/activity-tracker.d.ts.map +1 -1
- package/dist/core/activity-tracker.js +21 -4
- package/dist/core/activity-tracker.js.map +1 -1
- package/dist/core/anthropic-direct.d.ts +2 -0
- package/dist/core/anthropic-direct.d.ts.map +1 -1
- package/dist/core/anthropic-direct.js +43 -1
- package/dist/core/anthropic-direct.js.map +1 -1
- package/dist/core/chat-constants.d.ts +12 -0
- package/dist/core/chat-constants.d.ts.map +1 -1
- package/dist/core/chat-constants.js +5 -0
- package/dist/core/chat-constants.js.map +1 -1
- package/dist/core/create-agent-tool.d.ts +5 -0
- package/dist/core/create-agent-tool.d.ts.map +1 -1
- package/dist/core/create-agent-tool.js +57 -34
- package/dist/core/create-agent-tool.js.map +1 -1
- package/dist/core/events/index.d.ts +5 -2
- package/dist/core/events/index.d.ts.map +1 -1
- package/dist/core/events/index.js +5 -2
- package/dist/core/events/index.js.map +1 -1
- package/dist/core/events/memory-manager.d.ts +26 -1
- package/dist/core/events/memory-manager.d.ts.map +1 -1
- package/dist/core/events/memory-manager.js +877 -72
- package/dist/core/events/memory-manager.js.map +1 -1
- package/dist/core/events/orchestrator.d.ts +8 -0
- package/dist/core/events/orchestrator.d.ts.map +1 -1
- package/dist/core/events/orchestrator.js +203 -36
- package/dist/core/events/orchestrator.js.map +1 -1
- package/dist/core/events/persistence.d.ts +21 -14
- package/dist/core/events/persistence.d.ts.map +1 -1
- package/dist/core/events/persistence.js +100 -35
- package/dist/core/events/persistence.js.map +1 -1
- package/dist/core/events/publishers.d.ts +13 -7
- package/dist/core/events/publishers.d.ts.map +1 -1
- package/dist/core/events/publishers.js +53 -37
- package/dist/core/events/publishers.js.map +1 -1
- package/dist/core/events/subscribers.d.ts +17 -14
- package/dist/core/events/subscribers.d.ts.map +1 -1
- package/dist/core/events/subscribers.js +61 -148
- package/dist/core/events/subscribers.js.map +1 -1
- package/dist/core/events/title-scheduler.d.ts +27 -0
- package/dist/core/events/title-scheduler.d.ts.map +1 -0
- package/dist/core/events/title-scheduler.js +135 -0
- package/dist/core/events/title-scheduler.js.map +1 -0
- package/dist/core/events/tool-bridge-logging.d.ts +4 -1
- package/dist/core/events/tool-bridge-logging.d.ts.map +1 -1
- package/dist/core/events/tool-bridge-logging.js +112 -13
- package/dist/core/events/tool-bridge-logging.js.map +1 -1
- package/dist/core/events-metadata.d.ts.map +1 -1
- package/dist/core/events-metadata.js +8 -4
- package/dist/core/events-metadata.js.map +1 -1
- package/dist/core/export.d.ts +1 -1
- package/dist/core/export.d.ts.map +1 -1
- package/dist/core/export.js +2 -15
- package/dist/core/export.js.map +1 -1
- package/dist/core/feature-path-logging.d.ts +50 -0
- package/dist/core/feature-path-logging.d.ts.map +1 -0
- package/dist/core/feature-path-logging.js +130 -0
- package/dist/core/feature-path-logging.js.map +1 -0
- package/dist/core/file-tools.d.ts +57 -1
- package/dist/core/file-tools.d.ts.map +1 -1
- package/dist/core/file-tools.js +329 -29
- package/dist/core/file-tools.js.map +1 -1
- package/dist/core/google-direct.d.ts +6 -1
- package/dist/core/google-direct.d.ts.map +1 -1
- package/dist/core/google-direct.js +76 -7
- package/dist/core/google-direct.js.map +1 -1
- package/dist/core/heartbeat.d.ts +34 -0
- package/dist/core/heartbeat.d.ts.map +1 -0
- package/dist/core/heartbeat.js +153 -0
- package/dist/core/heartbeat.js.map +1 -0
- package/dist/core/hitl-tool.d.ts +6 -12
- package/dist/core/hitl-tool.d.ts.map +1 -1
- package/dist/core/hitl-tool.js +66 -88
- package/dist/core/hitl-tool.js.map +1 -1
- package/dist/core/hitl.d.ts +61 -4
- package/dist/core/hitl.d.ts.map +1 -1
- package/dist/core/hitl.js +324 -60
- package/dist/core/hitl.js.map +1 -1
- package/dist/core/index.d.ts +11 -7
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +10 -6
- package/dist/core/index.js.map +1 -1
- package/dist/core/llm-manager.d.ts +15 -0
- package/dist/core/llm-manager.d.ts.map +1 -1
- package/dist/core/llm-manager.js +325 -40
- package/dist/core/llm-manager.js.map +1 -1
- package/dist/core/load-skill-tool.d.ts +36 -3
- package/dist/core/load-skill-tool.d.ts.map +1 -1
- package/dist/core/load-skill-tool.js +807 -93
- package/dist/core/load-skill-tool.js.map +1 -1
- package/dist/core/logger.d.ts +14 -0
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +15 -0
- package/dist/core/logger.js.map +1 -1
- package/dist/core/managers.d.ts +18 -50
- package/dist/core/managers.d.ts.map +1 -1
- package/dist/core/managers.js +340 -502
- package/dist/core/managers.js.map +1 -1
- package/dist/core/mcp-server-registry.d.ts +16 -1
- package/dist/core/mcp-server-registry.d.ts.map +1 -1
- package/dist/core/mcp-server-registry.js +162 -12
- package/dist/core/mcp-server-registry.js.map +1 -1
- package/dist/core/message-cutoff.d.ts +29 -0
- package/dist/core/message-cutoff.d.ts.map +1 -0
- package/dist/core/message-cutoff.js +63 -0
- package/dist/core/message-cutoff.js.map +1 -0
- package/dist/core/message-edit-manager.d.ts +54 -0
- package/dist/core/message-edit-manager.d.ts.map +1 -0
- package/dist/core/message-edit-manager.js +602 -0
- package/dist/core/message-edit-manager.js.map +1 -0
- package/dist/core/message-prep.d.ts +2 -0
- package/dist/core/message-prep.d.ts.map +1 -1
- package/dist/core/message-prep.js +39 -12
- package/dist/core/message-prep.js.map +1 -1
- package/dist/core/message-processing-control.d.ts +1 -0
- package/dist/core/message-processing-control.d.ts.map +1 -1
- package/dist/core/message-processing-control.js +23 -6
- package/dist/core/message-processing-control.js.map +1 -1
- package/dist/core/openai-direct.d.ts +9 -3
- package/dist/core/openai-direct.d.ts.map +1 -1
- package/dist/core/openai-direct.js +267 -33
- package/dist/core/openai-direct.js.map +1 -1
- package/dist/core/optional-tracers/opik-runtime.d.ts +32 -0
- package/dist/core/optional-tracers/opik-runtime.d.ts.map +1 -0
- package/dist/core/optional-tracers/opik-runtime.js +141 -0
- package/dist/core/optional-tracers/opik-runtime.js.map +1 -0
- package/dist/core/queue-manager.d.ts +84 -0
- package/dist/core/queue-manager.d.ts.map +1 -0
- package/dist/core/queue-manager.js +814 -0
- package/dist/core/queue-manager.js.map +1 -0
- package/dist/core/reasoning-controls.d.ts +30 -0
- package/dist/core/reasoning-controls.d.ts.map +1 -0
- package/dist/core/reasoning-controls.js +118 -0
- package/dist/core/reasoning-controls.js.map +1 -0
- package/dist/core/reliability-config.d.ts +82 -0
- package/dist/core/reliability-config.d.ts.map +1 -0
- package/dist/core/reliability-config.js +106 -0
- package/dist/core/reliability-config.js.map +1 -0
- package/dist/core/reliability-runtime.d.ts +53 -0
- package/dist/core/reliability-runtime.d.ts.map +1 -0
- package/dist/core/reliability-runtime.js +92 -0
- package/dist/core/reliability-runtime.js.map +1 -0
- package/dist/core/security/guardrails.d.ts +21 -0
- package/dist/core/security/guardrails.d.ts.map +1 -0
- package/dist/core/security/guardrails.js +111 -0
- package/dist/core/security/guardrails.js.map +1 -0
- package/dist/core/send-message-tool.d.ts +79 -0
- package/dist/core/send-message-tool.d.ts.map +1 -0
- package/dist/core/send-message-tool.js +222 -0
- package/dist/core/send-message-tool.js.map +1 -0
- package/dist/core/shell-cmd-tool.d.ts +82 -1
- package/dist/core/shell-cmd-tool.d.ts.map +1 -1
- package/dist/core/shell-cmd-tool.js +854 -42
- package/dist/core/shell-cmd-tool.js.map +1 -1
- package/dist/core/skill-registry.d.ts +2 -0
- package/dist/core/skill-registry.d.ts.map +1 -1
- package/dist/core/skill-registry.js +52 -2
- package/dist/core/skill-registry.js.map +1 -1
- package/dist/core/storage/eventStorage/fileEventStorage.d.ts +5 -0
- package/dist/core/storage/eventStorage/fileEventStorage.d.ts.map +1 -1
- package/dist/core/storage/eventStorage/fileEventStorage.js +61 -0
- package/dist/core/storage/eventStorage/fileEventStorage.js.map +1 -1
- package/dist/core/storage/eventStorage/memoryEventStorage.d.ts +5 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.d.ts.map +1 -1
- package/dist/core/storage/eventStorage/memoryEventStorage.js +34 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.js.map +1 -1
- package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts +1 -0
- package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts.map +1 -1
- package/dist/core/storage/eventStorage/sqliteEventStorage.js +19 -2
- package/dist/core/storage/eventStorage/sqliteEventStorage.js.map +1 -1
- package/dist/core/storage/eventStorage/types.d.ts +6 -0
- package/dist/core/storage/eventStorage/types.d.ts.map +1 -1
- package/dist/core/storage/eventStorage/types.js +1 -0
- package/dist/core/storage/eventStorage/types.js.map +1 -1
- package/dist/core/storage/eventStorage/validation.d.ts.map +1 -1
- package/dist/core/storage/eventStorage/validation.js +2 -1
- package/dist/core/storage/eventStorage/validation.js.map +1 -1
- package/dist/core/storage/github-world-import.d.ts +84 -0
- package/dist/core/storage/github-world-import.d.ts.map +1 -0
- package/dist/core/storage/github-world-import.js +365 -0
- package/dist/core/storage/github-world-import.js.map +1 -0
- package/dist/core/storage/memory-storage.d.ts +19 -8
- package/dist/core/storage/memory-storage.d.ts.map +1 -1
- package/dist/core/storage/memory-storage.js +147 -49
- package/dist/core/storage/memory-storage.js.map +1 -1
- package/dist/core/storage/queue-storage.d.ts +1 -0
- package/dist/core/storage/queue-storage.d.ts.map +1 -1
- package/dist/core/storage/queue-storage.js +3 -2
- package/dist/core/storage/queue-storage.js.map +1 -1
- package/dist/core/storage/sqlite-storage.d.ts +14 -9
- package/dist/core/storage/sqlite-storage.d.ts.map +1 -1
- package/dist/core/storage/sqlite-storage.js +131 -154
- package/dist/core/storage/sqlite-storage.js.map +1 -1
- package/dist/core/storage/storage-factory.d.ts +3 -0
- package/dist/core/storage/storage-factory.d.ts.map +1 -1
- package/dist/core/storage/storage-factory.js +175 -89
- package/dist/core/storage/storage-factory.js.map +1 -1
- package/dist/core/storage/world-storage.d.ts +1 -1
- package/dist/core/storage/world-storage.d.ts.map +1 -1
- package/dist/core/storage/world-storage.js +5 -1
- package/dist/core/storage/world-storage.js.map +1 -1
- package/dist/core/storage-init.d.ts +11 -0
- package/dist/core/storage-init.d.ts.map +1 -0
- package/dist/core/storage-init.js +122 -0
- package/dist/core/storage-init.js.map +1 -0
- package/dist/core/subscription.d.ts +8 -1
- package/dist/core/subscription.d.ts.map +1 -1
- package/dist/core/subscription.js +130 -23
- package/dist/core/subscription.js.map +1 -1
- package/dist/core/tool-approval.d.ts +45 -0
- package/dist/core/tool-approval.d.ts.map +1 -0
- package/dist/core/tool-approval.js +223 -0
- package/dist/core/tool-approval.js.map +1 -0
- package/dist/core/tool-execution-envelope.d.ts +87 -0
- package/dist/core/tool-execution-envelope.d.ts.map +1 -0
- package/dist/core/tool-execution-envelope.js +168 -0
- package/dist/core/tool-execution-envelope.js.map +1 -0
- package/dist/core/tool-utils.d.ts +7 -2
- package/dist/core/tool-utils.d.ts.map +1 -1
- package/dist/core/tool-utils.js +81 -17
- package/dist/core/tool-utils.js.map +1 -1
- package/dist/core/types.d.ts +67 -19
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/utils.d.ts +7 -0
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core/utils.js +71 -21
- package/dist/core/utils.js.map +1 -1
- package/dist/core/web-fetch-tool.d.ts +72 -0
- package/dist/core/web-fetch-tool.d.ts.map +1 -0
- package/dist/core/web-fetch-tool.js +491 -0
- package/dist/core/web-fetch-tool.js.map +1 -0
- package/dist/core/world-registry.d.ts +84 -0
- package/dist/core/world-registry.d.ts.map +1 -0
- package/dist/core/world-registry.js +247 -0
- package/dist/core/world-registry.js.map +1 -0
- package/dist/public/assets/index-Be-1xtV-.js +104 -0
- package/dist/public/assets/index-tsDdiXDU.css +1 -0
- package/dist/public/index.html +2 -2
- package/dist/public/mcp-sandbox-proxy.html +148 -0
- package/dist/server/api.js +260 -18
- package/dist/server/error-response.d.ts +27 -0
- package/dist/server/error-response.js +77 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +6 -2
- package/dist/server/sse-handler.d.ts +11 -1
- package/dist/server/sse-handler.js +194 -34
- package/migrations/0015_add_message_queue.sql +36 -0
- package/migrations/0016_add_world_heartbeat.sql +13 -0
- package/migrations/0017_add_title_provenance.sql +7 -0
- package/package.json +31 -10
- package/dist/public/assets/index-BW41BxMy.css +0 -1
- package/dist/public/assets/index-kO6UJFwK.js +0 -96
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../core/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../core/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -94,6 +94,14 @@
|
|
|
94
94
|
* - Queue-based serialization prevents API rate limits and resource conflicts
|
|
95
95
|
*
|
|
96
96
|
* Recent Changes:
|
|
97
|
+
* - 2026-03-13: Added streamed `reasoningContent` forwarding and world-variable reasoning-effort propagation for OpenAI-compatible and Google direct providers.
|
|
98
|
+
* - 2026-03-06: Moved `shell_cmd` working-directory prompt guidance into tool-aware system-message injection.
|
|
99
|
+
* - 2026-03-06: Widened queue timeout field typing to `number` so runtime timeout overrides compile cleanly.
|
|
100
|
+
* - 2026-03-05: Added chat-scoped LLM timeout status system events (`taking too long` warning + hard-timeout event), enforced timeout-triggered abort signaling in queue processing, and classified queue timeouts separately from user cancellations.
|
|
101
|
+
* - 2026-03-05: Switched LLM queue timeout defaults to shared reliability config.
|
|
102
|
+
* - 2026-03-04: Azure client creation now maps `agent.model` to Azure deployment name (with config deployment fallback) so world/agent model selection controls deployment URL routing.
|
|
103
|
+
* - 2026-02-28: Added canonical feature-path diagnostics (`llm.prep`, `llm.request.*`, `llm.response.*`) with opt-in raw payload logging and correlation metadata.
|
|
104
|
+
* - 2026-02-24: Required explicit chatId for streaming SSE emission and propagated chatId through start/chunk/end/error events for strict chat-scoped frontend filtering.
|
|
97
105
|
* - 2026-02-20: Switched injected tool-usage guidance to shared `buildToolUsagePromptSection()` so HITL and other tool rules are centralized in one utility.
|
|
98
106
|
* - 2026-02-20: Updated injected tool-usage guidance to direct LLMs to use `human_intervention_request` for human clarifications and confirmations.
|
|
99
107
|
* - 2026-02-13: Reclassified stop-triggered aborts as cancellation/info logs (not errors) in queue and non-streaming paths.
|
|
@@ -114,6 +122,13 @@
|
|
|
114
122
|
* - Tool-specific guidance moved to individual tool descriptions (proper separation)
|
|
115
123
|
*/
|
|
116
124
|
import { World, Agent, AgentMessage, LLMProvider, WorldSSEEvent, LLMResponse } from './types.js';
|
|
125
|
+
/**
|
|
126
|
+
* Append tool usage guidance to system message when tools are available
|
|
127
|
+
* Returns a new array with updated system message (doesn't mutate original)
|
|
128
|
+
*/
|
|
129
|
+
export declare function appendToolRulesToSystemMessage(messages: AgentMessage[], toolNames: string[], options?: {
|
|
130
|
+
workingDirectory?: string;
|
|
131
|
+
}): AgentMessage[];
|
|
117
132
|
/**
|
|
118
133
|
* LLM configuration interface
|
|
119
134
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-manager.d.ts","sourceRoot":"","sources":["../../core/llm-manager.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"llm-manager.d.ts","sourceRoot":"","sources":["../../core/llm-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0HG;AAEH,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAe,WAAW,EAAE,MAAM,YAAY,CAAC;AAqK9G;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,YAAY,EAAE,EACxB,SAAS,EAAE,MAAM,EAAE,EACnB,OAAO,CAAC,EAAE;IAAE,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GACtC,YAAY,EAAE,CAuBhB;AAkTD;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAgED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,EAAE,EACxB,UAAU,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,EAChE,MAAM,GAAE,MAAM,GAAG,IAAW,EAC5B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC;IAAE,QAAQ,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAsCvD;AA8MD;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,EAAE,EACxB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,EAClE,SAAS,CAAC,EAAE,OAAO,EACnB,MAAM,GAAE,MAAM,GAAG,IAAW,EAC5B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC;IAAE,QAAQ,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAsCvD;AAqMD;;GAEG;AACH,wBAAgB,iBAAiB,IAAI;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,CAEA;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB;IAAE,eAAe,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAEpD"}
|
package/dist/core/llm-manager.js
CHANGED
|
@@ -94,6 +94,14 @@
|
|
|
94
94
|
* - Queue-based serialization prevents API rate limits and resource conflicts
|
|
95
95
|
*
|
|
96
96
|
* Recent Changes:
|
|
97
|
+
* - 2026-03-13: Added streamed `reasoningContent` forwarding and world-variable reasoning-effort propagation for OpenAI-compatible and Google direct providers.
|
|
98
|
+
* - 2026-03-06: Moved `shell_cmd` working-directory prompt guidance into tool-aware system-message injection.
|
|
99
|
+
* - 2026-03-06: Widened queue timeout field typing to `number` so runtime timeout overrides compile cleanly.
|
|
100
|
+
* - 2026-03-05: Added chat-scoped LLM timeout status system events (`taking too long` warning + hard-timeout event), enforced timeout-triggered abort signaling in queue processing, and classified queue timeouts separately from user cancellations.
|
|
101
|
+
* - 2026-03-05: Switched LLM queue timeout defaults to shared reliability config.
|
|
102
|
+
* - 2026-03-04: Azure client creation now maps `agent.model` to Azure deployment name (with config deployment fallback) so world/agent model selection controls deployment URL routing.
|
|
103
|
+
* - 2026-02-28: Added canonical feature-path diagnostics (`llm.prep`, `llm.request.*`, `llm.response.*`) with opt-in raw payload logging and correlation metadata.
|
|
104
|
+
* - 2026-02-24: Required explicit chatId for streaming SSE emission and propagated chatId through start/chunk/end/error events for strict chat-scoped frontend filtering.
|
|
97
105
|
* - 2026-02-20: Switched injected tool-usage guidance to shared `buildToolUsagePromptSection()` so HITL and other tool rules are centralized in one utility.
|
|
98
106
|
* - 2026-02-20: Updated injected tool-usage guidance to direct LLMs to use `human_intervention_request` for human clarifications and confirmations.
|
|
99
107
|
* - 2026-02-13: Reclassified stop-triggered aborts as cancellation/info logs (not errors) in queue and non-streaming paths.
|
|
@@ -119,9 +127,11 @@ import { filterClientSideMessages } from './message-prep.js';
|
|
|
119
127
|
import { createClientForProvider, streamOpenAIResponse, generateOpenAIResponse } from './openai-direct.js';
|
|
120
128
|
import { createAnthropicClientForAgent, streamAnthropicResponse, generateAnthropicResponse } from './anthropic-direct.js';
|
|
121
129
|
import { createGoogleClientForAgent, streamGoogleResponse, generateGoogleResponse } from './google-direct.js';
|
|
122
|
-
import { buildToolUsagePromptSection, generateId } from './utils.js';
|
|
130
|
+
import { buildToolUsagePromptSection, generateId, getDefaultWorkingDirectory, getEnvValueFromText } from './utils.js';
|
|
123
131
|
import { createCategoryLogger } from './logger.js';
|
|
132
|
+
import { buildFeaturePathCorrelation, mergeFeaturePathData, sanitizeRawPayloadForLog, shouldEmitRawLog } from './feature-path-logging.js';
|
|
124
133
|
import { createStorageWithWrappers } from './storage/storage-factory.js';
|
|
134
|
+
import { RELIABILITY_CONFIG } from './reliability-config.js';
|
|
125
135
|
// Granular function-specific loggers for detailed debugging control
|
|
126
136
|
const loggerQueue = createCategoryLogger('llm.queue');
|
|
127
137
|
const loggerStreaming = createCategoryLogger('llm.streaming');
|
|
@@ -129,6 +139,11 @@ const loggerGeneration = createCategoryLogger('llm.generation');
|
|
|
129
139
|
const loggerProvider = createCategoryLogger('llm.provider');
|
|
130
140
|
const loggerMCP = createCategoryLogger('llm.mcp');
|
|
131
141
|
const loggerUtil = createCategoryLogger('llm.util');
|
|
142
|
+
const loggerPrep = createCategoryLogger('llm.prep');
|
|
143
|
+
const loggerRequestMeta = createCategoryLogger('llm.request.meta');
|
|
144
|
+
const loggerRequestRaw = createCategoryLogger('llm.request.raw');
|
|
145
|
+
const loggerResponseMeta = createCategoryLogger('llm.response.meta');
|
|
146
|
+
const loggerResponseRaw = createCategoryLogger('llm.response.raw');
|
|
132
147
|
import { getLLMProviderConfig } from './llm-config.js';
|
|
133
148
|
// LLM Integration Utilities
|
|
134
149
|
function stripCustomFields(message) {
|
|
@@ -144,20 +159,90 @@ function stripCustomFieldsFromMessages(messages) {
|
|
|
144
159
|
// Then strip custom fields
|
|
145
160
|
return filteredMessages.map(stripCustomFields);
|
|
146
161
|
}
|
|
162
|
+
function summarizeMessagesForLLM(messages) {
|
|
163
|
+
return {
|
|
164
|
+
messageCount: messages.length,
|
|
165
|
+
systemMessages: messages.filter(m => m.role === 'system').length,
|
|
166
|
+
userMessages: messages.filter(m => m.role === 'user').length,
|
|
167
|
+
assistantMessages: messages.filter(m => m.role === 'assistant').length,
|
|
168
|
+
toolMessages: messages.filter(m => m.role === 'tool').length,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function emitLLMRequestDiagnostics(params) {
|
|
172
|
+
const correlation = buildFeaturePathCorrelation({
|
|
173
|
+
worldId: params.world.id,
|
|
174
|
+
chatId: params.chatId,
|
|
175
|
+
agentId: params.agent.id,
|
|
176
|
+
messageId: params.messageId,
|
|
177
|
+
turnId: params.messageId,
|
|
178
|
+
});
|
|
179
|
+
const messageSummary = summarizeMessagesForLLM(params.preparedMessages);
|
|
180
|
+
const toolNames = Object.keys(params.mcpTools);
|
|
181
|
+
loggerPrep.debug('Prepared messages for LLM request', mergeFeaturePathData(correlation, {
|
|
182
|
+
...messageSummary,
|
|
183
|
+
toolCount: toolNames.length,
|
|
184
|
+
}));
|
|
185
|
+
loggerRequestMeta.debug('LLM request ready', mergeFeaturePathData(correlation, {
|
|
186
|
+
provider: params.agent.provider,
|
|
187
|
+
model: params.agent.model,
|
|
188
|
+
...messageSummary,
|
|
189
|
+
toolCount: toolNames.length,
|
|
190
|
+
toolNames,
|
|
191
|
+
}));
|
|
192
|
+
if (shouldEmitRawLog('llm.request.raw')) {
|
|
193
|
+
loggerRequestRaw.debug('LLM request payload', mergeFeaturePathData(correlation, {
|
|
194
|
+
provider: params.agent.provider,
|
|
195
|
+
model: params.agent.model,
|
|
196
|
+
payload: sanitizeRawPayloadForLog({
|
|
197
|
+
messages: params.preparedMessages,
|
|
198
|
+
tools: params.mcpTools,
|
|
199
|
+
}),
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function emitLLMResponseDiagnostics(params) {
|
|
204
|
+
const correlation = buildFeaturePathCorrelation({
|
|
205
|
+
worldId: params.world.id,
|
|
206
|
+
chatId: params.chatId,
|
|
207
|
+
agentId: params.agent.id,
|
|
208
|
+
messageId: params.messageId,
|
|
209
|
+
turnId: params.messageId,
|
|
210
|
+
});
|
|
211
|
+
loggerResponseMeta.debug('LLM response received', mergeFeaturePathData(correlation, {
|
|
212
|
+
provider: params.agent.provider,
|
|
213
|
+
model: params.agent.model,
|
|
214
|
+
responseType: params.response.type,
|
|
215
|
+
contentLength: params.response.content?.length || 0,
|
|
216
|
+
toolCallCount: params.response.tool_calls?.length || 0,
|
|
217
|
+
}));
|
|
218
|
+
if (shouldEmitRawLog('llm.response.raw')) {
|
|
219
|
+
loggerResponseRaw.debug('LLM response payload', mergeFeaturePathData(correlation, {
|
|
220
|
+
provider: params.agent.provider,
|
|
221
|
+
model: params.agent.model,
|
|
222
|
+
payload: sanitizeRawPayloadForLog(params.response),
|
|
223
|
+
}));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
147
226
|
/**
|
|
148
227
|
* Append tool usage guidance to system message when tools are available
|
|
149
228
|
* Returns a new array with updated system message (doesn't mutate original)
|
|
150
229
|
*/
|
|
151
|
-
function appendToolRulesToSystemMessage(messages, toolNames) {
|
|
230
|
+
export function appendToolRulesToSystemMessage(messages, toolNames, options) {
|
|
152
231
|
if (messages.length === 0 || messages[0].role !== 'system') {
|
|
153
232
|
return messages;
|
|
154
233
|
}
|
|
155
234
|
const systemMessage = messages[0];
|
|
235
|
+
const normalizedToolNames = new Set(toolNames.map((toolName) => String(toolName || '').trim().toLowerCase()).filter(Boolean));
|
|
156
236
|
const toolUsageSection = buildToolUsagePromptSection({ toolNames });
|
|
157
|
-
|
|
237
|
+
const workingDirectory = typeof options?.workingDirectory === 'string' ? options.workingDirectory.trim() : '';
|
|
238
|
+
const shellExecutionRule = normalizedToolNames.has('shell_cmd') && workingDirectory
|
|
239
|
+
? 'When using `shell_cmd`, execute commands only within this trusted working directory scope: ' + workingDirectory
|
|
240
|
+
: '';
|
|
241
|
+
const injectedSections = [shellExecutionRule, toolUsageSection].filter(Boolean);
|
|
242
|
+
if (injectedSections.length === 0) {
|
|
158
243
|
return messages;
|
|
159
244
|
}
|
|
160
|
-
const toolRules =
|
|
245
|
+
const toolRules = `\n\n${injectedSections.join('\n\n')}`;
|
|
161
246
|
return [
|
|
162
247
|
{ ...systemMessage, content: systemMessage.content + toolRules },
|
|
163
248
|
...messages.slice(1)
|
|
@@ -176,13 +261,25 @@ function normalizeChatId(chatId) {
|
|
|
176
261
|
return '__none__';
|
|
177
262
|
return String(chatId);
|
|
178
263
|
}
|
|
264
|
+
function createLLMQueueTimeoutError(agentId, timeoutMs) {
|
|
265
|
+
const error = new Error(`LLM call timeout after ${timeoutMs}ms for agent ${agentId}`);
|
|
266
|
+
error.name = 'LLMQueueTimeoutError';
|
|
267
|
+
error.code = 'LLM_QUEUE_TIMEOUT';
|
|
268
|
+
return error;
|
|
269
|
+
}
|
|
270
|
+
function isLLMQueueTimeoutError(error) {
|
|
271
|
+
return Boolean(error &&
|
|
272
|
+
typeof error === 'object' &&
|
|
273
|
+
'code' in error &&
|
|
274
|
+
error.code === 'LLM_QUEUE_TIMEOUT');
|
|
275
|
+
}
|
|
179
276
|
class LLMQueue {
|
|
180
277
|
queue = [];
|
|
181
278
|
processing = false;
|
|
182
279
|
activeItem = null;
|
|
183
280
|
maxQueueSize = 100; // Prevent memory issues
|
|
184
|
-
processingTimeoutMs =
|
|
185
|
-
async add(agentId, worldId, chatId, task) {
|
|
281
|
+
processingTimeoutMs = RELIABILITY_CONFIG.llm.processingTimeoutMs; // 15 minute max processing time per call (for long-running tools)
|
|
282
|
+
async add(agentId, worldId, chatId, task, options) {
|
|
186
283
|
// Prevent queue overflow
|
|
187
284
|
if (this.queue.length >= this.maxQueueSize) {
|
|
188
285
|
throw new Error(`LLM queue is full (${this.maxQueueSize} items). Please try again later.`);
|
|
@@ -197,6 +294,8 @@ class LLMQueue {
|
|
|
197
294
|
abortController: new AbortController(),
|
|
198
295
|
canceled: false,
|
|
199
296
|
execute: task,
|
|
297
|
+
onTakingTooLong: options?.onTakingTooLong,
|
|
298
|
+
onTimedOut: options?.onTimedOut,
|
|
200
299
|
resolve,
|
|
201
300
|
reject
|
|
202
301
|
};
|
|
@@ -219,13 +318,13 @@ class LLMQueue {
|
|
|
219
318
|
this.activeItem = item;
|
|
220
319
|
const taskStartTime = Date.now();
|
|
221
320
|
loggerQueue.debug(`LLMQueue: Processing task for agent=${item.agentId}, world=${item.worldId}, chat=${normalizeChatId(item.chatId)}, queueItemId=${item.id}`);
|
|
222
|
-
// Add processing timeout to prevent stuck queue
|
|
321
|
+
// Add processing timeout to prevent stuck queue.
|
|
223
322
|
const processPromise = item.execute(item.abortController.signal);
|
|
224
|
-
// Store timeout
|
|
323
|
+
// Store timeout IDs so we can cancel them on all exits.
|
|
225
324
|
let timeoutId;
|
|
226
325
|
let warningTimeoutId;
|
|
227
|
-
// Warn if processing
|
|
228
|
-
const warningThreshold = this.processingTimeoutMs *
|
|
326
|
+
// Warn if processing exceeds configured threshold ratio of timeout.
|
|
327
|
+
const warningThreshold = this.processingTimeoutMs * RELIABILITY_CONFIG.llm.warningThresholdRatio;
|
|
229
328
|
warningTimeoutId = setTimeout(() => {
|
|
230
329
|
const elapsed = Date.now() - taskStartTime;
|
|
231
330
|
loggerQueue.warn(`LLM task is taking longer than expected`, {
|
|
@@ -235,22 +334,74 @@ class LLMQueue {
|
|
|
235
334
|
timeoutMs: this.processingTimeoutMs,
|
|
236
335
|
percentComplete: Math.round((elapsed / this.processingTimeoutMs) * 100)
|
|
237
336
|
});
|
|
337
|
+
try {
|
|
338
|
+
item.onTakingTooLong?.({
|
|
339
|
+
elapsedMs: elapsed,
|
|
340
|
+
timeoutMs: this.processingTimeoutMs,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
catch (callbackError) {
|
|
344
|
+
loggerQueue.warn('LLM queue taking-too-long callback failed', {
|
|
345
|
+
agentId: item.agentId,
|
|
346
|
+
worldId: item.worldId,
|
|
347
|
+
chatId: normalizeChatId(item.chatId),
|
|
348
|
+
queueItemId: item.id,
|
|
349
|
+
error: callbackError instanceof Error ? callbackError.message : String(callbackError)
|
|
350
|
+
});
|
|
351
|
+
}
|
|
238
352
|
}, warningThreshold);
|
|
239
353
|
const timeoutPromise = new Promise((_, reject) => {
|
|
240
354
|
timeoutId = setTimeout(() => {
|
|
241
|
-
|
|
355
|
+
const elapsed = Date.now() - taskStartTime;
|
|
356
|
+
if (!item.abortController.signal.aborted) {
|
|
357
|
+
item.abortController.abort();
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
item.onTimedOut?.({
|
|
361
|
+
elapsedMs: elapsed,
|
|
362
|
+
timeoutMs: this.processingTimeoutMs,
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
catch (callbackError) {
|
|
366
|
+
loggerQueue.warn('LLM queue timeout callback failed', {
|
|
367
|
+
agentId: item.agentId,
|
|
368
|
+
worldId: item.worldId,
|
|
369
|
+
chatId: normalizeChatId(item.chatId),
|
|
370
|
+
queueItemId: item.id,
|
|
371
|
+
error: callbackError instanceof Error ? callbackError.message : String(callbackError)
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
reject(createLLMQueueTimeoutError(item.agentId, this.processingTimeoutMs));
|
|
242
375
|
}, this.processingTimeoutMs);
|
|
243
376
|
});
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
377
|
+
let result;
|
|
378
|
+
try {
|
|
379
|
+
result = await Promise.race([processPromise, timeoutPromise]);
|
|
380
|
+
}
|
|
381
|
+
finally {
|
|
382
|
+
if (timeoutId) {
|
|
383
|
+
clearTimeout(timeoutId);
|
|
384
|
+
}
|
|
385
|
+
if (warningTimeoutId) {
|
|
386
|
+
clearTimeout(warningTimeoutId);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
248
389
|
item.resolve(result);
|
|
249
390
|
loggerQueue.debug(`LLMQueue: Finished processing task for agent=${item.agentId}, world=${item.worldId}, queueItemId=${item.id}`);
|
|
250
391
|
}
|
|
251
392
|
catch (error) {
|
|
252
|
-
const
|
|
253
|
-
|
|
393
|
+
const isTimeout = isLLMQueueTimeoutError(error);
|
|
394
|
+
const wasCanceled = !isTimeout && (item.canceled || item.abortController.signal.aborted || isAbortError(error));
|
|
395
|
+
if (isTimeout) {
|
|
396
|
+
loggerQueue.warn('LLM queue call timed out', {
|
|
397
|
+
agentId: item.agentId,
|
|
398
|
+
worldId: item.worldId,
|
|
399
|
+
chatId: normalizeChatId(item.chatId),
|
|
400
|
+
queueItemId: item.id,
|
|
401
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
else if (wasCanceled) {
|
|
254
405
|
loggerQueue.info('LLM queue call canceled', {
|
|
255
406
|
agentId: item.agentId,
|
|
256
407
|
worldId: item.worldId,
|
|
@@ -327,8 +478,8 @@ class LLMQueue {
|
|
|
327
478
|
}
|
|
328
479
|
// Set processing timeout (useful for testing or adjusting for long-running operations)
|
|
329
480
|
setProcessingTimeout(timeoutMs) {
|
|
330
|
-
if (timeoutMs <
|
|
331
|
-
throw new Error(
|
|
481
|
+
if (timeoutMs < RELIABILITY_CONFIG.llm.minProcessingTimeoutMs) {
|
|
482
|
+
throw new Error(`Processing timeout must be at least ${RELIABILITY_CONFIG.llm.minProcessingTimeoutMs}ms`);
|
|
332
483
|
}
|
|
333
484
|
this.processingTimeoutMs = timeoutMs;
|
|
334
485
|
loggerQueue.info('LLM queue processing timeout updated', { timeoutMs });
|
|
@@ -350,6 +501,18 @@ function isAbortError(error) {
|
|
|
350
501
|
const message = error instanceof Error ? error.message : String(error);
|
|
351
502
|
return message.toLowerCase().includes('abort');
|
|
352
503
|
}
|
|
504
|
+
function emitLLMTimeoutSystemStatus(world, chatId, content) {
|
|
505
|
+
const scopedChatId = typeof chatId === 'string' ? chatId.trim() : '';
|
|
506
|
+
if (!scopedChatId) {
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
world.eventEmitter.emit('system', {
|
|
510
|
+
content,
|
|
511
|
+
timestamp: new Date(),
|
|
512
|
+
messageId: generateId(),
|
|
513
|
+
chatId: scopedChatId,
|
|
514
|
+
});
|
|
515
|
+
}
|
|
353
516
|
function createCombinedAbortSignal(first, second) {
|
|
354
517
|
const signals = [first, second].filter((value) => Boolean(value));
|
|
355
518
|
if (signals.length === 0) {
|
|
@@ -385,24 +548,36 @@ export async function streamAgentResponse(world, agent, messages, publishSSE, ch
|
|
|
385
548
|
if (abortSignal?.aborted) {
|
|
386
549
|
throw new DOMException(`LLM call aborted before queue for agent ${agent.id}`, 'AbortError');
|
|
387
550
|
}
|
|
551
|
+
const normalizedChatId = typeof chatId === 'string' ? chatId.trim() : '';
|
|
552
|
+
const resolvedChatId = normalizedChatId || null;
|
|
553
|
+
if (!resolvedChatId) {
|
|
554
|
+
throw new Error(`streamAgentResponse: chatId is required for agent ${agent.id}`);
|
|
555
|
+
}
|
|
388
556
|
// Queue the LLM call to ensure serialized execution
|
|
389
|
-
return llmQueue.add(agent.id, world.id,
|
|
557
|
+
return llmQueue.add(agent.id, world.id, resolvedChatId, async (queueAbortSignal) => {
|
|
390
558
|
const { signal: mergedAbortSignal, dispose } = createCombinedAbortSignal(queueAbortSignal, abortSignal);
|
|
391
559
|
try {
|
|
392
560
|
if (mergedAbortSignal?.aborted) {
|
|
393
561
|
throw new DOMException(`LLM call aborted before execution for agent ${agent.id}`, 'AbortError');
|
|
394
562
|
}
|
|
395
|
-
return await executeStreamAgentResponse(world, agent, messages, publishSSE, mergedAbortSignal);
|
|
563
|
+
return await executeStreamAgentResponse(world, agent, messages, publishSSE, resolvedChatId, mergedAbortSignal);
|
|
396
564
|
}
|
|
397
565
|
finally {
|
|
398
566
|
dispose();
|
|
399
567
|
}
|
|
568
|
+
}, {
|
|
569
|
+
onTakingTooLong: ({ elapsedMs, timeoutMs }) => {
|
|
570
|
+
emitLLMTimeoutSystemStatus(world, resolvedChatId, `LLM processing taking too long for ${agent.id} (elapsed ${Math.floor(elapsedMs / 1000)}s, timeout ${Math.floor(timeoutMs / 1000)}s).`);
|
|
571
|
+
},
|
|
572
|
+
onTimedOut: ({ timeoutMs }) => {
|
|
573
|
+
emitLLMTimeoutSystemStatus(world, resolvedChatId, `LLM processing timed out for ${agent.id} after ${Math.floor(timeoutMs / 1000)}s.`);
|
|
574
|
+
},
|
|
400
575
|
});
|
|
401
576
|
}
|
|
402
577
|
/**
|
|
403
578
|
* Internal streaming implementation (executed within queue)
|
|
404
579
|
*/
|
|
405
|
-
async function executeStreamAgentResponse(world, agent, messages, publishSSE, abortSignal) {
|
|
580
|
+
async function executeStreamAgentResponse(world, agent, messages, publishSSE, chatId, abortSignal) {
|
|
406
581
|
const messageId = generateId();
|
|
407
582
|
try {
|
|
408
583
|
if (abortSignal?.aborted) {
|
|
@@ -412,7 +587,8 @@ async function executeStreamAgentResponse(world, agent, messages, publishSSE, ab
|
|
|
412
587
|
publishSSE(world, {
|
|
413
588
|
agentName: agent.id,
|
|
414
589
|
type: 'start',
|
|
415
|
-
messageId
|
|
590
|
+
messageId,
|
|
591
|
+
chatId
|
|
416
592
|
});
|
|
417
593
|
loggerStreaming.debug(`LLM: Starting streaming response for agent=${agent.id}, world=${world.id}, messageId=${messageId}`);
|
|
418
594
|
// Convert messages for LLM (strip custom fields)
|
|
@@ -422,8 +598,9 @@ async function executeStreamAgentResponse(world, agent, messages, publishSSE, ab
|
|
|
422
598
|
const mcpTools = await getMCPToolsForWorld(world.id);
|
|
423
599
|
const mcpToolNames = Object.keys(mcpTools);
|
|
424
600
|
const hasMCPTools = mcpToolNames.length > 0;
|
|
601
|
+
const workingDirectory = getEnvValueFromText(world.variables, 'working_directory') || getDefaultWorkingDirectory();
|
|
425
602
|
// Add tool usage instructions to system message when tools are available
|
|
426
|
-
preparedMessages = appendToolRulesToSystemMessage(preparedMessages, mcpToolNames);
|
|
603
|
+
preparedMessages = appendToolRulesToSystemMessage(preparedMessages, mcpToolNames, { workingDirectory });
|
|
427
604
|
if (hasMCPTools) {
|
|
428
605
|
loggerMCP.debug(`LLM: Including ${Object.keys(mcpTools).length} MCP tools for agent=${agent.id}, world=${world.id}`);
|
|
429
606
|
// Debug: Log complete tool definitions being sent to LLM
|
|
@@ -436,28 +613,71 @@ async function executeStreamAgentResponse(world, agent, messages, publishSSE, ab
|
|
|
436
613
|
});
|
|
437
614
|
}
|
|
438
615
|
}
|
|
616
|
+
emitLLMRequestDiagnostics({
|
|
617
|
+
world,
|
|
618
|
+
agent,
|
|
619
|
+
chatId,
|
|
620
|
+
messageId,
|
|
621
|
+
preparedMessages,
|
|
622
|
+
mcpTools,
|
|
623
|
+
});
|
|
439
624
|
// Use direct OpenAI integration for OpenAI providers
|
|
440
625
|
if (isOpenAIProvider(agent.provider)) {
|
|
441
626
|
const client = createOpenAIClientForAgent(agent);
|
|
442
|
-
const response = await streamOpenAIResponse(client, agent.model, preparedMessages, agent, mcpTools, world, (
|
|
627
|
+
const response = await streamOpenAIResponse(client, agent.model, preparedMessages, agent, mcpTools, world, (chunk) => publishSSE(world, {
|
|
628
|
+
agentName: agent.id,
|
|
629
|
+
type: 'chunk',
|
|
630
|
+
content: chunk.content,
|
|
631
|
+
reasoningContent: chunk.reasoningContent,
|
|
632
|
+
messageId,
|
|
633
|
+
chatId,
|
|
634
|
+
}), messageId, abortSignal);
|
|
635
|
+
emitLLMResponseDiagnostics({
|
|
636
|
+
world,
|
|
637
|
+
agent,
|
|
638
|
+
chatId,
|
|
639
|
+
messageId,
|
|
640
|
+
response,
|
|
641
|
+
});
|
|
443
642
|
// Emit end event after streaming completes
|
|
444
|
-
publishSSE(world, { agentName: agent.id, type: 'end', messageId });
|
|
643
|
+
publishSSE(world, { agentName: agent.id, type: 'end', messageId, chatId });
|
|
445
644
|
return { response, messageId };
|
|
446
645
|
}
|
|
447
646
|
// Use direct Anthropic integration for Anthropic provider
|
|
448
647
|
if (isAnthropicProvider(agent.provider)) {
|
|
449
648
|
const client = createAnthropicClientForAgent(agent);
|
|
450
|
-
const response = await streamAnthropicResponse(client, agent.model, preparedMessages, agent, mcpTools, world, (content) => publishSSE(world, { agentName: agent.id, type: 'chunk', content, messageId }), messageId, abortSignal);
|
|
649
|
+
const response = await streamAnthropicResponse(client, agent.model, preparedMessages, agent, mcpTools, world, (content) => publishSSE(world, { agentName: agent.id, type: 'chunk', content, messageId, chatId }), messageId, abortSignal);
|
|
650
|
+
emitLLMResponseDiagnostics({
|
|
651
|
+
world,
|
|
652
|
+
agent,
|
|
653
|
+
chatId,
|
|
654
|
+
messageId,
|
|
655
|
+
response,
|
|
656
|
+
});
|
|
451
657
|
// Emit end event after streaming completes
|
|
452
|
-
publishSSE(world, { agentName: agent.id, type: 'end', messageId });
|
|
658
|
+
publishSSE(world, { agentName: agent.id, type: 'end', messageId, chatId });
|
|
453
659
|
return { response, messageId };
|
|
454
660
|
}
|
|
455
661
|
// Use direct Google integration for Google provider
|
|
456
662
|
if (isGoogleProvider(agent.provider)) {
|
|
457
663
|
const client = createGoogleClientForAgent(agent);
|
|
458
|
-
const response = await streamGoogleResponse(client, agent.model, preparedMessages, agent, mcpTools, world, (
|
|
664
|
+
const response = await streamGoogleResponse(client, agent.model, preparedMessages, agent, mcpTools, world, (chunk) => publishSSE(world, {
|
|
665
|
+
agentName: agent.id,
|
|
666
|
+
type: 'chunk',
|
|
667
|
+
content: chunk.content,
|
|
668
|
+
reasoningContent: chunk.reasoningContent,
|
|
669
|
+
messageId,
|
|
670
|
+
chatId,
|
|
671
|
+
}), messageId, abortSignal);
|
|
672
|
+
emitLLMResponseDiagnostics({
|
|
673
|
+
world,
|
|
674
|
+
agent,
|
|
675
|
+
chatId,
|
|
676
|
+
messageId,
|
|
677
|
+
response,
|
|
678
|
+
});
|
|
459
679
|
// Emit end event after streaming completes
|
|
460
|
-
publishSSE(world, { agentName: agent.id, type: 'end', messageId });
|
|
680
|
+
publishSSE(world, { agentName: agent.id, type: 'end', messageId, chatId });
|
|
461
681
|
return { response, messageId };
|
|
462
682
|
}
|
|
463
683
|
// All providers now use direct integrations - no AI SDK needed
|
|
@@ -468,7 +688,8 @@ async function executeStreamAgentResponse(world, agent, messages, publishSSE, ab
|
|
|
468
688
|
publishSSE(world, {
|
|
469
689
|
agentName: agent.id,
|
|
470
690
|
type: 'end',
|
|
471
|
-
messageId
|
|
691
|
+
messageId,
|
|
692
|
+
chatId
|
|
472
693
|
});
|
|
473
694
|
loggerStreaming.info(`LLM: Streaming response canceled for agent=${agent.id}, world=${world.id}, messageId=${messageId}`);
|
|
474
695
|
throw new Error(`LLM call canceled for agent ${agent.id}`);
|
|
@@ -478,9 +699,16 @@ async function executeStreamAgentResponse(world, agent, messages, publishSSE, ab
|
|
|
478
699
|
agentName: agent.id,
|
|
479
700
|
type: 'error',
|
|
480
701
|
error: error.message,
|
|
481
|
-
messageId
|
|
702
|
+
messageId,
|
|
703
|
+
chatId
|
|
704
|
+
});
|
|
705
|
+
loggerStreaming.error('LLM: Error during streaming response', {
|
|
706
|
+
agentId: agent.id,
|
|
707
|
+
worldId: world.id,
|
|
708
|
+
chatId,
|
|
709
|
+
messageId,
|
|
710
|
+
error: error instanceof Error ? error.message : String(error)
|
|
482
711
|
});
|
|
483
|
-
loggerStreaming.error(`LLM: Error during streaming response for agent=${agent.id}, world=${world.id}, messageId=${messageId}, error=${error.message}`);
|
|
484
712
|
throw error;
|
|
485
713
|
}
|
|
486
714
|
}
|
|
@@ -491,24 +719,36 @@ export async function generateAgentResponse(world, agent, messages, _publishSSE,
|
|
|
491
719
|
if (abortSignal?.aborted) {
|
|
492
720
|
throw new DOMException(`LLM call aborted before queue for agent ${agent.id}`, 'AbortError');
|
|
493
721
|
}
|
|
722
|
+
const normalizedChatId = typeof chatId === 'string' ? chatId.trim() : '';
|
|
723
|
+
const resolvedChatId = normalizedChatId || null;
|
|
724
|
+
if (!resolvedChatId) {
|
|
725
|
+
throw new Error(`generateAgentResponse: chatId is required for agent ${agent.id}`);
|
|
726
|
+
}
|
|
494
727
|
// Queue the LLM call to ensure serialized execution
|
|
495
|
-
return llmQueue.add(agent.id, world.id,
|
|
728
|
+
return llmQueue.add(agent.id, world.id, resolvedChatId, async (queueAbortSignal) => {
|
|
496
729
|
const { signal: mergedAbortSignal, dispose } = createCombinedAbortSignal(queueAbortSignal, abortSignal);
|
|
497
730
|
try {
|
|
498
731
|
if (mergedAbortSignal?.aborted) {
|
|
499
732
|
throw new DOMException(`LLM call aborted before execution for agent ${agent.id}`, 'AbortError');
|
|
500
733
|
}
|
|
501
|
-
return await executeGenerateAgentResponse(world, agent, messages, skipTools, mergedAbortSignal);
|
|
734
|
+
return await executeGenerateAgentResponse(world, agent, messages, skipTools, resolvedChatId, mergedAbortSignal);
|
|
502
735
|
}
|
|
503
736
|
finally {
|
|
504
737
|
dispose();
|
|
505
738
|
}
|
|
739
|
+
}, {
|
|
740
|
+
onTakingTooLong: ({ elapsedMs, timeoutMs }) => {
|
|
741
|
+
emitLLMTimeoutSystemStatus(world, resolvedChatId, `LLM processing taking too long for ${agent.id} (elapsed ${Math.floor(elapsedMs / 1000)}s, timeout ${Math.floor(timeoutMs / 1000)}s).`);
|
|
742
|
+
},
|
|
743
|
+
onTimedOut: ({ timeoutMs }) => {
|
|
744
|
+
emitLLMTimeoutSystemStatus(world, resolvedChatId, `LLM processing timed out for ${agent.id} after ${Math.floor(timeoutMs / 1000)}s.`);
|
|
745
|
+
},
|
|
506
746
|
});
|
|
507
747
|
}
|
|
508
748
|
/**
|
|
509
749
|
* Internal generation implementation (executed within queue)
|
|
510
750
|
*/
|
|
511
|
-
async function executeGenerateAgentResponse(world, agent, messages, skipTools, abortSignal) {
|
|
751
|
+
async function executeGenerateAgentResponse(world, agent, messages, skipTools, chatId = null, abortSignal) {
|
|
512
752
|
if (abortSignal?.aborted) {
|
|
513
753
|
throw new DOMException('LLM call aborted before start', 'AbortError');
|
|
514
754
|
}
|
|
@@ -520,8 +760,17 @@ async function executeGenerateAgentResponse(world, agent, messages, skipTools, a
|
|
|
520
760
|
const mcpTools = skipTools ? {} : await getMCPToolsForWorld(world.id);
|
|
521
761
|
const mcpToolNames = Object.keys(mcpTools);
|
|
522
762
|
const hasMCPTools = mcpToolNames.length > 0;
|
|
763
|
+
const workingDirectory = getEnvValueFromText(world.variables, 'working_directory') || getDefaultWorkingDirectory();
|
|
523
764
|
// Add tool usage instructions to system message when tools are available
|
|
524
|
-
preparedMessages = appendToolRulesToSystemMessage(preparedMessages, mcpToolNames);
|
|
765
|
+
preparedMessages = appendToolRulesToSystemMessage(preparedMessages, mcpToolNames, { workingDirectory });
|
|
766
|
+
emitLLMRequestDiagnostics({
|
|
767
|
+
world,
|
|
768
|
+
agent,
|
|
769
|
+
chatId,
|
|
770
|
+
messageId,
|
|
771
|
+
preparedMessages,
|
|
772
|
+
mcpTools,
|
|
773
|
+
});
|
|
525
774
|
if (hasMCPTools) {
|
|
526
775
|
loggerMCP.debug(`LLM: Including ${Object.keys(mcpTools).length} MCP tools for agent=${agent.id}, world=${world.id}`);
|
|
527
776
|
// Debug: Log complete tool definitions being sent to LLM
|
|
@@ -555,6 +804,13 @@ async function executeGenerateAgentResponse(world, agent, messages, skipTools, a
|
|
|
555
804
|
agent.lastActive = new Date();
|
|
556
805
|
agent.llmCallCount++;
|
|
557
806
|
agent.lastLLMCall = new Date();
|
|
807
|
+
emitLLMResponseDiagnostics({
|
|
808
|
+
world,
|
|
809
|
+
agent,
|
|
810
|
+
chatId,
|
|
811
|
+
messageId,
|
|
812
|
+
response,
|
|
813
|
+
});
|
|
558
814
|
loggerGeneration.debug(`LLM: Finished non-streaming OpenAI response for agent=${agent.id}, world=${world.id}`, {
|
|
559
815
|
responseType: response.type,
|
|
560
816
|
contentLength: response.content?.length || 0,
|
|
@@ -572,6 +828,13 @@ async function executeGenerateAgentResponse(world, agent, messages, skipTools, a
|
|
|
572
828
|
agent.lastActive = new Date();
|
|
573
829
|
agent.llmCallCount++;
|
|
574
830
|
agent.lastLLMCall = new Date();
|
|
831
|
+
emitLLMResponseDiagnostics({
|
|
832
|
+
world,
|
|
833
|
+
agent,
|
|
834
|
+
chatId,
|
|
835
|
+
messageId,
|
|
836
|
+
response,
|
|
837
|
+
});
|
|
575
838
|
loggerGeneration.debug(`LLM: Finished non-streaming Anthropic response for agent=${agent.id}, world=${world.id}`, {
|
|
576
839
|
responseType: response.type,
|
|
577
840
|
contentLength: response.content?.length || 0,
|
|
@@ -589,6 +852,13 @@ async function executeGenerateAgentResponse(world, agent, messages, skipTools, a
|
|
|
589
852
|
agent.lastActive = new Date();
|
|
590
853
|
agent.llmCallCount++;
|
|
591
854
|
agent.lastLLMCall = new Date();
|
|
855
|
+
emitLLMResponseDiagnostics({
|
|
856
|
+
world,
|
|
857
|
+
agent,
|
|
858
|
+
chatId,
|
|
859
|
+
messageId,
|
|
860
|
+
response,
|
|
861
|
+
});
|
|
592
862
|
loggerGeneration.debug(`LLM: Finished non-streaming Google response for agent=${agent.id}, world=${world.id}`, {
|
|
593
863
|
responseType: response.type,
|
|
594
864
|
contentLength: response.content?.length || 0,
|
|
@@ -606,7 +876,13 @@ async function executeGenerateAgentResponse(world, agent, messages, skipTools, a
|
|
|
606
876
|
loggerGeneration.info(`LLM: Non-streaming response canceled for agent=${agent.id}, world=${world.id}, messageId=${messageId}`);
|
|
607
877
|
throw new Error(`LLM call canceled for agent ${agent.id}`);
|
|
608
878
|
}
|
|
609
|
-
loggerGeneration.error(
|
|
879
|
+
loggerGeneration.error('LLM: Error during non-streaming response', {
|
|
880
|
+
agentId: agent.id,
|
|
881
|
+
worldId: world.id,
|
|
882
|
+
chatId,
|
|
883
|
+
messageId,
|
|
884
|
+
error: error instanceof Error ? error.message : String(error)
|
|
885
|
+
});
|
|
610
886
|
throw error;
|
|
611
887
|
}
|
|
612
888
|
}
|
|
@@ -661,8 +937,17 @@ function createOpenAIClientForAgent(agent) {
|
|
|
661
937
|
switch (agent.provider) {
|
|
662
938
|
case LLMProvider.OPENAI:
|
|
663
939
|
return createClientForProvider('openai', config);
|
|
664
|
-
case LLMProvider.AZURE:
|
|
665
|
-
|
|
940
|
+
case LLMProvider.AZURE: {
|
|
941
|
+
const configuredDeployment = typeof config.deployment === 'string'
|
|
942
|
+
? config.deployment.trim()
|
|
943
|
+
: '';
|
|
944
|
+
const modelDeployment = typeof agent.model === 'string' ? agent.model.trim() : '';
|
|
945
|
+
// For Azure, deployment is selected in the URL path. Prefer runtime model when provided.
|
|
946
|
+
return createClientForProvider('azure', {
|
|
947
|
+
...config,
|
|
948
|
+
deployment: modelDeployment || configuredDeployment,
|
|
949
|
+
});
|
|
950
|
+
}
|
|
666
951
|
case LLMProvider.OPENAI_COMPATIBLE:
|
|
667
952
|
return createClientForProvider('openai-compatible', config);
|
|
668
953
|
case LLMProvider.XAI:
|