shennian 0.2.4 → 0.2.6

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/package.json +3 -2
  2. package/dist/bin/shennian.d.ts +0 -3
  3. package/dist/bin/shennian.d.ts.map +0 -1
  4. package/dist/bin/shennian.js +0 -3
  5. package/dist/bin/shennian.js.map +0 -1
  6. package/dist/src/__experiments__/probe-debug.d.ts +0 -2
  7. package/dist/src/__experiments__/probe-debug.d.ts.map +0 -1
  8. package/dist/src/__experiments__/probe-debug.js +0 -66
  9. package/dist/src/__experiments__/probe-debug.js.map +0 -1
  10. package/dist/src/__experiments__/probe-final-benchmark.d.ts +0 -3
  11. package/dist/src/__experiments__/probe-final-benchmark.d.ts.map +0 -1
  12. package/dist/src/__experiments__/probe-final-benchmark.js +0 -234
  13. package/dist/src/__experiments__/probe-final-benchmark.js.map +0 -1
  14. package/dist/src/__experiments__/probe-models-final.d.ts +0 -19
  15. package/dist/src/__experiments__/probe-models-final.d.ts.map +0 -1
  16. package/dist/src/__experiments__/probe-models-final.js +0 -250
  17. package/dist/src/__experiments__/probe-models-final.js.map +0 -1
  18. package/dist/src/__experiments__/probe-models.d.ts +0 -7
  19. package/dist/src/__experiments__/probe-models.d.ts.map +0 -1
  20. package/dist/src/__experiments__/probe-models.js +0 -251
  21. package/dist/src/__experiments__/probe-models.js.map +0 -1
  22. package/dist/src/__tests__/agents-e2e.d.ts +0 -21
  23. package/dist/src/__tests__/agents-e2e.d.ts.map +0 -1
  24. package/dist/src/__tests__/agents-e2e.js +0 -155
  25. package/dist/src/__tests__/agents-e2e.js.map +0 -1
  26. package/dist/src/__tests__/claude-adapter.test.d.ts +0 -2
  27. package/dist/src/__tests__/claude-adapter.test.d.ts.map +0 -1
  28. package/dist/src/__tests__/claude-adapter.test.js +0 -75
  29. package/dist/src/__tests__/claude-adapter.test.js.map +0 -1
  30. package/dist/src/__tests__/codex-adapter.test.d.ts +0 -2
  31. package/dist/src/__tests__/codex-adapter.test.d.ts.map +0 -1
  32. package/dist/src/__tests__/codex-adapter.test.js +0 -281
  33. package/dist/src/__tests__/codex-adapter.test.js.map +0 -1
  34. package/dist/src/__tests__/config.test.d.ts +0 -2
  35. package/dist/src/__tests__/config.test.d.ts.map +0 -1
  36. package/dist/src/__tests__/config.test.js +0 -60
  37. package/dist/src/__tests__/config.test.js.map +0 -1
  38. package/dist/src/__tests__/cursor-adapter.test.d.ts +0 -2
  39. package/dist/src/__tests__/cursor-adapter.test.d.ts.map +0 -1
  40. package/dist/src/__tests__/cursor-adapter.test.js +0 -69
  41. package/dist/src/__tests__/cursor-adapter.test.js.map +0 -1
  42. package/dist/src/__tests__/custom-agent-flow.test.d.ts +0 -2
  43. package/dist/src/__tests__/custom-agent-flow.test.d.ts.map +0 -1
  44. package/dist/src/__tests__/custom-agent-flow.test.js +0 -244
  45. package/dist/src/__tests__/custom-agent-flow.test.js.map +0 -1
  46. package/dist/src/__tests__/daemon-autostart.test.d.ts +0 -2
  47. package/dist/src/__tests__/daemon-autostart.test.d.ts.map +0 -1
  48. package/dist/src/__tests__/daemon-autostart.test.js +0 -60
  49. package/dist/src/__tests__/daemon-autostart.test.js.map +0 -1
  50. package/dist/src/__tests__/e2e-relay.d.ts +0 -19
  51. package/dist/src/__tests__/e2e-relay.d.ts.map +0 -1
  52. package/dist/src/__tests__/e2e-relay.js +0 -400
  53. package/dist/src/__tests__/e2e-relay.js.map +0 -1
  54. package/dist/src/__tests__/fs-handler.test.d.ts +0 -2
  55. package/dist/src/__tests__/fs-handler.test.d.ts.map +0 -1
  56. package/dist/src/__tests__/fs-handler.test.js +0 -19
  57. package/dist/src/__tests__/fs-handler.test.js.map +0 -1
  58. package/dist/src/__tests__/model-discovery.test.d.ts +0 -2
  59. package/dist/src/__tests__/model-discovery.test.d.ts.map +0 -1
  60. package/dist/src/__tests__/model-discovery.test.js +0 -47
  61. package/dist/src/__tests__/model-discovery.test.js.map +0 -1
  62. package/dist/src/__tests__/model-switching.test.d.ts +0 -2
  63. package/dist/src/__tests__/model-switching.test.d.ts.map +0 -1
  64. package/dist/src/__tests__/model-switching.test.js +0 -292
  65. package/dist/src/__tests__/model-switching.test.js.map +0 -1
  66. package/dist/src/__tests__/native-fusion-parsers.test.d.ts +0 -2
  67. package/dist/src/__tests__/native-fusion-parsers.test.d.ts.map +0 -1
  68. package/dist/src/__tests__/native-fusion-parsers.test.js +0 -253
  69. package/dist/src/__tests__/native-fusion-parsers.test.js.map +0 -1
  70. package/dist/src/__tests__/native-fusion-service.test.d.ts +0 -2
  71. package/dist/src/__tests__/native-fusion-service.test.d.ts.map +0 -1
  72. package/dist/src/__tests__/native-fusion-service.test.js +0 -157
  73. package/dist/src/__tests__/native-fusion-service.test.js.map +0 -1
  74. package/dist/src/__tests__/native-session-sync.test.d.ts +0 -2
  75. package/dist/src/__tests__/native-session-sync.test.d.ts.map +0 -1
  76. package/dist/src/__tests__/native-session-sync.test.js +0 -198
  77. package/dist/src/__tests__/native-session-sync.test.js.map +0 -1
  78. package/dist/src/__tests__/pair-qr.test.d.ts +0 -2
  79. package/dist/src/__tests__/pair-qr.test.d.ts.map +0 -1
  80. package/dist/src/__tests__/pair-qr.test.js +0 -13
  81. package/dist/src/__tests__/pair-qr.test.js.map +0 -1
  82. package/dist/src/__tests__/pi-context.test.d.ts +0 -2
  83. package/dist/src/__tests__/pi-context.test.d.ts.map +0 -1
  84. package/dist/src/__tests__/pi-context.test.js +0 -261
  85. package/dist/src/__tests__/pi-context.test.js.map +0 -1
  86. package/dist/src/__tests__/session-manager.test.d.ts +0 -2
  87. package/dist/src/__tests__/session-manager.test.d.ts.map +0 -1
  88. package/dist/src/__tests__/session-manager.test.js +0 -685
  89. package/dist/src/__tests__/session-manager.test.js.map +0 -1
  90. package/dist/src/__tests__/session-store.test.d.ts +0 -2
  91. package/dist/src/__tests__/session-store.test.d.ts.map +0 -1
  92. package/dist/src/__tests__/session-store.test.js +0 -106
  93. package/dist/src/__tests__/session-store.test.js.map +0 -1
  94. package/dist/src/agents/adapter.d.ts +0 -36
  95. package/dist/src/agents/adapter.d.ts.map +0 -1
  96. package/dist/src/agents/adapter.js +0 -20
  97. package/dist/src/agents/adapter.js.map +0 -1
  98. package/dist/src/agents/claude.d.ts +0 -25
  99. package/dist/src/agents/claude.d.ts.map +0 -1
  100. package/dist/src/agents/claude.js +0 -228
  101. package/dist/src/agents/claude.js.map +0 -1
  102. package/dist/src/agents/codex.d.ts +0 -50
  103. package/dist/src/agents/codex.d.ts.map +0 -1
  104. package/dist/src/agents/codex.js +0 -785
  105. package/dist/src/agents/codex.js.map +0 -1
  106. package/dist/src/agents/command-spec.d.ts +0 -11
  107. package/dist/src/agents/command-spec.d.ts.map +0 -1
  108. package/dist/src/agents/command-spec.js +0 -62
  109. package/dist/src/agents/command-spec.js.map +0 -1
  110. package/dist/src/agents/cursor.d.ts +0 -23
  111. package/dist/src/agents/cursor.d.ts.map +0 -1
  112. package/dist/src/agents/cursor.js +0 -250
  113. package/dist/src/agents/cursor.js.map +0 -1
  114. package/dist/src/agents/custom.d.ts +0 -36
  115. package/dist/src/agents/custom.d.ts.map +0 -1
  116. package/dist/src/agents/custom.js +0 -246
  117. package/dist/src/agents/custom.js.map +0 -1
  118. package/dist/src/agents/detect.d.ts +0 -10
  119. package/dist/src/agents/detect.d.ts.map +0 -1
  120. package/dist/src/agents/detect.js +0 -47
  121. package/dist/src/agents/detect.js.map +0 -1
  122. package/dist/src/agents/gemini.d.ts +0 -18
  123. package/dist/src/agents/gemini.d.ts.map +0 -1
  124. package/dist/src/agents/gemini.js +0 -168
  125. package/dist/src/agents/gemini.js.map +0 -1
  126. package/dist/src/agents/model-registry/cache.d.ts +0 -5
  127. package/dist/src/agents/model-registry/cache.d.ts.map +0 -1
  128. package/dist/src/agents/model-registry/cache.js +0 -38
  129. package/dist/src/agents/model-registry/cache.js.map +0 -1
  130. package/dist/src/agents/model-registry/discovery.d.ts +0 -5
  131. package/dist/src/agents/model-registry/discovery.d.ts.map +0 -1
  132. package/dist/src/agents/model-registry/discovery.js +0 -202
  133. package/dist/src/agents/model-registry/discovery.js.map +0 -1
  134. package/dist/src/agents/model-registry/parsers.d.ts +0 -9
  135. package/dist/src/agents/model-registry/parsers.d.ts.map +0 -1
  136. package/dist/src/agents/model-registry/parsers.js +0 -259
  137. package/dist/src/agents/model-registry/parsers.js.map +0 -1
  138. package/dist/src/agents/model-registry/runner.d.ts +0 -11
  139. package/dist/src/agents/model-registry/runner.d.ts.map +0 -1
  140. package/dist/src/agents/model-registry/runner.js +0 -160
  141. package/dist/src/agents/model-registry/runner.js.map +0 -1
  142. package/dist/src/agents/model-registry/service.d.ts +0 -7
  143. package/dist/src/agents/model-registry/service.d.ts.map +0 -1
  144. package/dist/src/agents/model-registry/service.js +0 -69
  145. package/dist/src/agents/model-registry/service.js.map +0 -1
  146. package/dist/src/agents/model-registry/types.d.ts +0 -31
  147. package/dist/src/agents/model-registry/types.d.ts.map +0 -1
  148. package/dist/src/agents/model-registry/types.js +0 -9
  149. package/dist/src/agents/model-registry/types.js.map +0 -1
  150. package/dist/src/agents/model-registry.d.ts +0 -13
  151. package/dist/src/agents/model-registry.d.ts.map +0 -1
  152. package/dist/src/agents/model-registry.js +0 -15
  153. package/dist/src/agents/model-registry.js.map +0 -1
  154. package/dist/src/agents/openclaw.d.ts +0 -21
  155. package/dist/src/agents/openclaw.d.ts.map +0 -1
  156. package/dist/src/agents/openclaw.js +0 -264
  157. package/dist/src/agents/openclaw.js.map +0 -1
  158. package/dist/src/agents/pi.d.ts +0 -52
  159. package/dist/src/agents/pi.d.ts.map +0 -1
  160. package/dist/src/agents/pi.js +0 -794
  161. package/dist/src/agents/pi.js.map +0 -1
  162. package/dist/src/commands/agent.d.ts +0 -3
  163. package/dist/src/commands/agent.d.ts.map +0 -1
  164. package/dist/src/commands/agent.js +0 -162
  165. package/dist/src/commands/agent.js.map +0 -1
  166. package/dist/src/commands/daemon.d.ts +0 -30
  167. package/dist/src/commands/daemon.d.ts.map +0 -1
  168. package/dist/src/commands/daemon.js +0 -477
  169. package/dist/src/commands/daemon.js.map +0 -1
  170. package/dist/src/commands/pair-qr.d.ts +0 -5
  171. package/dist/src/commands/pair-qr.d.ts.map +0 -1
  172. package/dist/src/commands/pair-qr.js +0 -7
  173. package/dist/src/commands/pair-qr.js.map +0 -1
  174. package/dist/src/commands/pair.d.ts +0 -9
  175. package/dist/src/commands/pair.d.ts.map +0 -1
  176. package/dist/src/commands/pair.js +0 -163
  177. package/dist/src/commands/pair.js.map +0 -1
  178. package/dist/src/commands/upgrade.d.ts +0 -6
  179. package/dist/src/commands/upgrade.d.ts.map +0 -1
  180. package/dist/src/commands/upgrade.js +0 -146
  181. package/dist/src/commands/upgrade.js.map +0 -1
  182. package/dist/src/config/index.d.ts +0 -33
  183. package/dist/src/config/index.d.ts.map +0 -1
  184. package/dist/src/config/index.js +0 -32
  185. package/dist/src/config/index.js.map +0 -1
  186. package/dist/src/fs/handler.d.ts +0 -27
  187. package/dist/src/fs/handler.d.ts.map +0 -1
  188. package/dist/src/fs/handler.js +0 -131
  189. package/dist/src/fs/handler.js.map +0 -1
  190. package/dist/src/fs/multimodal.d.ts +0 -5
  191. package/dist/src/fs/multimodal.d.ts.map +0 -1
  192. package/dist/src/fs/multimodal.js +0 -39
  193. package/dist/src/fs/multimodal.js.map +0 -1
  194. package/dist/src/fs/security.d.ts +0 -3
  195. package/dist/src/fs/security.d.ts.map +0 -1
  196. package/dist/src/fs/security.js +0 -28
  197. package/dist/src/fs/security.js.map +0 -1
  198. package/dist/src/index.d.ts +0 -2
  199. package/dist/src/index.d.ts.map +0 -1
  200. package/dist/src/index.js +0 -251
  201. package/dist/src/index.js.map +0 -1
  202. package/dist/src/log-reporter.d.ts +0 -19
  203. package/dist/src/log-reporter.d.ts.map +0 -1
  204. package/dist/src/log-reporter.js +0 -34
  205. package/dist/src/log-reporter.js.map +0 -1
  206. package/dist/src/native-fusion/parsers.d.ts +0 -13
  207. package/dist/src/native-fusion/parsers.d.ts.map +0 -1
  208. package/dist/src/native-fusion/parsers.js +0 -371
  209. package/dist/src/native-fusion/parsers.js.map +0 -1
  210. package/dist/src/native-fusion/service.d.ts +0 -26
  211. package/dist/src/native-fusion/service.d.ts.map +0 -1
  212. package/dist/src/native-fusion/service.js +0 -167
  213. package/dist/src/native-fusion/service.js.map +0 -1
  214. package/dist/src/native-fusion/state.d.ts +0 -4
  215. package/dist/src/native-fusion/state.d.ts.map +0 -1
  216. package/dist/src/native-fusion/state.js +0 -23
  217. package/dist/src/native-fusion/state.js.map +0 -1
  218. package/dist/src/native-fusion/types.d.ts +0 -25
  219. package/dist/src/native-fusion/types.d.ts.map +0 -1
  220. package/dist/src/native-fusion/types.js +0 -2
  221. package/dist/src/native-fusion/types.js.map +0 -1
  222. package/dist/src/native-sync/discover.d.ts +0 -6
  223. package/dist/src/native-sync/discover.d.ts.map +0 -1
  224. package/dist/src/native-sync/discover.js +0 -69
  225. package/dist/src/native-sync/discover.js.map +0 -1
  226. package/dist/src/native-sync/parsers.d.ts +0 -3
  227. package/dist/src/native-sync/parsers.d.ts.map +0 -1
  228. package/dist/src/native-sync/parsers.js +0 -373
  229. package/dist/src/native-sync/parsers.js.map +0 -1
  230. package/dist/src/native-sync/service.d.ts +0 -16
  231. package/dist/src/native-sync/service.d.ts.map +0 -1
  232. package/dist/src/native-sync/service.js +0 -95
  233. package/dist/src/native-sync/service.js.map +0 -1
  234. package/dist/src/native-sync/state.d.ts +0 -6
  235. package/dist/src/native-sync/state.d.ts.map +0 -1
  236. package/dist/src/native-sync/state.js +0 -34
  237. package/dist/src/native-sync/state.js.map +0 -1
  238. package/dist/src/native-sync/types.d.ts +0 -23
  239. package/dist/src/native-sync/types.d.ts.map +0 -1
  240. package/dist/src/native-sync/types.js +0 -4
  241. package/dist/src/native-sync/types.js.map +0 -1
  242. package/dist/src/region.d.ts +0 -16
  243. package/dist/src/region.d.ts.map +0 -1
  244. package/dist/src/region.js +0 -100
  245. package/dist/src/region.js.map +0 -1
  246. package/dist/src/relay/client.d.ts +0 -53
  247. package/dist/src/relay/client.d.ts.map +0 -1
  248. package/dist/src/relay/client.js +0 -293
  249. package/dist/src/relay/client.js.map +0 -1
  250. package/dist/src/session/handlers/agents.d.ts +0 -5
  251. package/dist/src/session/handlers/agents.d.ts.map +0 -1
  252. package/dist/src/session/handlers/agents.js +0 -56
  253. package/dist/src/session/handlers/agents.js.map +0 -1
  254. package/dist/src/session/handlers/chat.d.ts +0 -5
  255. package/dist/src/session/handlers/chat.d.ts.map +0 -1
  256. package/dist/src/session/handlers/chat.js +0 -327
  257. package/dist/src/session/handlers/chat.js.map +0 -1
  258. package/dist/src/session/handlers/control.d.ts +0 -6
  259. package/dist/src/session/handlers/control.d.ts.map +0 -1
  260. package/dist/src/session/handlers/control.js +0 -58
  261. package/dist/src/session/handlers/control.js.map +0 -1
  262. package/dist/src/session/handlers/fs.d.ts +0 -11
  263. package/dist/src/session/handlers/fs.d.ts.map +0 -1
  264. package/dist/src/session/handlers/fs.js +0 -253
  265. package/dist/src/session/handlers/fs.js.map +0 -1
  266. package/dist/src/session/handlers/queue.d.ts +0 -4
  267. package/dist/src/session/handlers/queue.d.ts.map +0 -1
  268. package/dist/src/session/handlers/queue.js +0 -66
  269. package/dist/src/session/handlers/queue.js.map +0 -1
  270. package/dist/src/session/manager.d.ts +0 -28
  271. package/dist/src/session/manager.d.ts.map +0 -1
  272. package/dist/src/session/manager.js +0 -155
  273. package/dist/src/session/manager.js.map +0 -1
  274. package/dist/src/session/store.d.ts +0 -8
  275. package/dist/src/session/store.d.ts.map +0 -1
  276. package/dist/src/session/store.js +0 -47
  277. package/dist/src/session/store.js.map +0 -1
  278. package/dist/src/session/types.d.ts +0 -36
  279. package/dist/src/session/types.d.ts.map +0 -1
  280. package/dist/src/session/types.js +0 -5
  281. package/dist/src/session/types.js.map +0 -1
  282. package/dist/src/upgrade/engine.d.ts +0 -65
  283. package/dist/src/upgrade/engine.d.ts.map +0 -1
  284. package/dist/src/upgrade/engine.js +0 -239
  285. package/dist/src/upgrade/engine.js.map +0 -1
  286. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,785 +0,0 @@
1
- // @arch docs/architecture/cli/agent-adapters.md
2
- // @test src/__tests__/codex-adapter.test.ts
3
- import { spawn } from 'node:child_process';
4
- import { createInterface } from 'node:readline';
5
- import { randomUUID } from 'node:crypto';
6
- import { AgentAdapter, registerAgent } from './adapter.js';
7
- export class CodexAdapter extends AgentAdapter {
8
- type = 'codex';
9
- process = null;
10
- workDir = null;
11
- seq = 0;
12
- runId = '';
13
- pendingUsage;
14
- agentSessionId = null;
15
- hasEmittedText = false;
16
- textTail = '';
17
- terminalState = 'open';
18
- forceCloseTimer = null;
19
- stderrBuf = '';
20
- rpcSeq = 1;
21
- pendingRequests = new Map();
22
- appServerReady = null;
23
- activeTurnId = null;
24
- namedThread = false;
25
- deltaItemIds = new Set();
26
- lastTransientStatus = '';
27
- async start(_sessionId, workDir, agentSessionId) {
28
- this.workDir = workDir;
29
- this.seq = 0;
30
- if (agentSessionId)
31
- this.agentSessionId = agentSessionId;
32
- }
33
- async send(text, modelId) {
34
- if (this.activeTurnId) {
35
- await this.killProcess();
36
- }
37
- const codexModelId = normalizeCodexModelId(modelId);
38
- this.runId = randomUUID();
39
- this.seq = 0;
40
- this.resetRunState();
41
- await this.ensureAppServer(codexModelId);
42
- const threadId = this.agentSessionId;
43
- if (!threadId)
44
- throw new Error('codex app-server did not create a thread');
45
- this.emitEvent({ state: 'start', agentSessionId: threadId });
46
- if (!this.namedThread) {
47
- await this.sendRpc('thread/name/set', {
48
- threadId,
49
- name: makeThreadTitle(text),
50
- }).catch(() => { });
51
- this.namedThread = true;
52
- }
53
- const response = await this.sendRpc('turn/start', {
54
- threadId,
55
- input: [{ type: 'text', text, text_elements: [] }],
56
- approvalPolicy: 'never',
57
- sandboxPolicy: { type: 'dangerFullAccess' },
58
- ...(codexModelId ? { model: codexModelId } : {}),
59
- });
60
- this.activeTurnId = response.turn?.id ?? null;
61
- }
62
- async resume(agentSessionId) {
63
- await this.killProcess();
64
- this.agentSessionId = agentSessionId;
65
- this.namedThread = true;
66
- this.resetTextState();
67
- }
68
- async stop() {
69
- await this.killProcess();
70
- }
71
- spawnCodex(args) {
72
- const proc = spawn('codex', args, {
73
- cwd: this.workDir ?? undefined,
74
- stdio: ['ignore', 'pipe', 'pipe'],
75
- env: { ...process.env },
76
- });
77
- this.process = proc;
78
- const rl = createInterface({ input: proc.stdout });
79
- rl.on('line', (line) => {
80
- if (!line.trim())
81
- return;
82
- try {
83
- const obj = JSON.parse(line);
84
- this.handleStreamEvent(obj);
85
- }
86
- catch {
87
- this.emitEvent({ state: 'delta', text: line });
88
- }
89
- });
90
- let stderrBuf = '';
91
- proc.stderr?.on('data', (chunk) => {
92
- stderrBuf += chunk.toString();
93
- });
94
- proc.on('close', (code) => {
95
- if (this.process !== proc)
96
- return;
97
- this.process = null;
98
- this.clearForceCloseTimer();
99
- this.handleProcessClose(code, stderrBuf);
100
- });
101
- proc.on('error', (err) => {
102
- if (this.process !== proc)
103
- return;
104
- this.process = null;
105
- if (err.code === 'ENOENT') {
106
- this.emit('error', new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));
107
- }
108
- else {
109
- this.emit('error', err);
110
- }
111
- });
112
- }
113
- spawnAppServer() {
114
- const proc = spawn('codex', ['app-server', '--listen', 'stdio://'], {
115
- cwd: this.workDir ?? undefined,
116
- stdio: ['pipe', 'pipe', 'pipe'],
117
- env: { ...process.env, NO_COLOR: '1' },
118
- });
119
- this.process = proc;
120
- this.stderrBuf = '';
121
- const rl = createInterface({ input: proc.stdout });
122
- rl.on('line', (line) => {
123
- if (!line.trim())
124
- return;
125
- let msg;
126
- try {
127
- msg = JSON.parse(line);
128
- }
129
- catch {
130
- return;
131
- }
132
- this.handleAppServerMessage(msg);
133
- });
134
- proc.stderr?.on('data', (chunk) => {
135
- this.stderrBuf += chunk.toString();
136
- });
137
- proc.on('close', (code) => {
138
- if (this.process !== proc)
139
- return;
140
- const hadActiveTurn = this.activeTurnId != null;
141
- this.process = null;
142
- this.appServerReady = null;
143
- this.activeTurnId = null;
144
- this.rejectAllPending(new Error(normalizeCodexStderr(this.stderrBuf) || `codex app-server exited with code ${code}`));
145
- if (this.terminalState === 'open' && hadActiveTurn) {
146
- this.handleProcessClose(code, this.stderrBuf);
147
- }
148
- });
149
- proc.on('error', (err) => {
150
- if (this.process !== proc)
151
- return;
152
- this.process = null;
153
- this.rejectAllPending(err);
154
- if (err.code === 'ENOENT') {
155
- this.emit('error', new Error('Command "codex" not found. Is OpenAI Codex CLI installed?'));
156
- }
157
- else {
158
- this.emit('error', err);
159
- }
160
- });
161
- }
162
- async ensureAppServer(modelId) {
163
- if (this.appServerReady)
164
- return this.appServerReady;
165
- this.spawnAppServer();
166
- this.appServerReady = this.initializeAppServer(modelId).catch(async (error) => {
167
- this.appServerReady = null;
168
- await this.killProcess();
169
- throw error;
170
- });
171
- return this.appServerReady;
172
- }
173
- async initializeAppServer(modelId) {
174
- const codexModelId = normalizeCodexModelId(modelId);
175
- await this.sendRpc('initialize', {
176
- clientInfo: { name: 'shennian', title: 'Shennian', version: '0.0.0' },
177
- capabilities: { experimentalApi: true },
178
- });
179
- if (this.agentSessionId) {
180
- const response = await this.sendRpc('thread/resume', {
181
- threadId: this.agentSessionId,
182
- cwd: this.workDir,
183
- approvalPolicy: 'never',
184
- sandbox: 'danger-full-access',
185
- persistExtendedHistory: true,
186
- ...(codexModelId ? { model: codexModelId } : {}),
187
- });
188
- this.agentSessionId = response.thread?.id ?? this.agentSessionId;
189
- this.namedThread = !!response.thread?.name;
190
- return;
191
- }
192
- const response = await this.sendRpc('thread/start', {
193
- cwd: this.workDir,
194
- approvalPolicy: 'never',
195
- sandbox: 'danger-full-access',
196
- serviceName: 'Shennian',
197
- experimentalRawEvents: false,
198
- persistExtendedHistory: true,
199
- ...(codexModelId ? { model: codexModelId } : {}),
200
- });
201
- const threadId = response.thread?.id;
202
- if (!threadId)
203
- throw new Error('codex app-server thread/start returned no thread id');
204
- this.agentSessionId = threadId;
205
- this.namedThread = !!response.thread?.name;
206
- }
207
- sendRpc(method, params, timeoutMs = 60_000) {
208
- const proc = this.process;
209
- if (!proc?.stdin)
210
- return Promise.reject(new Error('codex app-server is not running'));
211
- const id = this.rpcSeq++;
212
- const payload = JSON.stringify({ id, method, params });
213
- return new Promise((resolve, reject) => {
214
- const timer = setTimeout(() => {
215
- this.pendingRequests.delete(id);
216
- reject(new Error(`codex app-server request timed out: ${method}`));
217
- }, timeoutMs);
218
- this.pendingRequests.set(id, { resolve, reject, timer });
219
- proc.stdin.write(`${payload}\n`, (error) => {
220
- if (!error)
221
- return;
222
- clearTimeout(timer);
223
- this.pendingRequests.delete(id);
224
- reject(error);
225
- });
226
- });
227
- }
228
- handleAppServerMessage(msg) {
229
- if (msg.id != null) {
230
- const pending = this.pendingRequests.get(msg.id);
231
- if (pending) {
232
- clearTimeout(pending.timer);
233
- this.pendingRequests.delete(msg.id);
234
- if (msg.error) {
235
- pending.reject(new Error(msg.error.message || `codex app-server error ${msg.error.code ?? ''}`.trim()));
236
- }
237
- else {
238
- pending.resolve(msg.result);
239
- }
240
- }
241
- }
242
- if (!msg.method)
243
- return;
244
- const params = msg.params ?? {};
245
- switch (msg.method) {
246
- case 'item/agentMessage/delta': {
247
- const itemId = typeof params.itemId === 'string' ? params.itemId : '';
248
- if (itemId)
249
- this.deltaItemIds.add(itemId);
250
- if (typeof params.delta === 'string')
251
- this.emitText(params.delta);
252
- break;
253
- }
254
- case 'item/completed':
255
- this.handleAppServerCompletedItem(params);
256
- break;
257
- case 'thread/tokenUsage/updated':
258
- this.handleAppServerUsage(params);
259
- break;
260
- case 'turn/completed': {
261
- const turn = typeof params.turn === 'object' && params.turn !== null
262
- ? params.turn
263
- : null;
264
- const turnId = typeof turn?.id === 'string' ? turn.id : null;
265
- if (!this.activeTurnId || turnId === this.activeTurnId) {
266
- this.activeTurnId = null;
267
- this.emitFinalIfOpen();
268
- }
269
- break;
270
- }
271
- case 'error': {
272
- const message = extractAppServerErrorMessage(params);
273
- if (isTransientCodexErrorMessage(message)) {
274
- this.emitTransientStatus(message);
275
- return;
276
- }
277
- this.emitErrorIfOpen(message);
278
- break;
279
- }
280
- }
281
- }
282
- handleAppServerCompletedItem(params) {
283
- const item = typeof params.item === 'object' && params.item !== null
284
- ? params.item
285
- : null;
286
- if (!item || typeof item.type !== 'string')
287
- return;
288
- switch (item.type) {
289
- case 'agentMessage': {
290
- const id = typeof item.id === 'string' ? item.id : '';
291
- if (id && this.deltaItemIds.has(id))
292
- return;
293
- if (typeof item.text === 'string')
294
- this.emitText(item.text, 'block');
295
- break;
296
- }
297
- case 'commandExecution': {
298
- const command = typeof item.command === 'string' ? item.command : '';
299
- const output = typeof item.aggregatedOutput === 'string' ? item.aggregatedOutput : '';
300
- if (command) {
301
- this.emitEvent({ state: 'tool-call', name: 'command_execution', args: { command } });
302
- }
303
- this.emitEvent({
304
- state: 'tool-result',
305
- name: 'command_execution',
306
- result: [output, item.exitCode != null ? `\n(exit ${item.exitCode})` : ''].join('').trim(),
307
- });
308
- break;
309
- }
310
- case 'mcpToolCall':
311
- case 'dynamicToolCall': {
312
- const tool = typeof item.tool === 'string' ? item.tool : item.type;
313
- const args = typeof item.arguments === 'object' && item.arguments !== null
314
- ? item.arguments
315
- : {};
316
- this.emitEvent({ state: 'tool-call', name: tool, args });
317
- this.emitEvent({
318
- state: 'tool-result',
319
- name: tool,
320
- result: safeStringify(item.error ?? item.result ?? item.contentItems ?? ''),
321
- });
322
- break;
323
- }
324
- case 'fileChange': {
325
- const changes = Array.isArray(item.changes) ? item.changes : [];
326
- const summary = changes
327
- .map((change) => {
328
- if (typeof change !== 'object' || change === null)
329
- return '';
330
- const c = change;
331
- const path = typeof c.path === 'string' ? c.path : typeof c.file === 'string' ? c.file : '';
332
- const kind = typeof c.kind === 'string' ? c.kind : typeof c.type === 'string' ? c.type : 'change';
333
- return path ? `${kind}: ${path}` : '';
334
- })
335
- .filter(Boolean)
336
- .join('\n');
337
- if (summary)
338
- this.emitText(summary, 'block');
339
- break;
340
- }
341
- }
342
- }
343
- handleAppServerUsage(params) {
344
- const tokenUsage = typeof params.tokenUsage === 'object' && params.tokenUsage !== null
345
- ? params.tokenUsage
346
- : null;
347
- const last = typeof tokenUsage?.last === 'object' && tokenUsage.last !== null
348
- ? tokenUsage.last
349
- : null;
350
- const total = typeof tokenUsage?.total === 'object' && tokenUsage.total !== null
351
- ? tokenUsage.total
352
- : null;
353
- const usage = last ?? total;
354
- if (!usage)
355
- return;
356
- const input = typeof usage.inputTokens === 'number' ? usage.inputTokens : undefined;
357
- const output = typeof usage.outputTokens === 'number' ? usage.outputTokens : undefined;
358
- if (input != null || output != null) {
359
- this.pendingUsage = {
360
- inputTokens: input ?? 0,
361
- outputTokens: output ?? 0,
362
- };
363
- }
364
- }
365
- handleCodexItemLine(obj) {
366
- const item = obj.item;
367
- if (!item?.type)
368
- return;
369
- switch (item.type) {
370
- case 'agent_message':
371
- case 'reasoning': {
372
- if (obj.type === 'item.completed' && item.text) {
373
- this.emitText(item.text, 'block');
374
- }
375
- break;
376
- }
377
- case 'command_execution': {
378
- if (obj.type === 'item.started' && item.command) {
379
- this.emitEvent({
380
- state: 'tool-call',
381
- name: 'command_execution',
382
- args: { command: item.command },
383
- });
384
- }
385
- if (obj.type === 'item.completed') {
386
- const parts = [
387
- item.aggregated_output ?? '',
388
- item.exit_code != null ? `\n(exit ${item.exit_code})` : '',
389
- ];
390
- this.emitEvent({
391
- state: 'tool-result',
392
- name: 'command_execution',
393
- result: parts.join('').trim() || String(item.status ?? ''),
394
- });
395
- }
396
- break;
397
- }
398
- case 'mcp_tool_call': {
399
- if (obj.type === 'item.started') {
400
- this.emitEvent({
401
- state: 'tool-call',
402
- name: item.tool ?? 'mcp_tool',
403
- args: {
404
- server: item.server,
405
- ...(item.arguments && typeof item.arguments === 'object' ? item.arguments : {}),
406
- },
407
- });
408
- }
409
- if (obj.type === 'item.completed') {
410
- const errMsg = item.error && typeof item.error === 'object' ? item.error.message : undefined;
411
- this.emitEvent({
412
- state: 'tool-result',
413
- name: item.tool ?? 'mcp_tool',
414
- result: errMsg ?? safeStringify(item.result),
415
- });
416
- }
417
- break;
418
- }
419
- case 'file_change': {
420
- if (obj.type === 'item.completed' && item.changes?.length) {
421
- const summary = item.changes.map((c) => `${c.kind}: ${c.path}`).join('\n');
422
- this.emitText(summary, 'block');
423
- }
424
- break;
425
- }
426
- case 'web_search': {
427
- if (obj.type === 'item.completed' && item.query) {
428
- this.emitText(`[web_search] ${item.query}`, 'block');
429
- }
430
- break;
431
- }
432
- case 'todo_list': {
433
- if (obj.type === 'item.completed' && item.items?.length) {
434
- const lines = item.items.map((t) => `- [${t.completed ? 'x' : ' '}] ${t.text}`).join('\n');
435
- this.emitText(lines, 'block');
436
- }
437
- break;
438
- }
439
- case 'error': {
440
- if (obj.type === 'item.completed' && item.message) {
441
- this.emitEvent({ state: 'error', message: item.message });
442
- }
443
- break;
444
- }
445
- default:
446
- break;
447
- }
448
- }
449
- handleStreamEvent(obj) {
450
- const topType = obj.type ?? obj.event;
451
- if (topType?.startsWith('item.')) {
452
- this.handleCodexItemLine(obj);
453
- }
454
- switch (topType) {
455
- case 'turn.completed': {
456
- const u = obj.usage;
457
- if (u) {
458
- const input = u.input_tokens ?? u.prompt_tokens;
459
- const output = u.output_tokens ?? u.completion_tokens;
460
- if (input != null || output != null) {
461
- this.pendingUsage = {
462
- inputTokens: input ?? 0,
463
- outputTokens: output ?? 0,
464
- };
465
- }
466
- }
467
- this.emitFinalIfOpen();
468
- return;
469
- }
470
- case 'turn.failed': {
471
- const msg = typeof obj.error === 'object' && obj.error?.message
472
- ? obj.error.message
473
- : typeof obj.error === 'string'
474
- ? obj.error
475
- : 'turn failed';
476
- this.emitErrorIfOpen(msg);
477
- return;
478
- }
479
- case 'error': {
480
- const m = typeof obj.message === 'string' ? obj.message : '';
481
- if (m.includes('Reconnecting'))
482
- return;
483
- this.emitErrorIfOpen(m || (typeof obj.error === 'string' ? obj.error : 'stream error'));
484
- return;
485
- }
486
- case 'thread.started': {
487
- const sid = obj.thread_id ?? obj.session_id ?? obj.id;
488
- if (typeof sid === 'string' && sid) {
489
- this.agentSessionId = sid;
490
- this.emitEvent({ state: 'start', agentSessionId: this.agentSessionId });
491
- }
492
- return;
493
- }
494
- case 'turn.started':
495
- return;
496
- }
497
- if (topType?.startsWith('item.'))
498
- return;
499
- const eventType = obj.type ?? obj.event;
500
- switch (eventType) {
501
- case 'message':
502
- case 'text':
503
- case 'content': {
504
- const text = obj.content ?? obj.text;
505
- if (text) {
506
- this.emitText(text);
507
- }
508
- break;
509
- }
510
- case 'function_call':
511
- case 'tool_call': {
512
- this.emitEvent({
513
- state: 'tool-call',
514
- name: obj.name,
515
- args: obj.arguments ?? obj.input,
516
- });
517
- break;
518
- }
519
- case 'function_call_output':
520
- case 'tool_result': {
521
- this.emitEvent({
522
- state: 'tool-result',
523
- name: obj.name,
524
- result: obj.output ?? obj.result,
525
- });
526
- break;
527
- }
528
- case 'error': {
529
- break;
530
- }
531
- case 'done':
532
- case 'completed': {
533
- if (obj.usage) {
534
- this.pendingUsage = {
535
- inputTokens: obj.usage.prompt_tokens ?? obj.usage.input_tokens ?? 0,
536
- outputTokens: obj.usage.completion_tokens ?? obj.usage.output_tokens ?? 0,
537
- };
538
- }
539
- this.emitFinalIfOpen();
540
- break;
541
- }
542
- }
543
- }
544
- emitEvent(partial) {
545
- const event = {
546
- ...partial,
547
- runId: this.runId,
548
- seq: this.seq++,
549
- };
550
- this.emit('agentEvent', event);
551
- }
552
- async killProcess() {
553
- const proc = this.process;
554
- this.appServerReady = null;
555
- this.activeTurnId = null;
556
- if (!proc) {
557
- this.rejectAllPending(new Error('codex app-server stopped'));
558
- return;
559
- }
560
- this.process = null;
561
- this.clearForceCloseTimer();
562
- proc.kill('SIGTERM');
563
- await new Promise((resolve) => {
564
- proc.on('close', resolve);
565
- setTimeout(() => {
566
- proc.kill('SIGKILL');
567
- resolve();
568
- }, 3000);
569
- });
570
- this.rejectAllPending(new Error('codex app-server stopped'));
571
- }
572
- rejectAllPending(error) {
573
- for (const [id, pending] of this.pendingRequests.entries()) {
574
- clearTimeout(pending.timer);
575
- pending.reject(error);
576
- this.pendingRequests.delete(id);
577
- }
578
- }
579
- handleProcessClose(code, stderrBuf) {
580
- const stderr = normalizeCodexStderr(stderrBuf);
581
- if (code !== 0 && code !== null) {
582
- const msg = stderr || `codex exited with code ${code}`;
583
- this.emitErrorIfOpen(msg);
584
- }
585
- else if (looksLikeFatalCodexStderr(stderr)) {
586
- // Codex sometimes surfaces fatal API/auth errors on stderr without
587
- // emitting a protocol-level `turn.failed`, and may still exit 0.
588
- this.emitErrorIfOpen(stderr);
589
- }
590
- else {
591
- this.emitFinalIfOpen();
592
- }
593
- this.pendingUsage = undefined;
594
- }
595
- emitFinalIfOpen() {
596
- if (this.terminalState !== 'open')
597
- return;
598
- this.terminalState = 'final';
599
- this.emitEvent({
600
- state: 'final',
601
- usage: this.pendingUsage,
602
- agentSessionId: this.agentSessionId ?? undefined,
603
- });
604
- }
605
- emitErrorIfOpen(message) {
606
- if (this.terminalState !== 'open')
607
- return;
608
- this.terminalState = 'error';
609
- this.emitEvent({ state: 'error', message: formatCodexErrorMessage(message) });
610
- this.scheduleProcessClose();
611
- }
612
- resetRunState() {
613
- this.pendingUsage = undefined;
614
- this.terminalState = 'open';
615
- this.deltaItemIds.clear();
616
- this.lastTransientStatus = '';
617
- this.clearForceCloseTimer();
618
- this.resetTextState();
619
- }
620
- emitTransientStatus(message) {
621
- const formatted = formatTransientCodexStatus(message);
622
- if (!formatted || formatted === this.lastTransientStatus || this.terminalState !== 'open')
623
- return;
624
- this.lastTransientStatus = formatted;
625
- this.emitEvent({ state: 'delta', text: `${formatted}\n`, thinking: true });
626
- }
627
- resetTextState() {
628
- this.hasEmittedText = false;
629
- this.textTail = '';
630
- }
631
- emitText(text, mode = 'delta') {
632
- if (!text)
633
- return;
634
- let next = stripGitDirectiveArtifacts(text);
635
- if (!next)
636
- return;
637
- if (mode === 'block' && this.hasEmittedText && !next.startsWith('\n')) {
638
- if (this.textTail.endsWith('\n')) {
639
- next = `\n${next}`;
640
- }
641
- else if (!this.textTail.endsWith('\n\n')) {
642
- next = `\n\n${next}`;
643
- }
644
- }
645
- this.hasEmittedText = true;
646
- this.textTail = (this.textTail + next).slice(-4);
647
- this.emitEvent({ state: 'delta', text: next });
648
- }
649
- scheduleProcessClose() {
650
- const proc = this.process;
651
- if (!proc || this.forceCloseTimer)
652
- return;
653
- this.forceCloseTimer = setTimeout(() => {
654
- this.forceCloseTimer = null;
655
- if (this.process !== proc)
656
- return;
657
- proc.kill('SIGTERM');
658
- setTimeout(() => {
659
- if (this.process === proc) {
660
- proc.kill('SIGKILL');
661
- }
662
- }, 1000);
663
- }, 250);
664
- }
665
- clearForceCloseTimer() {
666
- if (!this.forceCloseTimer)
667
- return;
668
- clearTimeout(this.forceCloseTimer);
669
- this.forceCloseTimer = null;
670
- }
671
- }
672
- function makeThreadTitle(text) {
673
- const firstLine = normalizeTitleText(text).split('\n').find((line) => line.trim()) ?? 'Shennian';
674
- const title = firstLine.trim().slice(0, 80);
675
- return title || 'Shennian';
676
- }
677
- function normalizeTitleText(text) {
678
- return text
679
- .replace(/!\[[^\]]*]\([^)]+\)/g, '')
680
- .replace(/\s+/g, ' ')
681
- .trim();
682
- }
683
- export function normalizeCodexModelId(modelId) {
684
- const trimmed = modelId?.trim();
685
- if (!trimmed)
686
- return undefined;
687
- return trimmed.toLowerCase() === 'openai' ? undefined : trimmed;
688
- }
689
- function extractAppServerErrorMessage(params) {
690
- if (typeof params.message === 'string' && params.message.trim())
691
- return params.message.trim();
692
- const error = params.error;
693
- if (typeof error === 'string' && error.trim())
694
- return error.trim();
695
- if (typeof error === 'object' && error !== null) {
696
- const message = error.message;
697
- if (typeof message === 'string' && message.trim())
698
- return message.trim();
699
- }
700
- return 'codex app-server error';
701
- }
702
- function isTransientCodexErrorMessage(message) {
703
- return /\bReconnecting\.\.\.\s*\d+\/\d+/i.test(message);
704
- }
705
- function formatTransientCodexStatus(message) {
706
- const match = message.match(/\bReconnecting\.\.\.\s*(\d+\/\d+)/i);
707
- if (!match)
708
- return '';
709
- return `Codex API 暂时不可用,正在重试 ${match[1]}...`;
710
- }
711
- function formatCodexErrorMessage(message) {
712
- const statusMatch = message.match(/unexpected status\s+(\d+)\s+([^:,]+)(?::\s*([^,]+))?(?:,\s*url:\s*([^,\s]+))?(?:,\s*request id:\s*([^\s,]+))?/i);
713
- if (!statusMatch)
714
- return message;
715
- const [, status, statusText, detail, url, requestId] = statusMatch;
716
- const parts = [
717
- `Codex API 返回 ${status} ${statusText.trim()}`,
718
- detail?.trim() ? `:${detail.trim()}` : '',
719
- url ? `\n上游地址:${url}` : '',
720
- requestId ? `\nrequest id:${requestId}` : '',
721
- ];
722
- return parts.join('');
723
- }
724
- const GIT_DIRECTIVE_LINE_RE = /^\s*::git-[a-z-]+\{[^\n]*\}\s*$/gm;
725
- function stripGitDirectiveArtifacts(text) {
726
- if (!text)
727
- return '';
728
- const normalized = text.replace(/\r\n/g, '\n');
729
- const hadDirective = /(^|\n)\s*::git-[a-z-]+\{[^\n]*\}\s*(?=\n|$)/.test(normalized);
730
- const stripped = normalized
731
- .replace(GIT_DIRECTIVE_LINE_RE, '')
732
- .replace(/\n{3,}/g, '\n\n');
733
- if (!stripped.trim())
734
- return '';
735
- return hadDirective
736
- ? stripped.replace(/[ \t]+\n/g, '\n').replace(/\n+$/g, '')
737
- : stripped;
738
- }
739
- function safeStringify(value) {
740
- if (value == null)
741
- return '';
742
- if (typeof value === 'string')
743
- return value;
744
- try {
745
- return JSON.stringify(value);
746
- }
747
- catch {
748
- return String(value);
749
- }
750
- }
751
- function normalizeCodexStderr(stderr) {
752
- return stderr
753
- .split(/\r?\n/)
754
- .map((line) => line.trim())
755
- .filter(Boolean)
756
- .filter((line) => !isIgnorableCodexStderrLine(line))
757
- .join('\n');
758
- }
759
- function isIgnorableCodexStderrLine(line) {
760
- return [
761
- /WARNING: proceeding, even though we could not update PATH:/i,
762
- /Reading additional input from stdin\.\.\./i,
763
- /failed to record rollout items: failed to queue rollout items: channel closed/i,
764
- ].some((pattern) => pattern.test(line));
765
- }
766
- function looksLikeFatalCodexStderr(stderr) {
767
- if (!stderr)
768
- return false;
769
- return [
770
- /\bunauthorized\b/i,
771
- /\bforbidden\b/i,
772
- /\bpermission denied\b/i,
773
- /\brate limit\b/i,
774
- /\binsufficient quota\b/i,
775
- /\bapi key\b/i,
776
- /\bauth/i,
777
- /\bnetwork\b/i,
778
- /\btimeout\b/i,
779
- /\bnot found\b/i,
780
- /\berror\b/i,
781
- /\bfailed\b/i,
782
- ].some((pattern) => pattern.test(stderr));
783
- }
784
- registerAgent('codex', () => new CodexAdapter());
785
- //# sourceMappingURL=codex.js.map