aws-runtime-bridge 1.9.33 → 1.9.41
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/dist/adapter/AcodeSdkAdapter.d.ts +66 -5
- package/dist/adapter/AcodeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/AcodeSdkAdapter.js +771 -69
- package/dist/adapter/ClaudeSdkAdapter.d.ts +6 -0
- package/dist/adapter/ClaudeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/ClaudeSdkAdapter.js +24 -1
- package/dist/adapter/OpencodeSdkAdapter.d.ts +19 -0
- package/dist/adapter/OpencodeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/OpencodeSdkAdapter.js +62 -0
- package/dist/adapter/idle-poll-loop.d.ts +2 -1
- package/dist/adapter/idle-poll-loop.d.ts.map +1 -1
- package/dist/adapter/types.d.ts +86 -9
- package/dist/adapter/types.d.ts.map +1 -1
- package/dist/adapter/types.js +15 -5
- package/dist/index.js +15 -0
- package/dist/routes/acode-todos.d.ts +11 -0
- package/dist/routes/acode-todos.d.ts.map +1 -0
- package/dist/routes/acode-todos.js +75 -0
- package/dist/routes/ai-sources.js +4 -1
- package/dist/routes/dashboard.d.ts.map +1 -1
- package/dist/routes/dashboard.js +1 -1
- package/dist/routes/memory.d.ts +1 -1
- package/dist/routes/memory.d.ts.map +1 -1
- package/dist/routes/memory.js +3 -3
- package/dist/routes/pty.d.ts.map +1 -1
- package/dist/routes/pty.js +9 -0
- package/dist/routes/runtime-binding.d.ts.map +1 -1
- package/dist/routes/runtime-binding.js +6 -3
- package/dist/routes/sessions.js +89 -4
- package/dist/routes/sub-agents.d.ts +14 -0
- package/dist/routes/sub-agents.d.ts.map +1 -0
- package/dist/routes/sub-agents.js +267 -0
- package/dist/routes/terminal.d.ts +12 -1
- package/dist/routes/terminal.d.ts.map +1 -1
- package/dist/routes/terminal.js +326 -24
- package/dist/services/acode-package.d.ts +8 -1
- package/dist/services/acode-package.d.ts.map +1 -1
- package/dist/services/acode-package.js +33 -4
- package/dist/services/agent-event-store.d.ts +1 -0
- package/dist/services/agent-event-store.d.ts.map +1 -1
- package/dist/services/aws-client-agent-mcp.d.ts.map +1 -1
- package/dist/services/aws-client-agent-mcp.js +11 -4
- package/dist/services/event-delta-pusher.js +4 -4
- package/dist/services/fileSnapshotStore.js +1 -1
- package/dist/services/legacy-path-migration.d.ts +3 -0
- package/dist/services/legacy-path-migration.d.ts.map +1 -0
- package/dist/services/legacy-path-migration.js +66 -0
- package/dist/services/lifecycle-state.d.ts.map +1 -1
- package/dist/services/lifecycle-state.js +1 -1
- package/dist/services/runtime-binding.d.ts +5 -0
- package/dist/services/runtime-binding.d.ts.map +1 -1
- package/dist/services/runtime-binding.js +33 -1
- package/dist/services/session-output.d.ts +10 -1
- package/dist/services/session-output.d.ts.map +1 -1
- package/dist/services/session-output.js +54 -4
- package/dist/services/sub-agent-manager-instance.d.ts +4 -0
- package/dist/services/sub-agent-manager-instance.d.ts.map +1 -0
- package/dist/services/sub-agent-manager-instance.js +12 -0
- package/dist/services/workspace-files.d.ts +1 -0
- package/dist/services/workspace-files.d.ts.map +1 -1
- package/dist/services/workspace-files.js +57 -1
- package/package/acode/dist/ask-user-question-tool.d.ts +47 -0
- package/package/acode/dist/ask-user-question-tool.d.ts.map +1 -0
- package/package/acode/dist/ask-user-question-tool.js +233 -0
- package/package/acode/dist/built-in-file-tools.d.ts +2 -0
- package/package/acode/dist/built-in-file-tools.d.ts.map +1 -1
- package/package/acode/dist/built-in-file-tools.js +504 -3
- package/package/acode/dist/compaction.d.ts +242 -0
- package/package/acode/dist/compaction.d.ts.map +1 -0
- package/package/acode/dist/compaction.js +919 -0
- package/package/acode/dist/config.d.ts +6 -1
- package/package/acode/dist/config.d.ts.map +1 -1
- package/package/acode/dist/config.js +27 -2
- package/package/acode/dist/index.d.ts +4 -0
- package/package/acode/dist/index.d.ts.map +1 -1
- package/package/acode/dist/index.js +4 -0
- package/package/acode/dist/runtime.d.ts +257 -0
- package/package/acode/dist/runtime.d.ts.map +1 -1
- package/package/acode/dist/runtime.js +1843 -191
- package/package/acode/dist/skill-tool.d.ts +30 -0
- package/package/acode/dist/skill-tool.d.ts.map +1 -0
- package/package/acode/dist/skill-tool.js +174 -0
- package/package/acode/dist/sub-agent-manager.d.ts +264 -0
- package/package/acode/dist/sub-agent-manager.d.ts.map +1 -0
- package/package/acode/dist/sub-agent-manager.js +825 -0
- package/package/acode/dist/sub-agent-store.d.ts +40 -0
- package/package/acode/dist/sub-agent-store.d.ts.map +1 -0
- package/package/acode/dist/sub-agent-store.js +164 -0
- package/package/acode/dist/sub-agent-tools.d.ts +72 -0
- package/package/acode/dist/sub-agent-tools.d.ts.map +1 -0
- package/package/acode/dist/sub-agent-tools.js +429 -0
- package/package/acode/dist/sub-agent-types.d.ts +85 -0
- package/package/acode/dist/sub-agent-types.d.ts.map +1 -0
- package/package/acode/dist/sub-agent-types.js +8 -0
- package/package/acode/dist/todo-store.d.ts +42 -0
- package/package/acode/dist/todo-store.d.ts.map +1 -0
- package/package/acode/dist/todo-store.js +68 -0
- package/package/acode/dist/todo-tool.d.ts +6 -0
- package/package/acode/dist/todo-tool.d.ts.map +1 -0
- package/package/acode/dist/todo-tool.js +138 -0
- package/package/acode/dist/types.d.ts +41 -1
- package/package/acode/dist/types.d.ts.map +1 -1
- package/package/acode/package.json +13 -2
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +9 -0
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/agent-client.js +69 -10
- package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/config.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/config.js +4 -0
- package/package/aws-client-agent-mcp/dist/config.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/constants.d.ts +2 -0
- package/package/aws-client-agent-mcp/dist/constants.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/constants.js +3 -1
- package/package/aws-client-agent-mcp/dist/constants.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/context-manager.d.ts +4 -1
- package/package/aws-client-agent-mcp/dist/context-manager.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/context-manager.js +6 -2
- package/package/aws-client-agent-mcp/dist/context-manager.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/context-manager.test.js +5 -3
- package/package/aws-client-agent-mcp/dist/context-manager.test.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +5 -0
- package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.js +15 -1
- package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +162 -71
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.js +1007 -504
- package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js +371 -253
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +6 -17
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +20 -75
- package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts +45 -45
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-store.js +114 -162
- package/package/aws-client-agent-mcp/dist/memory-store.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-store.test.js +175 -164
- package/package/aws-client-agent-mcp/dist/memory-store.test.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.d.ts +3 -9
- package/package/aws-client-agent-mcp/dist/memory-tools.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.js +31 -58
- package/package/aws-client-agent-mcp/dist/memory-tools.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +40 -9
- package/package/aws-client-agent-mcp/dist/message-buffer.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.js +123 -23
- package/package/aws-client-agent-mcp/dist/message-buffer.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +13 -13
- package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/server-memory-store.js +23 -16
- package/package/aws-client-agent-mcp/dist/server-memory-store.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.js +8 -5
- package/package/aws-client-agent-mcp/dist/status-reporter.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/status-reporter.test.js +93 -0
- package/package/aws-client-agent-mcp/dist/status-reporter.test.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/types.d.ts +12 -25
- package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +34 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/websocket-client.js +146 -18
- package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
- package/package.json +17 -7
- package/dist/adapter/AcodeSdkAdapter.test.d.ts +0 -2
- package/dist/adapter/AcodeSdkAdapter.test.d.ts.map +0 -1
- package/dist/adapter/AcodeSdkAdapter.test.js +0 -2000
- package/dist/adapter/AdapterRegistry.test.d.ts +0 -5
- package/dist/adapter/AdapterRegistry.test.d.ts.map +0 -1
- package/dist/adapter/AdapterRegistry.test.js +0 -118
- package/dist/adapter/ClaudeSdkAdapter.test.d.ts +0 -2
- package/dist/adapter/ClaudeSdkAdapter.test.d.ts.map +0 -1
- package/dist/adapter/ClaudeSdkAdapter.test.js +0 -311
- package/dist/adapter/CodexSdkAdapter.test.d.ts +0 -2
- package/dist/adapter/CodexSdkAdapter.test.d.ts.map +0 -1
- package/dist/adapter/CodexSdkAdapter.test.js +0 -270
- package/dist/adapter/OpencodeSdkAdapter.test.d.ts +0 -2
- package/dist/adapter/OpencodeSdkAdapter.test.d.ts.map +0 -1
- package/dist/adapter/OpencodeSdkAdapter.test.js +0 -158
- package/dist/adapter/acode-tool-names.test.d.ts +0 -2
- package/dist/adapter/acode-tool-names.test.d.ts.map +0 -1
- package/dist/adapter/acode-tool-names.test.js +0 -28
- package/dist/adapter/adapter.test.d.ts +0 -5
- package/dist/adapter/adapter.test.d.ts.map +0 -1
- package/dist/adapter/adapter.test.js +0 -180
- package/dist/adapter/idle-poll-loop.test.d.ts +0 -2
- package/dist/adapter/idle-poll-loop.test.d.ts.map +0 -1
- package/dist/adapter/idle-poll-loop.test.js +0 -85
- package/dist/adapter/types.test.d.ts +0 -2
- package/dist/adapter/types.test.d.ts.map +0 -1
- package/dist/adapter/types.test.js +0 -50
- package/dist/adapters/cc-switch/mcp-acode.test.d.ts +0 -2
- package/dist/adapters/cc-switch/mcp-acode.test.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-acode.test.js +0 -80
- package/dist/adapters/cc-switch/mcp-claudecode.test.d.ts +0 -2
- package/dist/adapters/cc-switch/mcp-claudecode.test.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-claudecode.test.js +0 -75
- package/dist/adapters/cc-switch/mcp-codex.test.d.ts +0 -2
- package/dist/adapters/cc-switch/mcp-codex.test.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-codex.test.js +0 -126
- package/dist/adapters/cc-switch/mcp-opencode.test.d.ts +0 -2
- package/dist/adapters/cc-switch/mcp-opencode.test.d.ts.map +0 -1
- package/dist/adapters/cc-switch/mcp-opencode.test.js +0 -62
- package/dist/adapters/cc-switch/skill-directory.test.d.ts +0 -2
- package/dist/adapters/cc-switch/skill-directory.test.d.ts.map +0 -1
- package/dist/adapters/cc-switch/skill-directory.test.js +0 -74
- package/dist/config.test.d.ts +0 -2
- package/dist/config.test.d.ts.map +0 -1
- package/dist/config.test.js +0 -107
- package/dist/routes/ai-sources.test.d.ts +0 -2
- package/dist/routes/ai-sources.test.d.ts.map +0 -1
- package/dist/routes/ai-sources.test.js +0 -169
- package/dist/routes/file-browser.test.d.ts +0 -5
- package/dist/routes/file-browser.test.d.ts.map +0 -1
- package/dist/routes/file-browser.test.js +0 -155
- package/dist/routes/git.test.d.ts +0 -2
- package/dist/routes/git.test.d.ts.map +0 -1
- package/dist/routes/git.test.js +0 -330
- package/dist/routes/instance.test.d.ts +0 -5
- package/dist/routes/instance.test.d.ts.map +0 -1
- package/dist/routes/instance.test.js +0 -389
- package/dist/routes/mcp.test.d.ts +0 -5
- package/dist/routes/mcp.test.d.ts.map +0 -1
- package/dist/routes/mcp.test.js +0 -92
- package/dist/routes/memory-route-wiring.test.d.ts +0 -2
- package/dist/routes/memory-route-wiring.test.d.ts.map +0 -1
- package/dist/routes/memory-route-wiring.test.js +0 -15
- package/dist/routes/memory.test.d.ts +0 -2
- package/dist/routes/memory.test.d.ts.map +0 -1
- package/dist/routes/memory.test.js +0 -177
- package/dist/routes/properties.test.d.ts +0 -5
- package/dist/routes/properties.test.d.ts.map +0 -1
- package/dist/routes/properties.test.js +0 -72
- package/dist/routes/pty.test.d.ts +0 -2
- package/dist/routes/pty.test.d.ts.map +0 -1
- package/dist/routes/pty.test.js +0 -82
- package/dist/routes/runtime-binding.test.d.ts +0 -2
- package/dist/routes/runtime-binding.test.d.ts.map +0 -1
- package/dist/routes/runtime-binding.test.js +0 -32
- package/dist/routes/sessions.test.d.ts +0 -5
- package/dist/routes/sessions.test.d.ts.map +0 -1
- package/dist/routes/sessions.test.js +0 -86
- package/dist/routes/skills.test.d.ts +0 -5
- package/dist/routes/skills.test.d.ts.map +0 -1
- package/dist/routes/skills.test.js +0 -50
- package/dist/routes/system-metrics.test.d.ts +0 -2
- package/dist/routes/system-metrics.test.d.ts.map +0 -1
- package/dist/routes/system-metrics.test.js +0 -16
- package/dist/routes/terminal.stop-options.test.d.ts +0 -2
- package/dist/routes/terminal.stop-options.test.d.ts.map +0 -1
- package/dist/routes/terminal.stop-options.test.js +0 -39
- package/dist/routes/terminal.test.d.ts +0 -2
- package/dist/routes/terminal.test.d.ts.map +0 -1
- package/dist/routes/terminal.test.js +0 -746
- package/dist/routes/yml.test.d.ts +0 -5
- package/dist/routes/yml.test.d.ts.map +0 -1
- package/dist/routes/yml.test.js +0 -58
- package/dist/services/ai-source-apply.test.d.ts +0 -2
- package/dist/services/ai-source-apply.test.d.ts.map +0 -1
- package/dist/services/ai-source-apply.test.js +0 -138
- package/dist/services/auto-register.test.d.ts +0 -2
- package/dist/services/auto-register.test.d.ts.map +0 -1
- package/dist/services/auto-register.test.js +0 -184
- package/dist/services/aws-client-agent-mcp.test.d.ts +0 -2
- package/dist/services/aws-client-agent-mcp.test.d.ts.map +0 -1
- package/dist/services/aws-client-agent-mcp.test.js +0 -242
- package/dist/services/bridge-package-publish-hooks.test.d.ts +0 -2
- package/dist/services/bridge-package-publish-hooks.test.d.ts.map +0 -1
- package/dist/services/bridge-package-publish-hooks.test.js +0 -136
- package/dist/services/cc-switch-discovery.test.d.ts +0 -2
- package/dist/services/cc-switch-discovery.test.d.ts.map +0 -1
- package/dist/services/cc-switch-discovery.test.js +0 -56
- package/dist/services/cli-commands.test.d.ts +0 -2
- package/dist/services/cli-commands.test.d.ts.map +0 -1
- package/dist/services/cli-commands.test.js +0 -230
- package/dist/services/instance-init-service.test.d.ts +0 -2
- package/dist/services/instance-init-service.test.d.ts.map +0 -1
- package/dist/services/instance-init-service.test.js +0 -140
- package/dist/services/instance-state.test.d.ts +0 -2
- package/dist/services/instance-state.test.d.ts.map +0 -1
- package/dist/services/instance-state.test.js +0 -245
- package/dist/services/mcp-launch-binding-queue.test.d.ts +0 -2
- package/dist/services/mcp-launch-binding-queue.test.d.ts.map +0 -1
- package/dist/services/mcp-launch-binding-queue.test.js +0 -181
- package/dist/services/runtime-binding.test.d.ts +0 -2
- package/dist/services/runtime-binding.test.d.ts.map +0 -1
- package/dist/services/runtime-binding.test.js +0 -78
- package/dist/services/runtime-lifecycle-policy.test.d.ts +0 -2
- package/dist/services/runtime-lifecycle-policy.test.d.ts.map +0 -1
- package/dist/services/runtime-lifecycle-policy.test.js +0 -41
- package/dist/services/session-output.test.d.ts +0 -5
- package/dist/services/session-output.test.d.ts.map +0 -1
- package/dist/services/session-output.test.js +0 -177
- package/dist/services/startup-config-wizard.test.d.ts +0 -2
- package/dist/services/startup-config-wizard.test.d.ts.map +0 -1
- package/dist/services/startup-config-wizard.test.js +0 -184
- package/dist/services/terminal-persistence.test.d.ts +0 -5
- package/dist/services/terminal-persistence.test.d.ts.map +0 -1
- package/dist/services/terminal-persistence.test.js +0 -159
- package/dist/services/tool-installer.test.d.ts +0 -2
- package/dist/services/tool-installer.test.d.ts.map +0 -1
- package/dist/services/tool-installer.test.js +0 -225
- package/dist/services/workspace-files.test.d.ts +0 -2
- package/dist/services/workspace-files.test.d.ts.map +0 -1
- package/dist/services/workspace-files.test.js +0 -648
- package/dist/services/workspace-watch.test.d.ts +0 -2
- package/dist/services/workspace-watch.test.d.ts.map +0 -1
- package/dist/services/workspace-watch.test.js +0 -38
- package/dist/utils/file-utils.test.d.ts +0 -2
- package/dist/utils/file-utils.test.d.ts.map +0 -1
- package/dist/utils/file-utils.test.js +0 -244
- package/dist/utils/logger.test.d.ts +0 -2
- package/dist/utils/logger.test.d.ts.map +0 -1
- package/dist/utils/logger.test.js +0 -93
- package/dist/utils/sdk-package-loader.test.d.ts +0 -2
- package/dist/utils/sdk-package-loader.test.d.ts.map +0 -1
- package/dist/utils/sdk-package-loader.test.js +0 -84
- package/dist/utils/validation.test.d.ts +0 -2
- package/dist/utils/validation.test.d.ts.map +0 -1
- package/dist/utils/validation.test.js +0 -88
- package/dist/utils/yaml-utils.test.d.ts +0 -2
- package/dist/utils/yaml-utils.test.d.ts.map +0 -1
- package/dist/utils/yaml-utils.test.js +0 -363
package/dist/routes/terminal.js
CHANGED
|
@@ -27,6 +27,56 @@ import { logger as log } from "../utils/logger.js";
|
|
|
27
27
|
export const terminalRouter = Router();
|
|
28
28
|
// 导出 SDK 会话存储,供其他模块使用(如 sessions.ts)
|
|
29
29
|
export const sdkSessions = new Map();
|
|
30
|
+
// ── 活跃状态定期刷新,防止长时间 LLM 调用期间 WebSocket 心跳超时导致 LOST ──
|
|
31
|
+
/**
|
|
32
|
+
* 状态刷新间隔(毫秒)。
|
|
33
|
+
* 服务端 WebSocket 空闲超时默认 60 秒(maxIdleTimeMs),取 45 秒作为刷新周期,
|
|
34
|
+
* 留出足够的余量防止因网络抖动或事件循环延迟导致的超时。
|
|
35
|
+
*/
|
|
36
|
+
const STATUS_REFRESH_INTERVAL_MS = 45_000;
|
|
37
|
+
/** 每个 session 的定期刷新定时器,仅在 thinking/tool_using/compacting 时运行 */
|
|
38
|
+
const statusRefreshTimers = new Map();
|
|
39
|
+
/**
|
|
40
|
+
* 启动 session 定期状态刷新。
|
|
41
|
+
* 每隔 STATUS_REFRESH_INTERVAL_MS 向服务端发送一次当前运行状态,
|
|
42
|
+
* 刷新服务端 WebSocket 会话的 lastActiveTime,避免长时间无消息导致连接断开 → LOST。
|
|
43
|
+
*/
|
|
44
|
+
function startStatusRefresh(sessionId) {
|
|
45
|
+
if (statusRefreshTimers.has(sessionId))
|
|
46
|
+
return;
|
|
47
|
+
const timer = setInterval(() => {
|
|
48
|
+
const entry = sdkSessions.get(sessionId);
|
|
49
|
+
if (!entry) {
|
|
50
|
+
stopStatusRefresh(sessionId);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const status = entry.currentRuntimeStatus;
|
|
54
|
+
// 仅活跃状态需要刷新:thinking / tool_using / compacting
|
|
55
|
+
if (status !== "thinking" && status !== "tool_using" && status !== "compacting") {
|
|
56
|
+
stopStatusRefresh(sessionId);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// 发送轻量级状态刷新(不带 actionInfo),保持 WebSocket 会话活跃
|
|
60
|
+
void sendStatus(entry.agentId, sessionId, status, undefined, // 不传 actionInfo,避免创建额外时间线条目
|
|
61
|
+
undefined, {
|
|
62
|
+
runtimeAccessToken: entry.runtimeAccessToken,
|
|
63
|
+
schedulerBaseUrl: entry.schedulerBaseUrl,
|
|
64
|
+
}).catch(() => {
|
|
65
|
+
// sendStatus 失败静默处理,不影响主流程
|
|
66
|
+
});
|
|
67
|
+
}, STATUS_REFRESH_INTERVAL_MS);
|
|
68
|
+
statusRefreshTimers.set(sessionId, timer);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 停止 session 定期状态刷新。
|
|
72
|
+
*/
|
|
73
|
+
function stopStatusRefresh(sessionId) {
|
|
74
|
+
const timer = statusRefreshTimers.get(sessionId);
|
|
75
|
+
if (timer) {
|
|
76
|
+
clearInterval(timer);
|
|
77
|
+
statusRefreshTimers.delete(sessionId);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
30
80
|
const TOOL_RESULT_PREVIEW_MAX_LENGTH = 4000;
|
|
31
81
|
const AI_REQUEST_BODY_MARKER = "\n\n请求体:\n";
|
|
32
82
|
/**
|
|
@@ -58,10 +108,10 @@ const AI_REQUEST_HEADERS_MARKER = "\n\n请求头:\n";
|
|
|
58
108
|
const startingAgents = new Set();
|
|
59
109
|
// ============ 启动记忆加载 ============
|
|
60
110
|
/**
|
|
61
|
-
* 从工作区的 .agentswork/memory/ 目录加载
|
|
111
|
+
* 从工作区的 .agentswork/memory/ 目录加载 recently_memory 和 agent_memory,
|
|
62
112
|
* 格式化为可注入 System 3 的文本。
|
|
63
113
|
*
|
|
64
|
-
* 主流程:遍历目录下所有 domain JSON 文件 -> 提取
|
|
114
|
+
* 主流程:遍历目录下所有 domain JSON 文件 -> 提取 recently_memory/agent_memory 记录 ->
|
|
65
115
|
* 按类型分组排序 -> 返回格式化文本;目录不存在或解析失败时返回 undefined。
|
|
66
116
|
*/
|
|
67
117
|
async function loadAgentStartupMemories(workspacePath, options) {
|
|
@@ -93,10 +143,10 @@ async function loadAgentStartupMemories(workspacePath, options) {
|
|
|
93
143
|
const content = (record.content || "").trim();
|
|
94
144
|
if (!content)
|
|
95
145
|
continue;
|
|
96
|
-
if (type === "
|
|
146
|
+
if (type === "recently_memory") {
|
|
97
147
|
taskList.push({ title: record.title, content, uri: record.uri || "" });
|
|
98
148
|
}
|
|
99
|
-
else if (type === "
|
|
149
|
+
else if (type === "agent_memory") {
|
|
100
150
|
recentMemories.push({ title: record.title, content, uri: record.uri || "" });
|
|
101
151
|
}
|
|
102
152
|
}
|
|
@@ -115,8 +165,8 @@ async function loadAgentStartupMemories(workspacePath, options) {
|
|
|
115
165
|
"X-Runtime-Token": options.runtimeAccessToken,
|
|
116
166
|
Authorization: `Bearer ${options.runtimeAccessToken}`,
|
|
117
167
|
};
|
|
118
|
-
// 并行请求
|
|
119
|
-
const typesToFetch = ["
|
|
168
|
+
// 并行请求 recently_memory 和 agent_memory
|
|
169
|
+
const typesToFetch = ["recently_memory", "agent_memory"];
|
|
120
170
|
const results = await Promise.allSettled(typesToFetch.map((memoryType) => fetch(mcpUrl, {
|
|
121
171
|
method: "POST",
|
|
122
172
|
headers,
|
|
@@ -136,7 +186,7 @@ async function loadAgentStartupMemories(workspacePath, options) {
|
|
|
136
186
|
const records = settled.value;
|
|
137
187
|
if (!Array.isArray(records))
|
|
138
188
|
continue;
|
|
139
|
-
const target = typesToFetch[i] === "
|
|
189
|
+
const target = typesToFetch[i] === "recently_memory" ? taskList : recentMemories;
|
|
140
190
|
for (const r of records) {
|
|
141
191
|
const content = (r.content || "").trim();
|
|
142
192
|
if (!content)
|
|
@@ -156,12 +206,12 @@ async function loadAgentStartupMemories(workspacePath, options) {
|
|
|
156
206
|
if (taskList.length > 0) {
|
|
157
207
|
const items = taskList.slice(0, MAX_PER_TYPE);
|
|
158
208
|
const lines = items.map((t, i) => {
|
|
159
|
-
const titleLine = t.title ? `【${t.title}】` :
|
|
209
|
+
const titleLine = t.title ? `【${t.title}】` : `条目 ${i + 1}`;
|
|
160
210
|
return `${titleLine}\n${t.content}`;
|
|
161
211
|
});
|
|
162
|
-
sections.push(
|
|
212
|
+
sections.push(`【短期记忆】\n${lines.join("\n\n")}`);
|
|
163
213
|
if (taskList.length > MAX_PER_TYPE) {
|
|
164
|
-
sections.push(`... 及另外 ${taskList.length - MAX_PER_TYPE}
|
|
214
|
+
sections.push(`... 及另外 ${taskList.length - MAX_PER_TYPE} 条短期记忆`);
|
|
165
215
|
}
|
|
166
216
|
}
|
|
167
217
|
if (recentMemories.length > 0) {
|
|
@@ -170,9 +220,9 @@ async function loadAgentStartupMemories(workspacePath, options) {
|
|
|
170
220
|
const titleLine = t.title ? `【${t.title}】` : "";
|
|
171
221
|
return titleLine ? `${titleLine}\n${t.content}` : t.content;
|
|
172
222
|
});
|
|
173
|
-
sections.push(
|
|
223
|
+
sections.push(`【agent认知】\n${lines.join("\n\n")}`);
|
|
174
224
|
if (recentMemories.length > MAX_PER_TYPE) {
|
|
175
|
-
sections.push(`... 及另外 ${recentMemories.length - MAX_PER_TYPE}
|
|
225
|
+
sections.push(`... 及另外 ${recentMemories.length - MAX_PER_TYPE} 条 agent 认知`);
|
|
176
226
|
}
|
|
177
227
|
}
|
|
178
228
|
if (sections.length === 0)
|
|
@@ -226,21 +276,34 @@ export function parseRuntimeStopOptions(body) {
|
|
|
226
276
|
}
|
|
227
277
|
export function resolveStatusChangeUsage(actionInfo) {
|
|
228
278
|
const usage = actionInfo?.usage;
|
|
229
|
-
if (!usage)
|
|
279
|
+
if (!usage) {
|
|
230
280
|
return undefined;
|
|
281
|
+
}
|
|
231
282
|
const inputTokens = Number.isFinite(usage.inputTokens)
|
|
232
283
|
? usage.inputTokens
|
|
233
284
|
: 0;
|
|
234
285
|
const outputTokens = Number.isFinite(usage.outputTokens)
|
|
235
286
|
? usage.outputTokens
|
|
236
287
|
: 0;
|
|
237
|
-
|
|
288
|
+
// ★ 即使 input/output token 都为 0(如 session_started 初始状态),只要有任一压缩配置字段也应传出,
|
|
289
|
+
// 否则前端拿不到 compactionThreshold,压缩点竖线无法显示。
|
|
290
|
+
if (inputTokens <= 0 &&
|
|
291
|
+
outputTokens <= 0 &&
|
|
292
|
+
!usage.contextLimit &&
|
|
293
|
+
!usage.maxOutput &&
|
|
294
|
+
!usage.inputLimit &&
|
|
295
|
+
!usage.compactionThreshold) {
|
|
238
296
|
return undefined;
|
|
239
|
-
|
|
297
|
+
}
|
|
298
|
+
const result = {
|
|
240
299
|
inputTokens,
|
|
241
300
|
outputTokens,
|
|
242
301
|
...(usage.contextLimit ? { contextLimit: usage.contextLimit } : {}),
|
|
302
|
+
...(usage.maxOutput ? { maxOutput: usage.maxOutput } : {}),
|
|
303
|
+
...(usage.inputLimit ? { inputLimit: usage.inputLimit } : {}),
|
|
304
|
+
...(usage.compactionThreshold ? { compactionThreshold: usage.compactionThreshold } : {}),
|
|
243
305
|
};
|
|
306
|
+
return result;
|
|
244
307
|
}
|
|
245
308
|
export function resolveStatusChangeRuntimeState(status, actionInfo) {
|
|
246
309
|
const normalizedStatus = String(status || "")
|
|
@@ -937,10 +1000,15 @@ function formatSdkLogMessage(event) {
|
|
|
937
1000
|
}
|
|
938
1001
|
return undefined;
|
|
939
1002
|
}
|
|
1003
|
+
// 匹配 CSI 类 ANSI 转义序列(颜色/光标/清屏等),用于 DevTools 日志预览剥离
|
|
1004
|
+
const ANSI_ESCAPE_PATTERN = /\x1b\[[0-9;?]*[a-zA-Z]/g;
|
|
1005
|
+
function stripAnsiEscapeCodes(text) {
|
|
1006
|
+
return text.replace(ANSI_ESCAPE_PATTERN, "");
|
|
1007
|
+
}
|
|
940
1008
|
function formatCommandOutputLogMessage(event) {
|
|
941
1009
|
const stream = typeof event.data.stream === "string" ? event.data.stream : "mixed";
|
|
942
1010
|
const sequence = typeof event.data.sequence === "number" ? ` #${event.data.sequence}` : "";
|
|
943
|
-
const normalized = String(event.data.text || "")
|
|
1011
|
+
const normalized = stripAnsiEscapeCodes(String(event.data.text || ""))
|
|
944
1012
|
.replace(/\s+/g, " ")
|
|
945
1013
|
.trim();
|
|
946
1014
|
const preview = normalized.length > 240 ? `${normalized.slice(0, 240)}...` : normalized;
|
|
@@ -1083,17 +1151,45 @@ function isWaitingInputProgressEvent(event, currentRuntimeStatus) {
|
|
|
1083
1151
|
}
|
|
1084
1152
|
return event.type === "thinking" || event.type === "text_delta";
|
|
1085
1153
|
}
|
|
1154
|
+
/**
|
|
1155
|
+
* 从事件 data 中提取 estimatedContextTokens(兼容多种字段名)。
|
|
1156
|
+
* 返回 undefined 表示无有效值,使调用方能区分"无数据"和"0"。
|
|
1157
|
+
*/
|
|
1158
|
+
function extractEstimatedContextTokens(data) {
|
|
1159
|
+
for (const key of [
|
|
1160
|
+
"estimatedContextTokens",
|
|
1161
|
+
"contextTokens",
|
|
1162
|
+
"context_tokens",
|
|
1163
|
+
"contextUsedTokens",
|
|
1164
|
+
"context_used_tokens",
|
|
1165
|
+
]) {
|
|
1166
|
+
const value = data[key];
|
|
1167
|
+
const count = Number(value);
|
|
1168
|
+
if (Number.isFinite(count) && count > 0) {
|
|
1169
|
+
return count;
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
return undefined;
|
|
1173
|
+
}
|
|
1086
1174
|
export function resolveRuntimeStatusFromProviderEvent(event, currentRuntimeStatus) {
|
|
1087
1175
|
if (isWaitingInputProgressEvent(event, currentRuntimeStatus)) {
|
|
1088
1176
|
return undefined;
|
|
1089
1177
|
}
|
|
1090
1178
|
if (event.type === "ai_request") {
|
|
1179
|
+
// ★ 从 event.data 提取 estimatedContextTokens 构建 usage,
|
|
1180
|
+
// 确保 event handler 路径也能传递 token 用量到前端。
|
|
1181
|
+
// 这对压缩后面板刷新尤为关键:压缩后 ai_request 的 estimatedContextTokens
|
|
1182
|
+
// 反映了压缩后的真实上下文大小,前端据此更新进度条。
|
|
1183
|
+
const estimatedTokens = extractEstimatedContextTokens(event.data);
|
|
1091
1184
|
return {
|
|
1092
1185
|
status: "thinking",
|
|
1093
1186
|
actionInfo: {
|
|
1094
1187
|
actionType: "ai_request",
|
|
1095
1188
|
actionLabel: "AI请求",
|
|
1096
1189
|
actionDetail: formatAiRequestDetail(event.data),
|
|
1190
|
+
...(estimatedTokens !== undefined
|
|
1191
|
+
? { usage: { inputTokens: estimatedTokens, outputTokens: 0 } }
|
|
1192
|
+
: {}),
|
|
1097
1193
|
},
|
|
1098
1194
|
};
|
|
1099
1195
|
}
|
|
@@ -1145,11 +1241,39 @@ export function resolveRuntimeStatusFromProviderEvent(event, currentRuntimeStatu
|
|
|
1145
1241
|
if (event.type === "error") {
|
|
1146
1242
|
return { status: "error" };
|
|
1147
1243
|
}
|
|
1244
|
+
if (event.type === "context_compaction") {
|
|
1245
|
+
return {
|
|
1246
|
+
status: "compacting",
|
|
1247
|
+
actionInfo: {
|
|
1248
|
+
actionType: "context_compaction",
|
|
1249
|
+
actionLabel: event.data.actionLabel,
|
|
1250
|
+
actionDetail: event.data.actionDetail,
|
|
1251
|
+
...(event.data.actionId ? { actionId: event.data.actionId } : {}),
|
|
1252
|
+
...(event.data.parentId ? { parentId: event.data.parentId } : {}),
|
|
1253
|
+
},
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
1256
|
+
if (event.type === "runtime_capabilities") {
|
|
1257
|
+
// 运行时能力清单(MCP 工具 / Skill 列表)—— 保持当前运行态不变,仅推送 actionInfo 到时间线供调试面板展示
|
|
1258
|
+
return {
|
|
1259
|
+
status: currentRuntimeStatus || "waiting_input",
|
|
1260
|
+
actionInfo: {
|
|
1261
|
+
actionType: "runtime_capabilities",
|
|
1262
|
+
actionLabel: event.data.actionLabel || "运行时能力",
|
|
1263
|
+
actionDetail: event.data.actionDetail,
|
|
1264
|
+
},
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1148
1267
|
return undefined;
|
|
1149
1268
|
}
|
|
1150
1269
|
// Per-session 输出队列:确保 sendOutput HTTP POST 按事件顺序串行到达 Server,
|
|
1151
1270
|
// 避免并发 POST 因网络时序导致流式文本 chunk 乱序。
|
|
1152
1271
|
const sdkOutputQueueBySession = new Map();
|
|
1272
|
+
// Per-session 压缩状态事件队列:确保 context_compaction 事件(start/detect/prune/.../end)
|
|
1273
|
+
// 按发射顺序串行发送 HTTP POST,避免并发请求导致部分事件丢失(DB 证据:所有压缩都只保留了 2-4 个事件)。
|
|
1274
|
+
// ★ 根因:runtime.ts 同步连续发射 start/detect 等事件,多个 void sendStatus 并发执行 HTTP POST,
|
|
1275
|
+
// 部分 HTTP 请求因竞争/超时/Java 后端 FOR UPDATE 锁等待而失败,事件永久丢失(本地 buffer 不重推)。
|
|
1276
|
+
const compactionStatusChainBySession = new Map();
|
|
1153
1277
|
/** 小 chunk 积攒缓存:sessionId:sourceEventType → { buffer, seq, timer, sourceEventType, entry },不足 20 字符时积攒最多 500ms 再推送 */
|
|
1154
1278
|
const sdkOutputSmallChunkAccumulators = new Map();
|
|
1155
1279
|
/** 小 chunk 积攒阈值:字符数少于此值的 output 事件积攒发送 */
|
|
@@ -1272,11 +1396,29 @@ function wireSdkAdapterEvents(adapter, definition) {
|
|
|
1272
1396
|
const entry = sdkSessions.get(event.sessionId);
|
|
1273
1397
|
if (entry) {
|
|
1274
1398
|
console.log(`[${definition.displayName} Adapter] Event: ${event.type} for session ${event.sessionId}`);
|
|
1275
|
-
// Skip sendStatus for thinking/text_delta/tool_use_start events — the status-change
|
|
1399
|
+
// Skip sendStatus for thinking/text_delta/tool_use_start/context_compaction/ai_request events — the status-change
|
|
1276
1400
|
// listener already emits the authoritative status with restored actionInfo,
|
|
1277
1401
|
// avoiding duplicate timeline entries in agentEventStore.
|
|
1278
|
-
|
|
1402
|
+
// ★ context_compaction 加入此列表:adapter 对每个压缩事件(start/phase/end)都会同时
|
|
1403
|
+
// 调用 emitProviderEvent(触发 event 监听器)和 emit("status-change")(触发 status-change 监听器),
|
|
1404
|
+
// 两条路径都会 sendStatus,导致 Bridge 收到重复事件。虽然前端 seenActionIds 会去重,
|
|
1405
|
+
// 但异步 sendStatus 到达顺序不确定,会造成同时间戳事件顺序错乱(如 prune_end 排在 prune_start 前)。
|
|
1406
|
+
// 只保留 status-change 路径(含完整 actionId/parentId),确保父子事件正确匹配与排序。
|
|
1407
|
+
// ★ ai_request 加入此列表(修复 BUG:Agent 永久卡在 "AI请求" 状态):
|
|
1408
|
+
// ai_request 同时触发 provider event 路径和 status-change 路径两条 sendStatus,
|
|
1409
|
+
// 而 tool_use_start(编辑文件等)仅通过 status-change 路径发送。
|
|
1410
|
+
// 异步 HTTP 乱序导致 ai_request 的 provider-event sendStatus 可能晚于 tool_use_start 到达,
|
|
1411
|
+
// 覆盖前端状态为 "AI请求",而时间线正确显示 "编辑文件"。
|
|
1412
|
+
// 将 ai_request 加入 deferred 列表,使其仅通过 status-change 路径发送,
|
|
1413
|
+
// 与 tool_use_start 保持一致,消除双路径竞态。
|
|
1414
|
+
const isDeferredStatusEvent = event.type === "thinking" || event.type === "text_delta" || event.type === "tool_use_start" || event.type === "context_compaction" || event.type === "ai_request";
|
|
1279
1415
|
if (!isDeferredStatusEvent) {
|
|
1416
|
+
// ★ 修复时序竞争:runtime_capabilities 事件缓存 actionDetail,
|
|
1417
|
+
// 用于 session 稳定后重发(防止 "starting" 状态尚未更新 runtime_session_id
|
|
1418
|
+
// 导致服务端丢弃事件)
|
|
1419
|
+
if (event.type === "runtime_capabilities" && event.data.actionDetail) {
|
|
1420
|
+
entry.cachedCapabilitiesActionDetail = event.data.actionDetail;
|
|
1421
|
+
}
|
|
1280
1422
|
const runtimeStatus = resolveRuntimeStatusFromProviderEvent(event, entry.currentRuntimeStatus);
|
|
1281
1423
|
if (runtimeStatus) {
|
|
1282
1424
|
void sendStatus(entry.agentId, event.sessionId, runtimeStatus.status, runtimeStatus.actionInfo, resolveStatusChangeUsage(runtimeStatus.actionInfo), {
|
|
@@ -1308,6 +1450,13 @@ function wireSdkAdapterEvents(adapter, definition) {
|
|
|
1308
1450
|
adapter.on("status-change", (sessionId, status, actionInfo) => {
|
|
1309
1451
|
const entry = sdkSessions.get(sessionId);
|
|
1310
1452
|
if (entry) {
|
|
1453
|
+
// ★ 活跃状态定期刷新:防止长时间 LLM 调用期间服务端 WebSocket 空闲超时导致 LOST
|
|
1454
|
+
if (status === "thinking" || status === "tool_using" || status === "compacting") {
|
|
1455
|
+
startStatusRefresh(sessionId);
|
|
1456
|
+
}
|
|
1457
|
+
else {
|
|
1458
|
+
stopStatusRefresh(sessionId);
|
|
1459
|
+
}
|
|
1311
1460
|
const runtimeState = resolveStatusChangeRuntimeState(status, actionInfo);
|
|
1312
1461
|
entry.currentRuntimeStatus = runtimeState.status;
|
|
1313
1462
|
// 当新状态未携带动作且进入 thinking 时,保留上一个 idle 类动作(如 poll_message),
|
|
@@ -1351,10 +1500,69 @@ function wireSdkAdapterEvents(adapter, definition) {
|
|
|
1351
1500
|
actionInput: entry.currentRuntimeActionInput,
|
|
1352
1501
|
}
|
|
1353
1502
|
: undefined;
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1503
|
+
// ★ 对 compacting 状态(context_compaction 事件)使用 per-session 序列化队列,
|
|
1504
|
+
// 避免 start/detect/prune/.../end 等事件并发 HTTP POST 导致部分事件丢失。
|
|
1505
|
+
// DB 证据:所有压缩都只保留了 2-4 个事件(应该有 7 个),根因是并发请求竞争。
|
|
1506
|
+
if (runtimeState.status === "compacting") {
|
|
1507
|
+
const prev = compactionStatusChainBySession.get(sessionId) ?? Promise.resolve();
|
|
1508
|
+
const next = prev.then(async () => {
|
|
1509
|
+
// ★ 重试机制:HTTP 失败(sendStatus 返回 undefined)时重试,
|
|
1510
|
+
// 避免因网络超时/瞬时故障导致压缩事件(特别是父 start 事件)永久丢失。
|
|
1511
|
+
// scheduleEventPush 是 no-op,HTTP 回调是唯一投递路径,无 fallback。
|
|
1512
|
+
const maxRetries = 2;
|
|
1513
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
1514
|
+
const response = await sendStatus(entry.agentId, sessionId, runtimeState.status, restoredActionInfo, resolveStatusChangeUsage(runtimeState.actionInfo), {
|
|
1515
|
+
runtimeAccessToken: entry.runtimeAccessToken,
|
|
1516
|
+
schedulerBaseUrl: entry.schedulerBaseUrl,
|
|
1517
|
+
});
|
|
1518
|
+
if (response !== undefined)
|
|
1519
|
+
return; // HTTP 成功
|
|
1520
|
+
if (attempt < maxRetries) {
|
|
1521
|
+
log.warn(`[${definition.displayName}] compaction sendStatus attempt ${attempt + 1} failed (HTTP), retrying in ${1000 * (attempt + 1)}ms...`);
|
|
1522
|
+
await new Promise((r) => setTimeout(r, 1000 * (attempt + 1)));
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
log.warn(`[${definition.displayName}] compaction sendStatus failed after ${maxRetries + 1} attempts, event may be lost`);
|
|
1526
|
+
}).catch((err) => {
|
|
1527
|
+
// 链中某次失败不影响后续事件发送
|
|
1528
|
+
log.warn(`[${definition.displayName}] compaction status chain error:`, err);
|
|
1529
|
+
});
|
|
1530
|
+
compactionStatusChainBySession.set(sessionId, next);
|
|
1531
|
+
// 链结束后清理,避免内存泄漏
|
|
1532
|
+
next.finally(() => {
|
|
1533
|
+
if (compactionStatusChainBySession.get(sessionId) === next) {
|
|
1534
|
+
compactionStatusChainBySession.delete(sessionId);
|
|
1535
|
+
}
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
else {
|
|
1539
|
+
// ★ 修复重复时间线条目:当 shouldPreservePrevAction 为 true 且新 actionInfo 为 undefined
|
|
1540
|
+
// (idle 类型 poll_message 的 tool_use_end status-change 传 undefined)时,
|
|
1541
|
+
// 不传 restoredActionInfo,避免 dashboard 创建第二个"调用MCP"时间线条目。
|
|
1542
|
+
// tool_use_start 的 status-change 已创建了一个条目,这里只需纯状态变更。
|
|
1543
|
+
const skipRestoredActionInfo = shouldPreservePrevAction && !runtimeState.actionInfo?.actionType;
|
|
1544
|
+
void sendStatus(entry.agentId, sessionId, runtimeState.status, skipRestoredActionInfo ? undefined : restoredActionInfo, resolveStatusChangeUsage(runtimeState.actionInfo), {
|
|
1545
|
+
runtimeAccessToken: entry.runtimeAccessToken,
|
|
1546
|
+
schedulerBaseUrl: entry.schedulerBaseUrl,
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1549
|
+
// ★ 修复时序竞争:session 稳定到 waiting_input 时,若缓存了 runtime_capabilities
|
|
1550
|
+
// 但尚未被清除(说明第一次发送可能因 runtime_session_id 未及时更新而被服务端丢弃),
|
|
1551
|
+
// 在此重发确保前端最终能收到能力清单。
|
|
1552
|
+
if (runtimeState.status === "waiting_input" &&
|
|
1553
|
+
entry.cachedCapabilitiesActionDetail) {
|
|
1554
|
+
const cachedDetail = entry.cachedCapabilitiesActionDetail;
|
|
1555
|
+
entry.cachedCapabilitiesActionDetail = undefined;
|
|
1556
|
+
console.log(`[${definition.displayName} Adapter] Re-sending cached runtime_capabilities for agent ${entry.agentId} (session stabilized to waiting_input)`);
|
|
1557
|
+
void sendStatus(entry.agentId, sessionId, "waiting_input", {
|
|
1558
|
+
actionType: "runtime_capabilities",
|
|
1559
|
+
actionLabel: "运行时能力",
|
|
1560
|
+
actionDetail: cachedDetail,
|
|
1561
|
+
}, undefined, {
|
|
1562
|
+
runtimeAccessToken: entry.runtimeAccessToken,
|
|
1563
|
+
schedulerBaseUrl: entry.schedulerBaseUrl,
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1358
1566
|
}
|
|
1359
1567
|
});
|
|
1360
1568
|
adapter.on("ask-user-question", (data) => {
|
|
@@ -1364,7 +1572,7 @@ function wireSdkAdapterEvents(adapter, definition) {
|
|
|
1364
1572
|
void sendQuestionRequest(entry.agentId, data.sessionId, Array.isArray(data.questions) ? data.questions : [], {
|
|
1365
1573
|
runtimeAccessToken: entry.runtimeAccessToken,
|
|
1366
1574
|
schedulerBaseUrl: entry.schedulerBaseUrl,
|
|
1367
|
-
});
|
|
1575
|
+
}, data.toolCallId);
|
|
1368
1576
|
}
|
|
1369
1577
|
});
|
|
1370
1578
|
adapter.on("permission-request", (data) => {
|
|
@@ -1431,7 +1639,9 @@ async function startSdkSession(req, res) {
|
|
|
1431
1639
|
// Per-agent model override(优先于全局配置)
|
|
1432
1640
|
model: perAgentModel,
|
|
1433
1641
|
// Per-instance AI provider 覆盖(仅 ACode 消费;优先级:api > env > file > global)
|
|
1434
|
-
instanceAiConfig: perInstanceAiConfig,
|
|
1642
|
+
instanceAiConfig: perInstanceAiConfig,
|
|
1643
|
+
// Sub Agent 模型/强度覆盖(仅 ACode 消费,空值=继承主 Agent)
|
|
1644
|
+
subAgentModel: perAgentSubAgentModel, subAgentEffort: perAgentSubAgentEffort, } = req.body || {};
|
|
1435
1645
|
const _dbg = getInstanceAiConfigDebugLogger();
|
|
1436
1646
|
void _dbg.log({
|
|
1437
1647
|
level: "info",
|
|
@@ -1639,6 +1849,13 @@ async function startSdkSession(req, res) {
|
|
|
1639
1849
|
...(resolvedInstanceAiConfig
|
|
1640
1850
|
? { instanceAiConfig: resolvedInstanceAiConfig }
|
|
1641
1851
|
: {}),
|
|
1852
|
+
// Sub Agent 模型/强度覆盖(仅 ACode 消费)
|
|
1853
|
+
...(typeof perAgentSubAgentModel === "string" && perAgentSubAgentModel.trim()
|
|
1854
|
+
? { subAgentModel: perAgentSubAgentModel.trim() }
|
|
1855
|
+
: {}),
|
|
1856
|
+
...(typeof perAgentSubAgentEffort === "string" && perAgentSubAgentEffort.trim()
|
|
1857
|
+
? { subAgentEffort: perAgentSubAgentEffort.trim() }
|
|
1858
|
+
: {}),
|
|
1642
1859
|
extraMcpServers: extraMcpServers || {},
|
|
1643
1860
|
envOverrides: buildRuntimeEnv(String(agentId), String(workspacePath), process.env, effectiveEnvOverrides),
|
|
1644
1861
|
};
|
|
@@ -1693,6 +1910,7 @@ async function startSdkSession(req, res) {
|
|
|
1693
1910
|
catch (error) {
|
|
1694
1911
|
// 同步错误处理(校验失败等)
|
|
1695
1912
|
if (sessionId) {
|
|
1913
|
+
stopStatusRefresh(sessionId);
|
|
1696
1914
|
sdkSessions.delete(sessionId);
|
|
1697
1915
|
}
|
|
1698
1916
|
if (normalizedAgentId) {
|
|
@@ -1784,6 +2002,7 @@ async function startSdkSessionBg(params) {
|
|
|
1784
2002
|
}
|
|
1785
2003
|
catch (error) {
|
|
1786
2004
|
// 后台启动失败:清理本地状态 + 通知 server
|
|
2005
|
+
stopStatusRefresh(sessionId);
|
|
1787
2006
|
sdkSessions.delete(sessionId);
|
|
1788
2007
|
await removePersistedSession(sessionId);
|
|
1789
2008
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -1985,6 +2204,7 @@ terminalRouter.post("/sdk/stop", validateToken, async (req, res) => {
|
|
|
1985
2204
|
// 如果有活跃 AI 请求,先立即中止(fire-and-forget),再清理资源
|
|
1986
2205
|
adapter.abortCurrentTurn(sessionId).catch(() => { });
|
|
1987
2206
|
await adapter.terminateSession(sessionId);
|
|
2207
|
+
stopStatusRefresh(sessionId);
|
|
1988
2208
|
sdkSessions.delete(sessionId);
|
|
1989
2209
|
stopTerminalCommandProcess(sessionId);
|
|
1990
2210
|
await removePersistedSession(sessionId);
|
|
@@ -2036,6 +2256,86 @@ terminalRouter.get("/sdk/status/:sessionId", validateToken, (req, res) => {
|
|
|
2036
2256
|
res.status(500).json({ error: errorMessage });
|
|
2037
2257
|
}
|
|
2038
2258
|
});
|
|
2259
|
+
/**
|
|
2260
|
+
* GET /runtime/sdk/capabilities/:sessionId
|
|
2261
|
+
*
|
|
2262
|
+
* 主动查询会话的运行时能力清单(MCP 工具 + skills)。
|
|
2263
|
+
* 只读 adapter 内存缓存(lastCombinedCapabilities),不触发 runtime 重新探测。
|
|
2264
|
+
* 缓存由 mcp_status / skill_status 事件维护;若尚未收到任何事件则返回 capabilities: null。
|
|
2265
|
+
*/
|
|
2266
|
+
terminalRouter.get("/sdk/capabilities/:sessionId", validateToken, (req, res) => {
|
|
2267
|
+
const sessionId = req.params.sessionId;
|
|
2268
|
+
if (!sessionId) {
|
|
2269
|
+
res.status(400).json({ error: "sessionId is required" });
|
|
2270
|
+
return;
|
|
2271
|
+
}
|
|
2272
|
+
const entry = sdkSessions.get(sessionId);
|
|
2273
|
+
if (!entry) {
|
|
2274
|
+
res.status(404).json({ error: "SDK session not found" });
|
|
2275
|
+
return;
|
|
2276
|
+
}
|
|
2277
|
+
try {
|
|
2278
|
+
const providerId = entry.providerId || "claude-code";
|
|
2279
|
+
const adapter = adapterRegistry.get(providerId);
|
|
2280
|
+
// 仅 AcodeSdkAdapter 实现 getCapabilities;其他 adapter 返回 undefined
|
|
2281
|
+
const capabilities = adapter.getCapabilities?.(sessionId) ?? null;
|
|
2282
|
+
res.json({
|
|
2283
|
+
ok: true,
|
|
2284
|
+
sessionId,
|
|
2285
|
+
agentId: entry.agentId,
|
|
2286
|
+
capabilities,
|
|
2287
|
+
fetchedAt: Date.now(),
|
|
2288
|
+
});
|
|
2289
|
+
}
|
|
2290
|
+
catch (error) {
|
|
2291
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2292
|
+
res.status(500).json({ error: errorMessage });
|
|
2293
|
+
}
|
|
2294
|
+
});
|
|
2295
|
+
/**
|
|
2296
|
+
* 查询会话当前挂起的 ask_user_question(agent 提问)。
|
|
2297
|
+
*
|
|
2298
|
+
* 只读 adapter 内存缓存(pendingQuestionToolCallId + pendingQuestions)。
|
|
2299
|
+
* 用于前端刷新后重建提问 UI:bridge 在 session entry 中保留了最近一次提问的
|
|
2300
|
+
* toolCallId 与 questions 数组,前端刷新后通过此端点取回并重建 directMessages
|
|
2301
|
+
* 与 header 通知。toolCallId 封闭在 bridge 内部,前端无需感知。
|
|
2302
|
+
*
|
|
2303
|
+
* GET /runtime/sdk/pending-questions/:sessionId
|
|
2304
|
+
*/
|
|
2305
|
+
terminalRouter.get("/sdk/pending-questions/:sessionId", validateToken, (req, res) => {
|
|
2306
|
+
const sessionId = req.params.sessionId;
|
|
2307
|
+
if (!sessionId) {
|
|
2308
|
+
res.status(400).json({ error: "sessionId is required" });
|
|
2309
|
+
return;
|
|
2310
|
+
}
|
|
2311
|
+
const entry = sdkSessions.get(sessionId);
|
|
2312
|
+
if (!entry) {
|
|
2313
|
+
res.status(404).json({ error: "SDK session not found" });
|
|
2314
|
+
return;
|
|
2315
|
+
}
|
|
2316
|
+
try {
|
|
2317
|
+
const providerId = entry.providerId || "claude-code";
|
|
2318
|
+
const adapter = adapterRegistry.get(providerId);
|
|
2319
|
+
// 仅 AcodeSdkAdapter 实现 getPendingQuestion;其他 adapter 返回 undefined
|
|
2320
|
+
const pendingQuestion = adapter.getPendingQuestion?.(sessionId) ?? null;
|
|
2321
|
+
res.json({
|
|
2322
|
+
ok: true,
|
|
2323
|
+
sessionId,
|
|
2324
|
+
agentId: entry.agentId,
|
|
2325
|
+
pendingQuestion: pendingQuestion
|
|
2326
|
+
? {
|
|
2327
|
+
toolCallId: pendingQuestion.toolCallId,
|
|
2328
|
+
questions: pendingQuestion.questions,
|
|
2329
|
+
}
|
|
2330
|
+
: null,
|
|
2331
|
+
fetchedAt: Date.now(),
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
catch (error) {
|
|
2335
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2336
|
+
res.status(500).json({ error: errorMessage });
|
|
2337
|
+
}
|
|
2338
|
+
});
|
|
2039
2339
|
/**
|
|
2040
2340
|
* 执行当前 Agent 工作目录下的终端命令。
|
|
2041
2341
|
*
|
|
@@ -2240,6 +2540,7 @@ terminalRouter.post("/stop", validateToken, async (req, res) => {
|
|
|
2240
2540
|
// 如果有活跃 AI 请求,先立即中止(fire-and-forget),再清理资源
|
|
2241
2541
|
adapter.abortCurrentTurn(sessionId).catch(() => { });
|
|
2242
2542
|
await adapter.terminateSession(sessionId);
|
|
2543
|
+
stopStatusRefresh(sessionId);
|
|
2243
2544
|
sdkSessions.delete(sessionId);
|
|
2244
2545
|
stopTerminalCommandProcess(sessionId);
|
|
2245
2546
|
await removePersistedSession(sessionId);
|
|
@@ -2290,6 +2591,7 @@ terminalRouter.post("/stop-all", validateToken, async (_req, res) => {
|
|
|
2290
2591
|
// 如果有活跃 AI 请求,先立即中止(fire-and-forget),再清理资源
|
|
2291
2592
|
adapter.abortCurrentTurn(sessionId).catch(() => { });
|
|
2292
2593
|
await adapter.terminateSession(sessionId);
|
|
2594
|
+
stopStatusRefresh(sessionId);
|
|
2293
2595
|
sdkSessions.delete(sessionId);
|
|
2294
2596
|
stopTerminalCommandProcess(sessionId);
|
|
2295
2597
|
stoppedSdk.push(sessionId);
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 获取 ACode 入口文件路径。
|
|
3
|
+
* 本地开发模式:直接使用项目下 package/acode/dist/index.js(修改即生效,无需复制)。
|
|
4
|
+
* 部署模式:~/.aws-bridge/acode/dist/index.js。
|
|
5
|
+
*/
|
|
1
6
|
export declare function getReleasedAcodeEntryPath(): string;
|
|
2
7
|
/**
|
|
3
8
|
* 释放随 bridge 打包的内置 ACode runtime。
|
|
4
|
-
*
|
|
9
|
+
*
|
|
10
|
+
* 本地开发模式:直接使用项目下 package/acode/dist,跳过复制(修改源码后重新 build 即生效)。
|
|
11
|
+
* 部署模式:复制 dist 与 metadata 到 ~/.aws-bridge/acode,链接 bridge node_modules,
|
|
5
12
|
* 确保 ACode 无需安装即可被 Adapter 动态加载。
|
|
6
13
|
*/
|
|
7
14
|
export declare function ensureAcodePackageReleased(): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acode-package.d.ts","sourceRoot":"","sources":["../../src/services/acode-package.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"acode-package.d.ts","sourceRoot":"","sources":["../../src/services/acode-package.ts"],"names":[],"mappings":"AAqEA;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,MAAM,CAMlD;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,IAAI,MAAM,GAAG,IAAI,CAgC1D"}
|
|
@@ -10,8 +10,19 @@ function getBridgePackageRoot() {
|
|
|
10
10
|
function getBundledAcodeRoot(packageRoot = getBridgePackageRoot()) {
|
|
11
11
|
return path.join(packageRoot, 'package', 'acode');
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* 判断当前是否为本地开发模式(从项目源码目录运行)。
|
|
15
|
+
* 本地开发模式下 bridge packageRoot 下存在 src/ 目录,部署产物只有 dist/。
|
|
16
|
+
*/
|
|
17
|
+
function isLocalDevMode(packageRoot = getBridgePackageRoot()) {
|
|
18
|
+
return existsSync(path.join(packageRoot, 'src'));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 部署模式下的 released 根目录:~/.aws-bridge/acode
|
|
22
|
+
* 与 aws-client-agent-mcp 的 ~/.aws-bridge/mcp 路径保持一致。
|
|
23
|
+
*/
|
|
13
24
|
function getReleasedAcodeRoot() {
|
|
14
|
-
return path.join(getRuntimeHomeDir(), '.
|
|
25
|
+
return path.join(getRuntimeHomeDir(), '.aws-bridge', 'acode');
|
|
15
26
|
}
|
|
16
27
|
function shouldReplaceNodeModulesLink(targetPath) {
|
|
17
28
|
if (!existsSync(targetPath)) {
|
|
@@ -48,12 +59,23 @@ function ensureReleasedNodeModules(packageRoot, releasedRoot) {
|
|
|
48
59
|
rmSync(releasedNodeModules, { recursive: true, force: true });
|
|
49
60
|
symlinkSync(sourceNodeModules, releasedNodeModules, process.platform === 'win32' ? 'junction' : 'dir');
|
|
50
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* 获取 ACode 入口文件路径。
|
|
64
|
+
* 本地开发模式:直接使用项目下 package/acode/dist/index.js(修改即生效,无需复制)。
|
|
65
|
+
* 部署模式:~/.aws-bridge/acode/dist/index.js。
|
|
66
|
+
*/
|
|
51
67
|
export function getReleasedAcodeEntryPath() {
|
|
68
|
+
const packageRoot = getBridgePackageRoot();
|
|
69
|
+
if (isLocalDevMode(packageRoot)) {
|
|
70
|
+
return path.join(getBundledAcodeRoot(packageRoot), 'dist', 'index.js');
|
|
71
|
+
}
|
|
52
72
|
return path.join(getReleasedAcodeRoot(), 'dist', 'index.js');
|
|
53
73
|
}
|
|
54
74
|
/**
|
|
55
75
|
* 释放随 bridge 打包的内置 ACode runtime。
|
|
56
|
-
*
|
|
76
|
+
*
|
|
77
|
+
* 本地开发模式:直接使用项目下 package/acode/dist,跳过复制(修改源码后重新 build 即生效)。
|
|
78
|
+
* 部署模式:复制 dist 与 metadata 到 ~/.aws-bridge/acode,链接 bridge node_modules,
|
|
57
79
|
* 确保 ACode 无需安装即可被 Adapter 动态加载。
|
|
58
80
|
*/
|
|
59
81
|
export function ensureAcodePackageReleased() {
|
|
@@ -65,6 +87,12 @@ export function ensureAcodePackageReleased() {
|
|
|
65
87
|
logger.warn(`[runtime-bridge] 未找到 bundled ACode dist,ACode 启动可能失败: ${bundledEntry}`);
|
|
66
88
|
return null;
|
|
67
89
|
}
|
|
90
|
+
// 本地开发模式:直接使用项目下 dist,无需复制
|
|
91
|
+
if (isLocalDevMode(packageRoot)) {
|
|
92
|
+
logger.info(`[runtime-bridge] ACode 本地开发模式,直接使用项目 dist: ${bundledEntry}`);
|
|
93
|
+
return bundledEntry;
|
|
94
|
+
}
|
|
95
|
+
// 部署模式:复制到 ~/.aws-bridge/acode
|
|
68
96
|
const releasedRoot = getReleasedAcodeRoot();
|
|
69
97
|
const releasedDist = path.join(releasedRoot, 'dist');
|
|
70
98
|
mkdirSync(releasedRoot, { recursive: true });
|
|
@@ -77,6 +105,7 @@ export function ensureAcodePackageReleased() {
|
|
|
77
105
|
}
|
|
78
106
|
}
|
|
79
107
|
ensureReleasedNodeModules(packageRoot, releasedRoot);
|
|
80
|
-
|
|
81
|
-
|
|
108
|
+
const releasedEntry = path.join(releasedDist, 'index.js');
|
|
109
|
+
logger.info(`[runtime-bridge] ACode 已准备: ${releasedEntry}`);
|
|
110
|
+
return releasedEntry;
|
|
82
111
|
}
|
|
@@ -19,6 +19,7 @@ export interface BridgeEventPayload {
|
|
|
19
19
|
readonly actionInput?: string;
|
|
20
20
|
readonly actionResult?: string;
|
|
21
21
|
readonly actionId?: string;
|
|
22
|
+
readonly parentId?: string;
|
|
22
23
|
readonly inputTokens?: number;
|
|
23
24
|
readonly outputTokens?: number;
|
|
24
25
|
readonly sourceEventType?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-event-store.d.ts","sourceRoot":"","sources":["../../src/services/agent-event-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,cAAc,CAAC;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAQD;;;;GAIG;AACH,cAAM,eAAe;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAE9D,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,eAAe,CAAC,kBAAkB,CAAC;IAIzF;;;;;OAKG;IACH,mBAAmB,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,GAC1B,eAAe,CAAC,kBAAkB,CAAC;IA6BtC;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAG9B;AAED,WAAW;AACX,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"agent-event-store.d.ts","sourceRoot":"","sources":["../../src/services/agent-event-store.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEpE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,GAAG,cAAc,CAAC;IACrE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAQD;;;;GAIG;AACH,cAAM,eAAe;IACnB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuC;IAE9D,OAAO,CAAC,YAAY;IASpB;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,eAAe,CAAC,kBAAkB,CAAC;IAIzF;;;;;OAKG;IACH,mBAAmB,CACjB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,GAC1B,eAAe,CAAC,kBAAkB,CAAC;IA6BtC;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAG9B;AAED,WAAW;AACX,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|