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
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
|
-
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { describe, it } from "node:test";
|
|
6
6
|
import { AgentClient } from "./agent-client.js";
|
|
7
7
|
import { McpServer } from "./mcp-server.js";
|
|
8
8
|
import { MCP_TOOLS } from "./mcp-tools.js";
|
|
9
|
-
import {
|
|
9
|
+
import { MemoryStore, } from "./memory-store.js";
|
|
10
10
|
import { MessageBuffer } from "./message-buffer.js";
|
|
11
11
|
function createServerWithUnread(unreadMessages, overrides = {}) {
|
|
12
12
|
const server = new McpServer();
|
|
@@ -150,52 +150,40 @@ describe("McpServer unread backlog hydration", () => {
|
|
|
150
150
|
});
|
|
151
151
|
});
|
|
152
152
|
it("poll_message should keep blocking through empty polls until messages arrive", async () => {
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
assert.equal(fetchOptions[1].blockIfEmpty, true);
|
|
188
|
-
assert.ok(typeof fetchOptions[1].blockTimeoutMs === "number");
|
|
189
|
-
assert.equal(fetchOptions[1].blockTimeoutMs, 20);
|
|
190
|
-
}
|
|
191
|
-
finally {
|
|
192
|
-
if (previousBlockWait === undefined) {
|
|
193
|
-
delete process.env.AWS_POLL_MESSAGE_BLOCK_WAIT_MS;
|
|
194
|
-
}
|
|
195
|
-
else {
|
|
196
|
-
process.env.AWS_POLL_MESSAGE_BLOCK_WAIT_MS = previousBlockWait;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
153
|
+
const directMessage = {
|
|
154
|
+
msgId: "dm-delayed-1",
|
|
155
|
+
senderId: "agent-delayed",
|
|
156
|
+
senderName: "Agent Delayed",
|
|
157
|
+
content: "delayed dm",
|
|
158
|
+
requireReply: false,
|
|
159
|
+
timestamp: new Date().toISOString(),
|
|
160
|
+
};
|
|
161
|
+
const fetchOptions = [];
|
|
162
|
+
const server = createServerWithUnread({ directMessages: [], groupMessages: [] }, {
|
|
163
|
+
fetchUnreadMessages: async (options) => {
|
|
164
|
+
fetchOptions.push(options ?? {});
|
|
165
|
+
return { directMessages: [], groupMessages: [] };
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
// Simulate a WebSocket message arriving after hydration returns empty.
|
|
169
|
+
// poll_message must keep blocking on the local buffer until the message arrives.
|
|
170
|
+
const buffer = Reflect.get(server, "messageBuffer");
|
|
171
|
+
setTimeout(() => {
|
|
172
|
+
buffer.push(directMessage);
|
|
173
|
+
}, 50);
|
|
174
|
+
const handleToolCall = getHandleToolCall(server);
|
|
175
|
+
const result = await handleToolCall.call(server, "poll_message", {});
|
|
176
|
+
assert.deepEqual(result, {
|
|
177
|
+
directMessages: [directMessage],
|
|
178
|
+
groupMessages: [],
|
|
179
|
+
fromBuffer: true,
|
|
180
|
+
systemMessages: [],
|
|
181
|
+
});
|
|
182
|
+
// fetchUnreadMessages should only be called once (the initial non-blocking hydrate).
|
|
183
|
+
// The message must arrive via the local buffer (WebSocket push), not a second blocking fetch.
|
|
184
|
+
assert.equal(fetchOptions.length, 1);
|
|
185
|
+
assert.equal(fetchOptions[0].blockIfEmpty, false);
|
|
186
|
+
assert.equal(fetchOptions[0].includePipelineTasks, true);
|
|
199
187
|
});
|
|
200
188
|
it("poll_message should handle hydration error gracefully and receive WebSocket messages", async () => {
|
|
201
189
|
const directMessage = {
|
|
@@ -210,10 +198,7 @@ describe("McpServer unread backlog hydration", () => {
|
|
|
210
198
|
const server = createServerWithUnread({ directMessages: [], groupMessages: [] }, {
|
|
211
199
|
fetchUnreadMessages: async () => {
|
|
212
200
|
fetchCount += 1;
|
|
213
|
-
|
|
214
|
-
throw new Error("MCP tool poll_message timed out after 120000ms");
|
|
215
|
-
}
|
|
216
|
-
return { directMessages: [], groupMessages: [] };
|
|
201
|
+
throw new Error("MCP tool poll_message timed out after 120000ms");
|
|
217
202
|
},
|
|
218
203
|
});
|
|
219
204
|
// Simulate WebSocket message arriving after hydration fails
|
|
@@ -229,7 +214,10 @@ describe("McpServer unread backlog hydration", () => {
|
|
|
229
214
|
fromBuffer: true,
|
|
230
215
|
systemMessages: [],
|
|
231
216
|
});
|
|
232
|
-
|
|
217
|
+
// fetchUnreadMessages should only be called once (the initial hydrate, which throws).
|
|
218
|
+
// hydrateUnreadMessagesFromServer catches the error, and poll_message falls back to
|
|
219
|
+
// blocking on the local buffer until the WebSocket message arrives.
|
|
220
|
+
assert.equal(fetchCount, 1);
|
|
233
221
|
});
|
|
234
222
|
it("get_message should still hydrate unread group messages after profile push is received", async () => {
|
|
235
223
|
const groupMessage = {
|
|
@@ -448,7 +436,7 @@ describe("McpServer unread backlog hydration", () => {
|
|
|
448
436
|
assert.equal(result.fromBuffer, true);
|
|
449
437
|
assert.equal(fetchOptions.length, 1);
|
|
450
438
|
assert.equal(fetchOptions[0]?.blockIfEmpty, false);
|
|
451
|
-
assert.equal(fetchOptions[0]?.includePipelineTasks,
|
|
439
|
+
assert.equal(fetchOptions[0]?.includePipelineTasks, true);
|
|
452
440
|
assert.equal(fetchOptions[0]?.blockTimeoutMs, undefined);
|
|
453
441
|
});
|
|
454
442
|
it("poll_message should merge existing local cache with newly claimed task notification", async () => {
|
|
@@ -490,7 +478,7 @@ describe("McpServer unread backlog hydration", () => {
|
|
|
490
478
|
assert.equal(result.fromBuffer, true);
|
|
491
479
|
assert.equal(fetchOptions.length, 1);
|
|
492
480
|
assert.equal(fetchOptions[0]?.blockIfEmpty, false);
|
|
493
|
-
assert.equal(fetchOptions[0]?.includePipelineTasks,
|
|
481
|
+
assert.equal(fetchOptions[0]?.includePipelineTasks, true);
|
|
494
482
|
});
|
|
495
483
|
it("poll_message should wait for WebSocket messages when backend long polling returns empty", async () => {
|
|
496
484
|
const delayedMessage = {
|
|
@@ -519,54 +507,13 @@ describe("McpServer unread backlog hydration", () => {
|
|
|
519
507
|
}, 50);
|
|
520
508
|
const handleToolCall = getHandleToolCall(server);
|
|
521
509
|
const result = (await handleToolCall.call(server, "poll_message", {}));
|
|
522
|
-
|
|
510
|
+
// Only the initial non-blocking hydrate should call fetchUnreadMessages.
|
|
511
|
+
// The message must arrive via the local buffer (WebSocket push).
|
|
512
|
+
assert.equal(fetchCalls, 1);
|
|
523
513
|
assert.deepEqual(result.directMessages, [delayedMessage]);
|
|
524
514
|
assert.deepEqual(result.groupMessages, []);
|
|
525
515
|
assert.equal(result.fromBuffer, true);
|
|
526
516
|
});
|
|
527
|
-
it("poll_message should clamp block wait below HTTP request timeout", async () => {
|
|
528
|
-
const previousBlockWait = process.env.AWS_POLL_MESSAGE_BLOCK_WAIT_MS;
|
|
529
|
-
process.env.AWS_POLL_MESSAGE_BLOCK_WAIT_MS = "120000";
|
|
530
|
-
try {
|
|
531
|
-
const delayedMessage = {
|
|
532
|
-
msgId: "dm-after-clamped-poll",
|
|
533
|
-
senderId: "agent-later",
|
|
534
|
-
senderName: "Later Agent",
|
|
535
|
-
receiverId: "agent-self",
|
|
536
|
-
content: "arrived after clamped backend poll",
|
|
537
|
-
requireReply: false,
|
|
538
|
-
timestamp: new Date().toISOString(),
|
|
539
|
-
};
|
|
540
|
-
const fetchOptions = [];
|
|
541
|
-
const server = createServerWithUnread({
|
|
542
|
-
directMessages: [],
|
|
543
|
-
groupMessages: [],
|
|
544
|
-
}, {
|
|
545
|
-
fetchUnreadMessages: async (options) => {
|
|
546
|
-
fetchOptions.push(options ?? {});
|
|
547
|
-
return fetchOptions.length === 1
|
|
548
|
-
? { directMessages: [], groupMessages: [] }
|
|
549
|
-
: fetchOptions.length === 2
|
|
550
|
-
? { directMessages: [delayedMessage], groupMessages: [] }
|
|
551
|
-
: { directMessages: [], groupMessages: [] };
|
|
552
|
-
},
|
|
553
|
-
});
|
|
554
|
-
const handleToolCall = getHandleToolCall(server);
|
|
555
|
-
const result = (await handleToolCall.call(server, "poll_message", {}));
|
|
556
|
-
assert.deepEqual(result.directMessages, [delayedMessage]);
|
|
557
|
-
assert.equal(fetchOptions[0].blockIfEmpty, false);
|
|
558
|
-
assert.equal(fetchOptions[1].blockIfEmpty, true);
|
|
559
|
-
assert.equal(fetchOptions[1].blockTimeoutMs, 120000);
|
|
560
|
-
}
|
|
561
|
-
finally {
|
|
562
|
-
if (previousBlockWait === undefined) {
|
|
563
|
-
delete process.env.AWS_POLL_MESSAGE_BLOCK_WAIT_MS;
|
|
564
|
-
}
|
|
565
|
-
else {
|
|
566
|
-
process.env.AWS_POLL_MESSAGE_BLOCK_WAIT_MS = previousBlockWait;
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
});
|
|
570
517
|
it("poll_message should restore waiting status when task notification is returned", async () => {
|
|
571
518
|
const statusEvents = [];
|
|
572
519
|
const server = createServerWithUnread({
|
|
@@ -720,6 +667,93 @@ describe("McpServer unread backlog hydration", () => {
|
|
|
720
667
|
"thinking",
|
|
721
668
|
]);
|
|
722
669
|
});
|
|
670
|
+
it("poll_message should skip reportToolResult when only _acodeAutoDelegate messages are returned", async () => {
|
|
671
|
+
const statusEvents = [];
|
|
672
|
+
const reportedResults = [];
|
|
673
|
+
const delegateMessage = {
|
|
674
|
+
msgId: "memory-update-pending-1",
|
|
675
|
+
senderId: "MCP-System",
|
|
676
|
+
senderName: "系统",
|
|
677
|
+
receiverId: "agent-self",
|
|
678
|
+
content: "您有以下 Memory 正处于更新中状态",
|
|
679
|
+
requireReply: false,
|
|
680
|
+
timestamp: new Date().toISOString(),
|
|
681
|
+
_acodeAutoDelegate: {
|
|
682
|
+
type: "memory_file_change",
|
|
683
|
+
uris: ["architecture://relay/core-routing"],
|
|
684
|
+
},
|
|
685
|
+
};
|
|
686
|
+
const server = createServerWithUnread({
|
|
687
|
+
directMessages: [delegateMessage],
|
|
688
|
+
groupMessages: [],
|
|
689
|
+
}, {
|
|
690
|
+
getStatusReporter: () => ({
|
|
691
|
+
reportToolUse: () => statusEvents.push("tool_using"),
|
|
692
|
+
reportToolResult: (r) => {
|
|
693
|
+
statusEvents.push("tool_result");
|
|
694
|
+
reportedResults.push(r);
|
|
695
|
+
},
|
|
696
|
+
reportThinking: () => statusEvents.push("thinking"),
|
|
697
|
+
reportWaitingInput: () => statusEvents.push("waiting_input"),
|
|
698
|
+
reportError: () => statusEvents.push("error"),
|
|
699
|
+
reportToolError: () => statusEvents.push("tool_error"),
|
|
700
|
+
}),
|
|
701
|
+
});
|
|
702
|
+
const handleToolCall = getHandleToolCall(server);
|
|
703
|
+
const result = (await handleToolCall.call(server, "poll_message", {}));
|
|
704
|
+
assert.equal(result.directMessages.length, 1);
|
|
705
|
+
assert.deepEqual(statusEvents, ["tool_using", "thinking"]);
|
|
706
|
+
assert.equal(reportedResults.length, 0);
|
|
707
|
+
});
|
|
708
|
+
it("poll_message should filter _acodeAutoDelegate from reportToolResult but keep normal messages", async () => {
|
|
709
|
+
const statusEvents = [];
|
|
710
|
+
const reportedResults = [];
|
|
711
|
+
const delegateMessage = {
|
|
712
|
+
msgId: "memory-update-pending-2",
|
|
713
|
+
senderId: "MCP-System",
|
|
714
|
+
senderName: "系统",
|
|
715
|
+
receiverId: "agent-self",
|
|
716
|
+
content: "请继续完成更新工作",
|
|
717
|
+
requireReply: false,
|
|
718
|
+
timestamp: new Date().toISOString(),
|
|
719
|
+
_acodeAutoDelegate: {
|
|
720
|
+
type: "memory_file_change",
|
|
721
|
+
uris: ["architecture://overview/system-architecture"],
|
|
722
|
+
},
|
|
723
|
+
};
|
|
724
|
+
const normalMessage = {
|
|
725
|
+
msgId: "dm-normal-work",
|
|
726
|
+
senderId: "agent-colleague",
|
|
727
|
+
senderName: "Colleague",
|
|
728
|
+
content: "请帮忙看一下这个接口",
|
|
729
|
+
requireReply: false,
|
|
730
|
+
timestamp: new Date().toISOString(),
|
|
731
|
+
};
|
|
732
|
+
const server = createServerWithUnread({
|
|
733
|
+
directMessages: [delegateMessage, normalMessage],
|
|
734
|
+
groupMessages: [],
|
|
735
|
+
}, {
|
|
736
|
+
getStatusReporter: () => ({
|
|
737
|
+
reportToolUse: () => statusEvents.push("tool_using"),
|
|
738
|
+
reportToolResult: (r) => {
|
|
739
|
+
statusEvents.push("tool_result");
|
|
740
|
+
reportedResults.push(r);
|
|
741
|
+
},
|
|
742
|
+
reportThinking: () => statusEvents.push("thinking"),
|
|
743
|
+
reportWaitingInput: () => statusEvents.push("waiting_input"),
|
|
744
|
+
reportError: () => statusEvents.push("error"),
|
|
745
|
+
reportToolError: () => statusEvents.push("tool_error"),
|
|
746
|
+
}),
|
|
747
|
+
});
|
|
748
|
+
const handleToolCall = getHandleToolCall(server);
|
|
749
|
+
const result = (await handleToolCall.call(server, "poll_message", {}));
|
|
750
|
+
assert.equal(result.directMessages.length, 2);
|
|
751
|
+
assert.deepEqual(statusEvents, ["tool_using", "tool_result", "thinking"]);
|
|
752
|
+
assert.equal(reportedResults.length, 1);
|
|
753
|
+
const reported = reportedResults[0];
|
|
754
|
+
assert.equal(reported.directMessages.length, 1);
|
|
755
|
+
assert.equal(reported.directMessages[0].msgId, "dm-normal-work");
|
|
756
|
+
});
|
|
723
757
|
});
|
|
724
758
|
describe("McpServer memory store paths", () => {
|
|
725
759
|
it("uses project permanent memory directory by default", async () => {
|
|
@@ -768,7 +802,6 @@ describe("McpServer memory tools", () => {
|
|
|
768
802
|
assert.ok(toolNames.includes("search_memory"));
|
|
769
803
|
assert.ok(toolNames.includes("list_memories"));
|
|
770
804
|
assert.ok(toolNames.includes("get_memory_stats"));
|
|
771
|
-
assert.ok(toolNames.includes("archive_recently_memory"));
|
|
772
805
|
// Memory 近期记忆过期与回忆工具 (v1.11.0)
|
|
773
806
|
assert.ok(toolNames.includes("memory_recurrence"));
|
|
774
807
|
assert.ok(toolNames.includes("memory_recurrence_complete"));
|
|
@@ -777,7 +810,7 @@ describe("McpServer memory tools", () => {
|
|
|
777
810
|
await withMemoryServer(async (server) => {
|
|
778
811
|
const handleToolCall = getHandleToolCall(server);
|
|
779
812
|
const created = await handleToolCall.call(server, "create_memory", {
|
|
780
|
-
memory_type: "
|
|
813
|
+
memory_type: "project_memory",
|
|
781
814
|
uri: "Core://Agent/Profile/",
|
|
782
815
|
content: "prefers concise backend summaries",
|
|
783
816
|
});
|
|
@@ -785,12 +818,12 @@ describe("McpServer memory tools", () => {
|
|
|
785
818
|
assert.equal(created.content, undefined);
|
|
786
819
|
const read = await handleToolCall.call(server, "read_memory", {
|
|
787
820
|
uri: "core://Agent/Profile",
|
|
788
|
-
memory_type: "
|
|
821
|
+
memory_type: "project_memory",
|
|
789
822
|
});
|
|
790
823
|
assert.equal(read.content, "prefers concise backend summaries");
|
|
791
824
|
const updated = await handleToolCall.call(server, "update_memory", {
|
|
792
825
|
uri: "core://Agent/Profile",
|
|
793
|
-
memory_type: "
|
|
826
|
+
memory_type: "project_memory",
|
|
794
827
|
old_string: "concise",
|
|
795
828
|
new_string: "structured",
|
|
796
829
|
append: "\nuses MCP memory tools",
|
|
@@ -799,7 +832,7 @@ describe("McpServer memory tools", () => {
|
|
|
799
832
|
assert.equal(updated.version, 2);
|
|
800
833
|
const readUpdated = await handleToolCall.call(server, "read_memory", {
|
|
801
834
|
uri: "core://Agent/Profile",
|
|
802
|
-
memory_type: "
|
|
835
|
+
memory_type: "project_memory",
|
|
803
836
|
});
|
|
804
837
|
assert.match(readUpdated.content, /structured backend/);
|
|
805
838
|
assert.match(readUpdated.content, /MCP memory tools/);
|
|
@@ -810,7 +843,7 @@ describe("McpServer memory tools", () => {
|
|
|
810
843
|
assert.equal(searchResult.results.length, 1);
|
|
811
844
|
const deleted = await handleToolCall.call(server, "delete_memory", {
|
|
812
845
|
uri: "core://Agent/Profile",
|
|
813
|
-
memory_type: "
|
|
846
|
+
memory_type: "project_memory",
|
|
814
847
|
});
|
|
815
848
|
assert.deepEqual(deleted, { deleted: true });
|
|
816
849
|
});
|
|
@@ -819,25 +852,25 @@ describe("McpServer memory tools", () => {
|
|
|
819
852
|
await withMemoryServer(async (server) => {
|
|
820
853
|
const handleToolCall = getHandleToolCall(server);
|
|
821
854
|
await handleToolCall.call(server, "create_memory", {
|
|
822
|
-
memory_type: "
|
|
855
|
+
memory_type: "recently_memory",
|
|
823
856
|
uri: "task://todo/current",
|
|
824
857
|
content: "finish memory endpoint tests",
|
|
825
858
|
});
|
|
826
859
|
await handleToolCall.call(server, "create_memory", {
|
|
827
|
-
memory_type: "
|
|
860
|
+
memory_type: "agent_memory",
|
|
828
861
|
uri: "recent://discussion/memory-tools",
|
|
829
862
|
content: "memory tools should stay local for now",
|
|
830
863
|
});
|
|
831
864
|
const taskList = await handleToolCall.call(server, "list_memories", {
|
|
832
|
-
memory_type: "
|
|
865
|
+
memory_type: "recently_memory",
|
|
833
866
|
});
|
|
834
867
|
assert.equal(taskList.length, 1);
|
|
835
868
|
const recentList = await handleToolCall.call(server, "list_memories", {
|
|
836
|
-
memory_type: "
|
|
869
|
+
memory_type: "agent_memory",
|
|
837
870
|
});
|
|
838
871
|
assert.equal(recentList.length, 1);
|
|
839
872
|
await assert.rejects(() => handleToolCall.call(server, "list_memories", {
|
|
840
|
-
memory_type: "
|
|
873
|
+
memory_type: "project_memory",
|
|
841
874
|
}), /Invalid memory_type/);
|
|
842
875
|
});
|
|
843
876
|
});
|
|
@@ -846,76 +879,42 @@ describe("McpServer memory tools", () => {
|
|
|
846
879
|
const firstHandleToolCall = getHandleToolCall(firstServer);
|
|
847
880
|
const secondHandleToolCall = getHandleToolCall(secondServer);
|
|
848
881
|
await firstHandleToolCall.call(firstServer, "create_memory", {
|
|
849
|
-
memory_type: "
|
|
882
|
+
memory_type: "project_memory",
|
|
850
883
|
uri: "core://role/shared-profile",
|
|
851
884
|
content: "shared role knowledge",
|
|
852
885
|
});
|
|
853
886
|
await firstHandleToolCall.call(firstServer, "create_memory", {
|
|
854
|
-
memory_type: "
|
|
887
|
+
memory_type: "agent_memory",
|
|
855
888
|
uri: "recent://instance/private-context",
|
|
856
889
|
content: "agent one private context",
|
|
857
890
|
});
|
|
858
891
|
const roleMemory = await secondHandleToolCall.call(secondServer, "read_memory", {
|
|
859
892
|
uri: "core://role/shared-profile",
|
|
860
|
-
memory_type: "
|
|
893
|
+
memory_type: "project_memory",
|
|
861
894
|
});
|
|
862
895
|
const recentMemory = await secondHandleToolCall.call(secondServer, "read_memory", {
|
|
863
896
|
uri: "recent://instance/private-context",
|
|
864
|
-
memory_type: "
|
|
897
|
+
memory_type: "agent_memory",
|
|
865
898
|
});
|
|
866
899
|
assert.equal(roleMemory.content, "shared role knowledge");
|
|
867
900
|
assert.equal(recentMemory, null);
|
|
868
901
|
});
|
|
869
902
|
});
|
|
870
|
-
it("supports task-list removal and recent-memory archive semantics", async () => {
|
|
871
|
-
await withMemoryServer(async (server) => {
|
|
872
|
-
const handleToolCall = getHandleToolCall(server);
|
|
873
|
-
await handleToolCall.call(server, "create_memory", {
|
|
874
|
-
memory_type: "task_list",
|
|
875
|
-
uri: "task://todo/remove-me",
|
|
876
|
-
content: "temporary task",
|
|
877
|
-
});
|
|
878
|
-
await handleToolCall.call(server, "create_memory", {
|
|
879
|
-
memory_type: "recently_memory",
|
|
880
|
-
uri: "recent://note/archive-me",
|
|
881
|
-
content: "hot context",
|
|
882
|
-
});
|
|
883
|
-
const deleted = await handleToolCall.call(server, "delete_memory", {
|
|
884
|
-
uri: "task://todo/remove-me",
|
|
885
|
-
memory_type: "task_list",
|
|
886
|
-
});
|
|
887
|
-
assert.deepEqual(deleted, { deleted: true });
|
|
888
|
-
const archived = await handleToolCall.call(server, "archive_recently_memory", {
|
|
889
|
-
uri: "recent://note/archive-me",
|
|
890
|
-
});
|
|
891
|
-
assert.equal(archived.memory_type, "memory");
|
|
892
|
-
const archivedInRoleScope = await handleToolCall.call(server, "read_memory", {
|
|
893
|
-
uri: "recent://note/archive-me",
|
|
894
|
-
memory_type: "memory",
|
|
895
|
-
});
|
|
896
|
-
const removedFromInstanceScope = await handleToolCall.call(server, "read_memory", {
|
|
897
|
-
uri: "recent://note/archive-me",
|
|
898
|
-
memory_type: "recently_memory",
|
|
899
|
-
});
|
|
900
|
-
assert.equal(archivedInRoleScope.content, "hot context");
|
|
901
|
-
assert.equal(removedFromInstanceScope, null);
|
|
902
|
-
});
|
|
903
|
-
});
|
|
904
903
|
it("returns memory stats through MCP dispatch", async () => {
|
|
905
904
|
await withMemoryServer(async (server) => {
|
|
906
905
|
const handleToolCall = getHandleToolCall(server);
|
|
907
906
|
await handleToolCall.call(server, "create_memory", {
|
|
908
|
-
memory_type: "
|
|
907
|
+
memory_type: "recently_memory",
|
|
909
908
|
uri: "task://todo/stats",
|
|
910
909
|
content: "temporary task",
|
|
911
910
|
});
|
|
912
911
|
await handleToolCall.call(server, "create_memory", {
|
|
913
|
-
memory_type: "
|
|
912
|
+
memory_type: "agent_memory",
|
|
914
913
|
uri: "recent://note/stats",
|
|
915
914
|
content: "hot context",
|
|
916
915
|
});
|
|
917
916
|
await handleToolCall.call(server, "create_memory", {
|
|
918
|
-
memory_type: "
|
|
917
|
+
memory_type: "project_memory",
|
|
919
918
|
uri: "core://agent/profile",
|
|
920
919
|
content: "long-term profile",
|
|
921
920
|
});
|
|
@@ -929,15 +928,15 @@ describe("McpServer memory tools", () => {
|
|
|
929
928
|
exceeded: false,
|
|
930
929
|
hardExceeded: false,
|
|
931
930
|
});
|
|
932
|
-
assert.equal(typedStats.by_type.task_list.count, 1);
|
|
933
|
-
assert.equal(typedStats.by_type.task_list.domainCount, 1);
|
|
934
|
-
assert.equal(typedStats.by_type.task_list.by_domain.task?.count, 1);
|
|
935
931
|
assert.equal(typedStats.by_type.recently_memory.count, 1);
|
|
936
932
|
assert.equal(typedStats.by_type.recently_memory.domainCount, 1);
|
|
937
|
-
assert.equal(typedStats.by_type.recently_memory.by_domain.
|
|
938
|
-
assert.equal(typedStats.by_type.
|
|
939
|
-
assert.equal(typedStats.by_type.
|
|
940
|
-
assert.equal(typedStats.by_type.
|
|
933
|
+
assert.equal(typedStats.by_type.recently_memory.by_domain.task?.count, 1);
|
|
934
|
+
assert.equal(typedStats.by_type.agent_memory.count, 1);
|
|
935
|
+
assert.equal(typedStats.by_type.agent_memory.domainCount, 1);
|
|
936
|
+
assert.equal(typedStats.by_type.agent_memory.by_domain.recent?.count, 1);
|
|
937
|
+
assert.equal(typedStats.by_type.project_memory.count, 1);
|
|
938
|
+
assert.equal(typedStats.by_type.project_memory.domainCount, 1);
|
|
939
|
+
assert.equal(typedStats.by_type.project_memory.by_domain.core?.count, 1);
|
|
941
940
|
});
|
|
942
941
|
});
|
|
943
942
|
it("reports combined memory stats after long-term memory changes", async () => {
|
|
@@ -946,32 +945,13 @@ describe("McpServer memory tools", () => {
|
|
|
946
945
|
const reportedStats = [];
|
|
947
946
|
attachMemoryStatsReporter(server, reportedStats);
|
|
948
947
|
await handleToolCall.call(server, "create_memory", {
|
|
949
|
-
memory_type: "
|
|
948
|
+
memory_type: "project_memory",
|
|
950
949
|
uri: "project://test-aws/permanent-memory-check",
|
|
951
950
|
content: "dashboard should see this permanent memory count",
|
|
952
951
|
});
|
|
953
952
|
assert.equal(reportedStats.length, 1);
|
|
954
|
-
assert.equal(reportedStats[0]?.by_type.
|
|
955
|
-
assert.equal(reportedStats[0]?.by_type.
|
|
956
|
-
});
|
|
957
|
-
});
|
|
958
|
-
it("reports combined memory stats after archiving recent memory", async () => {
|
|
959
|
-
await withMemoryServer(async (server) => {
|
|
960
|
-
const handleToolCall = getHandleToolCall(server);
|
|
961
|
-
const reportedStats = [];
|
|
962
|
-
attachMemoryStatsReporter(server, reportedStats);
|
|
963
|
-
await handleToolCall.call(server, "create_memory", {
|
|
964
|
-
memory_type: "recently_memory",
|
|
965
|
-
uri: "project://test-aws/hot-note",
|
|
966
|
-
content: "hot note that will become permanent",
|
|
967
|
-
});
|
|
968
|
-
await handleToolCall.call(server, "archive_recently_memory", {
|
|
969
|
-
uri: "project://test-aws/hot-note",
|
|
970
|
-
});
|
|
971
|
-
const latestStats = reportedStats.at(-1);
|
|
972
|
-
assert.equal(latestStats?.by_type.recently_memory.count, 0);
|
|
973
|
-
assert.equal(latestStats?.by_type.memory.count, 1);
|
|
974
|
-
assert.equal(latestStats?.by_type.memory.by_domain.project?.count, 1);
|
|
953
|
+
assert.equal(reportedStats[0]?.by_type.project_memory.count, 1);
|
|
954
|
+
assert.equal(reportedStats[0]?.by_type.project_memory.by_domain.project?.count, 1);
|
|
975
955
|
});
|
|
976
956
|
});
|
|
977
957
|
it("reports existing combined memory stats after auto registration", async () => {
|
|
@@ -979,7 +959,7 @@ describe("McpServer memory tools", () => {
|
|
|
979
959
|
const reportedStats = [];
|
|
980
960
|
const roleMemoryStore = Reflect.get(server, "roleMemoryStore");
|
|
981
961
|
await roleMemoryStore.createMemory({
|
|
982
|
-
memory_type: "
|
|
962
|
+
memory_type: "project_memory",
|
|
983
963
|
uri: "project://test-aws/existing-permanent-memory",
|
|
984
964
|
content: "existing role memory should be visible on dashboard startup",
|
|
985
965
|
});
|
|
@@ -999,73 +979,45 @@ describe("McpServer memory tools", () => {
|
|
|
999
979
|
const autoRegister = Reflect.get(server, "autoRegister");
|
|
1000
980
|
await autoRegister.call(server);
|
|
1001
981
|
assert.equal(reportedStats.length, 1);
|
|
1002
|
-
assert.equal(reportedStats[0]?.by_type.
|
|
1003
|
-
assert.equal(reportedStats[0]?.by_type.
|
|
982
|
+
assert.equal(reportedStats[0]?.by_type.project_memory.count, 1);
|
|
983
|
+
assert.equal(reportedStats[0]?.by_type.project_memory.by_domain.project?.count, 1);
|
|
1004
984
|
});
|
|
1005
985
|
});
|
|
1006
986
|
it("returns memory stats for one requested memory type", async () => {
|
|
1007
987
|
await withMemoryServer(async (server) => {
|
|
1008
988
|
const handleToolCall = getHandleToolCall(server);
|
|
1009
989
|
await handleToolCall.call(server, "create_memory", {
|
|
1010
|
-
memory_type: "
|
|
990
|
+
memory_type: "recently_memory",
|
|
1011
991
|
uri: "task://todo/stats",
|
|
1012
992
|
content: "temporary task",
|
|
1013
993
|
});
|
|
1014
994
|
await handleToolCall.call(server, "create_memory", {
|
|
1015
|
-
memory_type: "
|
|
995
|
+
memory_type: "agent_memory",
|
|
1016
996
|
uri: "recent://note/stats",
|
|
1017
997
|
content: "hot context",
|
|
1018
998
|
});
|
|
1019
999
|
await handleToolCall.call(server, "create_memory", {
|
|
1020
|
-
memory_type: "
|
|
1000
|
+
memory_type: "project_memory",
|
|
1021
1001
|
uri: "core://agent/profile",
|
|
1022
1002
|
content: "long-term profile",
|
|
1023
1003
|
});
|
|
1024
1004
|
const stats = (await handleToolCall.call(server, "get_memory_stats", {
|
|
1025
|
-
memory_type: "
|
|
1005
|
+
memory_type: "agent_memory",
|
|
1026
1006
|
}));
|
|
1027
|
-
assert.equal(stats.memory_type, "
|
|
1007
|
+
assert.equal(stats.memory_type, "agent_memory");
|
|
1028
1008
|
assert.equal(stats.total, 1);
|
|
1029
|
-
assert.deepEqual(Object.keys(stats.by_type), ["
|
|
1030
|
-
assert.equal(stats.by_type.
|
|
1031
|
-
assert.equal(stats.by_type.
|
|
1032
|
-
const memoryStats = (await handleToolCall.call(server, "get_memory_stats", { memory_type: "
|
|
1033
|
-
assert.equal(memoryStats.memory_type, "
|
|
1009
|
+
assert.deepEqual(Object.keys(stats.by_type), ["agent_memory"]);
|
|
1010
|
+
assert.equal(stats.by_type.agent_memory?.domainCount, 1);
|
|
1011
|
+
assert.equal(stats.by_type.agent_memory?.by_domain.recent?.count, 1);
|
|
1012
|
+
const memoryStats = (await handleToolCall.call(server, "get_memory_stats", { memory_type: "project_memory" }));
|
|
1013
|
+
assert.equal(memoryStats.memory_type, "project_memory");
|
|
1034
1014
|
assert.equal(memoryStats.total, 1);
|
|
1035
|
-
assert.deepEqual(Object.keys(memoryStats.by_type), ["
|
|
1036
|
-
assert.equal(memoryStats.by_type.
|
|
1037
|
-
assert.equal(memoryStats.by_type.
|
|
1015
|
+
assert.deepEqual(Object.keys(memoryStats.by_type), ["project_memory"]);
|
|
1016
|
+
assert.equal(memoryStats.by_type.project_memory?.domainCount, 1);
|
|
1017
|
+
assert.equal(memoryStats.by_type.project_memory?.by_domain.core?.count, 1);
|
|
1038
1018
|
});
|
|
1039
1019
|
});
|
|
1040
|
-
it("
|
|
1041
|
-
await withMemoryServer(async (server) => {
|
|
1042
|
-
const handleToolCall = getHandleToolCall(server);
|
|
1043
|
-
for (let index = 0; index < 64; index += 1) {
|
|
1044
|
-
await handleToolCall.call(server, "create_memory", {
|
|
1045
|
-
memory_type: "recently_memory",
|
|
1046
|
-
uri: `recent://capacity/${index}`,
|
|
1047
|
-
content: `recent ${index}`,
|
|
1048
|
-
});
|
|
1049
|
-
}
|
|
1050
|
-
await assert.rejects(async () => {
|
|
1051
|
-
await handleToolCall.call(server, "create_memory", {
|
|
1052
|
-
memory_type: "recently_memory",
|
|
1053
|
-
uri: "recent://capacity/overflow",
|
|
1054
|
-
content: "overflow",
|
|
1055
|
-
});
|
|
1056
|
-
}, (error) => {
|
|
1057
|
-
assert.ok(error instanceof MemoryCapacityError);
|
|
1058
|
-
assert.equal(error.details.code, "MEMORY_TYPE_LIMIT_REACHED");
|
|
1059
|
-
assert.equal(error.details.memory_type, "recently_memory");
|
|
1060
|
-
assert.equal(error.details.domain, "recent");
|
|
1061
|
-
assert.equal(error.details.current, 64);
|
|
1062
|
-
assert.equal(error.details.limit, 64);
|
|
1063
|
-
assert.ok(error.details.recommended_actions.includes("archive_recently_memory({ uri })"));
|
|
1064
|
-
return true;
|
|
1065
|
-
});
|
|
1066
|
-
});
|
|
1067
|
-
});
|
|
1068
|
-
it("poll_message injects a cleanup notice when listable memory exceeds soft limits", async () => {
|
|
1020
|
+
it("poll_message returns cleanup notice as a while-type when no unread messages", async () => {
|
|
1069
1021
|
await withMemoryServer(async (server) => {
|
|
1070
1022
|
const handleToolCall = getHandleToolCall(server);
|
|
1071
1023
|
Reflect.set(server, "agentClient", {
|
|
@@ -1078,24 +1030,34 @@ describe("McpServer memory tools", () => {
|
|
|
1078
1030
|
});
|
|
1079
1031
|
for (let index = 0; index < 33; index += 1) {
|
|
1080
1032
|
await handleToolCall.call(server, "create_memory", {
|
|
1081
|
-
memory_type: "
|
|
1033
|
+
memory_type: "agent_memory",
|
|
1082
1034
|
uri: `recent://cleanup/${index}`,
|
|
1083
1035
|
content: `recent ${index}`,
|
|
1084
1036
|
});
|
|
1085
1037
|
}
|
|
1038
|
+
// Override poll to resolve immediately with empty (simulating timeout without waiting 30s)
|
|
1039
|
+
const buffer = Reflect.get(server, "messageBuffer");
|
|
1040
|
+
const originalPoll = buffer.poll.bind(buffer);
|
|
1041
|
+
let pollCallCount = 0;
|
|
1042
|
+
buffer.poll = ((_timeoutMs) => {
|
|
1043
|
+
pollCallCount++;
|
|
1044
|
+
return Promise.resolve({ directMessages: [], groupMessages: [] });
|
|
1045
|
+
});
|
|
1086
1046
|
const result = (await handleToolCall.call(server, "poll_message", {}));
|
|
1087
1047
|
assert.equal(result.groupMessages.length, 0);
|
|
1048
|
+
// cleanup notice returned as a while-type (no unread messages)
|
|
1088
1049
|
assert.equal(result.directMessages.length, 1);
|
|
1089
1050
|
assert.match(result.directMessages[0]?.msgId, /^memory-cleanup-/);
|
|
1090
1051
|
assert.equal(result.directMessages[0]?.senderId, "MCP-System");
|
|
1091
1052
|
assert.equal(result.directMessages[0]?.receiverId, "agent-self");
|
|
1092
1053
|
assert.match(result.directMessages[0]?.content ?? "", /本地 memory 已超过建议容量/);
|
|
1093
|
-
assert.match(result.directMessages[0]?.content ?? "", /recently_memory\/recent 类型下当前 33 条 memory/);
|
|
1094
1054
|
assert.match(result.directMessages[0]?.content ?? "", /get_memory_stats/);
|
|
1095
1055
|
assert.match(result.directMessages[0]?.prompt ?? "", /无需持久化/);
|
|
1056
|
+
// 非紧急类在初始路径直接返回,不进入 while 循环
|
|
1057
|
+
assert.equal(pollCallCount, 0);
|
|
1096
1058
|
});
|
|
1097
1059
|
});
|
|
1098
|
-
it("poll_message
|
|
1060
|
+
it("poll_message returns task notification without cleanup notice (while-type not stacked)", async () => {
|
|
1099
1061
|
await withMemoryServer(async (server) => {
|
|
1100
1062
|
const handleToolCall = getHandleToolCall(server);
|
|
1101
1063
|
const taskNotification = {
|
|
@@ -1121,19 +1083,17 @@ describe("McpServer memory tools", () => {
|
|
|
1121
1083
|
});
|
|
1122
1084
|
for (let index = 0; index < 33; index += 1) {
|
|
1123
1085
|
await handleToolCall.call(server, "create_memory", {
|
|
1124
|
-
memory_type: "
|
|
1086
|
+
memory_type: "agent_memory",
|
|
1125
1087
|
uri: `recent://cleanup-claim/${index}`,
|
|
1126
1088
|
content: `recent ${index}`,
|
|
1127
1089
|
});
|
|
1128
1090
|
}
|
|
1129
1091
|
const result = (await handleToolCall.call(server, "poll_message", {}));
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
assert.equal(fetchOptions[0]?.includePipelineTasks, false);
|
|
1092
|
+
// Task notification is returned as an unread message; cleanup is a while-type
|
|
1093
|
+
// that is only checked when there are no unread messages - not stacked with messages.
|
|
1133
1094
|
assert.equal(result.groupMessages.length, 0);
|
|
1134
|
-
assert.equal(result.directMessages.length,
|
|
1135
|
-
assert.
|
|
1136
|
-
assert.equal(result.directMessages[1]?.msgId, taskNotification.msgId);
|
|
1095
|
+
assert.equal(result.directMessages.length, 1);
|
|
1096
|
+
assert.equal(result.directMessages[0]?.msgId, taskNotification.msgId);
|
|
1137
1097
|
});
|
|
1138
1098
|
});
|
|
1139
1099
|
it("get_message injects a cleanup notice when listable memory exceeds soft limits", async () => {
|
|
@@ -1149,7 +1109,7 @@ describe("McpServer memory tools", () => {
|
|
|
1149
1109
|
});
|
|
1150
1110
|
for (let index = 0; index < 33; index += 1) {
|
|
1151
1111
|
await handleToolCall.call(server, "create_memory", {
|
|
1152
|
-
memory_type: "
|
|
1112
|
+
memory_type: "agent_memory",
|
|
1153
1113
|
uri: `recent://cleanup-get/${index}`,
|
|
1154
1114
|
content: `recent ${index}`,
|
|
1155
1115
|
});
|
|
@@ -1162,7 +1122,7 @@ describe("McpServer memory tools", () => {
|
|
|
1162
1122
|
assert.equal(result.directMessages[0]?.senderId, "MCP-System");
|
|
1163
1123
|
assert.equal(result.directMessages[0]?.receiverId, "agent-self");
|
|
1164
1124
|
assert.match(result.directMessages[0]?.content ?? "", /本地 memory 已超过建议容量/);
|
|
1165
|
-
assert.match(result.directMessages[0]?.content ?? "", /
|
|
1125
|
+
assert.match(result.directMessages[0]?.content ?? "", /agent_memory\/recent 类型下当前 33 条 memory/);
|
|
1166
1126
|
assert.match(result.directMessages[0]?.prompt ?? "", /无需持久化/);
|
|
1167
1127
|
});
|
|
1168
1128
|
});
|
|
@@ -1170,7 +1130,7 @@ describe("McpServer memory tools", () => {
|
|
|
1170
1130
|
await withMemoryServer(async (server) => {
|
|
1171
1131
|
const handleToolCall = getHandleToolCall(server);
|
|
1172
1132
|
await handleToolCall.call(server, "create_memory", {
|
|
1173
|
-
memory_type: "
|
|
1133
|
+
memory_type: "project_memory",
|
|
1174
1134
|
uri: "core://agent/incomplete-update",
|
|
1175
1135
|
content: "original",
|
|
1176
1136
|
});
|
|
@@ -1196,7 +1156,7 @@ describe("McpServer memory tools", () => {
|
|
|
1196
1156
|
});
|
|
1197
1157
|
const handleToolCall = getHandleToolCall(server);
|
|
1198
1158
|
await handleToolCall.call(server, "create_memory", {
|
|
1199
|
-
memory_type: "
|
|
1159
|
+
memory_type: "project_memory",
|
|
1200
1160
|
uri: "core://agent/private",
|
|
1201
1161
|
content: "secret local memory content",
|
|
1202
1162
|
});
|
|
@@ -1212,7 +1172,7 @@ describe("McpServer memory tools", () => {
|
|
|
1212
1172
|
});
|
|
1213
1173
|
assert.deepEqual(reported[0], {
|
|
1214
1174
|
name: "create_memory",
|
|
1215
|
-
args: { uri: "core://agent/private", memory_type: "
|
|
1175
|
+
args: { uri: "core://agent/private", memory_type: "project_memory" },
|
|
1216
1176
|
});
|
|
1217
1177
|
assert.deepEqual(reported[1], {
|
|
1218
1178
|
name: "update_memory",
|
|
@@ -1268,12 +1228,12 @@ describe("McpServer memory tools", () => {
|
|
|
1268
1228
|
await withMemoryServer(async (server) => {
|
|
1269
1229
|
const handleToolCall = getHandleToolCall(server);
|
|
1270
1230
|
await handleToolCall.call(server, "create_memory", {
|
|
1271
|
-
memory_type: "
|
|
1231
|
+
memory_type: "project_memory",
|
|
1272
1232
|
uri: "core://agent/duplicate",
|
|
1273
1233
|
content: "first",
|
|
1274
1234
|
});
|
|
1275
1235
|
await assert.rejects(() => handleToolCall.call(server, "create_memory", {
|
|
1276
|
-
memory_type: "
|
|
1236
|
+
memory_type: "project_memory",
|
|
1277
1237
|
uri: "core://agent/duplicate",
|
|
1278
1238
|
content: "second",
|
|
1279
1239
|
}), /Memory already exists/);
|
|
@@ -1283,25 +1243,27 @@ describe("McpServer memory tools", () => {
|
|
|
1283
1243
|
assert.deepEqual(missingDelete, { deleted: false });
|
|
1284
1244
|
});
|
|
1285
1245
|
});
|
|
1286
|
-
it("
|
|
1246
|
+
it("allows no-content update for status-only refresh (empty append)", async () => {
|
|
1287
1247
|
await withMemoryServer(async (server) => {
|
|
1288
1248
|
const handleToolCall = getHandleToolCall(server);
|
|
1289
1249
|
await handleToolCall.call(server, "create_memory", {
|
|
1290
|
-
memory_type: "
|
|
1250
|
+
memory_type: "project_memory",
|
|
1291
1251
|
uri: "core://agent/noop",
|
|
1292
1252
|
content: "original",
|
|
1293
1253
|
});
|
|
1294
|
-
|
|
1254
|
+
// 空 append 不再报错,而是执行无内容更新(仅刷新状态/MD5)
|
|
1255
|
+
const result = await handleToolCall.call(server, "update_memory", {
|
|
1295
1256
|
uri: "core://agent/noop",
|
|
1296
1257
|
append: "",
|
|
1297
|
-
})
|
|
1258
|
+
});
|
|
1259
|
+
assert.ok(result, "no-content update should succeed");
|
|
1298
1260
|
});
|
|
1299
1261
|
});
|
|
1300
1262
|
it("rejects create_memory when bound_files contain non-existent paths", async () => {
|
|
1301
1263
|
await withMemoryServer(async (server) => {
|
|
1302
1264
|
const handleToolCall = getHandleToolCall(server);
|
|
1303
1265
|
await assert.rejects(() => handleToolCall.call(server, "create_memory", {
|
|
1304
|
-
memory_type: "
|
|
1266
|
+
memory_type: "project_memory",
|
|
1305
1267
|
uri: "core://agent/missing-bound-file",
|
|
1306
1268
|
content: "memory with non-existent bound file",
|
|
1307
1269
|
bound_files: ["./non-existent-file.ts"],
|
|
@@ -1312,13 +1274,13 @@ describe("McpServer memory tools", () => {
|
|
|
1312
1274
|
await withMemoryServer(async (server) => {
|
|
1313
1275
|
const handleToolCall = getHandleToolCall(server);
|
|
1314
1276
|
await handleToolCall.call(server, "create_memory", {
|
|
1315
|
-
memory_type: "
|
|
1277
|
+
memory_type: "project_memory",
|
|
1316
1278
|
uri: "core://agent/update-with-missing-bound-file",
|
|
1317
1279
|
content: "original content",
|
|
1318
1280
|
});
|
|
1319
1281
|
await assert.rejects(() => handleToolCall.call(server, "update_memory", {
|
|
1320
1282
|
uri: "core://agent/update-with-missing-bound-file",
|
|
1321
|
-
memory_type: "
|
|
1283
|
+
memory_type: "project_memory",
|
|
1322
1284
|
old_string: "original",
|
|
1323
1285
|
new_string: "updated",
|
|
1324
1286
|
bound_files: ["./non-existent-file.ts"],
|
|
@@ -1335,7 +1297,7 @@ describe("McpServer memory tools", () => {
|
|
|
1335
1297
|
await withMemoryServer(async (server) => {
|
|
1336
1298
|
const handleToolCall = getHandleToolCall(server);
|
|
1337
1299
|
const created = await handleToolCall.call(server, "create_memory", {
|
|
1338
|
-
memory_type: "
|
|
1300
|
+
memory_type: "project_memory",
|
|
1339
1301
|
uri: "core://agent/valid-bound-file",
|
|
1340
1302
|
content: "memory with valid bound file",
|
|
1341
1303
|
bound_files: ["./existing-file.ts"],
|
|
@@ -1364,7 +1326,7 @@ describe("McpServer memory tools", () => {
|
|
|
1364
1326
|
await withMemoryServer(async (server) => {
|
|
1365
1327
|
const handleToolCall = getHandleToolCall(server);
|
|
1366
1328
|
await assert.rejects(() => handleToolCall.call(server, "create_memory", {
|
|
1367
|
-
memory_type: "
|
|
1329
|
+
memory_type: "project_memory",
|
|
1368
1330
|
uri: "core://agent/mixed-bound-file",
|
|
1369
1331
|
content: "memory with mixed bound files",
|
|
1370
1332
|
bound_files: ["./existing-file.ts", "./non-existent-file.ts"],
|
|
@@ -1385,14 +1347,14 @@ describe("McpServer memory tools", () => {
|
|
|
1385
1347
|
await withMemoryServer(async (server) => {
|
|
1386
1348
|
const handleToolCall = getHandleToolCall(server);
|
|
1387
1349
|
await handleToolCall.call(server, "create_memory", {
|
|
1388
|
-
memory_type: "
|
|
1350
|
+
memory_type: "project_memory",
|
|
1389
1351
|
uri: "core://agent/update-without-bound-files",
|
|
1390
1352
|
content: "original content",
|
|
1391
1353
|
});
|
|
1392
1354
|
// Update without bound_files should succeed even if existing bound files are invalid
|
|
1393
1355
|
const updated = await handleToolCall.call(server, "update_memory", {
|
|
1394
1356
|
uri: "core://agent/update-without-bound-files",
|
|
1395
|
-
memory_type: "
|
|
1357
|
+
memory_type: "project_memory",
|
|
1396
1358
|
old_string: "original",
|
|
1397
1359
|
new_string: "updated",
|
|
1398
1360
|
});
|
|
@@ -1882,4 +1844,160 @@ describe("AgentClient group room aggregation", () => {
|
|
|
1882
1844
|
assert.equal(result.count, 2);
|
|
1883
1845
|
});
|
|
1884
1846
|
});
|
|
1847
|
+
describe("McpServer todo reminder on poll_message", () => {
|
|
1848
|
+
// 使用唯一 agentId 避免污染开发者真实 todo 文件;每次测试写入并清理
|
|
1849
|
+
const testAgentId = `test-todo-reminder-${process.pid}-${Date.now()}`;
|
|
1850
|
+
const todoDir = path.join(os.homedir(), ".acode", "todos");
|
|
1851
|
+
const todoPath = path.join(todoDir, `${testAgentId}.json`);
|
|
1852
|
+
async function writeTodoFile(todos) {
|
|
1853
|
+
await mkdir(todoDir, { recursive: true });
|
|
1854
|
+
await writeFile(todoPath, JSON.stringify({
|
|
1855
|
+
agentId: testAgentId,
|
|
1856
|
+
updatedAt: new Date().toISOString(),
|
|
1857
|
+
background: "test background",
|
|
1858
|
+
todos,
|
|
1859
|
+
}), "utf-8");
|
|
1860
|
+
}
|
|
1861
|
+
async function cleanupTodoFile() {
|
|
1862
|
+
try {
|
|
1863
|
+
await rm(todoPath, { force: true });
|
|
1864
|
+
}
|
|
1865
|
+
catch {
|
|
1866
|
+
// 忽略清理失败
|
|
1867
|
+
}
|
|
1868
|
+
}
|
|
1869
|
+
function createServerForTodo() {
|
|
1870
|
+
return createServerWithUnread({ directMessages: [], groupMessages: [] }, {
|
|
1871
|
+
getState: () => ({ agentId: testAgentId }),
|
|
1872
|
+
});
|
|
1873
|
+
}
|
|
1874
|
+
function makeDirectMessage(msgId) {
|
|
1875
|
+
return {
|
|
1876
|
+
msgId,
|
|
1877
|
+
senderId: "agent-wake",
|
|
1878
|
+
senderName: "Wake Agent",
|
|
1879
|
+
content: `wake message ${msgId}`,
|
|
1880
|
+
requireReply: false,
|
|
1881
|
+
timestamp: new Date().toISOString(),
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
it("returns todo alone when incomplete todos exist and no unread messages", async () => {
|
|
1885
|
+
await writeTodoFile([
|
|
1886
|
+
{ content: "任务A", status: "pending", priority: "high" },
|
|
1887
|
+
{ content: "任务B", status: "completed", priority: "low" },
|
|
1888
|
+
]);
|
|
1889
|
+
try {
|
|
1890
|
+
const server = createServerForTodo();
|
|
1891
|
+
const handleToolCall = getHandleToolCall(server);
|
|
1892
|
+
const result = (await handleToolCall.call(server, "poll_message", {}));
|
|
1893
|
+
// 无未读消息时,todo 单独返回(组合2)
|
|
1894
|
+
assert.equal(result.directMessages.length, 1);
|
|
1895
|
+
assert.equal(result.directMessages[0].senderId, "MCP-System");
|
|
1896
|
+
assert.equal(result.directMessages[0].senderName, "系统");
|
|
1897
|
+
assert.match(result.directMessages[0].content, /Todo 列表存在 1 项未完成/);
|
|
1898
|
+
}
|
|
1899
|
+
finally {
|
|
1900
|
+
await cleanupTodoFile();
|
|
1901
|
+
}
|
|
1902
|
+
});
|
|
1903
|
+
it("returns messages + todo when both unread messages and incomplete todos exist", async () => {
|
|
1904
|
+
await writeTodoFile([
|
|
1905
|
+
{ content: "任务A", status: "pending", priority: "high" },
|
|
1906
|
+
]);
|
|
1907
|
+
try {
|
|
1908
|
+
const server = createServerForTodo();
|
|
1909
|
+
// 先把消息放入 buffer,模拟已有未读消息
|
|
1910
|
+
const buffer = Reflect.get(server, "messageBuffer");
|
|
1911
|
+
const msg = makeDirectMessage("msg-before-poll");
|
|
1912
|
+
buffer.push(msg);
|
|
1913
|
+
const handleToolCall = getHandleToolCall(server);
|
|
1914
|
+
const result = (await handleToolCall.call(server, "poll_message", {}));
|
|
1915
|
+
// 有未读消息 + todo -> 组合4: 未读消息 + todo
|
|
1916
|
+
assert.equal(result.directMessages.length, 2);
|
|
1917
|
+
assert.equal(result.directMessages[0].senderId, "MCP-System");
|
|
1918
|
+
assert.match(result.directMessages[0].content, /Todo 列表存在 1 项未完成/);
|
|
1919
|
+
assert.equal(result.directMessages[1].msgId, "msg-before-poll");
|
|
1920
|
+
}
|
|
1921
|
+
finally {
|
|
1922
|
+
await cleanupTodoFile();
|
|
1923
|
+
}
|
|
1924
|
+
});
|
|
1925
|
+
it("does not inject todo reminder when all todos are completed", async () => {
|
|
1926
|
+
await writeTodoFile([
|
|
1927
|
+
{ content: "任务A", status: "completed", priority: "high" },
|
|
1928
|
+
]);
|
|
1929
|
+
try {
|
|
1930
|
+
const server = createServerForTodo();
|
|
1931
|
+
const buffer = Reflect.get(server, "messageBuffer");
|
|
1932
|
+
const wake = makeDirectMessage("wake-completed");
|
|
1933
|
+
setTimeout(() => buffer.push(wake), 50);
|
|
1934
|
+
const handleToolCall = getHandleToolCall(server);
|
|
1935
|
+
const result = (await handleToolCall.call(server, "poll_message", {}));
|
|
1936
|
+
// 全完成时无 todo,进入 while 循环等待消息后返回
|
|
1937
|
+
assert.equal(result.directMessages.length, 1);
|
|
1938
|
+
assert.equal(result.directMessages[0].msgId, "wake-completed");
|
|
1939
|
+
}
|
|
1940
|
+
finally {
|
|
1941
|
+
await cleanupTodoFile();
|
|
1942
|
+
}
|
|
1943
|
+
});
|
|
1944
|
+
it("returns todo alone on every poll_message when incomplete todos exist", async () => {
|
|
1945
|
+
await writeTodoFile([
|
|
1946
|
+
{ content: "任务A", status: "pending", priority: "high" },
|
|
1947
|
+
]);
|
|
1948
|
+
try {
|
|
1949
|
+
const server = createServerForTodo();
|
|
1950
|
+
const handleToolCall = getHandleToolCall(server);
|
|
1951
|
+
// 第一次 poll:无未读消息 -> todo 单独返回(组合2)
|
|
1952
|
+
const result1 = (await handleToolCall.call(server, "poll_message", {}));
|
|
1953
|
+
assert.equal(result1.directMessages.length, 1);
|
|
1954
|
+
assert.match(result1.directMessages[0].content, /Todo 列表存在 1 项未完成/);
|
|
1955
|
+
// 第二次 poll(待办未变):仍返回 todo
|
|
1956
|
+
const result2 = (await handleToolCall.call(server, "poll_message", {}));
|
|
1957
|
+
assert.equal(result2.directMessages.length, 1);
|
|
1958
|
+
assert.match(result2.directMessages[0].content, /Todo 列表存在 1 项未完成/);
|
|
1959
|
+
}
|
|
1960
|
+
finally {
|
|
1961
|
+
await cleanupTodoFile();
|
|
1962
|
+
}
|
|
1963
|
+
});
|
|
1964
|
+
it("returns todo with updated count when todo file changes", async () => {
|
|
1965
|
+
await writeTodoFile([
|
|
1966
|
+
{ content: "任务A", status: "pending", priority: "high" },
|
|
1967
|
+
]);
|
|
1968
|
+
try {
|
|
1969
|
+
const server = createServerForTodo();
|
|
1970
|
+
const handleToolCall = getHandleToolCall(server);
|
|
1971
|
+
// 第一次 poll:1 项未完成
|
|
1972
|
+
const result1 = (await handleToolCall.call(server, "poll_message", {}));
|
|
1973
|
+
assert.equal(result1.directMessages.length, 1);
|
|
1974
|
+
assert.match(result1.directMessages[0].content, /Todo 列表存在 1 项未完成/);
|
|
1975
|
+
// 修改 todo:新增一项
|
|
1976
|
+
await writeTodoFile([
|
|
1977
|
+
{ content: "任务A", status: "pending", priority: "high" },
|
|
1978
|
+
{ content: "任务B", status: "in_progress", priority: "medium" },
|
|
1979
|
+
]);
|
|
1980
|
+
// 第二次 poll:2 项未完成
|
|
1981
|
+
const result2 = (await handleToolCall.call(server, "poll_message", {}));
|
|
1982
|
+
assert.equal(result2.directMessages.length, 1);
|
|
1983
|
+
assert.match(result2.directMessages[0].content, /Todo 列表存在 2 项未完成/);
|
|
1984
|
+
}
|
|
1985
|
+
finally {
|
|
1986
|
+
await cleanupTodoFile();
|
|
1987
|
+
}
|
|
1988
|
+
});
|
|
1989
|
+
it("does not inject todo reminder when todo file is absent", async () => {
|
|
1990
|
+
// 确保文件不存在
|
|
1991
|
+
await cleanupTodoFile();
|
|
1992
|
+
const server = createServerForTodo();
|
|
1993
|
+
const buffer = Reflect.get(server, "messageBuffer");
|
|
1994
|
+
const wake = makeDirectMessage("wake-no-file");
|
|
1995
|
+
setTimeout(() => buffer.push(wake), 50);
|
|
1996
|
+
const handleToolCall = getHandleToolCall(server);
|
|
1997
|
+
const result = (await handleToolCall.call(server, "poll_message", {}));
|
|
1998
|
+
// 无 todo 文件 -> 进入 while 循环等待消息后返回
|
|
1999
|
+
assert.equal(result.directMessages.length, 1);
|
|
2000
|
+
assert.equal(result.directMessages[0].msgId, "wake-no-file");
|
|
2001
|
+
});
|
|
2002
|
+
});
|
|
1885
2003
|
//# sourceMappingURL=mcp-server.test.js.map
|