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.
Files changed (276) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts +35 -1
  2. package/dist/adapter/AcodeSdkAdapter.d.ts.map +1 -1
  3. package/dist/adapter/AcodeSdkAdapter.js +417 -40
  4. package/dist/adapter/ClaudeSdkAdapter.d.ts +6 -0
  5. package/dist/adapter/ClaudeSdkAdapter.d.ts.map +1 -1
  6. package/dist/adapter/ClaudeSdkAdapter.js +23 -1
  7. package/dist/adapter/idle-poll-loop.d.ts +2 -1
  8. package/dist/adapter/idle-poll-loop.d.ts.map +1 -1
  9. package/dist/adapter/types.d.ts +65 -3
  10. package/dist/adapter/types.d.ts.map +1 -1
  11. package/dist/adapter/types.js +5 -4
  12. package/dist/index.js +4 -0
  13. package/dist/routes/acode-todos.d.ts +11 -0
  14. package/dist/routes/acode-todos.d.ts.map +1 -0
  15. package/dist/routes/acode-todos.js +75 -0
  16. package/dist/routes/memory.d.ts +1 -1
  17. package/dist/routes/memory.d.ts.map +1 -1
  18. package/dist/routes/memory.js +3 -3
  19. package/dist/routes/pty.d.ts.map +1 -1
  20. package/dist/routes/pty.js +9 -0
  21. package/dist/routes/sub-agents.d.ts +14 -0
  22. package/dist/routes/sub-agents.d.ts.map +1 -0
  23. package/dist/routes/sub-agents.js +253 -0
  24. package/dist/routes/terminal.d.ts +9 -1
  25. package/dist/routes/terminal.d.ts.map +1 -1
  26. package/dist/routes/terminal.js +207 -22
  27. package/dist/services/agent-event-store.d.ts +1 -0
  28. package/dist/services/agent-event-store.d.ts.map +1 -1
  29. package/dist/services/event-delta-pusher.js +4 -4
  30. package/dist/services/session-output.d.ts +3 -0
  31. package/dist/services/session-output.d.ts.map +1 -1
  32. package/dist/services/session-output.js +38 -2
  33. package/dist/services/sub-agent-manager-instance.d.ts +4 -0
  34. package/dist/services/sub-agent-manager-instance.d.ts.map +1 -0
  35. package/dist/services/sub-agent-manager-instance.js +12 -0
  36. package/dist/services/workspace-files.d.ts +1 -0
  37. package/dist/services/workspace-files.d.ts.map +1 -1
  38. package/dist/services/workspace-files.js +57 -1
  39. package/package/acode/dist/ask-user-question-tool.d.ts +47 -0
  40. package/package/acode/dist/ask-user-question-tool.d.ts.map +1 -0
  41. package/package/acode/dist/ask-user-question-tool.js +233 -0
  42. package/package/acode/dist/built-in-file-tools.d.ts +2 -0
  43. package/package/acode/dist/built-in-file-tools.d.ts.map +1 -1
  44. package/package/acode/dist/compaction.d.ts +206 -0
  45. package/package/acode/dist/compaction.d.ts.map +1 -0
  46. package/package/acode/dist/compaction.js +664 -0
  47. package/package/acode/dist/config.d.ts +6 -1
  48. package/package/acode/dist/config.d.ts.map +1 -1
  49. package/package/acode/dist/config.js +27 -2
  50. package/package/acode/dist/index.d.ts +4 -0
  51. package/package/acode/dist/index.d.ts.map +1 -1
  52. package/package/acode/dist/index.js +4 -0
  53. package/package/acode/dist/runtime.d.ts +137 -0
  54. package/package/acode/dist/runtime.d.ts.map +1 -1
  55. package/package/acode/dist/runtime.js +974 -172
  56. package/package/acode/dist/skill-tool.d.ts +30 -0
  57. package/package/acode/dist/skill-tool.d.ts.map +1 -0
  58. package/package/acode/dist/skill-tool.js +174 -0
  59. package/package/acode/dist/sub-agent-manager.d.ts +169 -0
  60. package/package/acode/dist/sub-agent-manager.d.ts.map +1 -0
  61. package/package/acode/dist/sub-agent-manager.js +535 -0
  62. package/package/acode/dist/sub-agent-store.d.ts +33 -0
  63. package/package/acode/dist/sub-agent-store.d.ts.map +1 -0
  64. package/package/acode/dist/sub-agent-store.js +109 -0
  65. package/package/acode/dist/sub-agent-tools.d.ts +72 -0
  66. package/package/acode/dist/sub-agent-tools.d.ts.map +1 -0
  67. package/package/acode/dist/sub-agent-tools.js +429 -0
  68. package/package/acode/dist/sub-agent-types.d.ts +81 -0
  69. package/package/acode/dist/sub-agent-types.d.ts.map +1 -0
  70. package/package/acode/dist/sub-agent-types.js +8 -0
  71. package/package/acode/dist/todo-store.d.ts +42 -0
  72. package/package/acode/dist/todo-store.d.ts.map +1 -0
  73. package/package/acode/dist/todo-store.js +68 -0
  74. package/package/acode/dist/todo-tool.d.ts +6 -0
  75. package/package/acode/dist/todo-tool.d.ts.map +1 -0
  76. package/package/acode/dist/todo-tool.js +138 -0
  77. package/package/acode/dist/types.d.ts +22 -1
  78. package/package/acode/dist/types.d.ts.map +1 -1
  79. package/package/acode/package.json +13 -2
  80. package/package/aws-client-agent-mcp/dist/context-manager.test.js +0 -2
  81. package/package/aws-client-agent-mcp/dist/context-manager.test.js.map +1 -1
  82. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +83 -45
  83. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -1
  84. package/package/aws-client-agent-mcp/dist/mcp-server.js +451 -325
  85. package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -1
  86. package/package/aws-client-agent-mcp/dist/mcp-server.test.js +259 -241
  87. package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +1 -1
  88. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +1 -19
  89. package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts.map +1 -1
  90. package/package/aws-client-agent-mcp/dist/mcp-tools.js +2 -69
  91. package/package/aws-client-agent-mcp/dist/mcp-tools.js.map +1 -1
  92. package/package/aws-client-agent-mcp/dist/memory-store.d.ts +17 -19
  93. package/package/aws-client-agent-mcp/dist/memory-store.d.ts.map +1 -1
  94. package/package/aws-client-agent-mcp/dist/memory-store.js +62 -99
  95. package/package/aws-client-agent-mcp/dist/memory-store.js.map +1 -1
  96. package/package/aws-client-agent-mcp/dist/memory-store.test.js +207 -125
  97. package/package/aws-client-agent-mcp/dist/memory-store.test.js.map +1 -1
  98. package/package/aws-client-agent-mcp/dist/memory-tools.d.ts +3 -4
  99. package/package/aws-client-agent-mcp/dist/memory-tools.d.ts.map +1 -1
  100. package/package/aws-client-agent-mcp/dist/memory-tools.js +28 -33
  101. package/package/aws-client-agent-mcp/dist/memory-tools.js.map +1 -1
  102. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts +27 -9
  103. package/package/aws-client-agent-mcp/dist/message-buffer.d.ts.map +1 -1
  104. package/package/aws-client-agent-mcp/dist/message-buffer.js +100 -23
  105. package/package/aws-client-agent-mcp/dist/message-buffer.js.map +1 -1
  106. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts +1 -3
  107. package/package/aws-client-agent-mcp/dist/server-memory-store.d.ts.map +1 -1
  108. package/package/aws-client-agent-mcp/dist/server-memory-store.js +7 -11
  109. package/package/aws-client-agent-mcp/dist/server-memory-store.js.map +1 -1
  110. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts.map +1 -1
  111. package/package/aws-client-agent-mcp/dist/status-reporter.js +8 -5
  112. package/package/aws-client-agent-mcp/dist/status-reporter.js.map +1 -1
  113. package/package/aws-client-agent-mcp/dist/status-reporter.test.js +93 -0
  114. package/package/aws-client-agent-mcp/dist/status-reporter.test.js.map +1 -1
  115. package/package/aws-client-agent-mcp/dist/types.d.ts +3 -25
  116. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
  117. package/package.json +17 -7
  118. package/dist/adapter/AcodeSdkAdapter.test.d.ts +0 -2
  119. package/dist/adapter/AcodeSdkAdapter.test.d.ts.map +0 -1
  120. package/dist/adapter/AcodeSdkAdapter.test.js +0 -2000
  121. package/dist/adapter/AdapterRegistry.test.d.ts +0 -5
  122. package/dist/adapter/AdapterRegistry.test.d.ts.map +0 -1
  123. package/dist/adapter/AdapterRegistry.test.js +0 -118
  124. package/dist/adapter/ClaudeSdkAdapter.test.d.ts +0 -2
  125. package/dist/adapter/ClaudeSdkAdapter.test.d.ts.map +0 -1
  126. package/dist/adapter/ClaudeSdkAdapter.test.js +0 -311
  127. package/dist/adapter/CodexSdkAdapter.test.d.ts +0 -2
  128. package/dist/adapter/CodexSdkAdapter.test.d.ts.map +0 -1
  129. package/dist/adapter/CodexSdkAdapter.test.js +0 -270
  130. package/dist/adapter/OpencodeSdkAdapter.test.d.ts +0 -2
  131. package/dist/adapter/OpencodeSdkAdapter.test.d.ts.map +0 -1
  132. package/dist/adapter/OpencodeSdkAdapter.test.js +0 -158
  133. package/dist/adapter/acode-tool-names.test.d.ts +0 -2
  134. package/dist/adapter/acode-tool-names.test.d.ts.map +0 -1
  135. package/dist/adapter/acode-tool-names.test.js +0 -28
  136. package/dist/adapter/adapter.test.d.ts +0 -5
  137. package/dist/adapter/adapter.test.d.ts.map +0 -1
  138. package/dist/adapter/adapter.test.js +0 -180
  139. package/dist/adapter/idle-poll-loop.test.d.ts +0 -2
  140. package/dist/adapter/idle-poll-loop.test.d.ts.map +0 -1
  141. package/dist/adapter/idle-poll-loop.test.js +0 -85
  142. package/dist/adapter/types.test.d.ts +0 -2
  143. package/dist/adapter/types.test.d.ts.map +0 -1
  144. package/dist/adapter/types.test.js +0 -50
  145. package/dist/adapters/cc-switch/mcp-acode.test.d.ts +0 -2
  146. package/dist/adapters/cc-switch/mcp-acode.test.d.ts.map +0 -1
  147. package/dist/adapters/cc-switch/mcp-acode.test.js +0 -80
  148. package/dist/adapters/cc-switch/mcp-claudecode.test.d.ts +0 -2
  149. package/dist/adapters/cc-switch/mcp-claudecode.test.d.ts.map +0 -1
  150. package/dist/adapters/cc-switch/mcp-claudecode.test.js +0 -75
  151. package/dist/adapters/cc-switch/mcp-codex.test.d.ts +0 -2
  152. package/dist/adapters/cc-switch/mcp-codex.test.d.ts.map +0 -1
  153. package/dist/adapters/cc-switch/mcp-codex.test.js +0 -126
  154. package/dist/adapters/cc-switch/mcp-opencode.test.d.ts +0 -2
  155. package/dist/adapters/cc-switch/mcp-opencode.test.d.ts.map +0 -1
  156. package/dist/adapters/cc-switch/mcp-opencode.test.js +0 -62
  157. package/dist/adapters/cc-switch/skill-directory.test.d.ts +0 -2
  158. package/dist/adapters/cc-switch/skill-directory.test.d.ts.map +0 -1
  159. package/dist/adapters/cc-switch/skill-directory.test.js +0 -74
  160. package/dist/config.test.d.ts +0 -2
  161. package/dist/config.test.d.ts.map +0 -1
  162. package/dist/config.test.js +0 -107
  163. package/dist/routes/ai-sources.test.d.ts +0 -2
  164. package/dist/routes/ai-sources.test.d.ts.map +0 -1
  165. package/dist/routes/ai-sources.test.js +0 -169
  166. package/dist/routes/file-browser.test.d.ts +0 -5
  167. package/dist/routes/file-browser.test.d.ts.map +0 -1
  168. package/dist/routes/file-browser.test.js +0 -155
  169. package/dist/routes/git.test.d.ts +0 -2
  170. package/dist/routes/git.test.d.ts.map +0 -1
  171. package/dist/routes/git.test.js +0 -330
  172. package/dist/routes/instance.test.d.ts +0 -5
  173. package/dist/routes/instance.test.d.ts.map +0 -1
  174. package/dist/routes/instance.test.js +0 -389
  175. package/dist/routes/mcp.test.d.ts +0 -5
  176. package/dist/routes/mcp.test.d.ts.map +0 -1
  177. package/dist/routes/mcp.test.js +0 -92
  178. package/dist/routes/memory-route-wiring.test.d.ts +0 -2
  179. package/dist/routes/memory-route-wiring.test.d.ts.map +0 -1
  180. package/dist/routes/memory-route-wiring.test.js +0 -15
  181. package/dist/routes/memory.test.d.ts +0 -2
  182. package/dist/routes/memory.test.d.ts.map +0 -1
  183. package/dist/routes/memory.test.js +0 -177
  184. package/dist/routes/properties.test.d.ts +0 -5
  185. package/dist/routes/properties.test.d.ts.map +0 -1
  186. package/dist/routes/properties.test.js +0 -72
  187. package/dist/routes/pty.test.d.ts +0 -2
  188. package/dist/routes/pty.test.d.ts.map +0 -1
  189. package/dist/routes/pty.test.js +0 -82
  190. package/dist/routes/runtime-binding.test.d.ts +0 -2
  191. package/dist/routes/runtime-binding.test.d.ts.map +0 -1
  192. package/dist/routes/runtime-binding.test.js +0 -32
  193. package/dist/routes/sessions.test.d.ts +0 -5
  194. package/dist/routes/sessions.test.d.ts.map +0 -1
  195. package/dist/routes/sessions.test.js +0 -86
  196. package/dist/routes/skills.test.d.ts +0 -5
  197. package/dist/routes/skills.test.d.ts.map +0 -1
  198. package/dist/routes/skills.test.js +0 -50
  199. package/dist/routes/system-metrics.test.d.ts +0 -2
  200. package/dist/routes/system-metrics.test.d.ts.map +0 -1
  201. package/dist/routes/system-metrics.test.js +0 -16
  202. package/dist/routes/terminal.stop-options.test.d.ts +0 -2
  203. package/dist/routes/terminal.stop-options.test.d.ts.map +0 -1
  204. package/dist/routes/terminal.stop-options.test.js +0 -39
  205. package/dist/routes/terminal.test.d.ts +0 -2
  206. package/dist/routes/terminal.test.d.ts.map +0 -1
  207. package/dist/routes/terminal.test.js +0 -746
  208. package/dist/routes/yml.test.d.ts +0 -5
  209. package/dist/routes/yml.test.d.ts.map +0 -1
  210. package/dist/routes/yml.test.js +0 -58
  211. package/dist/services/ai-source-apply.test.d.ts +0 -2
  212. package/dist/services/ai-source-apply.test.d.ts.map +0 -1
  213. package/dist/services/ai-source-apply.test.js +0 -138
  214. package/dist/services/auto-register.test.d.ts +0 -2
  215. package/dist/services/auto-register.test.d.ts.map +0 -1
  216. package/dist/services/auto-register.test.js +0 -184
  217. package/dist/services/aws-client-agent-mcp.test.d.ts +0 -2
  218. package/dist/services/aws-client-agent-mcp.test.d.ts.map +0 -1
  219. package/dist/services/aws-client-agent-mcp.test.js +0 -242
  220. package/dist/services/bridge-package-publish-hooks.test.d.ts +0 -2
  221. package/dist/services/bridge-package-publish-hooks.test.d.ts.map +0 -1
  222. package/dist/services/bridge-package-publish-hooks.test.js +0 -136
  223. package/dist/services/cc-switch-discovery.test.d.ts +0 -2
  224. package/dist/services/cc-switch-discovery.test.d.ts.map +0 -1
  225. package/dist/services/cc-switch-discovery.test.js +0 -56
  226. package/dist/services/cli-commands.test.d.ts +0 -2
  227. package/dist/services/cli-commands.test.d.ts.map +0 -1
  228. package/dist/services/cli-commands.test.js +0 -230
  229. package/dist/services/instance-init-service.test.d.ts +0 -2
  230. package/dist/services/instance-init-service.test.d.ts.map +0 -1
  231. package/dist/services/instance-init-service.test.js +0 -140
  232. package/dist/services/instance-state.test.d.ts +0 -2
  233. package/dist/services/instance-state.test.d.ts.map +0 -1
  234. package/dist/services/instance-state.test.js +0 -245
  235. package/dist/services/mcp-launch-binding-queue.test.d.ts +0 -2
  236. package/dist/services/mcp-launch-binding-queue.test.d.ts.map +0 -1
  237. package/dist/services/mcp-launch-binding-queue.test.js +0 -181
  238. package/dist/services/runtime-binding.test.d.ts +0 -2
  239. package/dist/services/runtime-binding.test.d.ts.map +0 -1
  240. package/dist/services/runtime-binding.test.js +0 -78
  241. package/dist/services/runtime-lifecycle-policy.test.d.ts +0 -2
  242. package/dist/services/runtime-lifecycle-policy.test.d.ts.map +0 -1
  243. package/dist/services/runtime-lifecycle-policy.test.js +0 -41
  244. package/dist/services/session-output.test.d.ts +0 -5
  245. package/dist/services/session-output.test.d.ts.map +0 -1
  246. package/dist/services/session-output.test.js +0 -177
  247. package/dist/services/startup-config-wizard.test.d.ts +0 -2
  248. package/dist/services/startup-config-wizard.test.d.ts.map +0 -1
  249. package/dist/services/startup-config-wizard.test.js +0 -184
  250. package/dist/services/terminal-persistence.test.d.ts +0 -5
  251. package/dist/services/terminal-persistence.test.d.ts.map +0 -1
  252. package/dist/services/terminal-persistence.test.js +0 -159
  253. package/dist/services/tool-installer.test.d.ts +0 -2
  254. package/dist/services/tool-installer.test.d.ts.map +0 -1
  255. package/dist/services/tool-installer.test.js +0 -225
  256. package/dist/services/workspace-files.test.d.ts +0 -2
  257. package/dist/services/workspace-files.test.d.ts.map +0 -1
  258. package/dist/services/workspace-files.test.js +0 -648
  259. package/dist/services/workspace-watch.test.d.ts +0 -2
  260. package/dist/services/workspace-watch.test.d.ts.map +0 -1
  261. package/dist/services/workspace-watch.test.js +0 -38
  262. package/dist/utils/file-utils.test.d.ts +0 -2
  263. package/dist/utils/file-utils.test.d.ts.map +0 -1
  264. package/dist/utils/file-utils.test.js +0 -244
  265. package/dist/utils/logger.test.d.ts +0 -2
  266. package/dist/utils/logger.test.d.ts.map +0 -1
  267. package/dist/utils/logger.test.js +0 -93
  268. package/dist/utils/sdk-package-loader.test.d.ts +0 -2
  269. package/dist/utils/sdk-package-loader.test.d.ts.map +0 -1
  270. package/dist/utils/sdk-package-loader.test.js +0 -84
  271. package/dist/utils/validation.test.d.ts +0 -2
  272. package/dist/utils/validation.test.d.ts.map +0 -1
  273. package/dist/utils/validation.test.js +0 -88
  274. package/dist/utils/yaml-utils.test.d.ts +0 -2
  275. package/dist/utils/yaml-utils.test.d.ts.map +0 -1
  276. package/dist/utils/yaml-utils.test.js +0 -363
@@ -1,389 +0,0 @@
1
- /**
2
- * Instance 路由单元测试
3
- */
4
- import { describe, it, expect, vi, afterEach } from 'vitest';
5
- import { EventEmitter } from 'node:events';
6
- const spawnMock = vi.hoisted(() => vi.fn());
7
- vi.mock('axios', () => ({
8
- default: {
9
- get: vi.fn(),
10
- post: vi.fn(),
11
- },
12
- }));
13
- vi.mock('../services/auto-register.js', () => ({
14
- getConfiguredConnectionKeys: vi.fn(() => []),
15
- requestRuntimeAccessTokenRefreshForServer: vi.fn(),
16
- }));
17
- vi.mock('../services/runtime-binding.js', () => ({
18
- getRuntimeAccessToken: vi.fn(() => 'stale-runtime-token-123456'),
19
- loadRuntimeBinding: vi.fn(() => ({ status: 'paired', userId: 'user-1', schedulerBaseUrl: 'http://server.local:7380' })),
20
- normalizeSchedulerBaseUrl: vi.fn((value) => (value ? String(value).replace(/\/+$/, '') : undefined)),
21
- }));
22
- vi.mock('../services/lifecycle-state.js', () => ({
23
- createBridgeLifecycleOperation: vi.fn((input) => ({
24
- operationId: 'operation-1',
25
- requestedAt: '2026-01-01T00:00:00.000Z',
26
- updatedAt: '2026-01-01T00:00:00.000Z',
27
- ...input,
28
- })),
29
- deliverPendingBridgeLifecycleNotifications: vi.fn(),
30
- upsertBridgeLifecycleOperation: vi.fn(),
31
- }));
32
- vi.mock('../config.js', async (importOriginal) => ({
33
- ...(await importOriginal()),
34
- getRuntimeHomeDir: vi.fn(() => process.cwd()),
35
- }));
36
- vi.mock('node:child_process', async (importOriginal) => ({
37
- ...(await importOriginal()),
38
- spawn: spawnMock,
39
- }));
40
- afterEach(() => {
41
- vi.useRealTimers();
42
- vi.clearAllMocks();
43
- });
44
- function mockSpawnResult(exitCode, stdoutText = '', stderrText = '') {
45
- spawnMock.mockImplementationOnce(() => {
46
- const child = new EventEmitter();
47
- child.stdout = new EventEmitter();
48
- child.stderr = new EventEmitter();
49
- process.nextTick(() => {
50
- if (stdoutText) {
51
- child.stdout.emit('data', Buffer.from(stdoutText));
52
- }
53
- if (stderrText) {
54
- child.stderr.emit('data', Buffer.from(stderrText));
55
- }
56
- child.emit('close', exitCode);
57
- });
58
- return child;
59
- });
60
- }
61
- function createMockResponse() {
62
- const json = vi.fn();
63
- const status = vi.fn(() => ({ json }));
64
- return { json, status };
65
- }
66
- describe('instance route validation', () => {
67
- it('builds correct ping response when healthy', () => {
68
- const buildPingResponse = (schedulerStatus, schedulerBaseUrl) => ({
69
- ok: true,
70
- runtimeBridge: 'healthy',
71
- schedulerReachable: schedulerStatus >= 200 && schedulerStatus < 300,
72
- schedulerBaseUrl,
73
- });
74
- const healthyResponse = buildPingResponse(200, 'http://localhost:8080');
75
- expect(healthyResponse.ok).toBe(true);
76
- expect(healthyResponse.schedulerReachable).toBe(true);
77
- const unhealthyResponse = buildPingResponse(502, 'http://localhost:8080');
78
- expect(unhealthyResponse.schedulerReachable).toBe(false);
79
- });
80
- it('requires agentId and workspacePath', () => {
81
- const validateInitRequest = (body) => {
82
- if (!body.agentId || !body.workspacePath)
83
- return { valid: false, error: 'agentId and workspacePath are required' };
84
- return { valid: true };
85
- };
86
- expect(validateInitRequest({}).valid).toBe(false);
87
- expect(validateInitRequest({ agentId: 'agent-1', workspacePath: '/path' }).valid).toBe(true);
88
- });
89
- it('builds correct init options', () => {
90
- const buildInitOptions = (body) => ({
91
- skillEnabled: body.skillEnabled,
92
- mcpEnabled: body.mcpEnabled,
93
- ccSwitchEnabledTools: body.ccSwitchEnabledTools,
94
- });
95
- const options = buildInitOptions({
96
- skillEnabled: true,
97
- mcpEnabled: false,
98
- ccSwitchEnabledTools: ['claude', 'opencode'],
99
- });
100
- expect(options.skillEnabled).toBe(true);
101
- expect(options.mcpEnabled).toBe(false);
102
- expect(options.ccSwitchEnabledTools).toEqual(['claude', 'opencode']);
103
- });
104
- it('requires agentId for state query', () => {
105
- const validateStateRequest = (body) => {
106
- if (!body.agentId)
107
- return { valid: false, error: 'agentId is required' };
108
- return { valid: true };
109
- };
110
- expect(validateStateRequest({}).valid).toBe(false);
111
- expect(validateStateRequest({ agentId: 'agent-1' }).valid).toBe(true);
112
- });
113
- it('always detects panel tool statuses even when legacy enabled tools omit codex', async () => {
114
- const { buildToolStatusDetectionTargets } = await import('./instance.js');
115
- expect(buildToolStatusDetectionTargets(['claude', 'opencode'])).toEqual([
116
- 'claude',
117
- 'opencode',
118
- 'acode',
119
- 'codex',
120
- ]);
121
- }, 15_000);
122
- it('accepts codex for cc-switch tool installation validation', async () => {
123
- const { SUPPORTED_INSTALLABLE_TOOLS } = await import('../services/tool-installer.js');
124
- const normalizeInstallableTools = (tools) => {
125
- const supported = new Set(SUPPORTED_INSTALLABLE_TOOLS);
126
- const requestedTools = Array.isArray(tools)
127
- ? tools.map((tool) => String(tool || '').trim().toLowerCase()).filter(Boolean)
128
- : [];
129
- return requestedTools.filter((tool) => supported.has(tool));
130
- };
131
- expect(normalizeInstallableTools(['Codex'])).toEqual(['codex']);
132
- expect(SUPPORTED_INSTALLABLE_TOOLS).toContain('codex');
133
- });
134
- it('accepts panel tools for cc-switch tool uninstallation validation', async () => {
135
- const { SUPPORTED_UNINSTALLABLE_TOOLS } = await import('../services/tool-installer.js');
136
- const normalizeUninstallableTools = (tools) => {
137
- const supported = new Set(SUPPORTED_UNINSTALLABLE_TOOLS);
138
- const requestedTools = Array.isArray(tools)
139
- ? tools.map((tool) => String(tool || '').trim().toLowerCase()).filter(Boolean)
140
- : [];
141
- return requestedTools.filter((tool) => supported.has(tool));
142
- };
143
- expect(normalizeUninstallableTools(['Claude', 'OpenCode', 'Codex'])).toEqual([
144
- 'claude',
145
- 'opencode',
146
- 'codex',
147
- ]);
148
- expect(normalizeUninstallableTools(['unknown-tool'])).toEqual([]);
149
- });
150
- it('reports uninstall failure when a requested tool remains installed', async () => {
151
- const { buildUninstallFailureMessage } = await import('./instance.js');
152
- expect(buildUninstallFailureMessage(['opencode'], {
153
- opencode: {
154
- tool: 'opencode',
155
- installed: true,
156
- executable: '/home/user/.opencode/bin/opencode',
157
- version: '1.14.39',
158
- installing: false,
159
- error: 'uninstall completed but command is still available',
160
- },
161
- })).toContain('opencode: uninstall completed but command is still available');
162
- });
163
- it('summarizes tool status for route diagnostics', async () => {
164
- const { summarizeToolStatus } = await import('./instance.js');
165
- expect(summarizeToolStatus({
166
- opencode: {
167
- tool: 'opencode',
168
- installed: false,
169
- executable: null,
170
- version: null,
171
- installing: false,
172
- error: 'SDK package @opencode-ai/sdk is not installed in aws-runtime-bridge',
173
- },
174
- claude: {
175
- tool: 'claude',
176
- installed: true,
177
- executable: '@anthropic-ai/claude-agent-sdk',
178
- version: '0.2.87',
179
- installing: false,
180
- error: null,
181
- },
182
- })).toEqual({
183
- opencode: {
184
- installed: false,
185
- executable: null,
186
- version: null,
187
- error: 'SDK package @opencode-ai/sdk is not installed in aws-runtime-bridge',
188
- },
189
- claude: {
190
- installed: true,
191
- executable: '@anthropic-ai/claude-agent-sdk',
192
- version: '0.2.87',
193
- error: null,
194
- },
195
- });
196
- });
197
- it('does not report uninstall failure when requested tools are no longer installed', async () => {
198
- const { buildUninstallFailureMessage } = await import('./instance.js');
199
- expect(buildUninstallFailureMessage(['claude'], {
200
- claude: {
201
- tool: 'claude',
202
- installed: false,
203
- executable: null,
204
- version: null,
205
- installing: false,
206
- error: 'command not installed',
207
- },
208
- })).toBe('');
209
- });
210
- it('allows connection check when no connection key is configured', async () => {
211
- const { getConfiguredConnectionKeys } = await import('../services/auto-register.js');
212
- vi.mocked(getConfiguredConnectionKeys).mockReturnValue([]);
213
- const { buildConnectionCheckResponse } = await import('./instance.js');
214
- expect(buildConnectionCheckResponse('')).toEqual({
215
- status: 200,
216
- body: {
217
- ok: true,
218
- runtimeBridge: 'healthy',
219
- version: expect.any(String),
220
- connectionKeyMatched: true,
221
- connectionKeyRequired: false,
222
- },
223
- });
224
- });
225
- it('requires matching connection key digest when a connection key is configured', async () => {
226
- const { createHash } = await import('node:crypto');
227
- const { getConfiguredConnectionKeys } = await import('../services/auto-register.js');
228
- vi.mocked(getConfiguredConnectionKeys).mockReturnValue(['secret-key']);
229
- const { buildConnectionCheckResponse } = await import('./instance.js');
230
- const digest = createHash('md5').update('secret-key', 'utf8').digest('hex');
231
- expect(buildConnectionCheckResponse(digest).status).toBe(200);
232
- expect(buildConnectionCheckResponse('00000000000000000000000000000000')).toEqual({
233
- status: 401,
234
- body: {
235
- ok: false,
236
- error: 'connection_key_mismatch',
237
- version: expect.any(String),
238
- connectionKeyMatched: false,
239
- connectionKeyRequired: true,
240
- },
241
- });
242
- });
243
- it('explains localhost scheduler ping failures with environment variable guidance', async () => {
244
- const { buildSchedulerPingFailureResponse } = await import('./instance.js');
245
- const response = buildSchedulerPingFailureResponse(new Error('connect ECONNREFUSED 127.0.0.1:8080'), 'http://localhost:8080');
246
- expect(response).toEqual({
247
- ok: false,
248
- error: 'connect ECONNREFUSED 127.0.0.1:8080',
249
- failureStage: 'scheduler_ping',
250
- runtimeBridge: 'healthy',
251
- schedulerBaseUrl: 'http://localhost:8080',
252
- hint: expect.stringContaining('AWS_RUNTIME_SCHEDULER_BASE_URL'),
253
- });
254
- expect(response.hint).toContain('http://<server-host>:7380');
255
- });
256
- it('explains non-localhost scheduler ping failures as reachability or token issues', async () => {
257
- const { buildSchedulerPingFailureResponse } = await import('./instance.js');
258
- const response = buildSchedulerPingFailureResponse(new Error('Request failed with status code 401'), 'http://10.0.0.8:7380');
259
- expect(response.schedulerBaseUrl).toBe('http://10.0.0.8:7380');
260
- expect(response.failureStage).toBe('scheduler_ping');
261
- expect(response.runtimeBridge).toBe('healthy');
262
- expect(response.hint).toContain('运行时访问令牌仍有效');
263
- });
264
- it('refreshes runtime token and retries scheduler ping after 401', async () => {
265
- process.env.AWS_RUNTIME_SCHEDULER_BASE_URL = 'http://localhost:8080';
266
- const { default: axios } = await import('axios');
267
- const { requestRuntimeAccessTokenRefreshForServer } = await import('../services/auto-register.js');
268
- const { instanceRouter } = await import('./instance.js');
269
- vi.mocked(requestRuntimeAccessTokenRefreshForServer).mockResolvedValue({
270
- success: true,
271
- runtimeAccessToken: 'fresh-runtime-token-123456',
272
- updated: true,
273
- });
274
- vi.mocked(axios.get)
275
- .mockRejectedValueOnce({ response: { status: 401 }, message: 'Request failed with status code 401' })
276
- .mockResolvedValueOnce({ status: 200 });
277
- const handler = instanceRouter.stack.find((layer) => layer.route?.path === '/ping')?.route?.stack[1]?.handle;
278
- expect(handler).toBeTypeOf('function');
279
- const json = vi.fn();
280
- const status = vi.fn(() => ({ json }));
281
- await handler?.({ header: vi.fn(() => '') }, { json, status }, vi.fn());
282
- expect(requestRuntimeAccessTokenRefreshForServer).toHaveBeenCalledWith('http://localhost:8080');
283
- expect(axios.get).toHaveBeenNthCalledWith(1, 'http://localhost:8080/api/runtime/ping', {
284
- headers: { 'X-Runtime-Token': 'stale-runtime-token-123456' },
285
- });
286
- expect(axios.get).toHaveBeenNthCalledWith(2, 'http://localhost:8080/api/runtime/ping', {
287
- headers: { 'X-Runtime-Token': 'fresh-runtime-token-123456' },
288
- });
289
- expect(json).toHaveBeenCalledWith({
290
- ok: true,
291
- runtimeBridge: 'healthy',
292
- version: expect.any(String),
293
- schedulerReachable: true,
294
- tokenRefreshed: true,
295
- schedulerBaseUrl: 'http://localhost:8080',
296
- });
297
- expect(status).not.toHaveBeenCalled();
298
- });
299
- it('uses scheduler base URL supplied by server ping request before local bridge config', async () => {
300
- process.env.AWS_RUNTIME_SCHEDULER_BASE_URL = 'http://localhost:8080';
301
- const { default: axios } = await import('axios');
302
- const { getRuntimeAccessToken } = await import('../services/runtime-binding.js');
303
- const { instanceRouter } = await import('./instance.js');
304
- vi.mocked(getRuntimeAccessToken).mockReturnValue('stale-runtime-token-123456');
305
- vi.mocked(axios.get).mockReset();
306
- vi.mocked(axios.get).mockResolvedValueOnce({ status: 200 });
307
- const handler = instanceRouter.stack.find((layer) => layer.route?.path === '/ping')?.route?.stack[1]?.handle;
308
- expect(handler).toBeTypeOf('function');
309
- const json = vi.fn();
310
- const status = vi.fn(() => ({ json }));
311
- const header = vi.fn((name) => (name === 'X-Scheduler-Base-Url' ? 'http://server.local:7380/api' : ''));
312
- await handler?.({ header }, { json, status }, vi.fn());
313
- expect(getRuntimeAccessToken).toHaveBeenCalledWith(undefined, 'http://server.local:7380');
314
- expect(axios.get).toHaveBeenCalledWith('http://server.local:7380/api/runtime/ping', {
315
- headers: { 'X-Runtime-Token': 'stale-runtime-token-123456' },
316
- });
317
- expect(json).toHaveBeenCalledWith({
318
- ok: true,
319
- runtimeBridge: 'healthy',
320
- version: expect.any(String),
321
- schedulerReachable: true,
322
- tokenRefreshed: false,
323
- schedulerBaseUrl: 'http://server.local:7380',
324
- });
325
- expect(status).not.toHaveBeenCalled();
326
- });
327
- it('explains ambiguous auto-register scheduler targets without picking the first one', async () => {
328
- const { buildAmbiguousSchedulerBaseUrlResponse } = await import('./instance.js');
329
- const response = buildAmbiguousSchedulerBaseUrlResponse([
330
- 'http://scheduler-a.local:7380',
331
- 'http://scheduler-b.local:7380',
332
- ]);
333
- expect(response).toEqual({
334
- ok: false,
335
- error: 'ambiguous_scheduler_base_url',
336
- failureStage: 'scheduler_ping',
337
- runtimeBridge: 'healthy',
338
- schedulerBaseUrl: '',
339
- autoRegisterTargetUrls: [
340
- 'http://scheduler-a.local:7380',
341
- 'http://scheduler-b.local:7380',
342
- ],
343
- hint: expect.stringContaining('AWS_RUNTIME_SCHEDULER_BASE_URL'),
344
- });
345
- });
346
- it('starts bridge package update in background and returns operation id', async () => {
347
- const { instanceRouter } = await import('./instance.js');
348
- mockSpawnResult(0, 'updated');
349
- const handler = instanceRouter.stack.find((layer) => layer.route?.path === '/update-bridge')?.route?.stack[1]?.handle;
350
- expect(handler).toBeTypeOf('function');
351
- const { json, status } = createMockResponse();
352
- await handler?.({ body: { requestedByUserId: 'user-1' }, get: () => 'bridge.local:18081', protocol: 'http' }, { json, status }, vi.fn());
353
- expect(status).not.toHaveBeenCalled();
354
- expect(json).toHaveBeenCalledWith(expect.objectContaining({
355
- ok: true,
356
- message: 'Bridge 更新已在后台开始,完成后会通过消息中心通知结果。',
357
- }));
358
- await new Promise((resolve) => setImmediate(resolve));
359
- expect(spawnMock).toHaveBeenCalledWith(process.platform === 'win32' ? 'npm.cmd' : 'npm', ['install', '-g', 'aws-runtime-bridge@latest'], { shell: false, windowsHide: true });
360
- });
361
- it('rejects background bridge update without requester user id', async () => {
362
- const { instanceRouter } = await import('./instance.js');
363
- const handler = instanceRouter.stack.find((layer) => layer.route?.path === '/update-bridge')?.route?.stack[1]?.handle;
364
- expect(handler).toBeTypeOf('function');
365
- const { json, status } = createMockResponse();
366
- await handler?.({}, { json, status }, vi.fn());
367
- expect(status).toHaveBeenCalledWith(400);
368
- expect(json).toHaveBeenCalledWith({ error: 'requestedByUserId is required' });
369
- });
370
- it('responds before triggering graceful bridge restart', async () => {
371
- vi.useFakeTimers();
372
- const { instanceRouter, setGracefulShutdownFn } = await import('./instance.js');
373
- const gracefulShutdown = vi.fn().mockResolvedValue(undefined);
374
- setGracefulShutdownFn(gracefulShutdown);
375
- const handler = instanceRouter.stack.find((layer) => layer.route?.path === '/restart-bridge')?.route?.stack[1]?.handle;
376
- expect(handler).toBeTypeOf('function');
377
- const { json, status } = createMockResponse();
378
- await handler?.({ body: { preserveSessions: true, requestedByUserId: 'user-1' }, get: () => 'bridge.local:18081', protocol: 'http' }, { json, status }, vi.fn());
379
- expect(status).not.toHaveBeenCalled();
380
- expect(json).toHaveBeenCalledWith(expect.objectContaining({
381
- ok: true,
382
- preserveSessions: true,
383
- message: 'Bridge 正在优雅退出;下次启动后会通过消息中心通知结果。若未由守护进程管理,请手动重新启动。',
384
- }));
385
- expect(gracefulShutdown).not.toHaveBeenCalled();
386
- await vi.advanceTimersByTimeAsync(250);
387
- expect(gracefulShutdown).toHaveBeenCalledWith('PANEL_RESTART', true);
388
- });
389
- });
@@ -1,5 +0,0 @@
1
- /**
2
- * MCP 路由单元测试
3
- */
4
- export {};
5
- //# sourceMappingURL=mcp.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mcp.test.d.ts","sourceRoot":"","sources":["../../src/routes/mcp.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -1,92 +0,0 @@
1
- /**
2
- * MCP 路由单元测试
3
- */
4
- import { describe, it, expect } from 'vitest';
5
- describe('mcp route validation', () => {
6
- it('requires agentId for list operation', () => {
7
- const validateListRequest = (body) => {
8
- if (!body.agentId)
9
- return { valid: false, error: 'agentId is required' };
10
- return { valid: true };
11
- };
12
- expect(validateListRequest({}).valid).toBe(false);
13
- expect(validateListRequest({ agentId: 'agent-123' }).valid).toBe(true);
14
- });
15
- it('requires agentId and mcpId for get operation', () => {
16
- const validateGetRequest = (body) => {
17
- if (!body.agentId || !body.mcpId)
18
- return { valid: false, error: 'agentId and mcpId are required' };
19
- return { valid: true };
20
- };
21
- expect(validateGetRequest({}).valid).toBe(false);
22
- expect(validateGetRequest({ agentId: 'agent-1' }).valid).toBe(false);
23
- expect(validateGetRequest({ agentId: 'agent-1', mcpId: 'mcp-1' }).valid).toBe(true);
24
- });
25
- it('requires mcp.name for create', () => {
26
- const validateCreateMcp = (mcp) => {
27
- const name = String(mcp?.name || '').trim();
28
- if (!name)
29
- return { valid: false, error: 'mcp.name is required' };
30
- return { valid: true, name };
31
- };
32
- expect(validateCreateMcp(undefined).valid).toBe(false);
33
- expect(validateCreateMcp({ name: 'filesystem' }).valid).toBe(true);
34
- });
35
- });
36
- describe('mcp server spec normalization', () => {
37
- it('normalizes stdio transport', () => {
38
- const normalizeMcpSpec = (mcp) => {
39
- if (mcp.command) {
40
- return {
41
- type: 'stdio',
42
- command: String(mcp.command),
43
- args: Array.isArray(mcp.args) ? mcp.args : [],
44
- };
45
- }
46
- return null;
47
- };
48
- const result = normalizeMcpSpec({
49
- command: 'npx',
50
- args: ['-y', '@modelcontextprotocol/server-filesystem'],
51
- });
52
- expect(result).toEqual({
53
- type: 'stdio',
54
- command: 'npx',
55
- args: ['-y', '@modelcontextprotocol/server-filesystem'],
56
- });
57
- });
58
- it('normalizes sse transport', () => {
59
- const normalizeMcpSpec = (mcp) => {
60
- if (mcp.url && !mcp.command) {
61
- return { type: 'sse', url: String(mcp.url) };
62
- }
63
- return null;
64
- };
65
- const result = normalizeMcpSpec({ url: 'http://localhost:3000/sse' });
66
- expect(result).toEqual({ type: 'sse', url: 'http://localhost:3000/sse' });
67
- });
68
- });
69
- describe('app flags normalization', () => {
70
- it('normalizes app flags from various formats', () => {
71
- const normalizeAppFlags = (apps) => {
72
- if (!apps)
73
- return [];
74
- if (typeof apps === 'string')
75
- return apps.split(',').map(s => s.trim()).filter(Boolean);
76
- if (Array.isArray(apps))
77
- return apps.filter(s => typeof s === 'string').map(s => String(s).trim()).filter(Boolean);
78
- return [];
79
- };
80
- expect(normalizeAppFlags('claude,opencode')).toEqual(['claude', 'opencode']);
81
- expect(normalizeAppFlags(['claude', 'opencode'])).toEqual(['claude', 'opencode']);
82
- expect(normalizeAppFlags(null)).toEqual([]);
83
- });
84
- it('allows supported per-tool toggle app ids', () => {
85
- const isSupportedToggleAppId = (appId) => ['acode', 'claudecode', 'opencode', 'codex'].includes(appId);
86
- expect(isSupportedToggleAppId('acode')).toBe(true);
87
- expect(isSupportedToggleAppId('claudecode')).toBe(true);
88
- expect(isSupportedToggleAppId('opencode')).toBe(true);
89
- expect(isSupportedToggleAppId('codex')).toBe(true);
90
- expect(isSupportedToggleAppId('gemini')).toBe(false);
91
- });
92
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=memory-route-wiring.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memory-route-wiring.test.d.ts","sourceRoot":"","sources":["../../src/routes/memory-route-wiring.test.ts"],"names":[],"mappings":""}
@@ -1,15 +0,0 @@
1
- import { readFileSync } from "node:fs";
2
- import { dirname, resolve } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
- import { describe, expect, it } from "vitest";
5
- const currentDir = dirname(fileURLToPath(import.meta.url));
6
- const srcDir = resolve(currentDir, "..");
7
- describe("memory route wiring", () => {
8
- it("mounts the authenticated memory list route under /runtime", () => {
9
- const routeSource = readFileSync(resolve(currentDir, "./memory.ts"), "utf-8");
10
- const indexSource = readFileSync(resolve(srcDir, "./index.ts"), "utf-8");
11
- expect(routeSource).toMatch(/memoryRouter\.post\(\s*"\/memory\/list",\s*validateToken/);
12
- expect(indexSource).toContain('import { memoryRouter } from "./routes/memory.js";');
13
- expect(indexSource).toContain('app.use("/runtime", memoryRouter);');
14
- });
15
- });
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=memory.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"memory.test.d.ts","sourceRoot":"","sources":["../../src/routes/memory.test.ts"],"names":[],"mappings":""}