shennian 0.2.4 → 0.2.5

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 (286) hide show
  1. package/dist/bin/shennian.d.ts +0 -1
  2. package/dist/bin/shennian.js +0 -1
  3. package/dist/src/agents/adapter.d.ts +0 -1
  4. package/dist/src/agents/adapter.js +0 -1
  5. package/dist/src/agents/claude.d.ts +1 -1
  6. package/dist/src/agents/claude.js +12 -6
  7. package/dist/src/agents/codex.d.ts +0 -1
  8. package/dist/src/agents/codex.js +13 -4
  9. package/dist/src/agents/command-spec.d.ts +28 -3
  10. package/dist/src/agents/command-spec.js +251 -10
  11. package/dist/src/agents/cursor.d.ts +0 -1
  12. package/dist/src/agents/cursor.js +2 -4
  13. package/dist/src/agents/custom.d.ts +0 -6
  14. package/dist/src/agents/custom.js +4 -40
  15. package/dist/src/agents/detect.d.ts +0 -1
  16. package/dist/src/agents/detect.js +0 -1
  17. package/dist/src/agents/gemini.d.ts +0 -1
  18. package/dist/src/agents/gemini.js +7 -3
  19. package/dist/src/agents/model-registry/cache.d.ts +0 -1
  20. package/dist/src/agents/model-registry/cache.js +0 -1
  21. package/dist/src/agents/model-registry/discovery.d.ts +0 -1
  22. package/dist/src/agents/model-registry/discovery.js +13 -54
  23. package/dist/src/agents/model-registry/parsers.d.ts +3 -1
  24. package/dist/src/agents/model-registry/parsers.js +92 -2
  25. package/dist/src/agents/model-registry/runner.d.ts +2 -7
  26. package/dist/src/agents/model-registry/runner.js +3 -134
  27. package/dist/src/agents/model-registry/service.d.ts +0 -1
  28. package/dist/src/agents/model-registry/service.js +12 -10
  29. package/dist/src/agents/model-registry/types.d.ts +0 -1
  30. package/dist/src/agents/model-registry/types.js +0 -1
  31. package/dist/src/agents/model-registry.d.ts +2 -2
  32. package/dist/src/agents/model-registry.js +2 -2
  33. package/dist/src/agents/openclaw.d.ts +0 -1
  34. package/dist/src/agents/openclaw.js +13 -4
  35. package/dist/src/agents/pi.d.ts +0 -1
  36. package/dist/src/agents/pi.js +0 -1
  37. package/dist/src/commands/agent.d.ts +0 -1
  38. package/dist/src/commands/agent.js +2 -33
  39. package/dist/src/commands/daemon.d.ts +6 -1
  40. package/dist/src/commands/daemon.js +153 -18
  41. package/dist/src/commands/pair-qr.d.ts +0 -1
  42. package/dist/src/commands/pair-qr.js +0 -1
  43. package/dist/src/commands/pair.d.ts +0 -1
  44. package/dist/src/commands/pair.js +0 -1
  45. package/dist/src/commands/upgrade.d.ts +0 -1
  46. package/dist/src/commands/upgrade.js +0 -1
  47. package/dist/src/config/index.d.ts +0 -1
  48. package/dist/src/config/index.js +0 -1
  49. package/dist/src/fs/handler.d.ts +0 -1
  50. package/dist/src/fs/handler.js +0 -1
  51. package/dist/src/fs/security.d.ts +0 -1
  52. package/dist/src/fs/security.js +5 -1
  53. package/dist/src/index.d.ts +0 -1
  54. package/dist/src/index.js +33 -7
  55. package/dist/src/log-reporter.d.ts +0 -1
  56. package/dist/src/log-reporter.js +2 -20
  57. package/dist/src/native-fusion/parsers.d.ts +0 -1
  58. package/dist/src/native-fusion/parsers.js +356 -40
  59. package/dist/src/native-fusion/service.d.ts +0 -1
  60. package/dist/src/native-fusion/service.js +14 -5
  61. package/dist/src/native-fusion/state.d.ts +0 -1
  62. package/dist/src/native-fusion/state.js +0 -1
  63. package/dist/src/native-fusion/types.d.ts +0 -1
  64. package/dist/src/native-fusion/types.js +0 -1
  65. package/dist/src/region.d.ts +0 -1
  66. package/dist/src/region.js +0 -1
  67. package/dist/src/relay/client.d.ts +11 -2
  68. package/dist/src/relay/client.js +22 -4
  69. package/dist/src/session/handlers/agents.d.ts +0 -1
  70. package/dist/src/session/handlers/agents.js +0 -1
  71. package/dist/src/session/handlers/chat.d.ts +0 -1
  72. package/dist/src/session/handlers/chat.js +0 -1
  73. package/dist/src/session/handlers/control.d.ts +0 -1
  74. package/dist/src/session/handlers/control.js +0 -1
  75. package/dist/src/session/handlers/fs.d.ts +0 -1
  76. package/dist/src/session/handlers/fs.js +5 -2
  77. package/dist/src/session/manager.d.ts +1 -1
  78. package/dist/src/session/manager.js +23 -4
  79. package/dist/src/session/store.d.ts +0 -1
  80. package/dist/src/session/store.js +0 -1
  81. package/dist/src/session/types.d.ts +0 -1
  82. package/dist/src/session/types.js +0 -1
  83. package/dist/src/upgrade/engine.d.ts +0 -1
  84. package/dist/src/upgrade/engine.js +0 -1
  85. package/package.json +3 -2
  86. package/dist/bin/shennian.d.ts.map +0 -1
  87. package/dist/bin/shennian.js.map +0 -1
  88. package/dist/src/__experiments__/probe-debug.d.ts +0 -2
  89. package/dist/src/__experiments__/probe-debug.d.ts.map +0 -1
  90. package/dist/src/__experiments__/probe-debug.js +0 -66
  91. package/dist/src/__experiments__/probe-debug.js.map +0 -1
  92. package/dist/src/__experiments__/probe-final-benchmark.d.ts +0 -3
  93. package/dist/src/__experiments__/probe-final-benchmark.d.ts.map +0 -1
  94. package/dist/src/__experiments__/probe-final-benchmark.js +0 -234
  95. package/dist/src/__experiments__/probe-final-benchmark.js.map +0 -1
  96. package/dist/src/__experiments__/probe-models-final.d.ts +0 -19
  97. package/dist/src/__experiments__/probe-models-final.d.ts.map +0 -1
  98. package/dist/src/__experiments__/probe-models-final.js +0 -250
  99. package/dist/src/__experiments__/probe-models-final.js.map +0 -1
  100. package/dist/src/__experiments__/probe-models.d.ts +0 -7
  101. package/dist/src/__experiments__/probe-models.d.ts.map +0 -1
  102. package/dist/src/__experiments__/probe-models.js +0 -251
  103. package/dist/src/__experiments__/probe-models.js.map +0 -1
  104. package/dist/src/__tests__/agents-e2e.d.ts +0 -21
  105. package/dist/src/__tests__/agents-e2e.d.ts.map +0 -1
  106. package/dist/src/__tests__/agents-e2e.js +0 -155
  107. package/dist/src/__tests__/agents-e2e.js.map +0 -1
  108. package/dist/src/__tests__/claude-adapter.test.d.ts +0 -2
  109. package/dist/src/__tests__/claude-adapter.test.d.ts.map +0 -1
  110. package/dist/src/__tests__/claude-adapter.test.js +0 -75
  111. package/dist/src/__tests__/claude-adapter.test.js.map +0 -1
  112. package/dist/src/__tests__/codex-adapter.test.d.ts +0 -2
  113. package/dist/src/__tests__/codex-adapter.test.d.ts.map +0 -1
  114. package/dist/src/__tests__/codex-adapter.test.js +0 -281
  115. package/dist/src/__tests__/codex-adapter.test.js.map +0 -1
  116. package/dist/src/__tests__/config.test.d.ts +0 -2
  117. package/dist/src/__tests__/config.test.d.ts.map +0 -1
  118. package/dist/src/__tests__/config.test.js +0 -60
  119. package/dist/src/__tests__/config.test.js.map +0 -1
  120. package/dist/src/__tests__/cursor-adapter.test.d.ts +0 -2
  121. package/dist/src/__tests__/cursor-adapter.test.d.ts.map +0 -1
  122. package/dist/src/__tests__/cursor-adapter.test.js +0 -69
  123. package/dist/src/__tests__/cursor-adapter.test.js.map +0 -1
  124. package/dist/src/__tests__/custom-agent-flow.test.d.ts +0 -2
  125. package/dist/src/__tests__/custom-agent-flow.test.d.ts.map +0 -1
  126. package/dist/src/__tests__/custom-agent-flow.test.js +0 -244
  127. package/dist/src/__tests__/custom-agent-flow.test.js.map +0 -1
  128. package/dist/src/__tests__/daemon-autostart.test.d.ts +0 -2
  129. package/dist/src/__tests__/daemon-autostart.test.d.ts.map +0 -1
  130. package/dist/src/__tests__/daemon-autostart.test.js +0 -60
  131. package/dist/src/__tests__/daemon-autostart.test.js.map +0 -1
  132. package/dist/src/__tests__/e2e-relay.d.ts +0 -19
  133. package/dist/src/__tests__/e2e-relay.d.ts.map +0 -1
  134. package/dist/src/__tests__/e2e-relay.js +0 -400
  135. package/dist/src/__tests__/e2e-relay.js.map +0 -1
  136. package/dist/src/__tests__/fs-handler.test.d.ts +0 -2
  137. package/dist/src/__tests__/fs-handler.test.d.ts.map +0 -1
  138. package/dist/src/__tests__/fs-handler.test.js +0 -19
  139. package/dist/src/__tests__/fs-handler.test.js.map +0 -1
  140. package/dist/src/__tests__/model-discovery.test.d.ts +0 -2
  141. package/dist/src/__tests__/model-discovery.test.d.ts.map +0 -1
  142. package/dist/src/__tests__/model-discovery.test.js +0 -47
  143. package/dist/src/__tests__/model-discovery.test.js.map +0 -1
  144. package/dist/src/__tests__/model-switching.test.d.ts +0 -2
  145. package/dist/src/__tests__/model-switching.test.d.ts.map +0 -1
  146. package/dist/src/__tests__/model-switching.test.js +0 -292
  147. package/dist/src/__tests__/model-switching.test.js.map +0 -1
  148. package/dist/src/__tests__/native-fusion-parsers.test.d.ts +0 -2
  149. package/dist/src/__tests__/native-fusion-parsers.test.d.ts.map +0 -1
  150. package/dist/src/__tests__/native-fusion-parsers.test.js +0 -253
  151. package/dist/src/__tests__/native-fusion-parsers.test.js.map +0 -1
  152. package/dist/src/__tests__/native-fusion-service.test.d.ts +0 -2
  153. package/dist/src/__tests__/native-fusion-service.test.d.ts.map +0 -1
  154. package/dist/src/__tests__/native-fusion-service.test.js +0 -157
  155. package/dist/src/__tests__/native-fusion-service.test.js.map +0 -1
  156. package/dist/src/__tests__/native-session-sync.test.d.ts +0 -2
  157. package/dist/src/__tests__/native-session-sync.test.d.ts.map +0 -1
  158. package/dist/src/__tests__/native-session-sync.test.js +0 -198
  159. package/dist/src/__tests__/native-session-sync.test.js.map +0 -1
  160. package/dist/src/__tests__/pair-qr.test.d.ts +0 -2
  161. package/dist/src/__tests__/pair-qr.test.d.ts.map +0 -1
  162. package/dist/src/__tests__/pair-qr.test.js +0 -13
  163. package/dist/src/__tests__/pair-qr.test.js.map +0 -1
  164. package/dist/src/__tests__/pi-context.test.d.ts +0 -2
  165. package/dist/src/__tests__/pi-context.test.d.ts.map +0 -1
  166. package/dist/src/__tests__/pi-context.test.js +0 -261
  167. package/dist/src/__tests__/pi-context.test.js.map +0 -1
  168. package/dist/src/__tests__/session-manager.test.d.ts +0 -2
  169. package/dist/src/__tests__/session-manager.test.d.ts.map +0 -1
  170. package/dist/src/__tests__/session-manager.test.js +0 -685
  171. package/dist/src/__tests__/session-manager.test.js.map +0 -1
  172. package/dist/src/__tests__/session-store.test.d.ts +0 -2
  173. package/dist/src/__tests__/session-store.test.d.ts.map +0 -1
  174. package/dist/src/__tests__/session-store.test.js +0 -106
  175. package/dist/src/__tests__/session-store.test.js.map +0 -1
  176. package/dist/src/agents/adapter.d.ts.map +0 -1
  177. package/dist/src/agents/adapter.js.map +0 -1
  178. package/dist/src/agents/claude.d.ts.map +0 -1
  179. package/dist/src/agents/claude.js.map +0 -1
  180. package/dist/src/agents/codex.d.ts.map +0 -1
  181. package/dist/src/agents/codex.js.map +0 -1
  182. package/dist/src/agents/command-spec.d.ts.map +0 -1
  183. package/dist/src/agents/command-spec.js.map +0 -1
  184. package/dist/src/agents/cursor.d.ts.map +0 -1
  185. package/dist/src/agents/cursor.js.map +0 -1
  186. package/dist/src/agents/custom.d.ts.map +0 -1
  187. package/dist/src/agents/custom.js.map +0 -1
  188. package/dist/src/agents/detect.d.ts.map +0 -1
  189. package/dist/src/agents/detect.js.map +0 -1
  190. package/dist/src/agents/gemini.d.ts.map +0 -1
  191. package/dist/src/agents/gemini.js.map +0 -1
  192. package/dist/src/agents/model-registry/cache.d.ts.map +0 -1
  193. package/dist/src/agents/model-registry/cache.js.map +0 -1
  194. package/dist/src/agents/model-registry/discovery.d.ts.map +0 -1
  195. package/dist/src/agents/model-registry/discovery.js.map +0 -1
  196. package/dist/src/agents/model-registry/parsers.d.ts.map +0 -1
  197. package/dist/src/agents/model-registry/parsers.js.map +0 -1
  198. package/dist/src/agents/model-registry/runner.d.ts.map +0 -1
  199. package/dist/src/agents/model-registry/runner.js.map +0 -1
  200. package/dist/src/agents/model-registry/service.d.ts.map +0 -1
  201. package/dist/src/agents/model-registry/service.js.map +0 -1
  202. package/dist/src/agents/model-registry/types.d.ts.map +0 -1
  203. package/dist/src/agents/model-registry/types.js.map +0 -1
  204. package/dist/src/agents/model-registry.d.ts.map +0 -1
  205. package/dist/src/agents/model-registry.js.map +0 -1
  206. package/dist/src/agents/openclaw.d.ts.map +0 -1
  207. package/dist/src/agents/openclaw.js.map +0 -1
  208. package/dist/src/agents/pi.d.ts.map +0 -1
  209. package/dist/src/agents/pi.js.map +0 -1
  210. package/dist/src/commands/agent.d.ts.map +0 -1
  211. package/dist/src/commands/agent.js.map +0 -1
  212. package/dist/src/commands/daemon.d.ts.map +0 -1
  213. package/dist/src/commands/daemon.js.map +0 -1
  214. package/dist/src/commands/pair-qr.d.ts.map +0 -1
  215. package/dist/src/commands/pair-qr.js.map +0 -1
  216. package/dist/src/commands/pair.d.ts.map +0 -1
  217. package/dist/src/commands/pair.js.map +0 -1
  218. package/dist/src/commands/upgrade.d.ts.map +0 -1
  219. package/dist/src/commands/upgrade.js.map +0 -1
  220. package/dist/src/config/index.d.ts.map +0 -1
  221. package/dist/src/config/index.js.map +0 -1
  222. package/dist/src/fs/handler.d.ts.map +0 -1
  223. package/dist/src/fs/handler.js.map +0 -1
  224. package/dist/src/fs/multimodal.d.ts +0 -5
  225. package/dist/src/fs/multimodal.d.ts.map +0 -1
  226. package/dist/src/fs/multimodal.js +0 -39
  227. package/dist/src/fs/multimodal.js.map +0 -1
  228. package/dist/src/fs/security.d.ts.map +0 -1
  229. package/dist/src/fs/security.js.map +0 -1
  230. package/dist/src/index.d.ts.map +0 -1
  231. package/dist/src/index.js.map +0 -1
  232. package/dist/src/log-reporter.d.ts.map +0 -1
  233. package/dist/src/log-reporter.js.map +0 -1
  234. package/dist/src/native-fusion/parsers.d.ts.map +0 -1
  235. package/dist/src/native-fusion/parsers.js.map +0 -1
  236. package/dist/src/native-fusion/service.d.ts.map +0 -1
  237. package/dist/src/native-fusion/service.js.map +0 -1
  238. package/dist/src/native-fusion/state.d.ts.map +0 -1
  239. package/dist/src/native-fusion/state.js.map +0 -1
  240. package/dist/src/native-fusion/types.d.ts.map +0 -1
  241. package/dist/src/native-fusion/types.js.map +0 -1
  242. package/dist/src/native-sync/discover.d.ts +0 -6
  243. package/dist/src/native-sync/discover.d.ts.map +0 -1
  244. package/dist/src/native-sync/discover.js +0 -69
  245. package/dist/src/native-sync/discover.js.map +0 -1
  246. package/dist/src/native-sync/parsers.d.ts +0 -3
  247. package/dist/src/native-sync/parsers.d.ts.map +0 -1
  248. package/dist/src/native-sync/parsers.js +0 -373
  249. package/dist/src/native-sync/parsers.js.map +0 -1
  250. package/dist/src/native-sync/service.d.ts +0 -16
  251. package/dist/src/native-sync/service.d.ts.map +0 -1
  252. package/dist/src/native-sync/service.js +0 -95
  253. package/dist/src/native-sync/service.js.map +0 -1
  254. package/dist/src/native-sync/state.d.ts +0 -6
  255. package/dist/src/native-sync/state.d.ts.map +0 -1
  256. package/dist/src/native-sync/state.js +0 -34
  257. package/dist/src/native-sync/state.js.map +0 -1
  258. package/dist/src/native-sync/types.d.ts +0 -23
  259. package/dist/src/native-sync/types.d.ts.map +0 -1
  260. package/dist/src/native-sync/types.js +0 -4
  261. package/dist/src/native-sync/types.js.map +0 -1
  262. package/dist/src/region.d.ts.map +0 -1
  263. package/dist/src/region.js.map +0 -1
  264. package/dist/src/relay/client.d.ts.map +0 -1
  265. package/dist/src/relay/client.js.map +0 -1
  266. package/dist/src/session/handlers/agents.d.ts.map +0 -1
  267. package/dist/src/session/handlers/agents.js.map +0 -1
  268. package/dist/src/session/handlers/chat.d.ts.map +0 -1
  269. package/dist/src/session/handlers/chat.js.map +0 -1
  270. package/dist/src/session/handlers/control.d.ts.map +0 -1
  271. package/dist/src/session/handlers/control.js.map +0 -1
  272. package/dist/src/session/handlers/fs.d.ts.map +0 -1
  273. package/dist/src/session/handlers/fs.js.map +0 -1
  274. package/dist/src/session/handlers/queue.d.ts +0 -4
  275. package/dist/src/session/handlers/queue.d.ts.map +0 -1
  276. package/dist/src/session/handlers/queue.js +0 -66
  277. package/dist/src/session/handlers/queue.js.map +0 -1
  278. package/dist/src/session/manager.d.ts.map +0 -1
  279. package/dist/src/session/manager.js.map +0 -1
  280. package/dist/src/session/store.d.ts.map +0 -1
  281. package/dist/src/session/store.js.map +0 -1
  282. package/dist/src/session/types.d.ts.map +0 -1
  283. package/dist/src/session/types.js.map +0 -1
  284. package/dist/src/upgrade/engine.d.ts.map +0 -1
  285. package/dist/src/upgrade/engine.js.map +0 -1
  286. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,685 +0,0 @@
1
- // @covers src/session/manager.ts
2
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
3
- import { EventEmitter } from 'node:events';
4
- import fs from 'node:fs';
5
- import os from 'node:os';
6
- vi.mock('node:fs', async (importOriginal) => {
7
- const actual = await importOriginal();
8
- return {
9
- ...actual,
10
- statSync: vi.fn((_p) => ({ size: 1024 * 100 })), // default: 100 KB
11
- mkdirSync: vi.fn(),
12
- writeFileSync: vi.fn(),
13
- readFileSync: vi.fn(() => Buffer.from('')),
14
- readdirSync: vi.fn(() => []),
15
- };
16
- });
17
- const mockAdapter = () => {
18
- const adapter = Object.assign(new EventEmitter(), {
19
- type: 'claude',
20
- start: vi.fn(async () => { }),
21
- send: vi.fn(async (_text, _modelId) => { }),
22
- resume: vi.fn(async () => { }),
23
- stop: vi.fn(async () => { }),
24
- });
25
- return adapter;
26
- };
27
- const { mockCreateAgent } = vi.hoisted(() => ({
28
- mockCreateAgent: vi.fn(),
29
- }));
30
- const { mockLookupClaudeTranscriptCwd } = vi.hoisted(() => ({
31
- mockLookupClaudeTranscriptCwd: vi.fn(),
32
- }));
33
- vi.mock('../agents/adapter.js', async (importOriginal) => {
34
- const orig = await importOriginal();
35
- return { ...orig, createAgent: mockCreateAgent };
36
- });
37
- vi.mock('../agents/claude.js', () => ({}));
38
- vi.mock('../agents/codex.js', () => ({}));
39
- vi.mock('../agents/gemini.js', () => ({}));
40
- vi.mock('../agents/cursor.js', () => ({}));
41
- vi.mock('../agents/openclaw.js', () => ({}));
42
- vi.mock('../agents/pi.js', () => ({}));
43
- vi.mock('../native-fusion/parsers.js', () => ({
44
- lookupClaudeTranscriptCwd: mockLookupClaudeTranscriptCwd,
45
- }));
46
- import { SessionManager } from '../session/manager.js';
47
- function createMockClient() {
48
- return {
49
- sendRes: vi.fn(),
50
- sendEvent: vi.fn(),
51
- sendAgentEvent: vi.fn(),
52
- };
53
- }
54
- describe('SessionManager', () => {
55
- let client;
56
- let manager;
57
- beforeEach(() => {
58
- vi.clearAllMocks();
59
- mockLookupClaudeTranscriptCwd.mockReturnValue(null);
60
- client = createMockClient();
61
- manager = new SessionManager(client);
62
- });
63
- afterEach(() => {
64
- vi.restoreAllMocks();
65
- });
66
- describe('agent events include sessionId', () => {
67
- it('includes sessionId in agentEvent payloads', async () => {
68
- const adapter = mockAdapter();
69
- mockCreateAgent.mockReturnValue(adapter);
70
- await manager.handleReq({
71
- type: 'req',
72
- id: 'r1',
73
- method: 'chat.send',
74
- params: { sessionId: 'sess-abc', text: 'hello', agentType: 'claude', workDir: '/tmp' },
75
- });
76
- // Simulate adapter emitting text and then ending the run.
77
- const agentEvent = { state: 'delta', runId: 'run1', seq: 0, text: 'Hi' };
78
- adapter.emit('agentEvent', agentEvent);
79
- adapter.emit('agentEvent', { state: 'final', runId: 'run1', seq: 1 });
80
- expect(client.sendAgentEvent).toHaveBeenCalledWith(expect.objectContaining({
81
- type: 'event',
82
- event: 'agent',
83
- id: 'agent-evt-run1-0',
84
- payload: expect.objectContaining({
85
- state: 'delta',
86
- sessionId: 'sess-abc',
87
- text: 'Hi',
88
- }),
89
- }));
90
- });
91
- it('aggregates consecutive text deltas before sending them to the server', async () => {
92
- const adapter = mockAdapter();
93
- mockCreateAgent.mockReturnValue(adapter);
94
- await manager.handleReq({
95
- type: 'req',
96
- id: 'r1',
97
- method: 'chat.send',
98
- params: { sessionId: 'sess-abc', text: 'hello', agentType: 'claude', workDir: '/tmp' },
99
- });
100
- adapter.emit('agentEvent', { state: 'delta', runId: 'run1', seq: 0, text: 'Hello' });
101
- adapter.emit('agentEvent', { state: 'delta', runId: 'run1', seq: 1, text: ' world' });
102
- expect(client.sendAgentEvent).not.toHaveBeenCalled();
103
- adapter.emit('agentEvent', { state: 'final', runId: 'run1', seq: 2 });
104
- expect(client.sendAgentEvent).toHaveBeenCalledWith(expect.objectContaining({
105
- type: 'event',
106
- event: 'agent',
107
- id: 'agent-evt-run1-1',
108
- payload: expect.objectContaining({
109
- state: 'delta',
110
- sessionId: 'sess-abc',
111
- text: 'Hello world',
112
- }),
113
- }));
114
- expect(client.sendAgentEvent).toHaveBeenCalledWith(expect.objectContaining({
115
- id: 'agent-evt-run1-2',
116
- payload: expect.objectContaining({
117
- state: 'final',
118
- sessionId: 'sess-abc',
119
- }),
120
- }));
121
- });
122
- it('flushes aggregated text before forwarding a tool call', async () => {
123
- const adapter = mockAdapter();
124
- mockCreateAgent.mockReturnValue(adapter);
125
- await manager.handleReq({
126
- type: 'req',
127
- id: 'r1',
128
- method: 'chat.send',
129
- params: { sessionId: 'sess-tool', text: 'hello', agentType: 'claude', workDir: '/tmp' },
130
- });
131
- adapter.emit('agentEvent', { state: 'delta', runId: 'run1', seq: 0, text: 'Before ' });
132
- adapter.emit('agentEvent', { state: 'delta', runId: 'run1', seq: 1, text: 'tool' });
133
- adapter.emit('agentEvent', { state: 'tool-call', runId: 'run1', seq: 2, name: 'bash', args: { command: 'ls' } });
134
- expect(client.sendAgentEvent).toHaveBeenNthCalledWith(1, expect.objectContaining({
135
- id: 'agent-evt-run1-1',
136
- payload: expect.objectContaining({
137
- state: 'delta',
138
- sessionId: 'sess-tool',
139
- text: 'Before tool',
140
- }),
141
- }));
142
- expect(client.sendAgentEvent).toHaveBeenNthCalledWith(2, expect.objectContaining({
143
- id: 'agent-evt-run1-2',
144
- payload: expect.objectContaining({
145
- state: 'tool-call',
146
- sessionId: 'sess-tool',
147
- name: 'bash',
148
- }),
149
- }));
150
- });
151
- it('includes sessionId in error events', async () => {
152
- const adapter = mockAdapter();
153
- mockCreateAgent.mockReturnValue(adapter);
154
- await manager.handleReq({
155
- type: 'req',
156
- id: 'r1',
157
- method: 'chat.send',
158
- params: { sessionId: 'sess-xyz', text: 'hi', agentType: 'claude', workDir: '/tmp' },
159
- });
160
- adapter.emit('error', new Error('CLI crashed'));
161
- expect(client.sendEvent).toHaveBeenCalledWith(expect.objectContaining({
162
- payload: expect.objectContaining({
163
- state: 'error',
164
- sessionId: 'sess-xyz',
165
- message: 'CLI crashed',
166
- }),
167
- }));
168
- });
169
- it('events from different sessions have correct sessionId', async () => {
170
- const adapterA = mockAdapter();
171
- const adapterB = mockAdapter();
172
- mockCreateAgent.mockReturnValueOnce(adapterA).mockReturnValueOnce(adapterB);
173
- await manager.handleReq({
174
- type: 'req', id: 'r1', method: 'chat.send',
175
- params: { sessionId: 'sess-A', text: 'hi', agentType: 'claude', workDir: '/tmp' },
176
- });
177
- await manager.handleReq({
178
- type: 'req', id: 'r2', method: 'chat.send',
179
- params: { sessionId: 'sess-B', text: 'yo', agentType: 'codex', workDir: '/tmp' },
180
- });
181
- adapterA.emit('agentEvent', { state: 'delta', runId: 'rA', seq: 0, text: 'from A' });
182
- adapterB.emit('agentEvent', { state: 'delta', runId: 'rB', seq: 0, text: 'from B' });
183
- adapterA.emit('agentEvent', { state: 'final', runId: 'rA', seq: 1 });
184
- adapterB.emit('agentEvent', { state: 'final', runId: 'rB', seq: 1 });
185
- const calls = client.sendAgentEvent.mock.calls.map((c) => c[0].payload);
186
- const aEvent = calls.find((p) => p.text === 'from A');
187
- const bEvent = calls.find((p) => p.text === 'from B');
188
- expect(aEvent?.sessionId).toBe('sess-A');
189
- expect(bEvent?.sessionId).toBe('sess-B');
190
- });
191
- });
192
- describe('attachments', () => {
193
- it('无附件时直接传递原始文本', async () => {
194
- const adapter = mockAdapter();
195
- mockCreateAgent.mockReturnValue(adapter);
196
- await manager.handleReq({
197
- type: 'req', id: 'r1', method: 'chat.send',
198
- params: { sessionId: 'sess-1', text: 'hello', agentType: 'claude', workDir: '/tmp' },
199
- });
200
- expect(adapter.send).toHaveBeenCalledWith('hello', undefined);
201
- });
202
- it('有附件时在文本前注入 [附件] 路径行', async () => {
203
- const adapter = mockAdapter();
204
- mockCreateAgent.mockReturnValue(adapter);
205
- await manager.handleReq({
206
- type: 'req', id: 'r1', method: 'chat.send',
207
- params: {
208
- sessionId: 'sess-2',
209
- text: '这是什么图?',
210
- agentType: 'claude',
211
- workDir: '/tmp',
212
- attachments: [{ path: '/tmp/.uploads/shot.png', name: 'shot.png', mimeType: 'image/png' }],
213
- },
214
- });
215
- const sentText = adapter.send.mock.calls[0][0];
216
- expect(sentText).toBe('这是什么图?');
217
- });
218
- it('附件参数不再影响发送文本', async () => {
219
- const adapter = mockAdapter();
220
- mockCreateAgent.mockReturnValue(adapter);
221
- await manager.handleReq({
222
- type: 'req', id: 'r1', method: 'chat.send',
223
- params: {
224
- sessionId: 'sess-3',
225
- text: '帮我看看',
226
- agentType: 'claude',
227
- workDir: '/tmp',
228
- attachments: [
229
- { path: '/tmp/a.png', name: 'a.png', mimeType: 'image/png' },
230
- { path: '/tmp/b.json', name: 'b.json', mimeType: 'application/json' },
231
- ],
232
- },
233
- });
234
- const sentText = adapter.send.mock.calls[0][0];
235
- expect(sentText).toBe('帮我看看');
236
- });
237
- });
238
- describe('fs.ls roots navigation', () => {
239
- it('returns Windows drive roots for __roots__', async () => {
240
- vi.spyOn(os, 'platform').mockReturnValue('win32');
241
- vi.spyOn(fs, 'existsSync')
242
- .mockImplementation((target) => target === 'C:\\' || target === 'D:\\');
243
- await manager.handleReq({
244
- type: 'req',
245
- id: 'fs-roots',
246
- method: 'fs.ls',
247
- params: { path: '__roots__' },
248
- });
249
- expect(client.sendRes).toHaveBeenCalledWith({
250
- type: 'res',
251
- id: 'fs-roots',
252
- ok: true,
253
- payload: {
254
- path: '__roots__',
255
- entries: [
256
- { name: 'C:\\', path: 'C:\\', isDir: true },
257
- { name: 'D:\\', path: 'D:\\', isDir: true },
258
- ],
259
- },
260
- });
261
- });
262
- });
263
- describe('agentSessionId persistence', () => {
264
- it('passes agentSessionId from chat.send params to adapter.start', async () => {
265
- const adapter = mockAdapter();
266
- mockCreateAgent.mockReturnValue(adapter);
267
- await manager.handleReq({
268
- type: 'req', id: 'r1', method: 'chat.send',
269
- params: {
270
- sessionId: 'sess-resume',
271
- text: 'hello',
272
- agentType: 'claude',
273
- workDir: '/tmp',
274
- agentSessionId: 'claude-sid-123',
275
- },
276
- });
277
- expect(adapter.start).toHaveBeenCalledWith('sess-resume', expect.any(String), 'claude-sid-123');
278
- });
279
- it('emits session.update when agent reports agentSessionId on final', async () => {
280
- const adapter = mockAdapter();
281
- mockCreateAgent.mockReturnValue(adapter);
282
- await manager.handleReq({
283
- type: 'req', id: 'r1', method: 'chat.send',
284
- params: { sessionId: 'sess-new', text: 'hi', agentType: 'claude', workDir: '/tmp' },
285
- });
286
- const finalEvent = {
287
- state: 'final',
288
- runId: 'run1',
289
- seq: 1,
290
- agentSessionId: 'claude-sid-456',
291
- };
292
- adapter.emit('agentEvent', finalEvent);
293
- const sessionUpdateCall = client.sendEvent.mock.calls.find((c) => c[0].event === 'session.update');
294
- expect(sessionUpdateCall).toBeDefined();
295
- expect(sessionUpdateCall[0]).toEqual(expect.objectContaining({
296
- type: 'event',
297
- event: 'session.update',
298
- payload: {
299
- session: {
300
- id: 'sess-new',
301
- agentType: 'claude',
302
- agentSessionId: 'claude-sid-456',
303
- },
304
- },
305
- }));
306
- });
307
- it('does not emit session.update when final has no agentSessionId', async () => {
308
- const adapter = mockAdapter();
309
- mockCreateAgent.mockReturnValue(adapter);
310
- await manager.handleReq({
311
- type: 'req', id: 'r1', method: 'chat.send',
312
- params: { sessionId: 'sess-no-sid', text: 'hi', agentType: 'codex', workDir: '/tmp' },
313
- });
314
- adapter.emit('agentEvent', { state: 'final', runId: 'run1', seq: 1 });
315
- const sessionUpdateCall = client.sendEvent.mock.calls.find((c) => c[0].event === 'session.update');
316
- expect(sessionUpdateCall).toBeUndefined();
317
- });
318
- it('reuses existing adapter (with agentSessionId) for same session', async () => {
319
- const adapter = mockAdapter();
320
- mockCreateAgent.mockReturnValue(adapter);
321
- await manager.handleReq({
322
- type: 'req', id: 'r1', method: 'chat.send',
323
- params: { sessionId: 'sess-reuse', text: 'first', agentType: 'claude', workDir: '/tmp' },
324
- });
325
- await manager.handleReq({
326
- type: 'req', id: 'r2', method: 'chat.send',
327
- params: { sessionId: 'sess-reuse', text: 'second', agentType: 'claude', workDir: '/tmp' },
328
- });
329
- expect(mockCreateAgent).toHaveBeenCalledTimes(1);
330
- expect(adapter.send).toHaveBeenCalledTimes(2);
331
- expect(adapter.send).toHaveBeenNthCalledWith(1, 'first', undefined);
332
- expect(adapter.send).toHaveBeenNthCalledWith(2, 'second', undefined);
333
- });
334
- it('resumes an existing adapter when a newer agentSessionId arrives', async () => {
335
- const adapter = mockAdapter();
336
- mockCreateAgent.mockReturnValue(adapter);
337
- await manager.handleReq({
338
- type: 'req',
339
- id: 'r1',
340
- method: 'chat.send',
341
- params: {
342
- sessionId: 'sess-resume-existing',
343
- text: 'first',
344
- agentType: 'claude',
345
- workDir: '/tmp',
346
- agentSessionId: 'sid-1',
347
- },
348
- });
349
- await manager.handleReq({
350
- type: 'req',
351
- id: 'r2',
352
- method: 'chat.send',
353
- params: {
354
- sessionId: 'sess-resume-existing',
355
- text: 'second',
356
- agentType: 'claude',
357
- workDir: '/tmp',
358
- agentSessionId: 'sid-2',
359
- },
360
- });
361
- expect(adapter.resume).toHaveBeenCalledWith('sid-2');
362
- expect(adapter.send).toHaveBeenNthCalledWith(2, 'second', undefined);
363
- });
364
- it('rebuilds the cached adapter when the incoming session metadata drifts', async () => {
365
- const firstAdapter = mockAdapter();
366
- const secondAdapter = mockAdapter();
367
- secondAdapter.type = 'codex';
368
- mockCreateAgent.mockReturnValueOnce(firstAdapter).mockReturnValueOnce(secondAdapter);
369
- await manager.handleReq({
370
- type: 'req',
371
- id: 'r1',
372
- method: 'chat.send',
373
- params: {
374
- sessionId: 'sess-drift',
375
- text: 'first',
376
- agentType: 'claude',
377
- workDir: '/tmp/original',
378
- },
379
- });
380
- await manager.handleReq({
381
- type: 'req',
382
- id: 'r2',
383
- method: 'chat.send',
384
- params: {
385
- sessionId: 'sess-drift',
386
- text: 'second',
387
- agentType: 'codex',
388
- workDir: '/tmp/next',
389
- agentSessionId: 'thread-2',
390
- },
391
- });
392
- expect(firstAdapter.stop).toHaveBeenCalledTimes(1);
393
- expect(secondAdapter.start).toHaveBeenCalledWith('sess-drift', '/tmp/next', 'thread-2');
394
- expect(secondAdapter.send).toHaveBeenCalledWith('second', undefined);
395
- });
396
- it('passes modelId to adapter.send when provided', async () => {
397
- const adapter = mockAdapter();
398
- mockCreateAgent.mockReturnValue(adapter);
399
- await manager.handleReq({
400
- type: 'req',
401
- id: 'r1',
402
- method: 'chat.send',
403
- params: {
404
- sessionId: 'sess-model',
405
- text: 'hello',
406
- agentType: 'claude',
407
- workDir: '/tmp',
408
- modelId: 'sonnet',
409
- },
410
- });
411
- expect(adapter.send).toHaveBeenCalledWith('hello', 'sonnet');
412
- });
413
- it('repairs claude imported workDir from transcript cwd before starting the adapter', async () => {
414
- const adapter = mockAdapter();
415
- mockCreateAgent.mockReturnValue(adapter);
416
- mockLookupClaudeTranscriptCwd.mockReturnValue('/Users/lichen/Documents/code/projects/shennian');
417
- await manager.handleReq({
418
- type: 'req',
419
- id: 'r1',
420
- method: 'chat.send',
421
- params: {
422
- sessionId: 'sess-imported',
423
- text: 'continue',
424
- agentType: 'claude',
425
- workDir: '-Users-lichen-Documents-code-projects-shennian',
426
- agentSessionId: 'claude-sid-imported',
427
- },
428
- });
429
- expect(adapter.start).toHaveBeenCalledWith('sess-imported', '/Users/lichen/Documents/code/projects/shennian', 'claude-sid-imported');
430
- expect(adapter.send).toHaveBeenCalledWith('continue', undefined);
431
- });
432
- });
433
- describe('codex resume flow', () => {
434
- it('passes agentSessionId to codex adapter via start()', async () => {
435
- const adapter = mockAdapter();
436
- adapter.type = 'codex';
437
- mockCreateAgent.mockReturnValue(adapter);
438
- await manager.handleReq({
439
- type: 'req', id: 'r1', method: 'chat.send',
440
- params: {
441
- sessionId: 'sess-codex',
442
- text: 'fix bug',
443
- agentType: 'codex',
444
- workDir: '/tmp',
445
- agentSessionId: 'thread-abc-123',
446
- },
447
- });
448
- expect(adapter.start).toHaveBeenCalledWith('sess-codex', expect.any(String), 'thread-abc-123');
449
- });
450
- it('persists codex agentSessionId from final event', async () => {
451
- const adapter = mockAdapter();
452
- adapter.type = 'codex';
453
- mockCreateAgent.mockReturnValue(adapter);
454
- await manager.handleReq({
455
- type: 'req', id: 'r1', method: 'chat.send',
456
- params: { sessionId: 'sess-codex-new', text: 'hello', agentType: 'codex', workDir: '/tmp' },
457
- });
458
- adapter.emit('agentEvent', {
459
- state: 'final', runId: 'run1', seq: 1,
460
- agentSessionId: 'thread-xyz-789',
461
- });
462
- const updateCall = client.sendEvent.mock.calls.find((c) => c[0].event === 'session.update');
463
- expect(updateCall).toBeDefined();
464
- expect(updateCall[0]).toEqual(expect.objectContaining({
465
- payload: {
466
- session: {
467
- id: 'sess-codex-new',
468
- agentType: 'codex',
469
- agentSessionId: 'thread-xyz-789',
470
- },
471
- },
472
- }));
473
- });
474
- });
475
- describe('custom agent agentSessionId', () => {
476
- it('persists custom agent session ID from final event', async () => {
477
- const adapter = mockAdapter();
478
- adapter.type = 'custom:my-agent';
479
- mockCreateAgent.mockReturnValue(adapter);
480
- await manager.handleReq({
481
- type: 'req', id: 'r1', method: 'chat.send',
482
- params: { sessionId: 'sess-custom', text: 'hello', agentType: 'custom:my-agent', workDir: '/tmp' },
483
- });
484
- adapter.emit('agentEvent', {
485
- state: 'final', runId: 'run1', seq: 1,
486
- agentSessionId: 'custom-session-456',
487
- });
488
- const updateCall = client.sendEvent.mock.calls.find((c) => c[0].event === 'session.update');
489
- expect(updateCall).toBeDefined();
490
- expect(updateCall[0]).toEqual(expect.objectContaining({
491
- payload: {
492
- session: {
493
- id: 'sess-custom',
494
- agentType: 'custom:my-agent',
495
- agentSessionId: 'custom-session-456',
496
- },
497
- },
498
- }));
499
- });
500
- });
501
- describe('error handling', () => {
502
- it('waits for adapter.send to resolve before acknowledging chat.send success', async () => {
503
- const adapter = mockAdapter();
504
- let resolveSend = null;
505
- adapter.send.mockReturnValue(new Promise((resolve) => {
506
- resolveSend = resolve;
507
- }));
508
- mockCreateAgent.mockReturnValue(adapter);
509
- const sendPromise = manager.handleReq({
510
- type: 'req', id: 'r-wait', method: 'chat.send',
511
- params: { sessionId: 'sess-wait', text: 'hi', agentType: 'claude', workDir: '/tmp' },
512
- });
513
- await Promise.resolve();
514
- expect(client.sendRes).not.toHaveBeenCalled();
515
- expect(resolveSend).toBeTypeOf('function');
516
- resolveSend();
517
- await sendPromise;
518
- expect(client.sendRes).toHaveBeenCalledWith(expect.objectContaining({
519
- type: 'res',
520
- id: 'r-wait',
521
- ok: true,
522
- }));
523
- });
524
- it('sends error with sessionId when agent not found', async () => {
525
- mockCreateAgent.mockReturnValue(null);
526
- await manager.handleReq({
527
- type: 'req', id: 'r1', method: 'chat.send',
528
- params: { sessionId: 'sess-1', text: 'hi', agentType: 'unknown', workDir: '/tmp' },
529
- });
530
- expect(client.sendEvent).toHaveBeenCalledWith(expect.objectContaining({
531
- payload: expect.objectContaining({
532
- state: 'error',
533
- sessionId: 'sess-1',
534
- }),
535
- }));
536
- expect(client.sendRes).toHaveBeenCalledWith(expect.objectContaining({
537
- type: 'res',
538
- id: 'r1',
539
- ok: false,
540
- error: 'Unsupported agent: unknown',
541
- }));
542
- });
543
- it('sends error with sessionId when adapter.start fails', async () => {
544
- const adapter = mockAdapter();
545
- adapter.start.mockRejectedValue(new Error('start failed'));
546
- mockCreateAgent.mockReturnValue(adapter);
547
- await manager.handleReq({
548
- type: 'req', id: 'r1', method: 'chat.send',
549
- params: { sessionId: 'sess-2', text: 'hi', agentType: 'claude', workDir: '/tmp' },
550
- });
551
- expect(client.sendEvent).toHaveBeenCalledWith(expect.objectContaining({
552
- payload: expect.objectContaining({
553
- state: 'error',
554
- sessionId: 'sess-2',
555
- message: expect.stringContaining('start failed'),
556
- }),
557
- }));
558
- expect(client.sendRes).toHaveBeenCalledWith(expect.objectContaining({
559
- type: 'res',
560
- id: 'r1',
561
- ok: false,
562
- error: expect.stringContaining('start failed'),
563
- }));
564
- });
565
- it('cleans up session and sends error when adapter.send fails', async () => {
566
- const adapter = mockAdapter();
567
- adapter.send.mockRejectedValue(new Error('send failed'));
568
- mockCreateAgent.mockReturnValue(adapter);
569
- await manager.handleReq({
570
- type: 'req', id: 'r1', method: 'chat.send',
571
- params: { sessionId: 'sess-3', text: 'hi', agentType: 'claude', workDir: '/tmp' },
572
- });
573
- expect(client.sendEvent).toHaveBeenCalledWith(expect.objectContaining({
574
- payload: expect.objectContaining({
575
- state: 'error',
576
- sessionId: 'sess-3',
577
- message: expect.stringContaining('send failed'),
578
- }),
579
- }));
580
- expect(client.sendRes).toHaveBeenCalledWith(expect.objectContaining({
581
- type: 'res',
582
- id: 'r1',
583
- ok: false,
584
- error: expect.stringContaining('send failed'),
585
- }));
586
- });
587
- it('retries the same req.id after a failed send instead of silently deduping it', async () => {
588
- const firstAdapter = mockAdapter();
589
- firstAdapter.send.mockRejectedValueOnce(new Error('send failed'));
590
- const secondAdapter = mockAdapter();
591
- mockCreateAgent.mockReturnValueOnce(firstAdapter).mockReturnValueOnce(secondAdapter);
592
- const frame = {
593
- type: 'req',
594
- id: 'req-retry',
595
- method: 'chat.send',
596
- params: { sessionId: 'sess-retry', text: 'hi', agentType: 'claude', workDir: '/tmp' },
597
- };
598
- await manager.handleReq(frame);
599
- await manager.handleReq(frame);
600
- expect(mockCreateAgent).toHaveBeenCalledTimes(2);
601
- expect(firstAdapter.stop).toHaveBeenCalledTimes(1);
602
- expect(secondAdapter.send).toHaveBeenCalledWith('hi', undefined);
603
- });
604
- });
605
- describe('chat.abort', () => {
606
- it('emits a synthetic aborted event for the active run after stop succeeds', async () => {
607
- const adapter = mockAdapter();
608
- mockCreateAgent.mockReturnValue(adapter);
609
- await manager.handleReq({
610
- type: 'req',
611
- id: 'send-1',
612
- method: 'chat.send',
613
- params: { sessionId: 'sess-abort', text: 'hi', agentType: 'claude', workDir: '/tmp' },
614
- });
615
- adapter.emit('agentEvent', { state: 'delta', runId: 'run-abort', seq: 0, text: 'working' });
616
- await manager.handleReq({
617
- type: 'req',
618
- id: 'abort-1',
619
- method: 'chat.abort',
620
- params: { sessionId: 'sess-abort' },
621
- });
622
- expect(adapter.stop).toHaveBeenCalledTimes(1);
623
- expect(client.sendAgentEvent).toHaveBeenCalledWith(expect.objectContaining({
624
- type: 'event',
625
- event: 'agent',
626
- id: 'agent-evt-run-abort-1',
627
- seq: 1,
628
- payload: expect.objectContaining({
629
- state: 'aborted',
630
- sessionId: 'sess-abort',
631
- runId: 'run-abort',
632
- seq: 1,
633
- }),
634
- }));
635
- expect(client.sendRes).toHaveBeenCalledWith(expect.objectContaining({ type: 'res', id: 'abort-1', ok: true }));
636
- });
637
- });
638
- describe('session eviction', () => {
639
- it('evicts oldest idle session when exceeding MAX_SESSIONS', async () => {
640
- const adapters = [];
641
- mockCreateAgent.mockImplementation(() => {
642
- const a = mockAdapter();
643
- adapters.push(a);
644
- return a;
645
- });
646
- for (let i = 0; i < 50; i++) {
647
- await manager.handleReq({
648
- type: 'req', id: `r-${i}`, method: 'chat.send',
649
- params: { sessionId: `sess-${i}`, text: 'hi', agentType: 'claude', workDir: '/tmp' },
650
- });
651
- }
652
- expect(adapters).toHaveLength(50);
653
- expect(adapters[0].stop).not.toHaveBeenCalled();
654
- await manager.handleReq({
655
- type: 'req', id: 'r-51', method: 'chat.send',
656
- params: { sessionId: 'sess-new', text: 'hi', agentType: 'claude', workDir: '/tmp' },
657
- });
658
- expect(adapters[0].stop).toHaveBeenCalled();
659
- expect(adapters).toHaveLength(51);
660
- });
661
- it('does not evict when reusing existing session', async () => {
662
- const adapters = [];
663
- mockCreateAgent.mockImplementation(() => {
664
- const a = mockAdapter();
665
- adapters.push(a);
666
- return a;
667
- });
668
- for (let i = 0; i < 50; i++) {
669
- await manager.handleReq({
670
- type: 'req', id: `r-${i}`, method: 'chat.send',
671
- params: { sessionId: `sess-${i}`, text: 'hi', agentType: 'claude', workDir: '/tmp' },
672
- });
673
- }
674
- await manager.handleReq({
675
- type: 'req', id: 'r-reuse', method: 'chat.send',
676
- params: { sessionId: 'sess-0', text: 'second msg', agentType: 'claude', workDir: '/tmp' },
677
- });
678
- expect(adapters).toHaveLength(50);
679
- for (const a of adapters) {
680
- expect(a.stop).not.toHaveBeenCalled();
681
- }
682
- });
683
- });
684
- });
685
- //# sourceMappingURL=session-manager.test.js.map