@jingyi0605/codingns 0.1.0 → 0.1.2

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 (241) hide show
  1. package/README.md +14 -0
  2. package/dist/public/assets/TerminalPage-Dr7knYq2.js +55 -0
  3. package/dist/public/assets/index-BpUi6zoT.js +108 -0
  4. package/dist/public/assets/index-NMtdQNda.css +1 -0
  5. package/dist/public/index.html +2 -2
  6. package/dist/server/config/env.js +72 -7
  7. package/dist/server/config/env.js.map +1 -1
  8. package/dist/server/config/opencode-base-url-resolver.d.ts +13 -8
  9. package/dist/server/config/opencode-base-url-resolver.js +117 -147
  10. package/dist/server/config/opencode-base-url-resolver.js.map +1 -1
  11. package/dist/server/config/opencode-system-probe-helper-client.d.ts +18 -0
  12. package/dist/server/config/opencode-system-probe-helper-client.js +127 -0
  13. package/dist/server/config/opencode-system-probe-helper-client.js.map +1 -0
  14. package/dist/server/config/opencode-system-probe-helper-process.d.ts +1 -0
  15. package/dist/server/config/opencode-system-probe-helper-process.js +208 -0
  16. package/dist/server/config/opencode-system-probe-helper-process.js.map +1 -0
  17. package/dist/server/modules/git/git-command-helper-client.d.ts +25 -0
  18. package/dist/server/modules/git/git-command-helper-client.js +143 -0
  19. package/dist/server/modules/git/git-command-helper-client.js.map +1 -0
  20. package/dist/server/modules/git/git-command-helper-process.d.ts +1 -0
  21. package/dist/server/modules/git/git-command-helper-process.js +237 -0
  22. package/dist/server/modules/git/git-command-helper-process.js.map +1 -0
  23. package/dist/server/modules/git/git-command-runner.d.ts +8 -0
  24. package/dist/server/modules/git/git-command-runner.js +77 -6
  25. package/dist/server/modules/git/git-command-runner.js.map +1 -1
  26. package/dist/server/modules/git/git-controller.d.ts +4 -0
  27. package/dist/server/modules/git/git-controller.js +4 -1
  28. package/dist/server/modules/git/git-controller.js.map +1 -1
  29. package/dist/server/modules/git/git-read-service.d.ts +2 -1
  30. package/dist/server/modules/git/git-read-service.js +30 -0
  31. package/dist/server/modules/git/git-read-service.js.map +1 -1
  32. package/dist/server/modules/git/git-write-service.d.ts +1 -1
  33. package/dist/server/modules/git/git-write-service.js +8 -7
  34. package/dist/server/modules/git/git-write-service.js.map +1 -1
  35. package/dist/server/modules/git/types.d.ts +5 -0
  36. package/dist/server/modules/preferences/common.d.ts +2 -0
  37. package/dist/server/modules/preferences/common.js +13 -0
  38. package/dist/server/modules/preferences/common.js.map +1 -0
  39. package/dist/server/modules/preferences/profile-controller.d.ts +11 -0
  40. package/dist/server/modules/preferences/profile-controller.js +14 -0
  41. package/dist/server/modules/preferences/profile-controller.js.map +1 -0
  42. package/dist/server/modules/preferences/profile-service.d.ts +17 -0
  43. package/dist/server/modules/preferences/profile-service.js +213 -0
  44. package/dist/server/modules/preferences/profile-service.js.map +1 -0
  45. package/dist/server/modules/preferences/quick-phrase-controller.js +2 -12
  46. package/dist/server/modules/preferences/quick-phrase-controller.js.map +1 -1
  47. package/dist/server/modules/provider/codex-model-options.js +26 -165
  48. package/dist/server/modules/provider/codex-model-options.js.map +1 -1
  49. package/dist/server/modules/provider/opencode-model-options.js +6 -71
  50. package/dist/server/modules/provider/opencode-model-options.js.map +1 -1
  51. package/dist/server/modules/provider/provider-controller.d.ts +2 -0
  52. package/dist/server/modules/provider/provider-controller.js +21 -1
  53. package/dist/server/modules/provider/provider-controller.js.map +1 -1
  54. package/dist/server/modules/provider/provider-discovery-helper-client.d.ts +25 -0
  55. package/dist/server/modules/provider/provider-discovery-helper-client.js +114 -0
  56. package/dist/server/modules/provider/provider-discovery-helper-client.js.map +1 -0
  57. package/dist/server/modules/provider/provider-discovery-helper-process.d.ts +1 -0
  58. package/dist/server/modules/provider/provider-discovery-helper-process.js +296 -0
  59. package/dist/server/modules/provider/provider-discovery-helper-process.js.map +1 -0
  60. package/dist/server/modules/sessions/claude-runtime-helper-client.d.ts +28 -0
  61. package/dist/server/modules/sessions/claude-runtime-helper-client.js +221 -0
  62. package/dist/server/modules/sessions/claude-runtime-helper-client.js.map +1 -0
  63. package/dist/server/modules/sessions/claude-runtime-helper-process.d.ts +1 -0
  64. package/dist/server/modules/sessions/claude-runtime-helper-process.js +146 -0
  65. package/dist/server/modules/sessions/claude-runtime-helper-process.js.map +1 -0
  66. package/dist/server/modules/sessions/codex-app-server-helper-client.d.ts +16 -0
  67. package/dist/server/modules/sessions/codex-app-server-helper-client.js +237 -0
  68. package/dist/server/modules/sessions/codex-app-server-helper-client.js.map +1 -0
  69. package/dist/server/modules/sessions/codex-app-server-helper-process.d.ts +1 -0
  70. package/dist/server/modules/sessions/codex-app-server-helper-process.js +484 -0
  71. package/dist/server/modules/sessions/codex-app-server-helper-process.js.map +1 -0
  72. package/dist/server/modules/sessions/session-activity-authority-service.d.ts +52 -0
  73. package/dist/server/modules/sessions/session-activity-authority-service.js +377 -0
  74. package/dist/server/modules/sessions/session-activity-authority-service.js.map +1 -0
  75. package/dist/server/modules/sessions/session-activity-inspector.js +80 -40
  76. package/dist/server/modules/sessions/session-activity-inspector.js.map +1 -1
  77. package/dist/server/modules/sessions/session-controller.d.ts +15 -1
  78. package/dist/server/modules/sessions/session-controller.js +14 -1
  79. package/dist/server/modules/sessions/session-controller.js.map +1 -1
  80. package/dist/server/modules/sessions/session-history-service.d.ts +8 -3
  81. package/dist/server/modules/sessions/session-history-service.js +303 -64
  82. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  83. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +40 -4
  84. package/dist/server/modules/sessions/session-live-runtime-service.js +334 -44
  85. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  86. package/dist/server/modules/sessions/session-permission-request-service.d.ts +175 -0
  87. package/dist/server/modules/sessions/session-permission-request-service.js +1615 -0
  88. package/dist/server/modules/sessions/session-permission-request-service.js.map +1 -0
  89. package/dist/server/modules/sessions/session-provider-error-mapper.js +14 -0
  90. package/dist/server/modules/sessions/session-provider-error-mapper.js.map +1 -1
  91. package/dist/server/modules/terminal/command-template-service.d.ts +2 -2
  92. package/dist/server/modules/terminal/command-template-service.js +3 -3
  93. package/dist/server/modules/terminal/command-template-service.js.map +1 -1
  94. package/dist/server/modules/terminal/runtime/adapters/conpty-control-helper-client.d.ts +24 -0
  95. package/dist/server/modules/terminal/runtime/adapters/conpty-control-helper-client.js +104 -0
  96. package/dist/server/modules/terminal/runtime/adapters/conpty-control-helper-client.js.map +1 -0
  97. package/dist/server/modules/terminal/runtime/adapters/conpty-control-helper-process.d.ts +1 -0
  98. package/dist/server/modules/terminal/runtime/adapters/conpty-control-helper-process.js +96 -0
  99. package/dist/server/modules/terminal/runtime/adapters/conpty-control-helper-process.js.map +1 -0
  100. package/dist/server/modules/terminal/runtime/adapters/conpty-runtime-adapter.d.ts +37 -0
  101. package/dist/server/modules/terminal/runtime/adapters/conpty-runtime-adapter.js +123 -0
  102. package/dist/server/modules/terminal/runtime/adapters/conpty-runtime-adapter.js.map +1 -0
  103. package/dist/server/modules/terminal/runtime/adapters/embedded-pty-runtime-adapter.d.ts +12 -5
  104. package/dist/server/modules/terminal/runtime/adapters/embedded-pty-runtime-adapter.js +44 -4
  105. package/dist/server/modules/terminal/runtime/adapters/embedded-pty-runtime-adapter.js.map +1 -1
  106. package/dist/server/modules/terminal/runtime/adapters/tmux-helper-client.d.ts +14 -0
  107. package/dist/server/modules/terminal/runtime/adapters/tmux-helper-client.js +105 -0
  108. package/dist/server/modules/terminal/runtime/adapters/tmux-helper-client.js.map +1 -0
  109. package/dist/server/modules/terminal/runtime/adapters/tmux-helper-process.d.ts +1 -0
  110. package/dist/server/modules/terminal/runtime/adapters/tmux-helper-process.js +67 -0
  111. package/dist/server/modules/terminal/runtime/adapters/tmux-helper-process.js.map +1 -0
  112. package/dist/server/modules/terminal/runtime/adapters/tmux-runtime-adapter.d.ts +8 -12
  113. package/dist/server/modules/terminal/runtime/adapters/tmux-runtime-adapter.js +112 -21
  114. package/dist/server/modules/terminal/runtime/adapters/tmux-runtime-adapter.js.map +1 -1
  115. package/dist/server/modules/terminal/runtime/conpty-runtime-shared.d.ts +25 -0
  116. package/dist/server/modules/terminal/runtime/conpty-runtime-shared.js +124 -0
  117. package/dist/server/modules/terminal/runtime/conpty-runtime-shared.js.map +1 -0
  118. package/dist/server/modules/terminal/runtime/conpty-session-agent-process.d.ts +1 -0
  119. package/dist/server/modules/terminal/runtime/conpty-session-agent-process.js +205 -0
  120. package/dist/server/modules/terminal/runtime/conpty-session-agent-process.js.map +1 -0
  121. package/dist/server/modules/terminal/runtime/conpty-session-attach-client.d.ts +1 -0
  122. package/dist/server/modules/terminal/runtime/conpty-session-attach-client.js +108 -0
  123. package/dist/server/modules/terminal/runtime/conpty-session-attach-client.js.map +1 -0
  124. package/dist/server/modules/terminal/runtime/conpty-session-control-client.d.ts +1 -0
  125. package/dist/server/modules/terminal/runtime/conpty-session-control-client.js +90 -0
  126. package/dist/server/modules/terminal/runtime/conpty-session-control-client.js.map +1 -0
  127. package/dist/server/modules/terminal/runtime/pty-broker-agent-process.d.ts +1 -0
  128. package/dist/server/modules/terminal/runtime/pty-broker-agent-process.js +179 -0
  129. package/dist/server/modules/terminal/runtime/pty-broker-agent-process.js.map +1 -0
  130. package/dist/server/modules/terminal/runtime/pty-broker-client.d.ts +29 -0
  131. package/dist/server/modules/terminal/runtime/pty-broker-client.js +169 -0
  132. package/dist/server/modules/terminal/runtime/pty-broker-client.js.map +1 -0
  133. package/dist/server/modules/terminal/runtime/pty-broker-shared.d.ts +22 -0
  134. package/dist/server/modules/terminal/runtime/pty-broker-shared.js +123 -0
  135. package/dist/server/modules/terminal/runtime/pty-broker-shared.js.map +1 -0
  136. package/dist/server/modules/terminal/runtime/pty-host-attachment-manager.d.ts +1 -0
  137. package/dist/server/modules/terminal/runtime/pty-host-attachment-manager.js +11 -1
  138. package/dist/server/modules/terminal/runtime/pty-host-attachment-manager.js.map +1 -1
  139. package/dist/server/modules/terminal/runtime/terminal-log-file-store.d.ts +1 -0
  140. package/dist/server/modules/terminal/runtime/terminal-log-file-store.js +7 -1
  141. package/dist/server/modules/terminal/runtime/terminal-log-file-store.js.map +1 -1
  142. package/dist/server/modules/terminal/runtime/terminal-log-spooler.js +3 -2
  143. package/dist/server/modules/terminal/runtime/terminal-log-spooler.js.map +1 -1
  144. package/dist/server/modules/terminal/runtime/terminal-runtime-adapter.d.ts +5 -3
  145. package/dist/server/modules/terminal/runtime/terminal-runtime-manager.d.ts +11 -5
  146. package/dist/server/modules/terminal/runtime/terminal-runtime-manager.js +110 -13
  147. package/dist/server/modules/terminal/runtime/terminal-runtime-manager.js.map +1 -1
  148. package/dist/server/modules/terminal/terminal-controller.js +7 -7
  149. package/dist/server/modules/terminal/terminal-controller.js.map +1 -1
  150. package/dist/server/modules/terminal/terminal-service.d.ts +30 -14
  151. package/dist/server/modules/terminal/terminal-service.js +260 -51
  152. package/dist/server/modules/terminal/terminal-service.js.map +1 -1
  153. package/dist/server/modules/terminal/terminal-shell.d.ts +4 -0
  154. package/dist/server/modules/terminal/terminal-shell.js +165 -18
  155. package/dist/server/modules/terminal/terminal-shell.js.map +1 -1
  156. package/dist/server/modules/workbench/workspace-file-watcher.d.ts +30 -0
  157. package/dist/server/modules/workbench/workspace-file-watcher.js +137 -0
  158. package/dist/server/modules/workbench/workspace-file-watcher.js.map +1 -0
  159. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js +43 -7
  160. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js.map +1 -1
  161. package/dist/server/routes/git.js +1 -0
  162. package/dist/server/routes/git.js.map +1 -1
  163. package/dist/server/routes/preferences.d.ts +2 -1
  164. package/dist/server/routes/preferences.js +3 -1
  165. package/dist/server/routes/preferences.js.map +1 -1
  166. package/dist/server/routes/sessions.js +2 -0
  167. package/dist/server/routes/sessions.js.map +1 -1
  168. package/dist/server/server/create-server.d.ts +4 -0
  169. package/dist/server/server/create-server.js +22 -5
  170. package/dist/server/server/create-server.js.map +1 -1
  171. package/dist/server/shared/utils/command-launch.d.ts +6 -0
  172. package/dist/server/shared/utils/command-launch.js +39 -0
  173. package/dist/server/shared/utils/command-launch.js.map +1 -0
  174. package/dist/server/shared/utils/perf-log.d.ts +1 -0
  175. package/dist/server/shared/utils/perf-log.js +8 -2
  176. package/dist/server/shared/utils/perf-log.js.map +1 -1
  177. package/dist/server/shared/utils/permission-debug-log.d.ts +2 -0
  178. package/dist/server/shared/utils/permission-debug-log.js +40 -0
  179. package/dist/server/shared/utils/permission-debug-log.js.map +1 -0
  180. package/dist/server/shared/utils/terminal-debug-log.d.ts +4 -0
  181. package/dist/server/shared/utils/terminal-debug-log.js +71 -0
  182. package/dist/server/shared/utils/terminal-debug-log.js.map +1 -0
  183. package/dist/server/storage/repositories/user-preference-profile-repository.d.ts +8 -0
  184. package/dist/server/storage/repositories/user-preference-profile-repository.js +46 -0
  185. package/dist/server/storage/repositories/user-preference-profile-repository.js.map +1 -0
  186. package/dist/server/storage/sqlite/schema.sql +13 -0
  187. package/dist/server/types/domain.d.ts +28 -1
  188. package/dist/server/ws/terminal-ws-hub.d.ts +2 -0
  189. package/dist/server/ws/terminal-ws-hub.js +42 -5
  190. package/dist/server/ws/terminal-ws-hub.js.map +1 -1
  191. package/dist/server/ws/workbench-ws-hub.d.ts +9 -1
  192. package/dist/server/ws/workbench-ws-hub.js +132 -21
  193. package/dist/server/ws/workbench-ws-hub.js.map +1 -1
  194. package/dist/server/ws/ws-server.d.ts +22 -1
  195. package/dist/server/ws/ws-server.js +134 -46
  196. package/dist/server/ws/ws-server.js.map +1 -1
  197. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.d.ts +4 -1
  198. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.js +107 -6
  199. package/node_modules/@codingns/session-sync-core/dist/claude-message-utils.js.map +1 -1
  200. package/node_modules/@codingns/session-sync-core/dist/patch-builder.d.ts +30 -0
  201. package/node_modules/@codingns/session-sync-core/dist/patch-builder.js +103 -0
  202. package/node_modules/@codingns/session-sync-core/dist/patch-builder.js.map +1 -0
  203. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +1 -1
  204. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +38 -6
  205. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -1
  206. package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +1 -1
  207. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +1 -1
  208. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
  209. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-permissions.d.ts +1 -0
  210. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-permissions.js +8 -0
  211. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-permissions.js.map +1 -0
  212. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.js +87 -7
  213. package/node_modules/@codingns/session-sync-core/dist/providers/opencode-shared.js.map +1 -1
  214. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +1 -1
  215. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +8 -4
  216. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -1
  217. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.d.ts +1 -0
  218. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js +5 -0
  219. package/node_modules/@codingns/session-sync-core/dist/runtime/active-run-registry.js.map +1 -1
  220. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.d.ts +5 -0
  221. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js +114 -6
  222. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js.map +1 -1
  223. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +23 -0
  224. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +721 -18
  225. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
  226. package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.d.ts +3 -0
  227. package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js +106 -23
  228. package/node_modules/@codingns/session-sync-core/dist/runtime/opencode-runtime.js.map +1 -1
  229. package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.d.ts +1 -0
  230. package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.js +3 -0
  231. package/node_modules/@codingns/session-sync-core/dist/runtime/provider-runtime-service.js.map +1 -1
  232. package/node_modules/@codingns/session-sync-core/dist/runtime/types.d.ts +1 -0
  233. package/node_modules/@codingns/session-sync-core/dist/services.d.ts +1 -1
  234. package/node_modules/@codingns/session-sync-core/dist/services.js +2 -2
  235. package/node_modules/@codingns/session-sync-core/dist/services.js.map +1 -1
  236. package/node_modules/@codingns/session-sync-core/dist/types.d.ts +1 -1
  237. package/package.json +6 -2
  238. package/scripts/postinstall.mjs +218 -0
  239. package/dist/public/assets/TerminalPage-Dj_VDew3.js +0 -54
  240. package/dist/public/assets/index-C1GZV2wq.js +0 -106
  241. package/dist/public/assets/index-DU7f8NaZ.css +0 -1
@@ -1,8 +1,11 @@
1
1
  import { randomUUID } from "node:crypto";
2
+ import { spawn } from "node:child_process";
2
3
  import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
3
4
  import { homedir } from "node:os";
4
5
  import { basename, dirname, join, resolve } from "node:path";
6
+ import { createInterface } from "node:readline";
5
7
  import { DatabaseSync } from "node:sqlite";
8
+ import { fileURLToPath, pathToFileURL } from "node:url";
6
9
  import { appendJsonLine, createRawRef, ensureDirectory, extractTextBlocks, messageIdFromRawRef, nextTimestamp, normalizeWorkspacePath } from "../providers/utils.js";
7
10
  import { createCodexThreadPermissionOptions } from "./codex-permissions.js";
8
11
  export class CodexRuntimeAdapter {
@@ -13,29 +16,59 @@ export class CodexRuntimeAdapter {
13
16
  }
14
17
  async startSession(request, sink) {
15
18
  const launchedAtMs = Date.now();
16
- const client = await loadCodexClient();
17
- const thread = client.startThread(createThreadOptions(request));
19
+ const transport = this.options.transportFactory
20
+ ? this.options.transportFactory()
21
+ : createCodexAppServerTransport(this.options);
22
+ await transport.initialize();
18
23
  const abortController = new AbortController();
19
- const streamed = await thread.runStreamed(createCodexInput(request), {
20
- signal: abortController.signal
21
- });
22
- const events = streamed.events[Symbol.asyncIterator]();
23
- const startedSession = await this.awaitThreadStarted(thread, events, request.workspacePath, request.options.content, launchedAtMs);
24
+ const eventQueue = createAsyncEventQueue();
25
+ const startedSession = await transport.startThread(request);
24
26
  const providerSessionId = startedSession.providerSessionId;
25
- const fallbackRawStoreRef = request.rawStoreRef ?? buildRuntimeRawStoreRef(resolveRuntimeStoreKey(providerSessionId, request.sessionId));
27
+ const fallbackRawStoreRef = startedSession.rawStoreRef ??
28
+ request.rawStoreRef ??
29
+ buildRuntimeRawStoreRef(resolveRuntimeStoreKey(providerSessionId, request.sessionId));
26
30
  const resolvedBinding = await this.resolveExistingSessionBinding(providerSessionId, fallbackRawStoreRef, request.workspacePath);
27
31
  const rawStoreRef = resolvedBinding?.rawStoreRef ?? fallbackRawStoreRef;
28
32
  sink.updateSessionBinding({
29
33
  providerSessionId,
30
34
  rawStoreRef
31
35
  });
36
+ transport.setNotificationHandler(async (notification) => {
37
+ const translated = translateCodexAppServerNotification(notification);
38
+ if (translated.turnId) {
39
+ eventQueue.setTurnId(translated.turnId);
40
+ }
41
+ if (translated.event) {
42
+ eventQueue.push(translated.event);
43
+ }
44
+ if (translated.terminal) {
45
+ eventQueue.close();
46
+ }
47
+ });
48
+ transport.setServerRequestHandler(async (serverRequest) => {
49
+ if (!this.options.handleServerRequest) {
50
+ throw new Error("CODEX_APP_SERVER_REQUEST_NOT_SUPPORTED");
51
+ }
52
+ return this.options.handleServerRequest({
53
+ sessionId: request.sessionId,
54
+ providerSessionId,
55
+ request: serverRequest
56
+ });
57
+ });
58
+ await transport.startTurn(request, providerSessionId);
32
59
  return {
33
60
  providerSessionId,
34
61
  rawStoreRef,
35
62
  interrupt: async () => {
36
63
  abortController.abort();
64
+ await transport.interruptTurn().catch(() => {
65
+ return;
66
+ });
67
+ transport.close();
37
68
  },
38
- completed: this.runTurn(null, request, sink, providerSessionId, rawStoreRef, abortController, events, startedSession.bufferedEvents, launchedAtMs)
69
+ completed: this.runTurn(null, request, sink, providerSessionId, rawStoreRef, abortController, eventQueue.iterator, [], launchedAtMs).finally(() => {
70
+ transport.close();
71
+ })
39
72
  };
40
73
  }
41
74
  async continueSession(request, sink) {
@@ -43,31 +76,66 @@ export class CodexRuntimeAdapter {
43
76
  if (!providerSessionId) {
44
77
  throw new Error("PROVIDER_SESSION_ID_REQUIRED");
45
78
  }
46
- const client = await loadCodexClient();
47
- const thread = client.resumeThread(providerSessionId, createThreadOptions(request));
79
+ const transport = this.options.transportFactory
80
+ ? this.options.transportFactory()
81
+ : createCodexAppServerTransport(this.options);
82
+ await transport.initialize();
48
83
  const fallbackRawStoreRef = request.rawStoreRef ?? buildRuntimeRawStoreRef(providerSessionId);
49
84
  const resolvedBinding = await this.resolveExistingSessionBinding(providerSessionId, fallbackRawStoreRef, request.workspacePath);
50
85
  const resolvedSessionId = resolvedBinding?.providerSessionId ?? providerSessionId;
51
- const rawStoreRef = resolvedBinding?.rawStoreRef ?? fallbackRawStoreRef;
86
+ const resumed = await transport.resumeThread(request, resolvedSessionId);
87
+ const rawStoreRef = resolvedBinding?.rawStoreRef ?? resumed.rawStoreRef ?? fallbackRawStoreRef;
52
88
  const abortController = new AbortController();
89
+ const eventQueue = createAsyncEventQueue();
53
90
  sink.updateSessionBinding({
54
91
  providerSessionId: resolvedSessionId,
55
92
  rawStoreRef
56
93
  });
94
+ transport.setNotificationHandler(async (notification) => {
95
+ const translated = translateCodexAppServerNotification(notification);
96
+ if (translated.turnId) {
97
+ eventQueue.setTurnId(translated.turnId);
98
+ }
99
+ if (translated.event) {
100
+ eventQueue.push(translated.event);
101
+ }
102
+ if (translated.terminal) {
103
+ eventQueue.close();
104
+ }
105
+ });
106
+ transport.setServerRequestHandler(async (serverRequest) => {
107
+ if (!this.options.handleServerRequest) {
108
+ throw new Error("CODEX_APP_SERVER_REQUEST_NOT_SUPPORTED");
109
+ }
110
+ return this.options.handleServerRequest({
111
+ sessionId: request.sessionId,
112
+ providerSessionId: resolvedSessionId,
113
+ request: serverRequest
114
+ });
115
+ });
116
+ await transport.startTurn(request, resolvedSessionId);
57
117
  return {
58
118
  providerSessionId: resolvedSessionId,
59
119
  rawStoreRef,
60
120
  interrupt: async () => {
61
121
  abortController.abort();
122
+ await transport.interruptTurn().catch(() => {
123
+ return;
124
+ });
125
+ transport.close();
62
126
  },
63
- completed: this.runTurn(thread, request, sink, resolvedSessionId, rawStoreRef, abortController, undefined, [], Date.now())
127
+ completed: this.runTurn(null, request, sink, resolvedSessionId, rawStoreRef, abortController, eventQueue.iterator, [], Date.now()).finally(() => {
128
+ transport.close();
129
+ })
64
130
  };
65
131
  }
66
132
  async runTurn(thread, request, sink, providerSessionId, rawStoreRef, abortController, preparedEvents, bufferedEvents = [], launchedAtMs = Date.now()) {
67
133
  const context = {
68
134
  providerSessionId,
69
135
  rawStoreRef,
70
- sequence: 0,
136
+ // 运行时消息必须接在历史消息后面,不能每轮都从 1 重新编号,
137
+ // 否则前端会把新 assistant/tool 消息排到旧消息前面,表现成用户消息一直挂在底部。
138
+ sequence: Math.max(0, request.sequenceBase ?? 0),
71
139
  toolNameByCallId: new Map(),
72
140
  sink,
73
141
  workspacePath: request.workspacePath,
@@ -147,12 +215,23 @@ export class CodexRuntimeAdapter {
147
215
  status: "failed",
148
216
  providerSessionId: context.providerSessionId,
149
217
  rawStoreRef: context.rawStoreRef,
150
- errorCode: "CODEX_CLI_TURN_FAILED",
218
+ errorCode: classifyCodexDetailErrorCode(detail, "CODEX_CLI_TURN_FAILED"),
151
219
  detail,
152
220
  timestamp: pickTimestamp(event)
153
221
  });
154
222
  return;
155
223
  }
224
+ if (eventType === "turn.interrupted") {
225
+ await context.sink.emit({
226
+ type: "interrupted",
227
+ status: "interrupted",
228
+ providerSessionId: context.providerSessionId,
229
+ rawStoreRef: context.rawStoreRef,
230
+ detail: "codex turn interrupted",
231
+ timestamp: pickTimestamp(event)
232
+ });
233
+ return;
234
+ }
156
235
  if (interrupted) {
157
236
  return;
158
237
  }
@@ -450,6 +529,392 @@ export class CodexRuntimeAdapter {
450
529
  }
451
530
  }
452
531
  }
532
+ function createCodexAppServerTransport(options) {
533
+ const commandPath = resolveCodexCommand(options.commandPath);
534
+ const launch = resolveCodexCommandLaunch(commandPath, ["app-server"]);
535
+ const child = spawn(launch.command, launch.args, {
536
+ env: process.env,
537
+ stdio: ["pipe", "pipe", "pipe"],
538
+ shell: launch.shell,
539
+ windowsHide: true
540
+ });
541
+ const stdout = createInterface({ input: child.stdout });
542
+ let notificationHandler = () => undefined;
543
+ let serverRequestHandler = async () => {
544
+ throw new Error("CODEX_APP_SERVER_REQUEST_NOT_SUPPORTED");
545
+ };
546
+ let requestSequence = 0;
547
+ let closed = false;
548
+ let activeTurnId = null;
549
+ let activeThreadId = null;
550
+ const pendingResponses = new Map();
551
+ const finalize = (error) => {
552
+ if (closed) {
553
+ return;
554
+ }
555
+ closed = true;
556
+ stdout.close();
557
+ for (const pending of pendingResponses.values()) {
558
+ pending.reject(error ?? new Error("CODEX_APP_SERVER_CLOSED"));
559
+ }
560
+ pendingResponses.clear();
561
+ };
562
+ child.on("error", (error) => {
563
+ finalize(error);
564
+ });
565
+ child.on("exit", (code, signal) => {
566
+ if (closed) {
567
+ return;
568
+ }
569
+ const detail = signal
570
+ ? `codex app-server exited with signal ${signal}`
571
+ : `codex app-server exited with code ${String(code ?? "unknown")}`;
572
+ finalize(new Error(detail));
573
+ });
574
+ stdout.on("line", (line) => {
575
+ const trimmed = line.trim();
576
+ if (!trimmed) {
577
+ return;
578
+ }
579
+ let parsed;
580
+ try {
581
+ parsed = JSON.parse(trimmed);
582
+ }
583
+ catch {
584
+ return;
585
+ }
586
+ if (typeof parsed.method === "string" && parsed.id !== undefined) {
587
+ void Promise.resolve(serverRequestHandler(parsed))
588
+ .then((result) => {
589
+ writeJsonRpcMessage(child, {
590
+ jsonrpc: "2.0",
591
+ id: parsed.id,
592
+ result
593
+ });
594
+ })
595
+ .catch((error) => {
596
+ writeJsonRpcMessage(child, {
597
+ jsonrpc: "2.0",
598
+ id: parsed.id,
599
+ error: {
600
+ code: -32000,
601
+ message: error instanceof Error ? error.message : "CODEX_APP_SERVER_REQUEST_FAILED"
602
+ }
603
+ });
604
+ });
605
+ return;
606
+ }
607
+ if (typeof parsed.method === "string") {
608
+ const method = parsed.method.trim();
609
+ const params = readJsonRpcParams(parsed);
610
+ if (method === "turn/started") {
611
+ activeTurnId = ensureText(readProp(readProp(params, "turn"), "id")).trim() || activeTurnId;
612
+ }
613
+ if (method === "thread/started") {
614
+ activeThreadId = ensureText(readProp(readProp(params, "thread"), "id")).trim() || activeThreadId;
615
+ }
616
+ void notificationHandler({
617
+ method,
618
+ params
619
+ });
620
+ return;
621
+ }
622
+ const responseId = String(parsed.id ?? "");
623
+ const pending = pendingResponses.get(responseId);
624
+ if (!pending) {
625
+ return;
626
+ }
627
+ pendingResponses.delete(responseId);
628
+ if (parsed.error && typeof parsed.error === "object") {
629
+ const message = ensureText(readProp(parsed.error, "message")).trim() || "CODEX_APP_SERVER_ERROR";
630
+ pending.reject(new Error(message));
631
+ return;
632
+ }
633
+ pending.resolve(readJsonRpcResult(parsed));
634
+ });
635
+ return {
636
+ async initialize() {
637
+ await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("initialize", () => ++requestSequence), {
638
+ method: "initialize",
639
+ params: {
640
+ clientInfo: {
641
+ name: "codingns-runtime",
642
+ version: "0.0.0"
643
+ },
644
+ capabilities: null
645
+ }
646
+ });
647
+ writeJsonRpcMessage(child, {
648
+ jsonrpc: "2.0",
649
+ method: "initialized",
650
+ params: {}
651
+ });
652
+ },
653
+ async startThread(request) {
654
+ const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("thread-start", () => ++requestSequence), {
655
+ method: "thread/start",
656
+ params: createThreadStartParams(request)
657
+ });
658
+ const thread = toRecord(result.thread);
659
+ const providerSessionId = ensureText(thread?.id).trim();
660
+ if (!providerSessionId) {
661
+ throw new Error("CODEX_APP_SERVER_THREAD_ID_MISSING");
662
+ }
663
+ activeThreadId = providerSessionId;
664
+ return {
665
+ providerSessionId,
666
+ rawStoreRef: normalizeText(thread?.path) || null
667
+ };
668
+ },
669
+ async resumeThread(request, providerSessionId) {
670
+ const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("thread-resume", () => ++requestSequence), {
671
+ method: "thread/resume",
672
+ params: createThreadResumeParams(request, providerSessionId)
673
+ });
674
+ const thread = toRecord(result.thread);
675
+ activeThreadId = ensureText(thread?.id).trim() || providerSessionId;
676
+ return {
677
+ providerSessionId: activeThreadId,
678
+ rawStoreRef: normalizeText(thread?.path) || null
679
+ };
680
+ },
681
+ async startTurn(request, providerSessionId) {
682
+ const result = await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("turn-start", () => ++requestSequence), {
683
+ method: "turn/start",
684
+ params: createTurnStartParams(request, providerSessionId)
685
+ });
686
+ activeTurnId = ensureText(readProp(readProp(result, "turn"), "id")).trim() || activeTurnId;
687
+ },
688
+ async interruptTurn() {
689
+ if (!activeThreadId || !activeTurnId) {
690
+ return;
691
+ }
692
+ await sendJsonRpcRequest(child, pendingResponses, () => nextJsonRpcId("turn-interrupt", () => ++requestSequence), {
693
+ method: "turn/interrupt",
694
+ params: {
695
+ threadId: activeThreadId,
696
+ turnId: activeTurnId
697
+ }
698
+ });
699
+ },
700
+ setNotificationHandler(handler) {
701
+ notificationHandler = handler;
702
+ },
703
+ setServerRequestHandler(handler) {
704
+ serverRequestHandler = handler;
705
+ },
706
+ close() {
707
+ if (closed) {
708
+ return;
709
+ }
710
+ finalize(null);
711
+ if (!child.stdin.destroyed) {
712
+ child.stdin.end();
713
+ }
714
+ if (!child.killed) {
715
+ child.kill("SIGTERM");
716
+ }
717
+ }
718
+ };
719
+ }
720
+ function createAsyncEventQueue() {
721
+ const values = [];
722
+ const waiters = [];
723
+ let closed = false;
724
+ let turnId = null;
725
+ return {
726
+ iterator: {
727
+ next() {
728
+ if (values.length > 0) {
729
+ return Promise.resolve({
730
+ done: false,
731
+ value: values.shift()
732
+ });
733
+ }
734
+ if (closed) {
735
+ return Promise.resolve({
736
+ done: true,
737
+ value: undefined
738
+ });
739
+ }
740
+ return new Promise((resolve) => {
741
+ waiters.push(resolve);
742
+ });
743
+ }
744
+ },
745
+ push(value) {
746
+ if (closed) {
747
+ return;
748
+ }
749
+ const waiter = waiters.shift();
750
+ if (waiter) {
751
+ waiter({
752
+ done: false,
753
+ value
754
+ });
755
+ return;
756
+ }
757
+ values.push(value);
758
+ },
759
+ close() {
760
+ if (closed) {
761
+ return;
762
+ }
763
+ closed = true;
764
+ while (waiters.length > 0) {
765
+ waiters.shift()?.({
766
+ done: true,
767
+ value: undefined
768
+ });
769
+ }
770
+ },
771
+ setTurnId(nextTurnId) {
772
+ turnId = nextTurnId;
773
+ },
774
+ getTurnId() {
775
+ return turnId;
776
+ }
777
+ };
778
+ }
779
+ function translateCodexAppServerNotification(notification) {
780
+ const method = ensureText(notification.method).trim();
781
+ const params = toRecord(notification.params) ?? {};
782
+ if (method === "turn/started") {
783
+ return {
784
+ event: null,
785
+ terminal: false,
786
+ turnId: ensureText(readProp(readProp(params, "turn"), "id")).trim() || null
787
+ };
788
+ }
789
+ if (method === "turn/completed") {
790
+ const turn = toRecord(params.turn);
791
+ const status = ensureText(turn?.status).trim();
792
+ if (status === "failed") {
793
+ return {
794
+ event: {
795
+ type: "turn.failed",
796
+ timestamp: nextTimestamp(),
797
+ error: ensureText(readProp(turn?.error, "message")).trim() || "codex turn failed"
798
+ },
799
+ terminal: true,
800
+ turnId: ensureText(turn?.id).trim() || null
801
+ };
802
+ }
803
+ if (status === "interrupted") {
804
+ return {
805
+ event: {
806
+ type: "turn.interrupted",
807
+ timestamp: nextTimestamp()
808
+ },
809
+ terminal: true,
810
+ turnId: ensureText(turn?.id).trim() || null
811
+ };
812
+ }
813
+ return {
814
+ event: {
815
+ type: "turn.completed",
816
+ timestamp: nextTimestamp()
817
+ },
818
+ terminal: true,
819
+ turnId: ensureText(turn?.id).trim() || null
820
+ };
821
+ }
822
+ if (method === "item/started" || method === "item/completed") {
823
+ const item = translateCodexAppServerItem(toRecord(params.item));
824
+ if (!item) {
825
+ return {
826
+ event: null,
827
+ terminal: false,
828
+ turnId: null
829
+ };
830
+ }
831
+ return {
832
+ event: {
833
+ type: method === "item/started" ? "item.started" : "item.completed",
834
+ item,
835
+ timestamp: nextTimestamp()
836
+ },
837
+ terminal: false,
838
+ turnId: null
839
+ };
840
+ }
841
+ return {
842
+ event: null,
843
+ terminal: false,
844
+ turnId: null
845
+ };
846
+ }
847
+ function translateCodexAppServerItem(item) {
848
+ if (!item) {
849
+ return null;
850
+ }
851
+ const itemType = ensureText(item.type).trim();
852
+ if (!itemType) {
853
+ return null;
854
+ }
855
+ if (itemType === "agentMessage") {
856
+ return {
857
+ type: "agent_message",
858
+ id: item.id,
859
+ text: item.text
860
+ };
861
+ }
862
+ if (itemType === "reasoning") {
863
+ return {
864
+ type: "reasoning",
865
+ id: item.id,
866
+ text: Array.isArray(item.content) ? item.content.join("\n") : "",
867
+ summary: Array.isArray(item.summary) ? item.summary.join("\n") : ""
868
+ };
869
+ }
870
+ if (itemType === "commandExecution") {
871
+ return {
872
+ type: "command_execution",
873
+ id: item.id,
874
+ command: item.command,
875
+ cwd: item.cwd,
876
+ status: normalizeCodexItemStatus(item.status),
877
+ commandActions: item.commandActions,
878
+ aggregated_output: item.aggregatedOutput,
879
+ exit_code: item.exitCode
880
+ };
881
+ }
882
+ if (itemType === "fileChange") {
883
+ const diffText = buildCodexFileChangeOutput(item.changes);
884
+ return {
885
+ type: "custom_tool_call",
886
+ id: item.id,
887
+ tool: "apply_patch",
888
+ input: diffText,
889
+ output: diffText,
890
+ status: normalizeCodexItemStatus(item.status)
891
+ };
892
+ }
893
+ if (itemType === "mcpToolCall") {
894
+ return {
895
+ type: "mcp_tool_call",
896
+ id: item.id,
897
+ tool: item.tool,
898
+ server: item.server,
899
+ arguments: item.arguments,
900
+ result: item.result,
901
+ error: item.error,
902
+ status: normalizeCodexItemStatus(item.status)
903
+ };
904
+ }
905
+ if (itemType === "dynamicToolCall") {
906
+ return {
907
+ type: "custom_tool_call",
908
+ id: item.id,
909
+ tool: item.tool,
910
+ input: item.arguments,
911
+ output: item.contentItems,
912
+ success: item.success,
913
+ status: normalizeCodexItemStatus(item.status)
914
+ };
915
+ }
916
+ return null;
917
+ }
453
918
  export function createThreadOptions(request) {
454
919
  const options = {
455
920
  workingDirectory: request.workspacePath,
@@ -469,6 +934,61 @@ export function createThreadOptions(request) {
469
934
  }
470
935
  return options;
471
936
  }
937
+ function createThreadStartParams(request) {
938
+ const permissionOptions = createCodexThreadPermissionOptions(request.options.permissionMode ?? "default");
939
+ const params = {
940
+ cwd: request.workspacePath,
941
+ approvalsReviewer: "user"
942
+ };
943
+ if (permissionOptions.approvalPolicy) {
944
+ params.approvalPolicy = permissionOptions.approvalPolicy;
945
+ }
946
+ if (permissionOptions.sandboxMode) {
947
+ params.sandbox = permissionOptions.sandboxMode;
948
+ }
949
+ if (request.options.model) {
950
+ params.model = request.options.model;
951
+ }
952
+ return params;
953
+ }
954
+ function createThreadResumeParams(request, providerSessionId) {
955
+ const permissionOptions = createCodexThreadPermissionOptions(request.options.permissionMode ?? "default");
956
+ const params = {
957
+ threadId: providerSessionId,
958
+ cwd: request.workspacePath,
959
+ approvalsReviewer: "user"
960
+ };
961
+ if (permissionOptions.approvalPolicy) {
962
+ params.approvalPolicy = permissionOptions.approvalPolicy;
963
+ }
964
+ if (permissionOptions.sandboxMode) {
965
+ params.sandbox = permissionOptions.sandboxMode;
966
+ }
967
+ if (request.options.model) {
968
+ params.model = request.options.model;
969
+ }
970
+ return params;
971
+ }
972
+ function createTurnStartParams(request, providerSessionId) {
973
+ const permissionOptions = createCodexThreadPermissionOptions(request.options.permissionMode ?? "default");
974
+ const params = {
975
+ threadId: providerSessionId,
976
+ input: createCodexAppServerInput(request),
977
+ cwd: request.workspacePath,
978
+ approvalsReviewer: "user"
979
+ };
980
+ if (permissionOptions.approvalPolicy) {
981
+ params.approvalPolicy = permissionOptions.approvalPolicy;
982
+ }
983
+ if (request.options.model) {
984
+ params.model = request.options.model;
985
+ }
986
+ const reasoningEffort = normalizeCodexReasoningEffort(request.options.reasoningLevel);
987
+ if (reasoningEffort) {
988
+ params.effort = reasoningEffort;
989
+ }
990
+ return params;
991
+ }
472
992
  function normalizeCodexReasoningEffort(value) {
473
993
  const normalized = value?.trim().toLowerCase() ?? null;
474
994
  if (!normalized) {
@@ -506,21 +1026,143 @@ function createCodexInput(request) {
506
1026
  });
507
1027
  return input;
508
1028
  }
1029
+ function createCodexAppServerInput(request) {
1030
+ const input = [];
1031
+ const promptText = (request.options.providerPrompt ?? request.options.content).trim();
1032
+ if (promptText.length > 0) {
1033
+ input.push({
1034
+ type: "text",
1035
+ text: promptText
1036
+ });
1037
+ }
1038
+ for (const attachment of request.options.attachments) {
1039
+ input.push({
1040
+ type: "localImage",
1041
+ path: attachment.filePath
1042
+ });
1043
+ }
1044
+ return input;
1045
+ }
509
1046
  async function loadCodexClient() {
510
1047
  const moduleName = "@openai/codex-sdk";
511
1048
  const runtimeImport = new Function("name", "return import(name);");
512
- const module = (await runtimeImport(moduleName));
1049
+ const resolvedModuleName = resolveCodexSdkModuleSpecifier(moduleName);
1050
+ const module = (await runtimeImport(resolvedModuleName));
513
1051
  if (!module.Codex) {
514
1052
  throw new Error("CODEX_SDK_UNAVAILABLE");
515
1053
  }
516
1054
  return new module.Codex();
517
1055
  }
1056
+ function resolveCodexSdkModuleSpecifier(moduleName) {
1057
+ const localSdkEntry = findNodeModulesFile(dirname(fileURLToPath(import.meta.url)), ["@openai", "codex-sdk", "dist", "index.js"]);
1058
+ if (localSdkEntry) {
1059
+ return pathToFileURL(localSdkEntry).href;
1060
+ }
1061
+ if (typeof import.meta.resolve === "function") {
1062
+ return import.meta.resolve(moduleName);
1063
+ }
1064
+ return moduleName;
1065
+ }
1066
+ function findNodeModulesFile(startDirectory, relativeSegments) {
1067
+ let currentDirectory = startDirectory;
1068
+ while (true) {
1069
+ const candidate = resolveNodeModulesCandidate(currentDirectory, relativeSegments);
1070
+ if (existsSync(candidate)) {
1071
+ return candidate;
1072
+ }
1073
+ const parentDirectory = dirname(currentDirectory);
1074
+ if (parentDirectory === currentDirectory) {
1075
+ return null;
1076
+ }
1077
+ currentDirectory = parentDirectory;
1078
+ }
1079
+ }
1080
+ function resolveNodeModulesCandidate(currentDirectory, relativeSegments) {
1081
+ if (basename(currentDirectory) === "node_modules") {
1082
+ return resolve(currentDirectory, ...relativeSegments);
1083
+ }
1084
+ return resolve(currentDirectory, "node_modules", ...relativeSegments);
1085
+ }
518
1086
  function buildRuntimeRawStoreRef(providerSessionId) {
519
1087
  return resolve(process.cwd(), "runtime", "codex", `${providerSessionId}.stream`);
520
1088
  }
521
1089
  function resolveRuntimeStoreKey(providerSessionId, sessionId) {
522
1090
  return providerSessionId.trim() || sessionId;
523
1091
  }
1092
+ function resolveCodexCommand(explicitPath) {
1093
+ const explicitCandidate = explicitPath?.trim() ||
1094
+ process.env.CODINGNS_CODEX_COMMAND?.trim() ||
1095
+ "codex";
1096
+ return explicitCandidate;
1097
+ }
1098
+ function resolveCodexCommandLaunch(commandPath, args) {
1099
+ const normalizedCommandPath = commandPath.trim();
1100
+ if (isNodeScriptPath(normalizedCommandPath)) {
1101
+ return {
1102
+ command: process.execPath,
1103
+ args: [normalizedCommandPath, ...args],
1104
+ shell: false
1105
+ };
1106
+ }
1107
+ return {
1108
+ command: normalizedCommandPath,
1109
+ args: [...args],
1110
+ shell: shouldSpawnViaShellOnWindows(normalizedCommandPath)
1111
+ };
1112
+ }
1113
+ function isNodeScriptPath(commandPath) {
1114
+ return /\.(?:c|m)?js$/i.test(commandPath);
1115
+ }
1116
+ function shouldSpawnViaShellOnWindows(commandPath) {
1117
+ if (process.platform !== "win32") {
1118
+ return false;
1119
+ }
1120
+ if (/\.(cmd|bat)$/i.test(commandPath)) {
1121
+ return true;
1122
+ }
1123
+ // Windows 上裸名命令(无扩展名、无路径分隔符)需要 shell 才能从 PATH 解析 .cmd 文件
1124
+ const extension = commandPath.split(".").pop()?.toLowerCase();
1125
+ const hasPathSep = commandPath.includes("\\") || commandPath.includes("/");
1126
+ if (!extension || extension === commandPath.toLowerCase()) {
1127
+ if (!hasPathSep) {
1128
+ return true;
1129
+ }
1130
+ }
1131
+ return false;
1132
+ }
1133
+ function nextJsonRpcId(prefix, allocate) {
1134
+ return `${prefix}:${allocate()}`;
1135
+ }
1136
+ function writeJsonRpcMessage(child, payload) {
1137
+ if (!child.stdin || child.stdin.destroyed || !child.stdin.writable) {
1138
+ throw new Error("CODEX_APP_SERVER_STDIN_UNAVAILABLE");
1139
+ }
1140
+ child.stdin.write(`${JSON.stringify(payload)}\n`, "utf8");
1141
+ }
1142
+ function sendJsonRpcRequest(child, pendingResponses, createRequestId, input) {
1143
+ const id = createRequestId();
1144
+ return new Promise((resolve, reject) => {
1145
+ pendingResponses.set(id, { resolve, reject });
1146
+ try {
1147
+ writeJsonRpcMessage(child, {
1148
+ jsonrpc: "2.0",
1149
+ id,
1150
+ method: input.method,
1151
+ params: input.params
1152
+ });
1153
+ }
1154
+ catch (error) {
1155
+ pendingResponses.delete(id);
1156
+ reject(error instanceof Error ? error : new Error("CODEX_APP_SERVER_REQUEST_WRITE_FAILED"));
1157
+ }
1158
+ });
1159
+ }
1160
+ function readJsonRpcParams(parsed) {
1161
+ return toRecord(parsed.params) ?? {};
1162
+ }
1163
+ function readJsonRpcResult(parsed) {
1164
+ return toRecord(parsed.result) ?? {};
1165
+ }
524
1166
  function resolveResumeThreadId(providerSessionId, rawStoreRef) {
525
1167
  const normalizedProviderSessionId = ensureText(providerSessionId).trim();
526
1168
  const fromRawStore = readThreadIdFromRawStore(rawStoreRef);
@@ -538,6 +1180,12 @@ function readProp(value, key) {
538
1180
  }
539
1181
  return value[key];
540
1182
  }
1183
+ function toRecord(value) {
1184
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1185
+ return null;
1186
+ }
1187
+ return value;
1188
+ }
541
1189
  function ensureText(value) {
542
1190
  if (typeof value === "string") {
543
1191
  return value;
@@ -552,6 +1200,10 @@ function ensureText(value) {
552
1200
  return String(value);
553
1201
  }
554
1202
  }
1203
+ function normalizeText(value) {
1204
+ const normalized = ensureText(value).trim();
1205
+ return normalized.length > 0 ? normalized : null;
1206
+ }
555
1207
  function readThreadIdFromRawStore(rawStoreRef) {
556
1208
  const filePath = ensureText(rawStoreRef).trim();
557
1209
  if (!filePath || !existsSync(filePath)) {
@@ -683,9 +1335,14 @@ function pickFirstNonEmpty(...values) {
683
1335
  }
684
1336
  function isToolItem(itemType) {
685
1337
  return (itemType === "command_execution" ||
1338
+ itemType === "file_change" ||
686
1339
  itemType === "mcp_tool_call" ||
687
1340
  itemType === "function_call" ||
688
- itemType === "custom_tool_call");
1341
+ itemType === "custom_tool_call" ||
1342
+ itemType === "commandExecution" ||
1343
+ itemType === "fileChange" ||
1344
+ itemType === "mcpToolCall" ||
1345
+ itemType === "dynamicToolCall");
689
1346
  }
690
1347
  function inferToolSuccess(item, output) {
691
1348
  const status = ensureText(readProp(item, "status")).trim().toLowerCase();
@@ -726,10 +1383,23 @@ function classifyCodexRuntimeFailure(error) {
726
1383
  };
727
1384
  }
728
1385
  return {
729
- errorCode: "CODEX_RUNTIME_ERROR",
1386
+ errorCode: classifyCodexDetailErrorCode(detail, "CODEX_RUNTIME_ERROR"),
730
1387
  detail
731
1388
  };
732
1389
  }
1390
+ function classifyCodexDetailErrorCode(detail, fallback) {
1391
+ const normalized = detail.trim();
1392
+ if (!normalized) {
1393
+ return fallback;
1394
+ }
1395
+ const statusMatch = normalized.match(/\bstatus\s+(\d{3})\b/i)
1396
+ ?? normalized.match(/\bHTTP\s+(\d{3})\b/i)
1397
+ ?? normalized.match(/\b(\d{3})\s+(?:Bad Gateway|Too Many Requests|Gateway Timeout|Service Unavailable)\b/i);
1398
+ if (!statusMatch) {
1399
+ return fallback;
1400
+ }
1401
+ return `CODEX_HTTP_${statusMatch[1]}`;
1402
+ }
733
1403
  function persistSyntheticUserMessageIfNeeded(rawStoreRef, providerSessionId, input) {
734
1404
  if (!isSyntheticRawStoreRef(rawStoreRef) || input.content.trim().length === 0) {
735
1405
  return;
@@ -889,4 +1559,37 @@ function mapToolStartItemType(itemType) {
889
1559
  function mapToolResultItemType(itemType) {
890
1560
  return itemType === "custom_tool_call" ? "custom_tool_call_output" : "function_call_output";
891
1561
  }
1562
+ function normalizeCodexItemStatus(value) {
1563
+ const normalized = ensureText(value).trim();
1564
+ if (!normalized) {
1565
+ return "in_progress";
1566
+ }
1567
+ if (normalized === "inProgress") {
1568
+ return "running";
1569
+ }
1570
+ if (normalized === "declined") {
1571
+ return "failed";
1572
+ }
1573
+ return normalized;
1574
+ }
1575
+ function buildCodexFileChangeOutput(value) {
1576
+ if (!Array.isArray(value)) {
1577
+ return "";
1578
+ }
1579
+ return value
1580
+ .map((change) => {
1581
+ const record = toRecord(change);
1582
+ if (!record) {
1583
+ return "";
1584
+ }
1585
+ const diff = ensureText(record.diff).trim();
1586
+ if (diff.length > 0) {
1587
+ return diff;
1588
+ }
1589
+ const path = ensureText(record.path).trim();
1590
+ return path.length > 0 ? `Updated ${path}` : "";
1591
+ })
1592
+ .filter((entry) => entry.length > 0)
1593
+ .join("\n\n");
1594
+ }
892
1595
  //# sourceMappingURL=codex-runtime.js.map