aws-runtime-bridge 1.7.49 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/dist/adapter/AcodeSdkAdapter.d.ts +104 -0
  2. package/dist/adapter/AcodeSdkAdapter.d.ts.map +1 -0
  3. package/dist/adapter/AcodeSdkAdapter.js +644 -0
  4. package/dist/adapter/AcodeSdkAdapter.test.d.ts +2 -0
  5. package/dist/adapter/AcodeSdkAdapter.test.d.ts.map +1 -0
  6. package/dist/adapter/AcodeSdkAdapter.test.js +1280 -0
  7. package/dist/adapter/AdapterRegistry.d.ts +1 -1
  8. package/dist/adapter/AdapterRegistry.d.ts.map +1 -1
  9. package/dist/adapter/AdapterRegistry.js +2 -0
  10. package/dist/adapter/AdapterRegistry.test.js +10 -1
  11. package/dist/adapter/ClaudeSdkAdapter.test.js +31 -8
  12. package/dist/adapter/CodexSdkAdapter.d.ts.map +1 -1
  13. package/dist/adapter/CodexSdkAdapter.js +2 -0
  14. package/dist/adapter/OpencodeSdkAdapter.d.ts.map +1 -1
  15. package/dist/adapter/OpencodeSdkAdapter.js +2 -0
  16. package/dist/adapter/SdkProviderSpi.d.ts.map +1 -1
  17. package/dist/adapter/SdkProviderSpi.js +10 -1
  18. package/dist/adapter/adapter.test.js +2 -2
  19. package/dist/adapter/idle-poll-loop.d.ts +4 -4
  20. package/dist/adapter/idle-poll-loop.d.ts.map +1 -1
  21. package/dist/adapter/idle-poll-loop.js +3 -3
  22. package/dist/adapter/idle-poll-loop.test.js +15 -1
  23. package/dist/adapter/index.d.ts +1 -0
  24. package/dist/adapter/index.d.ts.map +1 -1
  25. package/dist/adapter/index.js +1 -0
  26. package/dist/adapter/types.d.ts +25 -6
  27. package/dist/adapter/types.d.ts.map +1 -1
  28. package/dist/adapter/types.js +221 -110
  29. package/dist/adapter/types.test.js +10 -3
  30. package/dist/adapters/cc-switch/index.d.ts +2 -0
  31. package/dist/adapters/cc-switch/index.d.ts.map +1 -1
  32. package/dist/adapters/cc-switch/index.js +6 -0
  33. package/dist/adapters/cc-switch/mcp-acode.d.ts +17 -0
  34. package/dist/adapters/cc-switch/mcp-acode.d.ts.map +1 -0
  35. package/dist/adapters/cc-switch/mcp-acode.js +71 -0
  36. package/dist/adapters/cc-switch/mcp-acode.test.d.ts +2 -0
  37. package/dist/adapters/cc-switch/mcp-acode.test.d.ts.map +1 -0
  38. package/dist/adapters/cc-switch/mcp-acode.test.js +80 -0
  39. package/dist/adapters/cc-switch/mcp-claude.d.ts.map +1 -1
  40. package/dist/adapters/cc-switch/mcp-claude.js +1 -0
  41. package/dist/adapters/cc-switch/mcp-claudecode.d.ts.map +1 -1
  42. package/dist/adapters/cc-switch/mcp-claudecode.js +1 -0
  43. package/dist/adapters/cc-switch/mcp-claudecode.test.js +1 -0
  44. package/dist/adapters/cc-switch/mcp-codex.d.ts.map +1 -1
  45. package/dist/adapters/cc-switch/mcp-codex.js +1 -0
  46. package/dist/adapters/cc-switch/mcp-codex.test.js +1 -0
  47. package/dist/adapters/cc-switch/mcp-opencode.d.ts.map +1 -1
  48. package/dist/adapters/cc-switch/mcp-opencode.js +1 -0
  49. package/dist/adapters/cc-switch/mcp-opencode.test.js +1 -0
  50. package/dist/adapters/cc-switch/skill-acode.d.ts +11 -0
  51. package/dist/adapters/cc-switch/skill-acode.d.ts.map +1 -0
  52. package/dist/adapters/cc-switch/skill-acode.js +12 -0
  53. package/dist/adapters/cc-switch/skill-directory.test.js +1 -0
  54. package/dist/config.d.ts +4 -0
  55. package/dist/config.d.ts.map +1 -1
  56. package/dist/config.js +10 -0
  57. package/dist/index.js +2 -0
  58. package/dist/routes/ai-sources.js +3 -2
  59. package/dist/routes/instance.d.ts.map +1 -1
  60. package/dist/routes/instance.js +7 -8
  61. package/dist/routes/instance.test.js +2 -1
  62. package/dist/routes/mcp.js +2 -2
  63. package/dist/routes/mcp.test.js +2 -1
  64. package/dist/routes/runtime-binding.d.ts +3 -2
  65. package/dist/routes/runtime-binding.d.ts.map +1 -1
  66. package/dist/routes/runtime-binding.js +11 -58
  67. package/dist/routes/runtime-binding.test.js +4 -80
  68. package/dist/routes/sessions.d.ts +5 -0
  69. package/dist/routes/sessions.d.ts.map +1 -1
  70. package/dist/routes/sessions.js +36 -16
  71. package/dist/routes/sessions.test.js +13 -0
  72. package/dist/routes/skills.js +2 -2
  73. package/dist/routes/skills.test.js +2 -1
  74. package/dist/routes/terminal.d.ts +27 -7
  75. package/dist/routes/terminal.d.ts.map +1 -1
  76. package/dist/routes/terminal.js +439 -171
  77. package/dist/routes/terminal.test.js +385 -197
  78. package/dist/services/acode-package.d.ts +8 -0
  79. package/dist/services/acode-package.d.ts.map +1 -0
  80. package/dist/services/acode-package.js +82 -0
  81. package/dist/services/ai-source-apply.d.ts +4 -0
  82. package/dist/services/ai-source-apply.d.ts.map +1 -1
  83. package/dist/services/ai-source-apply.js +8 -0
  84. package/dist/services/ai-source-apply.test.js +8 -1
  85. package/dist/services/cc-switch-sdk.d.ts.map +1 -1
  86. package/dist/services/cc-switch-sdk.js +9 -1
  87. package/dist/services/instance-init-service.d.ts.map +1 -1
  88. package/dist/services/instance-init-service.js +3 -2
  89. package/dist/services/instance-init-service.test.js +6 -5
  90. package/dist/services/instance-service.d.ts.map +1 -1
  91. package/dist/services/instance-service.js +1 -0
  92. package/dist/services/instance-state.js +1 -1
  93. package/dist/services/instance-state.test.js +4 -4
  94. package/dist/services/mcp-launch-binding-queue.d.ts +1 -0
  95. package/dist/services/mcp-launch-binding-queue.d.ts.map +1 -1
  96. package/dist/services/mcp-launch-binding-queue.js +8 -2
  97. package/dist/services/mcp-launch-binding-queue.test.js +47 -4
  98. package/dist/services/session-output.d.ts +10 -6
  99. package/dist/services/session-output.d.ts.map +1 -1
  100. package/dist/services/session-output.js +29 -14
  101. package/dist/services/session-output.test.js +93 -39
  102. package/dist/services/tool-installer.d.ts.map +1 -1
  103. package/dist/services/tool-installer.js +10 -0
  104. package/dist/types.d.ts +5 -0
  105. package/dist/types.d.ts.map +1 -1
  106. package/dist/utils/file-utils.d.ts.map +1 -1
  107. package/dist/utils/file-utils.js +1 -0
  108. package/dist/utils/mcp-utils.d.ts.map +1 -1
  109. package/dist/utils/mcp-utils.js +4 -1
  110. package/dist/utils/validation.js +1 -1
  111. package/node_modules/@cc-switch/sdk/dist/constants.d.ts.map +1 -1
  112. package/node_modules/@cc-switch/sdk/dist/constants.js +7 -0
  113. package/node_modules/@cc-switch/sdk/dist/schemas.d.ts.map +1 -1
  114. package/node_modules/@cc-switch/sdk/dist/schemas.js +1 -0
  115. package/node_modules/@cc-switch/sdk/dist/sdk.d.ts.map +1 -1
  116. package/node_modules/@cc-switch/sdk/dist/sdk.js +7 -3
  117. package/node_modules/@cc-switch/sdk/dist/services/ai-config-service.d.ts +6 -0
  118. package/node_modules/@cc-switch/sdk/dist/services/ai-config-service.d.ts.map +1 -1
  119. package/node_modules/@cc-switch/sdk/dist/services/ai-config-service.js +27 -1
  120. package/node_modules/@cc-switch/sdk/dist/types.d.ts +4 -1
  121. package/node_modules/@cc-switch/sdk/dist/types.d.ts.map +1 -1
  122. package/package/acode/README.md +88 -0
  123. package/package/acode/dist/built-in-file-tools.d.ts +16 -0
  124. package/package/acode/dist/built-in-file-tools.d.ts.map +1 -0
  125. package/package/acode/dist/built-in-file-tools.js +569 -0
  126. package/package/acode/dist/cli.d.ts +3 -0
  127. package/package/acode/dist/cli.d.ts.map +1 -0
  128. package/package/acode/dist/cli.js +37 -0
  129. package/package/acode/dist/commands/commandLoader.d.ts +7 -0
  130. package/package/acode/dist/commands/commandLoader.d.ts.map +1 -0
  131. package/package/acode/dist/commands/commandLoader.js +33 -0
  132. package/package/acode/dist/commands/commandParser.d.ts +7 -0
  133. package/package/acode/dist/commands/commandParser.d.ts.map +1 -0
  134. package/package/acode/dist/commands/commandParser.js +77 -0
  135. package/package/acode/dist/commands/commandRegistry.d.ts +13 -0
  136. package/package/acode/dist/commands/commandRegistry.d.ts.map +1 -0
  137. package/package/acode/dist/commands/commandRegistry.js +30 -0
  138. package/package/acode/dist/config.d.ts +4 -0
  139. package/package/acode/dist/config.d.ts.map +1 -0
  140. package/package/acode/dist/config.js +80 -0
  141. package/package/acode/dist/hooks/hookBus.d.ts +19 -0
  142. package/package/acode/dist/hooks/hookBus.d.ts.map +1 -0
  143. package/package/acode/dist/hooks/hookBus.js +40 -0
  144. package/package/acode/dist/index.d.ts +8 -0
  145. package/package/acode/dist/index.d.ts.map +1 -0
  146. package/package/acode/dist/index.js +7 -0
  147. package/package/acode/dist/runtime.d.ts +42 -0
  148. package/package/acode/dist/runtime.d.ts.map +1 -0
  149. package/package/acode/dist/runtime.js +1283 -0
  150. package/package/acode/dist/types.d.ts +112 -0
  151. package/package/acode/dist/types.d.ts.map +1 -0
  152. package/package/acode/dist/types.js +1 -0
  153. package/package/acode/package.json +24 -0
  154. package/package/aws-client-agent-mcp/dist/agent-client.d.ts +4 -4
  155. package/package/aws-client-agent-mcp/dist/agent-client.d.ts.map +1 -1
  156. package/package/aws-client-agent-mcp/dist/agent-client.js +9 -6
  157. package/package/aws-client-agent-mcp/dist/agent-client.js.map +1 -1
  158. package/package/aws-client-agent-mcp/dist/agent-client.test.js +21 -0
  159. package/package/aws-client-agent-mcp/dist/agent-client.test.js.map +1 -1
  160. package/package/aws-client-agent-mcp/dist/http-client.d.ts +1 -17
  161. package/package/aws-client-agent-mcp/dist/http-client.d.ts.map +1 -1
  162. package/package/aws-client-agent-mcp/dist/http-client.js +7 -113
  163. package/package/aws-client-agent-mcp/dist/http-client.js.map +1 -1
  164. package/package/aws-client-agent-mcp/dist/http-client.test.js +22 -2
  165. package/package/aws-client-agent-mcp/dist/http-client.test.js.map +1 -1
  166. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +0 -5
  167. package/package/aws-client-agent-mcp/dist/mcp-server.d.ts.map +1 -1
  168. package/package/aws-client-agent-mcp/dist/mcp-server.js +3 -24
  169. package/package/aws-client-agent-mcp/dist/mcp-server.js.map +1 -1
  170. package/package/aws-client-agent-mcp/dist/mcp-server.test.js +90 -5
  171. package/package/aws-client-agent-mcp/dist/mcp-server.test.js.map +1 -1
  172. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.d.ts.map +1 -1
  173. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js +1 -0
  174. package/package/aws-client-agent-mcp/dist/runtime-launch-binding.js.map +1 -1
  175. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts +2 -0
  176. package/package/aws-client-agent-mcp/dist/status-reporter.d.ts.map +1 -1
  177. package/package/aws-client-agent-mcp/dist/status-reporter.js +31 -3
  178. package/package/aws-client-agent-mcp/dist/status-reporter.js.map +1 -1
  179. package/package/aws-client-agent-mcp/dist/types.d.ts +4 -1
  180. package/package/aws-client-agent-mcp/dist/types.d.ts.map +1 -1
  181. package/package/aws-client-agent-mcp/dist/types.js.map +1 -1
  182. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts +0 -13
  183. package/package/aws-client-agent-mcp/dist/websocket-client.d.ts.map +1 -1
  184. package/package/aws-client-agent-mcp/dist/websocket-client.js +5 -100
  185. package/package/aws-client-agent-mcp/dist/websocket-client.js.map +1 -1
  186. package/package/aws-client-agent-mcp/dist/websocket-client.test.js +43 -0
  187. package/package/aws-client-agent-mcp/dist/websocket-client.test.js.map +1 -1
  188. package/package/cc-switch-sdk/dist/constants.d.ts.map +1 -1
  189. package/package/cc-switch-sdk/dist/constants.js +7 -0
  190. package/package/cc-switch-sdk/dist/schemas.d.ts.map +1 -1
  191. package/package/cc-switch-sdk/dist/schemas.js +1 -0
  192. package/package/cc-switch-sdk/dist/sdk.d.ts.map +1 -1
  193. package/package/cc-switch-sdk/dist/sdk.js +7 -3
  194. package/package/cc-switch-sdk/dist/services/ai-config-service.d.ts +6 -0
  195. package/package/cc-switch-sdk/dist/services/ai-config-service.d.ts.map +1 -1
  196. package/package/cc-switch-sdk/dist/services/ai-config-service.js +27 -1
  197. package/package/cc-switch-sdk/dist/types.d.ts +4 -1
  198. package/package/cc-switch-sdk/dist/types.d.ts.map +1 -1
  199. package/package.json +8 -4
@@ -1,10 +1,6 @@
1
1
  import { afterEach, describe, expect, it, vi } from "vitest";
2
- const getRuntimeAccessTokenMock = vi.hoisted(() => vi.fn());
3
- const requestRuntimeAccessTokenRefreshMock = vi.hoisted(() => vi.fn());
4
- const requestRuntimeAccessTokenRefreshForServerMock = vi.hoisted(() => vi.fn());
5
2
  vi.mock("../services/runtime-binding.js", () => ({
6
3
  clearRuntimeBinding: vi.fn(),
7
- getRuntimeAccessToken: getRuntimeAccessTokenMock,
8
4
  getRuntimeBindingPublicState: vi.fn(() => ({ paired: true })),
9
5
  getRuntimePairingCode: vi.fn(() => "000-000"),
10
6
  hasRuntimeBinding: vi.fn(() => true),
@@ -12,10 +8,6 @@ vi.mock("../services/runtime-binding.js", () => ({
12
8
  validateRuntimeBindingToken: vi.fn(() => true),
13
9
  validateRuntimePairingCode: vi.fn(() => true),
14
10
  }));
15
- vi.mock("../services/auto-register.js", () => ({
16
- requestRuntimeAccessTokenRefresh: requestRuntimeAccessTokenRefreshMock,
17
- requestRuntimeAccessTokenRefreshForServer: requestRuntimeAccessTokenRefreshForServerMock,
18
- }));
19
11
  vi.mock("../services/mcp-launch-binding-queue.js", () => ({
20
12
  claimMcpLaunchBinding: vi.fn(),
21
13
  getMcpLaunchQueueSize: vi.fn(() => 0),
@@ -24,85 +16,17 @@ afterEach(() => {
24
16
  vi.clearAllMocks();
25
17
  });
26
18
  describe("runtime binding token request", () => {
27
- it("reuses a newer scoped token instead of rotating again after another MCP process refreshed it", async () => {
28
- getRuntimeAccessTokenMock.mockReturnValue("fresh-token-from-other-process");
29
- const { resolveRuntimeTokenRequest } = await import("./runtime-binding.js");
30
- const result = await resolveRuntimeTokenRequest({
31
- userId: "user-1",
32
- serverUrl: "ws://localhost:7380/ws/agent",
33
- forceRefresh: true,
34
- rejectedRuntimeAccessToken: "stale-token",
35
- });
36
- expect(result).toEqual({
37
- success: true,
38
- runtimeAccessToken: "fresh-token-from-other-process",
39
- updated: false,
40
- });
41
- expect(requestRuntimeAccessTokenRefreshForServerMock).not.toHaveBeenCalled();
42
- expect(requestRuntimeAccessTokenRefreshMock).not.toHaveBeenCalled();
43
- });
44
- it("rotates the runtime token when the latest scoped token is the rejected token", async () => {
45
- getRuntimeAccessTokenMock.mockReturnValue("stale-token");
46
- requestRuntimeAccessTokenRefreshForServerMock.mockResolvedValue({
47
- success: true,
48
- runtimeAccessToken: "rotated-token",
49
- updated: true,
50
- });
19
+ it("rejects bridge-scoped token refresh for MCP nodes", async () => {
51
20
  const { resolveRuntimeTokenRequest } = await import("./runtime-binding.js");
52
- const result = await resolveRuntimeTokenRequest({
21
+ const result = resolveRuntimeTokenRequest({
53
22
  userId: "user-1",
54
23
  serverUrl: "ws://localhost:7380/ws/agent",
55
24
  forceRefresh: true,
56
25
  rejectedRuntimeAccessToken: "stale-token",
57
26
  });
58
27
  expect(result).toEqual({
59
- success: true,
60
- runtimeAccessToken: "rotated-token",
61
- updated: true,
62
- });
63
- expect(requestRuntimeAccessTokenRefreshForServerMock).toHaveBeenCalledWith("ws://localhost:7380/ws/agent");
64
- });
65
- it("serializes concurrent force refreshes and lets the loser reuse the winner token", async () => {
66
- let cachedToken = "stale-token";
67
- let releaseRefresh = () => undefined;
68
- const refreshGate = new Promise((resolve) => {
69
- releaseRefresh = resolve;
70
- });
71
- getRuntimeAccessTokenMock.mockImplementation(() => cachedToken);
72
- requestRuntimeAccessTokenRefreshForServerMock.mockImplementation(async () => {
73
- await refreshGate;
74
- cachedToken = "winner-token";
75
- return {
76
- success: true,
77
- runtimeAccessToken: "winner-token",
78
- updated: true,
79
- };
80
- });
81
- const { resolveRuntimeTokenRequest } = await import("./runtime-binding.js");
82
- const first = resolveRuntimeTokenRequest({
83
- userId: "user-1",
84
- serverUrl: "ws://localhost:7380/ws/agent",
85
- forceRefresh: true,
86
- rejectedRuntimeAccessToken: "stale-token",
87
- });
88
- const second = resolveRuntimeTokenRequest({
89
- userId: "user-1",
90
- serverUrl: "ws://localhost:7380/ws/agent",
91
- forceRefresh: true,
92
- rejectedRuntimeAccessToken: "stale-token",
93
- });
94
- releaseRefresh();
95
- const [firstResult, secondResult] = await Promise.all([first, second]);
96
- expect(firstResult).toEqual({
97
- success: true,
98
- runtimeAccessToken: "winner-token",
99
- updated: true,
100
- });
101
- expect(secondResult).toEqual({
102
- success: true,
103
- runtimeAccessToken: "winner-token",
104
- updated: false,
28
+ success: false,
29
+ error: "MCP runtime token must be claimed from launch binding; bridge-scoped token refresh is disabled",
105
30
  });
106
- expect(requestRuntimeAccessTokenRefreshForServerMock).toHaveBeenCalledTimes(1);
107
31
  });
108
32
  });
@@ -4,4 +4,9 @@
4
4
  * 提供 SDK Agent 会话的查询和恢复功能
5
5
  */
6
6
  export declare const sessionsRouter: import("express-serve-static-core").Router;
7
+ /**
8
+ * 解析 active SDK 会话快照状态。
9
+ * 主流程:优先使用 adapter 细粒度状态,其次使用 terminal 路由内存里的最近 runtimeStatus,最后兼容旧会话回退 running。
10
+ */
11
+ export declare function resolveActiveSdkSessionSnapshotStatus(adapterStatus?: string, currentRuntimeStatus?: string): string;
7
12
  //# sourceMappingURL=sessions.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAqBH,eAAO,MAAM,cAAc,4CAAW,CAAC"}
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/routes/sessions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAqBH,eAAO,MAAM,cAAc,4CAAW,CAAC;AAEvC;;;GAGG;AACH,wBAAgB,qCAAqC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,MAAM,GAAG,MAAM,CAOnH"}
@@ -13,6 +13,18 @@ import { createLogger } from '../utils/logger.js';
13
13
  import { sdkSessions } from './terminal.js';
14
14
  const log = createLogger('sessions');
15
15
  export const sessionsRouter = Router();
16
+ /**
17
+ * 解析 active SDK 会话快照状态。
18
+ * 主流程:优先使用 adapter 细粒度状态,其次使用 terminal 路由内存里的最近 runtimeStatus,最后兼容旧会话回退 running。
19
+ */
20
+ export function resolveActiveSdkSessionSnapshotStatus(adapterStatus, currentRuntimeStatus) {
21
+ const normalizedAdapterStatus = String(adapterStatus || '').trim();
22
+ if (normalizedAdapterStatus) {
23
+ return normalizedAdapterStatus;
24
+ }
25
+ const normalizedRuntimeStatus = String(currentRuntimeStatus || '').trim();
26
+ return normalizedRuntimeStatus || 'running';
27
+ }
16
28
  /**
17
29
  * 获取所有 SDK Agent 会话
18
30
  * GET /runtime/sessions
@@ -20,18 +32,22 @@ export const sessionsRouter = Router();
20
32
  sessionsRouter.get('/sessions', validateToken, async (_req, res) => {
21
33
  try {
22
34
  // 1. 获取 SDK 会话
23
- const activeSdkSessions = Array.from(sdkSessions.entries()).map(([sessionId, entry]) => ({
24
- sessionId,
25
- agentId: entry.agentId,
26
- workspacePath: entry.workspacePath,
27
- status: 'running',
28
- runtimeStatus: entry.currentRuntimeStatus,
29
- runtimeActionType: entry.currentRuntimeActionType,
30
- runtimeActionLabel: entry.currentRuntimeActionLabel,
31
- runtimeActionDetail: entry.currentRuntimeActionDetail,
32
- mode: 'sdk',
33
- startedAt: null,
34
- }));
35
+ const activeSdkSessions = Array.from(sdkSessions.entries()).map(([sessionId, entry]) => {
36
+ const adapter = adapterRegistry.get(entry.providerId || 'claude-code');
37
+ const status = resolveActiveSdkSessionSnapshotStatus(adapter.getSessionStatus(sessionId), entry.currentRuntimeStatus);
38
+ return {
39
+ sessionId,
40
+ agentId: entry.agentId,
41
+ workspacePath: entry.workspacePath,
42
+ status,
43
+ runtimeStatus: status,
44
+ runtimeActionType: entry.currentRuntimeActionType,
45
+ runtimeActionLabel: entry.currentRuntimeActionLabel,
46
+ runtimeActionDetail: entry.currentRuntimeActionDetail,
47
+ mode: 'sdk',
48
+ startedAt: null,
49
+ };
50
+ });
35
51
  // 2. SDK-only:活跃会话全部来自 SDK adapter。
36
52
  const activeSessions = activeSdkSessions;
37
53
  const persistedSessions = await loadPersistedSessions();
@@ -66,14 +82,16 @@ sessionsRouter.post('/sessions/recover', validateToken, async (req, res) => {
66
82
  // 1. 检查是否有 SDK 活跃会话
67
83
  const existingSdkSession = Array.from(sdkSessions.entries()).find(([, s]) => s.agentId === agentId);
68
84
  if (existingSdkSession) {
85
+ const adapter = adapterRegistry.get(existingSdkSession[1].providerId || 'claude-code');
86
+ const status = resolveActiveSdkSessionSnapshotStatus(adapter.getSessionStatus(existingSdkSession[0]), existingSdkSession[1].currentRuntimeStatus);
69
87
  res.json({
70
88
  ok: true,
71
89
  sessionId: existingSdkSession[0],
72
90
  agentId,
73
91
  workspacePath: existingSdkSession[1].workspacePath,
74
92
  command: existingSdkSession[1].config.command,
75
- status: 'running',
76
- runtimeStatus: existingSdkSession[1].currentRuntimeStatus,
93
+ status,
94
+ runtimeStatus: status,
77
95
  runtimeActionType: existingSdkSession[1].currentRuntimeActionType,
78
96
  runtimeActionLabel: existingSdkSession[1].currentRuntimeActionLabel,
79
97
  runtimeActionDetail: existingSdkSession[1].currentRuntimeActionDetail,
@@ -103,7 +121,7 @@ sessionsRouter.post('/sessions/recover', validateToken, async (req, res) => {
103
121
  }
104
122
  }
105
123
  const resolvedWorkspacePath = workspacePath || persistedSession?.workspacePath;
106
- const resolvedCommand = command || persistedSession?.command || 'claude';
124
+ const resolvedCommand = command || persistedSession?.command || 'acode';
107
125
  const resolvedMode = persistedSession?.mode || 'sdk';
108
126
  if (!resolvedWorkspacePath) {
109
127
  res.status(400).json({ error: 'workspacePath is required (not found in persisted session)' });
@@ -343,12 +361,14 @@ sessionsRouter.get('/sessions/by-agent/:agentId', validateToken, async (req, res
343
361
  if (activeSdkSession) {
344
362
  const adapter = adapterRegistry.get(activeSdkSession[1].providerId || 'claude-code');
345
363
  const pid = adapter.getSessionPid?.(activeSdkSession[0]);
364
+ const status = resolveActiveSdkSessionSnapshotStatus(adapter.getSessionStatus(activeSdkSession[0]), activeSdkSession[1].currentRuntimeStatus);
346
365
  res.json({
347
366
  ok: true,
348
367
  sessionId: activeSdkSession[0],
349
368
  agentId,
350
369
  workspacePath: activeSdkSession[1].workspacePath,
351
- status: 'running',
370
+ status,
371
+ runtimeStatus: status,
352
372
  isActive: true,
353
373
  mode: 'sdk',
354
374
  pid,
@@ -2,6 +2,7 @@
2
2
  * Sessions 路由单元测试
3
3
  */
4
4
  import { describe, it, expect } from 'vitest';
5
+ import { resolveActiveSdkSessionSnapshotStatus } from './sessions.js';
5
6
  describe('sessions route validation', () => {
6
7
  it('requires agentId for recovery', () => {
7
8
  const validateRecoverRequest = (body) => {
@@ -48,6 +49,18 @@ describe('session persistence', () => {
48
49
  expect(result[0].sessionId).toBe('session-2');
49
50
  });
50
51
  });
52
+ describe('active SDK session snapshots', () => {
53
+ it('reports the adapter fine-grained status instead of hardcoded running', () => {
54
+ expect(resolveActiveSdkSessionSnapshotStatus('waiting_input', 'running')).toBe('waiting_input');
55
+ expect(resolveActiveSdkSessionSnapshotStatus('tool_using', undefined)).toBe('tool_using');
56
+ });
57
+ it('uses current runtime status when adapter status is unavailable', () => {
58
+ expect(resolveActiveSdkSessionSnapshotStatus(undefined, 'thinking')).toBe('thinking');
59
+ });
60
+ it('falls back to running only for legacy sessions without status details', () => {
61
+ expect(resolveActiveSdkSessionSnapshotStatus(undefined, undefined)).toBe('running');
62
+ });
63
+ });
51
64
  describe('terminal configuration', () => {
52
65
  it('selects correct shell for platform', () => {
53
66
  const getShellConfig = (platform) => {
@@ -5,7 +5,7 @@ import { syncLegacyStateFromSdk } from '../services/instance-init-service.js';
5
5
  import { resolveSkillSourceDir, ensureDirectoryExists } from '../utils/file-utils.js';
6
6
  import { normalizeSdkAppFlags } from '../utils/mcp-utils.js';
7
7
  export const skillsRouter = Router();
8
- const TOGGLEABLE_APP_IDS = new Set(['claudecode', 'opencode']);
8
+ const TOGGLEABLE_APP_IDS = new Set(['acode', 'claudecode', 'opencode']);
9
9
  skillsRouter.post('/cc-switch/skills/list', validateToken, async (req, res) => {
10
10
  const { agentId } = req.body || {};
11
11
  if (!agentId) {
@@ -100,7 +100,7 @@ skillsRouter.post('/cc-switch/skills/toggle-app', validateToken, async (req, res
100
100
  try {
101
101
  const normalizedAppId = String(appId).trim().toLowerCase();
102
102
  if (!TOGGLEABLE_APP_IDS.has(normalizedAppId)) {
103
- res.status(400).json({ error: 'appId must be one of claudecode, opencode' });
103
+ res.status(400).json({ error: 'appId must be one of acode, claudecode, opencode' });
104
104
  return;
105
105
  }
106
106
  const sdk = await loadCcSwitchSdk(agentId);
@@ -40,7 +40,8 @@ describe('skills route validation', () => {
40
40
  expect(normalizeApps(['claude', 'opencode'])).toEqual(['claude', 'opencode']);
41
41
  });
42
42
  it('allows supported per-tool toggle app ids', () => {
43
- const isSupportedToggleAppId = (appId) => ['claudecode', 'opencode'].includes(appId);
43
+ const isSupportedToggleAppId = (appId) => ['acode', 'claudecode', 'opencode'].includes(appId);
44
+ expect(isSupportedToggleAppId('acode')).toBe(true);
44
45
  expect(isSupportedToggleAppId('claudecode')).toBe(true);
45
46
  expect(isSupportedToggleAppId('opencode')).toBe(true);
46
47
  expect(isSupportedToggleAppId('codex')).toBe(false);
@@ -4,9 +4,9 @@
4
4
  * 提供 SDK Agent 会话的启动、输入、调整大小和停止功能
5
5
  * 终端 UI 仅作为 SDK Agent 的消息输入/状态输出载体
6
6
  */
7
- import { TextDecoder } from 'node:util';
8
- import { type AdapterSessionConfig, type ProviderEvent, type RuntimeStatusActionInfo } from '../adapter/index.js';
9
- import type { PersistedSession } from '../types.js';
7
+ import { TextDecoder } from "node:util";
8
+ import { type AdapterSessionConfig, type ProviderEvent, type RuntimeStatusActionInfo } from "../adapter/index.js";
9
+ import type { PersistedSession } from "../types.js";
10
10
  export declare const terminalRouter: import("express-serve-static-core").Router;
11
11
  export interface SdkSessionEntry {
12
12
  agentId: string;
@@ -15,6 +15,7 @@ export interface SdkSessionEntry {
15
15
  config: AdapterSessionConfig;
16
16
  providerId: string;
17
17
  seq: number;
18
+ runtimeAccessToken?: string;
18
19
  currentRuntimeStatus?: string;
19
20
  currentRuntimeActionType?: string;
20
21
  currentRuntimeActionLabel?: string;
@@ -25,6 +26,10 @@ export declare function resolveStatusChangeUsage(actionInfo?: RuntimeStatusActio
25
26
  inputTokens: number;
26
27
  outputTokens: number;
27
28
  } | undefined;
29
+ export declare function buildAcodeCommandOutputPath(workspacePath: string, now?: Date): string;
30
+ export declare function countTerminalOutputLines(output: string): number;
31
+ export declare function formatCommandOutputSpilloverNotice(outputPath: string, lineLimit?: number): string;
32
+ export declare function formatCommandInactivityTimeoutNotice(timeoutMs?: number): string;
28
33
  /**
29
34
  * 标准化终端输入:将前端回车符还原为 shell 可执行命令文本。
30
35
  */
@@ -46,15 +51,20 @@ export declare function decodeTerminalOutputChunk(decoder: TextDecoder, chunk?:
46
51
  * 解析 cd 命令目标;返回 undefined 表示不是目录切换命令,null 表示仅查看当前目录。
47
52
  */
48
53
  export declare function parseTerminalDirectoryChangeTarget(command: string): string | null | undefined;
54
+ /**
55
+ * 解析 SDK 会话对外展示状态。
56
+ * 主流程:优先使用 adapter 当前细粒度状态,其次使用路由内存记录的最近状态,最后才兼容旧会话回退 running。
57
+ */
58
+ export declare function resolveSdkSessionDisplayStatus(adapterStatus?: string, currentRuntimeStatus?: string): string;
49
59
  export interface PersistedSessionReuseDecision {
50
60
  reusable: boolean;
51
- reason: 'active-pid' | 'missing-pid' | 'dead-pid';
61
+ reason: "active-pid" | "missing-pid" | "dead-pid" | "in-process-provider";
52
62
  }
53
63
  /**
54
- * 判断持久化 SDK 会话能否在显式启动请求中复用。
55
- * 主流程:必须存在 PID OS 仍能确认该进程存活;否则视为重启后遗留的陈旧会话。
64
+ * Decide whether a persisted SDK session can be reused for a start request.
65
+ * Main flow: require a live PID, then reject in-process providers whose adapter control channel cannot be restored.
56
66
  */
57
- export declare function evaluatePersistedSessionReuse(session: Pick<PersistedSession, 'pid'>, isPidRunning?: (pid: number) => boolean): PersistedSessionReuseDecision;
67
+ export declare function evaluatePersistedSessionReuse(session: Pick<PersistedSession, "pid"> & Partial<Pick<PersistedSession, "command">>, isPidRunning?: (pid: number) => boolean): PersistedSessionReuseDecision;
58
68
  /**
59
69
  * 生成显示在终端输出流中的工作目录提示符。
60
70
  */
@@ -81,5 +91,15 @@ export declare function buildClaudeCodeLaunchConfig(savedClaudeConfig: {
81
91
  */
82
92
  export declare function buildToolResultTimelineActionInfo(event: ProviderEvent): RuntimeStatusActionInfo | undefined;
83
93
  export declare function formatSdkOutputEvent(event: ProviderEvent): string | undefined;
94
+ /**
95
+ * 主干流程:把 provider 事件转换为面板运行状态。
96
+ *
97
+ * text_delta 表示助手正在生成;thinking 表示推理/内部过程。
98
+ * tool_use_start 表示正在执行工具;turn_complete 才表示真正空闲。
99
+ */
100
+ export declare function resolveRuntimeStatusFromProviderEvent(event: ProviderEvent): {
101
+ status: string;
102
+ actionInfo?: RuntimeStatusActionInfo;
103
+ } | undefined;
84
104
  export declare function resolveSdkProviderId(command?: string): string;
85
105
  //# sourceMappingURL=terminal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/routes/terminal.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAKxC,OAAO,EAOL,KAAK,oBAAoB,EAEzB,KAAK,aAAa,EAClB,KAAK,uBAAuB,EAE7B,MAAM,qBAAqB,CAAC;AAe7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,eAAO,MAAM,cAAc,4CAAW,CAAC;AAIvC,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,oBAAoB,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,yBAAyB,CAAC,EAAE,MAAM,CAAC;IACnC,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC;AAGD,eAAO,MAAM,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAa,CAAC;AAKnE,wBAAgB,wBAAwB,CAAC,UAAU,CAAC,EAAE,uBAAuB;;;cAS5E;AAaD;;GAEG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpE;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAMR;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,SAAkC,GAAG,WAAW,CAMnG;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,UAAQ,GAAG,MAAM,CAQnG;AAED;;GAEG;AACH,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAiB7F;AA2CD,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,YAAY,GAAG,aAAa,GAAG,UAAU,CAAC;CACnD;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,EACtC,YAAY,GAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAA0B,GACxD,6BAA6B,CAU/B;AA4BD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAErE;AAgHD,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,OAAO,EAAE,MAAM,CAAC,UAAU,EAC1B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GACrC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA+BxB;AAYD;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAY5E;AAED,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,iBAAiB,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,EACvE,mBAAmB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5C,sBAAsB,CAwBxB;AA2CD;;;GAGG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,aAAa,GAAG,uBAAuB,GAAG,SAAS,CAiC3G;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAU7E;AAYD,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAE7D"}
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/routes/terminal.ts"],"names":[],"mappings":"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"}