aws-runtime-bridge 1.9.32 → 1.9.40
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 +35 -1
- package/dist/adapter/AcodeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/AcodeSdkAdapter.js +417 -40
- package/dist/adapter/ClaudeSdkAdapter.d.ts +6 -0
- package/dist/adapter/ClaudeSdkAdapter.d.ts.map +1 -1
- package/dist/adapter/ClaudeSdkAdapter.js +23 -1
- 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 +65 -3
- package/dist/adapter/types.d.ts.map +1 -1
- package/dist/adapter/types.js +5 -4
- package/dist/index.js +4 -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/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/sub-agents.d.ts +14 -0
- package/dist/routes/sub-agents.d.ts.map +1 -0
- package/dist/routes/sub-agents.js +253 -0
- package/dist/routes/terminal.d.ts +9 -1
- package/dist/routes/terminal.d.ts.map +1 -1
- package/dist/routes/terminal.js +207 -22
- package/dist/services/agent-event-store.d.ts +1 -0
- package/dist/services/agent-event-store.d.ts.map +1 -1
- package/dist/services/event-delta-pusher.js +4 -4
- package/dist/services/session-output.d.ts +3 -0
- package/dist/services/session-output.d.ts.map +1 -1
- package/dist/services/session-output.js +38 -2
- 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/compaction.d.ts +206 -0
- package/package/acode/dist/compaction.d.ts.map +1 -0
- package/package/acode/dist/compaction.js +664 -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 +137 -0
- package/package/acode/dist/runtime.d.ts.map +1 -1
- package/package/acode/dist/runtime.js +974 -172
- 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 +169 -0
- package/package/acode/dist/sub-agent-manager.d.ts.map +1 -0
- package/package/acode/dist/sub-agent-manager.js +535 -0
- package/package/acode/dist/sub-agent-store.d.ts +33 -0
- package/package/acode/dist/sub-agent-store.d.ts.map +1 -0
- package/package/acode/dist/sub-agent-store.js +109 -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 +81 -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 +22 -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/context-manager.test.js +0 -2
- package/package/aws-client-agent-mcp/dist/context-manager.test.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +83 -45
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.js +451 -325
- package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.test.js +259 -241
- 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 +1 -19
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +2 -69
- package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts +17 -19
- package/package/aws-client-agent-mcp/dist/memory-store.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-store.js +62 -99
- package/package/aws-client-agent-mcp/dist/memory-store.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-store.test.js +207 -125
- 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 -4
- package/package/aws-client-agent-mcp/dist/memory-tools.d.ts.map +1 -1
- package/package/aws-client-agent-mcp/dist/memory-tools.js +28 -33
- package/package/aws-client-agent-mcp/dist/memory-tools.js.map +1 -1
- package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +27 -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 +100 -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 +1 -3
- 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 +7 -11
- 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 +3 -25
- package/package/aws-client-agent-mcp/dist/types.d.ts.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,270 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { CodexSdkAdapter } from './CodexSdkAdapter.js';
|
|
3
|
-
let lastThread = null;
|
|
4
|
-
let lastCodexOptions;
|
|
5
|
-
let lastThreadOptions;
|
|
6
|
-
let runMessages = [];
|
|
7
|
-
let nextThreadPendingRun = null;
|
|
8
|
-
const POLL_PROMPT = '系统提醒:当前工作已完成或运行时已进入空闲状态。请立即调用 poll_message 工具阻塞等待新消息和流程线任务提醒;收到流程任务提醒后调用 my_task 查看已由后台静默抢占的任务详情并直接处理;完成任务后调用 submit_task_result 提交结果,然后继续 poll_message。';
|
|
9
|
-
class MockThread {
|
|
10
|
-
constructor() {
|
|
11
|
-
this.id = null;
|
|
12
|
-
this.events = [];
|
|
13
|
-
this.rejectOnRun = null;
|
|
14
|
-
this.waitForAbort = false;
|
|
15
|
-
this.pendingRun = null;
|
|
16
|
-
}
|
|
17
|
-
async runStreamed(_message, options) {
|
|
18
|
-
runMessages.push(_message);
|
|
19
|
-
this.id = 'codex-thread-1';
|
|
20
|
-
if (this.rejectOnRun) {
|
|
21
|
-
throw this.rejectOnRun;
|
|
22
|
-
}
|
|
23
|
-
if (this.waitForAbort) {
|
|
24
|
-
await new Promise((_resolve, reject) => {
|
|
25
|
-
options?.signal?.addEventListener('abort', () => reject(new Error('aborted')), { once: true });
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
if (this.pendingRun) {
|
|
29
|
-
await this.pendingRun;
|
|
30
|
-
}
|
|
31
|
-
const events = this.events;
|
|
32
|
-
return {
|
|
33
|
-
events: (async function* streamEvents() {
|
|
34
|
-
for (const event of events) {
|
|
35
|
-
yield event;
|
|
36
|
-
}
|
|
37
|
-
})(),
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
vi.mock('@openai/codex-sdk', () => ({
|
|
42
|
-
Codex: vi.fn().mockImplementation((options) => {
|
|
43
|
-
lastCodexOptions = options;
|
|
44
|
-
return {
|
|
45
|
-
startThread: vi.fn().mockImplementation((options) => {
|
|
46
|
-
lastThreadOptions = options;
|
|
47
|
-
lastThread = new MockThread();
|
|
48
|
-
lastThread.pendingRun = nextThreadPendingRun;
|
|
49
|
-
nextThreadPendingRun = null;
|
|
50
|
-
return lastThread;
|
|
51
|
-
}),
|
|
52
|
-
resumeThread: vi.fn().mockImplementation((_id, options) => {
|
|
53
|
-
lastThreadOptions = options;
|
|
54
|
-
lastThread = new MockThread();
|
|
55
|
-
lastThread.pendingRun = nextThreadPendingRun;
|
|
56
|
-
nextThreadPendingRun = null;
|
|
57
|
-
return lastThread;
|
|
58
|
-
}),
|
|
59
|
-
};
|
|
60
|
-
}),
|
|
61
|
-
}));
|
|
62
|
-
afterEach(() => {
|
|
63
|
-
vi.useRealTimers();
|
|
64
|
-
lastThread = null;
|
|
65
|
-
lastCodexOptions = undefined;
|
|
66
|
-
lastThreadOptions = undefined;
|
|
67
|
-
runMessages = [];
|
|
68
|
-
nextThreadPendingRun = null;
|
|
69
|
-
});
|
|
70
|
-
describe('CodexSdkAdapter', () => {
|
|
71
|
-
it('should expose codex provider identity', () => {
|
|
72
|
-
const adapter = new CodexSdkAdapter();
|
|
73
|
-
expect(adapter.providerId).toBe('codex');
|
|
74
|
-
expect(adapter.displayName).toBe('Codex');
|
|
75
|
-
});
|
|
76
|
-
it('should start with no active sessions', () => {
|
|
77
|
-
const adapter = new CodexSdkAdapter();
|
|
78
|
-
expect(adapter.hasSession('missing-session')).toBe(false);
|
|
79
|
-
expect(adapter.getSessionStatus('missing-session')).toBeUndefined();
|
|
80
|
-
});
|
|
81
|
-
it('maps streamed text and turn completion into conversation state', async () => {
|
|
82
|
-
const adapter = new CodexSdkAdapter();
|
|
83
|
-
await adapter.startSession('session-1', {
|
|
84
|
-
command: 'codex',
|
|
85
|
-
workingDirectory: process.cwd(),
|
|
86
|
-
autoAccept: true,
|
|
87
|
-
});
|
|
88
|
-
if (!lastThread)
|
|
89
|
-
throw new Error('Mock Codex thread was not created');
|
|
90
|
-
lastThread.events = [
|
|
91
|
-
{ type: 'thread.started', thread_id: 'codex-thread-1' },
|
|
92
|
-
{ type: 'turn.started' },
|
|
93
|
-
{ type: 'item.completed', item: { id: 'msg-1', type: 'agent_message', text: 'hello from codex' } },
|
|
94
|
-
{
|
|
95
|
-
type: 'turn.completed',
|
|
96
|
-
usage: {
|
|
97
|
-
input_tokens: 3,
|
|
98
|
-
cached_input_tokens: 0,
|
|
99
|
-
output_tokens: 4,
|
|
100
|
-
reasoning_output_tokens: 0,
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
];
|
|
104
|
-
await adapter.sendMessage('session-1', 'hello');
|
|
105
|
-
expect(adapter.getProviderSessionId('session-1')).toBe('codex-thread-1');
|
|
106
|
-
expect(adapter.getSessionStatus('session-1')).toBe('waiting_input');
|
|
107
|
-
expect(adapter.getConversation('session-1').map((message) => message.role)).toEqual(['user', 'assistant']);
|
|
108
|
-
});
|
|
109
|
-
it('does not emit waiting_input after terminating an aborted turn', async () => {
|
|
110
|
-
const adapter = new CodexSdkAdapter();
|
|
111
|
-
const statuses = [];
|
|
112
|
-
adapter.on('status-change', (_sessionId, status) => {
|
|
113
|
-
statuses.push(status);
|
|
114
|
-
});
|
|
115
|
-
await adapter.startSession('session-1', {
|
|
116
|
-
command: 'codex',
|
|
117
|
-
workingDirectory: process.cwd(),
|
|
118
|
-
autoAccept: true,
|
|
119
|
-
});
|
|
120
|
-
if (!lastThread)
|
|
121
|
-
throw new Error('Mock Codex thread was not created');
|
|
122
|
-
lastThread.waitForAbort = true;
|
|
123
|
-
const sendPromise = adapter.sendMessage('session-1', 'long running task');
|
|
124
|
-
await adapter.terminateSession('session-1');
|
|
125
|
-
await sendPromise;
|
|
126
|
-
expect(statuses.at(-1)).toBe('terminated');
|
|
127
|
-
const terminatedIndex = statuses.lastIndexOf('terminated');
|
|
128
|
-
expect(statuses.slice(terminatedIndex + 1)).not.toContain('waiting_input');
|
|
129
|
-
expect(adapter.hasSession('session-1')).toBe(false);
|
|
130
|
-
});
|
|
131
|
-
it('starts a Codex session without waiting for the initial prompt turn to finish', async () => {
|
|
132
|
-
const adapter = new CodexSdkAdapter();
|
|
133
|
-
let releaseRun;
|
|
134
|
-
nextThreadPendingRun = new Promise((resolve) => {
|
|
135
|
-
releaseRun = resolve;
|
|
136
|
-
});
|
|
137
|
-
await adapter.startSession('session-1', {
|
|
138
|
-
command: 'codex',
|
|
139
|
-
workingDirectory: process.cwd(),
|
|
140
|
-
autoAccept: true,
|
|
141
|
-
initialPrompt: 'boot prompt',
|
|
142
|
-
});
|
|
143
|
-
if (!lastThread)
|
|
144
|
-
throw new Error('Mock Codex thread was not created');
|
|
145
|
-
await new Promise((resolve) => queueMicrotask(resolve));
|
|
146
|
-
expect(adapter.hasSession('session-1')).toBe(true);
|
|
147
|
-
expect(runMessages).toContain('boot prompt');
|
|
148
|
-
releaseRun?.();
|
|
149
|
-
});
|
|
150
|
-
it('waits before sending idle commands after an already idle start', async () => {
|
|
151
|
-
vi.useFakeTimers();
|
|
152
|
-
const adapter = new CodexSdkAdapter();
|
|
153
|
-
await adapter.startSession('session-1', {
|
|
154
|
-
command: 'codex',
|
|
155
|
-
workingDirectory: process.cwd(),
|
|
156
|
-
autoAccept: true,
|
|
157
|
-
});
|
|
158
|
-
if (!lastThread)
|
|
159
|
-
throw new Error('Mock Codex thread was not created');
|
|
160
|
-
lastThread.events = [
|
|
161
|
-
{
|
|
162
|
-
type: 'turn.completed',
|
|
163
|
-
usage: {
|
|
164
|
-
input_tokens: 1,
|
|
165
|
-
cached_input_tokens: 0,
|
|
166
|
-
output_tokens: 1,
|
|
167
|
-
reasoning_output_tokens: 0,
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
];
|
|
171
|
-
adapter.setIdleCommands('session-1', {
|
|
172
|
-
idleInputCommand: 'continue',
|
|
173
|
-
nonInputCommand: '',
|
|
174
|
-
});
|
|
175
|
-
await vi.advanceTimersByTimeAsync(1000);
|
|
176
|
-
expect(adapter.getConversation('session-1').some((message) => message.content === 'continue')).toBe(false);
|
|
177
|
-
await vi.advanceTimersByTimeAsync(600);
|
|
178
|
-
expect(runMessages).toContain('continue');
|
|
179
|
-
expect(adapter.getConversation('session-1').some((message) => message.content === 'continue')).toBe(false);
|
|
180
|
-
});
|
|
181
|
-
it('starts a blocking poll turn for poll_message-style idle commands', async () => {
|
|
182
|
-
vi.useFakeTimers();
|
|
183
|
-
const adapter = new CodexSdkAdapter();
|
|
184
|
-
await adapter.startSession('session-1', {
|
|
185
|
-
command: 'codex',
|
|
186
|
-
workingDirectory: process.cwd(),
|
|
187
|
-
autoAccept: true,
|
|
188
|
-
});
|
|
189
|
-
if (!lastThread)
|
|
190
|
-
throw new Error('Mock Codex thread was not created');
|
|
191
|
-
lastThread.events = [
|
|
192
|
-
{
|
|
193
|
-
type: 'turn.completed',
|
|
194
|
-
usage: {
|
|
195
|
-
input_tokens: 1,
|
|
196
|
-
cached_input_tokens: 0,
|
|
197
|
-
output_tokens: 1,
|
|
198
|
-
reasoning_output_tokens: 0,
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
];
|
|
202
|
-
adapter.setIdleCommands('session-1', {
|
|
203
|
-
idleInputCommand: 'system: 请保持工作循环:持续调用 poll_message 阻塞等待新消息和流程线任务提醒;收到流程任务提醒后调用 my_task 查看已由后台静默抢占的任务详情并直接处理,完成后调用 submit_task_result 提交结果,然后继续 poll_message。',
|
|
204
|
-
nonInputCommand: '',
|
|
205
|
-
});
|
|
206
|
-
await vi.advanceTimersByTimeAsync(1499);
|
|
207
|
-
expect(runMessages).toEqual([]);
|
|
208
|
-
await vi.advanceTimersByTimeAsync(1);
|
|
209
|
-
expect(runMessages).toEqual([POLL_PROMPT]);
|
|
210
|
-
expect(adapter.getSessionStatus('session-1')).toBe('waiting_input');
|
|
211
|
-
const userMessages = adapter.getConversation('session-1').filter((message) => message.role === 'user');
|
|
212
|
-
expect(userMessages).toHaveLength(0);
|
|
213
|
-
});
|
|
214
|
-
it('does not start duplicate poll turns while a Codex turn is already running', async () => {
|
|
215
|
-
const adapter = new CodexSdkAdapter();
|
|
216
|
-
let releaseRun;
|
|
217
|
-
nextThreadPendingRun = new Promise((resolve) => {
|
|
218
|
-
releaseRun = resolve;
|
|
219
|
-
});
|
|
220
|
-
await adapter.startSession('session-1', {
|
|
221
|
-
command: 'codex',
|
|
222
|
-
workingDirectory: process.cwd(),
|
|
223
|
-
autoAccept: true,
|
|
224
|
-
});
|
|
225
|
-
const sendPromise = adapter.sendMessage('session-1', 'long task');
|
|
226
|
-
adapter.setIdleCommands('session-1', {
|
|
227
|
-
idleInputCommand: 'poll_message',
|
|
228
|
-
nonInputCommand: '',
|
|
229
|
-
});
|
|
230
|
-
await new Promise((resolve) => queueMicrotask(resolve));
|
|
231
|
-
expect(runMessages).toEqual(['long task']);
|
|
232
|
-
releaseRun?.();
|
|
233
|
-
await sendPromise;
|
|
234
|
-
});
|
|
235
|
-
it('maps codex command flags into SDK thread options instead of codexPathOverride', async () => {
|
|
236
|
-
const adapter = new CodexSdkAdapter();
|
|
237
|
-
await adapter.startSession('session-1', {
|
|
238
|
-
command: 'codex --model gpt-5.5 --sandbox workspace-write --skip-git-repo-check --config model_reasoning_effort="high"',
|
|
239
|
-
workingDirectory: process.cwd(),
|
|
240
|
-
autoAccept: true,
|
|
241
|
-
});
|
|
242
|
-
expect(lastCodexOptions?.codexPathOverride).toBeUndefined();
|
|
243
|
-
expect(lastThreadOptions).toMatchObject({
|
|
244
|
-
model: 'gpt-5.5',
|
|
245
|
-
sandboxMode: 'workspace-write',
|
|
246
|
-
skipGitRepoCheck: true,
|
|
247
|
-
modelReasoningEffort: 'high',
|
|
248
|
-
});
|
|
249
|
-
});
|
|
250
|
-
it('treats npx codex command as the bundled SDK codex binary with parsed flags', async () => {
|
|
251
|
-
const adapter = new CodexSdkAdapter();
|
|
252
|
-
await adapter.startSession('session-1', {
|
|
253
|
-
command: 'npx codex --model gpt-5-codex',
|
|
254
|
-
workingDirectory: process.cwd(),
|
|
255
|
-
autoAccept: true,
|
|
256
|
-
});
|
|
257
|
-
expect(lastCodexOptions?.codexPathOverride).toBeUndefined();
|
|
258
|
-
expect(lastThreadOptions?.model).toBe('gpt-5-codex');
|
|
259
|
-
});
|
|
260
|
-
it('uses only a custom executable path as codexPathOverride', async () => {
|
|
261
|
-
const adapter = new CodexSdkAdapter();
|
|
262
|
-
await adapter.startSession('session-1', {
|
|
263
|
-
command: 'C:/Tools/codex.exe --model gpt-5-codex',
|
|
264
|
-
workingDirectory: process.cwd(),
|
|
265
|
-
autoAccept: true,
|
|
266
|
-
});
|
|
267
|
-
expect(lastCodexOptions?.codexPathOverride).toBe('C:/Tools/codex.exe');
|
|
268
|
-
expect(lastThreadOptions?.model).toBe('gpt-5-codex');
|
|
269
|
-
});
|
|
270
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"OpencodeSdkAdapter.test.d.ts","sourceRoot":"","sources":["../../src/adapter/OpencodeSdkAdapter.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
-
import { OpencodeSdkAdapter } from './OpencodeSdkAdapter.js';
|
|
3
|
-
const POLL_PROMPT = '系统提醒:当前工作已完成或运行时已进入空闲状态。请立即调用 poll_message 工具阻塞等待新消息和流程线任务提醒;收到流程任务提醒后调用 my_task 查看已由后台静默抢占的任务详情并直接处理;完成任务后调用 submit_task_result 提交结果,然后继续 poll_message。';
|
|
4
|
-
afterEach(() => {
|
|
5
|
-
vi.useRealTimers();
|
|
6
|
-
vi.restoreAllMocks();
|
|
7
|
-
});
|
|
8
|
-
describe('OpencodeSdkAdapter', () => {
|
|
9
|
-
it('should expose opencode provider identity', () => {
|
|
10
|
-
const adapter = new OpencodeSdkAdapter();
|
|
11
|
-
expect(adapter.providerId).toBe('opencode');
|
|
12
|
-
expect(adapter.displayName).toBe('OpenCode');
|
|
13
|
-
});
|
|
14
|
-
it('should start with no active sessions', () => {
|
|
15
|
-
const adapter = new OpencodeSdkAdapter();
|
|
16
|
-
expect(adapter.hasSession('missing-session')).toBe(false);
|
|
17
|
-
expect(adapter.getSessionStatus('missing-session')).toBeUndefined();
|
|
18
|
-
});
|
|
19
|
-
it('normalizes poll_message-style idle commands into a blocking poll prompt', () => {
|
|
20
|
-
const adapter = new OpencodeSdkAdapter();
|
|
21
|
-
const prompt = Reflect.get(adapter, 'toIdlePrompt').call(adapter, 'system: 请保持工作循环:持续调用 poll_message 阻塞等待新消息和流程线任务提醒;收到流程任务提醒后调用 my_task 查看已由后台静默抢占的任务详情并直接处理,完成后调用 submit_task_result 提交结果,然后继续 poll_message。');
|
|
22
|
-
expect(prompt).toBe(POLL_PROMPT);
|
|
23
|
-
});
|
|
24
|
-
it('starts idle detection when commands are set after OpenCode is already waiting for input', async () => {
|
|
25
|
-
vi.useFakeTimers();
|
|
26
|
-
const adapter = new OpencodeSdkAdapter();
|
|
27
|
-
const sentMessages = [];
|
|
28
|
-
Reflect.set(adapter, 'sessions', new Map([
|
|
29
|
-
[
|
|
30
|
-
'session-1',
|
|
31
|
-
{
|
|
32
|
-
adapterSession: {
|
|
33
|
-
sessionId: 'session-1',
|
|
34
|
-
status: 'waiting_input',
|
|
35
|
-
messages: [],
|
|
36
|
-
createdAt: new Date().toISOString(),
|
|
37
|
-
totalUsage: { inputTokens: 0, outputTokens: 0 },
|
|
38
|
-
},
|
|
39
|
-
config: {
|
|
40
|
-
command: 'opencode',
|
|
41
|
-
workingDirectory: process.cwd(),
|
|
42
|
-
autoAccept: true,
|
|
43
|
-
},
|
|
44
|
-
sseActive: false,
|
|
45
|
-
pendingPermissions: new Map(),
|
|
46
|
-
emittedToolStarts: new Set(),
|
|
47
|
-
workingDirectory: process.cwd(),
|
|
48
|
-
userMessageIds: new Set(),
|
|
49
|
-
currentAssistantText: '',
|
|
50
|
-
seenTextPartIds: new Set(),
|
|
51
|
-
},
|
|
52
|
-
],
|
|
53
|
-
]));
|
|
54
|
-
vi.spyOn(adapter, 'sendMessage').mockImplementation(async (_sessionId, message) => {
|
|
55
|
-
sentMessages.push(message);
|
|
56
|
-
});
|
|
57
|
-
adapter.setIdleCommands('session-1', {
|
|
58
|
-
idleInputCommand: 'system: 使用poll_message阻塞获取消息',
|
|
59
|
-
nonInputCommand: '',
|
|
60
|
-
});
|
|
61
|
-
await vi.advanceTimersByTimeAsync(1499);
|
|
62
|
-
expect(sentMessages).toEqual([]);
|
|
63
|
-
await vi.advanceTimersByTimeAsync(1);
|
|
64
|
-
expect(sentMessages).toEqual([POLL_PROMPT]);
|
|
65
|
-
expect(adapter.getSessionStatus('session-1')).toBe('waiting_input');
|
|
66
|
-
});
|
|
67
|
-
it('re-arms polling idle detection after OpenCode returns to waiting for input', async () => {
|
|
68
|
-
vi.useFakeTimers();
|
|
69
|
-
const adapter = new OpencodeSdkAdapter();
|
|
70
|
-
const sentMessages = [];
|
|
71
|
-
const session = {
|
|
72
|
-
adapterSession: {
|
|
73
|
-
sessionId: 'session-1',
|
|
74
|
-
status: 'waiting_input',
|
|
75
|
-
messages: [],
|
|
76
|
-
createdAt: new Date().toISOString(),
|
|
77
|
-
totalUsage: { inputTokens: 0, outputTokens: 0 },
|
|
78
|
-
},
|
|
79
|
-
config: {
|
|
80
|
-
command: 'opencode',
|
|
81
|
-
workingDirectory: process.cwd(),
|
|
82
|
-
autoAccept: true,
|
|
83
|
-
},
|
|
84
|
-
sseActive: false,
|
|
85
|
-
pendingPermissions: new Map(),
|
|
86
|
-
emittedToolStarts: new Set(),
|
|
87
|
-
workingDirectory: process.cwd(),
|
|
88
|
-
userMessageIds: new Set(),
|
|
89
|
-
currentAssistantText: '',
|
|
90
|
-
seenTextPartIds: new Set(),
|
|
91
|
-
};
|
|
92
|
-
Reflect.set(adapter, 'sessions', new Map([['session-1', session]]));
|
|
93
|
-
vi.spyOn(adapter, 'sendMessage').mockImplementation(async (_sessionId, message) => {
|
|
94
|
-
sentMessages.push(message);
|
|
95
|
-
session.adapterSession.status = 'thinking';
|
|
96
|
-
});
|
|
97
|
-
adapter.setIdleCommands('session-1', {
|
|
98
|
-
idleInputCommand: 'system: 使用poll_message阻塞获取消息',
|
|
99
|
-
nonInputCommand: '',
|
|
100
|
-
});
|
|
101
|
-
await vi.advanceTimersByTimeAsync(1500);
|
|
102
|
-
expect(sentMessages).toHaveLength(1);
|
|
103
|
-
session.adapterSession.status = 'waiting_input';
|
|
104
|
-
Reflect.get(adapter, 'startIdleDetection').call(adapter, 'session-1');
|
|
105
|
-
await vi.advanceTimersByTimeAsync(1500);
|
|
106
|
-
expect(sentMessages).toHaveLength(2);
|
|
107
|
-
});
|
|
108
|
-
it('does not send polling prompts while OpenCode is busy', () => {
|
|
109
|
-
const adapter = new OpencodeSdkAdapter();
|
|
110
|
-
const sentMessages = [];
|
|
111
|
-
Reflect.set(adapter, 'sessions', new Map([
|
|
112
|
-
[
|
|
113
|
-
'session-1',
|
|
114
|
-
{
|
|
115
|
-
adapterSession: {
|
|
116
|
-
sessionId: 'session-1',
|
|
117
|
-
status: 'thinking',
|
|
118
|
-
messages: [],
|
|
119
|
-
createdAt: new Date().toISOString(),
|
|
120
|
-
totalUsage: { inputTokens: 0, outputTokens: 0 },
|
|
121
|
-
},
|
|
122
|
-
config: {
|
|
123
|
-
command: 'opencode',
|
|
124
|
-
workingDirectory: process.cwd(),
|
|
125
|
-
autoAccept: true,
|
|
126
|
-
},
|
|
127
|
-
sseActive: false,
|
|
128
|
-
pendingPermissions: new Map(),
|
|
129
|
-
emittedToolStarts: new Set(),
|
|
130
|
-
workingDirectory: process.cwd(),
|
|
131
|
-
userMessageIds: new Set(),
|
|
132
|
-
currentAssistantText: '',
|
|
133
|
-
seenTextPartIds: new Set(),
|
|
134
|
-
},
|
|
135
|
-
],
|
|
136
|
-
]));
|
|
137
|
-
vi.spyOn(adapter, 'sendMessage').mockImplementation(async (_sessionId, message) => {
|
|
138
|
-
sentMessages.push(message);
|
|
139
|
-
});
|
|
140
|
-
adapter.setIdleCommands('session-1', {
|
|
141
|
-
idleInputCommand: 'system: 使用poll_message阻塞获取消息',
|
|
142
|
-
nonInputCommand: '',
|
|
143
|
-
});
|
|
144
|
-
expect(sentMessages).toEqual([]);
|
|
145
|
-
});
|
|
146
|
-
it('includes serve startup output when the OpenCode process exits early', () => {
|
|
147
|
-
const adapter = new OpencodeSdkAdapter();
|
|
148
|
-
const message = Reflect.get(adapter, 'formatStartupExitMessage').call(adapter, { code: 1, signal: null }, ['missing auth configuration']);
|
|
149
|
-
expect(message).toContain('OpenCode server exited during startup (code 1)');
|
|
150
|
-
expect(message).toContain('missing auth configuration');
|
|
151
|
-
});
|
|
152
|
-
it('dispatches the initial prompt asynchronously so launch can return after session creation', () => {
|
|
153
|
-
const adapter = new OpencodeSdkAdapter();
|
|
154
|
-
const sendMessage = vi.spyOn(adapter, 'sendMessage').mockResolvedValue(undefined);
|
|
155
|
-
Reflect.get(adapter, 'dispatchInitialPrompt').call(adapter, 'session-1', 'hello');
|
|
156
|
-
expect(sendMessage).toHaveBeenCalledWith('session-1', 'hello');
|
|
157
|
-
});
|
|
158
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"acode-tool-names.test.d.ts","sourceRoot":"","sources":["../../src/adapter/acode-tool-names.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { getSemanticToolName, isMessagePollingIdleCommand, isPollMessageToolDescriptor, } from "./acode-tool-names.js";
|
|
3
|
-
describe("ACode tool name helpers", () => {
|
|
4
|
-
it("extracts semantic tool names from MCP prefixes", () => {
|
|
5
|
-
expect(getSemanticToolName("aws-mcp__poll_message")).toBe("poll_message");
|
|
6
|
-
expect(getSemanticToolName("aws-mcp.poll_message")).toBe("poll_message");
|
|
7
|
-
expect(getSemanticToolName("mcp/aws-mcp/get_message")).toBe("get_message");
|
|
8
|
-
});
|
|
9
|
-
it("recognizes only exact poll_message tool descriptors as listeners", () => {
|
|
10
|
-
expect(isPollMessageToolDescriptor({
|
|
11
|
-
name: "aws-mcp__poll_message",
|
|
12
|
-
source: "aws-mcp.poll_message",
|
|
13
|
-
})).toBe(true);
|
|
14
|
-
expect(isPollMessageToolDescriptor({
|
|
15
|
-
name: "other-mcp__not_poll_message",
|
|
16
|
-
source: "other-mcp.not_poll_message",
|
|
17
|
-
})).toBe(false);
|
|
18
|
-
expect(isPollMessageToolDescriptor({
|
|
19
|
-
name: "poll_message_backup",
|
|
20
|
-
source: "other-mcp.poll_message_backup",
|
|
21
|
-
})).toBe(false);
|
|
22
|
-
});
|
|
23
|
-
it("detects configured idle commands that ask the agent to poll messages", () => {
|
|
24
|
-
expect(isMessagePollingIdleCommand("poll_message")).toBe(true);
|
|
25
|
-
expect(isMessagePollingIdleCommand("system: call get_message now")).toBe(true);
|
|
26
|
-
expect(isMessagePollingIdleCommand("continue the current task")).toBe(false);
|
|
27
|
-
});
|
|
28
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.test.d.ts","sourceRoot":"","sources":["../../src/adapter/adapter.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Adapter 类型定义测试
|
|
3
|
-
*/
|
|
4
|
-
import { describe, expect, it } from 'vitest';
|
|
5
|
-
import { getToolActionInfo } from '../adapter/types.js';
|
|
6
|
-
describe('Adapter Types', () => {
|
|
7
|
-
it('should define valid SessionStatus values', () => {
|
|
8
|
-
const statuses = [
|
|
9
|
-
'starting',
|
|
10
|
-
'thinking',
|
|
11
|
-
'tool_using',
|
|
12
|
-
'waiting_input',
|
|
13
|
-
'completed',
|
|
14
|
-
'terminated',
|
|
15
|
-
'error',
|
|
16
|
-
];
|
|
17
|
-
expect(statuses).toHaveLength(7);
|
|
18
|
-
});
|
|
19
|
-
it('should define valid ProviderEventType values', () => {
|
|
20
|
-
const eventTypes = [
|
|
21
|
-
'text_delta',
|
|
22
|
-
'thinking',
|
|
23
|
-
'tool_use_start',
|
|
24
|
-
'tool_use_end',
|
|
25
|
-
'permission_request',
|
|
26
|
-
'ask_user_question',
|
|
27
|
-
'exit_plan_mode',
|
|
28
|
-
'turn_complete',
|
|
29
|
-
'session_complete',
|
|
30
|
-
'error',
|
|
31
|
-
];
|
|
32
|
-
expect(eventTypes).toHaveLength(10);
|
|
33
|
-
});
|
|
34
|
-
it('should create valid AdapterSessionConfig', () => {
|
|
35
|
-
const config = {
|
|
36
|
-
command: 'claude',
|
|
37
|
-
workingDirectory: '/tmp/test',
|
|
38
|
-
autoAccept: true,
|
|
39
|
-
};
|
|
40
|
-
expect(config.command).toBe('claude');
|
|
41
|
-
expect(config.autoAccept).toBe(true);
|
|
42
|
-
});
|
|
43
|
-
it('should create valid ConversationMessage', () => {
|
|
44
|
-
const message = {
|
|
45
|
-
id: 'msg-1',
|
|
46
|
-
sessionId: 'session-1',
|
|
47
|
-
role: 'user',
|
|
48
|
-
content: 'Hello',
|
|
49
|
-
timestamp: new Date().toISOString(),
|
|
50
|
-
};
|
|
51
|
-
expect(message.role).toBe('user');
|
|
52
|
-
expect(message.content).toBe('Hello');
|
|
53
|
-
});
|
|
54
|
-
it('classifies direct skill tool calls as skill actions', () => {
|
|
55
|
-
expect(getToolActionInfo('Skill', { skill: 'brainstorming' })).toEqual({
|
|
56
|
-
actionType: 'skill',
|
|
57
|
-
actionLabel: '使用技能',
|
|
58
|
-
actionDetail: 'brainstorming',
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
it('classifies task tool calls with load_skills as skill actions', () => {
|
|
62
|
-
expect(getToolActionInfo('Task', { load_skills: ['brainstorming', 'writing-plans'] })).toEqual({
|
|
63
|
-
actionType: 'skill',
|
|
64
|
-
actionLabel: '加载技能',
|
|
65
|
-
actionDetail: 'brainstorming, writing-plans',
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
it('prefers explicit skill name fields for skill tools', () => {
|
|
69
|
-
expect(getToolActionInfo('load_skill', { name: 'frontend-design' })).toEqual({
|
|
70
|
-
actionType: 'skill',
|
|
71
|
-
actionLabel: '使用技能',
|
|
72
|
-
actionDetail: 'frontend-design',
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
it('classifies SDK tool_use_start aliases as skill actions', () => {
|
|
76
|
-
expect(getToolActionInfo('Task', { load_skills: ['requesting-code-review'] })).toEqual({
|
|
77
|
-
actionType: 'skill',
|
|
78
|
-
actionLabel: '加载技能',
|
|
79
|
-
actionDetail: 'requesting-code-review',
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
it('keeps plain task tool calls as generic tool actions', () => {
|
|
83
|
-
expect(getToolActionInfo('Task', { prompt: 'search the repo' })).toEqual({
|
|
84
|
-
actionType: 'other',
|
|
85
|
-
actionLabel: '调用工具',
|
|
86
|
-
actionDetail: 'Task',
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
// MCP 工具分类测试
|
|
90
|
-
it('classifies semantic file MCP tools as file actions', () => {
|
|
91
|
-
// 标准格式: mcp__server__tool;文件类工具优先按语义展示,而不是泛化为 MCP
|
|
92
|
-
expect(getToolActionInfo('mcp__filesystem__read_file', { path: '/tmp/test.txt' })).toEqual({
|
|
93
|
-
actionType: 'read_file',
|
|
94
|
-
actionLabel: '读取文件',
|
|
95
|
-
actionDetail: '/tmp/test.txt',
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
it('classifies semantic shell MCP tools as bash actions', () => {
|
|
99
|
-
expect(getToolActionInfo('mcp__shell__execute_command', { command: 'npm test' })).toEqual({
|
|
100
|
-
actionType: 'bash',
|
|
101
|
-
actionLabel: '执行命令',
|
|
102
|
-
actionDetail: 'npm test',
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
it('classifies custom MCP tools with server name in detail', () => {
|
|
106
|
-
// 自定义格式: xxx-mcp__tool (如 aws-mcp__get_profile)
|
|
107
|
-
expect(getToolActionInfo('aws-mcp__get_profile', {})).toEqual({
|
|
108
|
-
actionType: 'mcp',
|
|
109
|
-
actionLabel: '调用MCP',
|
|
110
|
-
actionDetail: 'aws-mcp/get_profile',
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
it('classifies MCP tools with complex server names', () => {
|
|
114
|
-
// 复杂 MCP server 名称
|
|
115
|
-
expect(getToolActionInfo('my-custom-mcp__do_something', {})).toEqual({
|
|
116
|
-
actionType: 'mcp',
|
|
117
|
-
actionLabel: '调用MCP',
|
|
118
|
-
actionDetail: 'my-custom-mcp/do_something',
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
it('handles MCP tools with multiple underscores in tool name', () => {
|
|
122
|
-
// 工具名本身包含下划线
|
|
123
|
-
expect(getToolActionInfo('mcp__aws__get_colleague_list', {})).toEqual({
|
|
124
|
-
actionType: 'mcp',
|
|
125
|
-
actionLabel: '调用MCP',
|
|
126
|
-
actionDetail: 'aws/get_colleague_list',
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
// metadata 中包含 MCP server 信息的测试
|
|
130
|
-
it('uses metadata.mcpServer for MCP tool classification', () => {
|
|
131
|
-
// 当 metadata 中有 mcpServer 时,优先使用它
|
|
132
|
-
expect(getToolActionInfo('get_profile', {}, { mcpServer: 'aws-mcp' })).toEqual({
|
|
133
|
-
actionType: 'mcp',
|
|
134
|
-
actionLabel: '调用MCP',
|
|
135
|
-
actionDetail: 'aws-mcp/get_profile',
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
it('uses metadata.mcpServer even for simple tool names', () => {
|
|
139
|
-
// 简单工具名 + metadata 也能识别为 MCP 工具
|
|
140
|
-
expect(getToolActionInfo('get_colleague', {}, { mcpServer: 'aws-mcp' })).toEqual({
|
|
141
|
-
actionType: 'mcp',
|
|
142
|
-
actionLabel: '调用MCP',
|
|
143
|
-
actionDetail: 'aws-mcp/get_colleague',
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
it('prefers metadata over tool name pattern for MCP detection', () => {
|
|
147
|
-
// metadata 优先级高于工具名格式
|
|
148
|
-
expect(getToolActionInfo('custom_tool', {}, { mcpServer: 'my-server' })).toEqual({
|
|
149
|
-
actionType: 'mcp',
|
|
150
|
-
actionLabel: '调用MCP',
|
|
151
|
-
actionDetail: 'my-server/custom_tool',
|
|
152
|
-
});
|
|
153
|
-
});
|
|
154
|
-
// 已知 MCP 工具列表测试
|
|
155
|
-
it('recognizes known MCP tools from whitelist', () => {
|
|
156
|
-
// 已知的 aws-mcp 工具,即使没有 metadata 也能识别
|
|
157
|
-
expect(getToolActionInfo('get_profile', {})).toEqual({
|
|
158
|
-
actionType: 'mcp',
|
|
159
|
-
actionLabel: '调用MCP',
|
|
160
|
-
actionDetail: 'aws-mcp/get_profile',
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
it('recognizes all aws-mcp tools', () => {
|
|
164
|
-
expect(getToolActionInfo('get_colleague', {})).toEqual({
|
|
165
|
-
actionType: 'mcp',
|
|
166
|
-
actionLabel: '调用MCP',
|
|
167
|
-
actionDetail: 'aws-mcp/get_colleague',
|
|
168
|
-
});
|
|
169
|
-
expect(getToolActionInfo('send_group', {})).toEqual({
|
|
170
|
-
actionType: 'mcp',
|
|
171
|
-
actionLabel: '调用MCP',
|
|
172
|
-
actionDetail: 'aws-mcp/send_group',
|
|
173
|
-
});
|
|
174
|
-
expect(getToolActionInfo('poll_message', {})).toEqual({
|
|
175
|
-
actionType: 'idle',
|
|
176
|
-
actionLabel: '监听消息',
|
|
177
|
-
actionDetail: 'aws-mcp/poll_message',
|
|
178
|
-
});
|
|
179
|
-
});
|
|
180
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"idle-poll-loop.test.d.ts","sourceRoot":"","sources":["../../src/adapter/idle-poll-loop.test.ts"],"names":[],"mappings":""}
|