@renseiai/agentfactory 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +125 -0
  3. package/dist/src/config/index.d.ts +3 -0
  4. package/dist/src/config/index.d.ts.map +1 -0
  5. package/dist/src/config/index.js +1 -0
  6. package/dist/src/config/repository-config.d.ts +44 -0
  7. package/dist/src/config/repository-config.d.ts.map +1 -0
  8. package/dist/src/config/repository-config.js +88 -0
  9. package/dist/src/config/repository-config.test.d.ts +2 -0
  10. package/dist/src/config/repository-config.test.d.ts.map +1 -0
  11. package/dist/src/config/repository-config.test.js +249 -0
  12. package/dist/src/deployment/deployment-checker.d.ts +110 -0
  13. package/dist/src/deployment/deployment-checker.d.ts.map +1 -0
  14. package/dist/src/deployment/deployment-checker.js +242 -0
  15. package/dist/src/deployment/index.d.ts +3 -0
  16. package/dist/src/deployment/index.d.ts.map +1 -0
  17. package/dist/src/deployment/index.js +2 -0
  18. package/dist/src/frontend/index.d.ts +2 -0
  19. package/dist/src/frontend/index.d.ts.map +1 -0
  20. package/dist/src/frontend/index.js +1 -0
  21. package/dist/src/frontend/types.d.ts +106 -0
  22. package/dist/src/frontend/types.d.ts.map +1 -0
  23. package/dist/src/frontend/types.js +11 -0
  24. package/dist/src/governor/decision-engine.d.ts +52 -0
  25. package/dist/src/governor/decision-engine.d.ts.map +1 -0
  26. package/dist/src/governor/decision-engine.js +220 -0
  27. package/dist/src/governor/decision-engine.test.d.ts +2 -0
  28. package/dist/src/governor/decision-engine.test.d.ts.map +1 -0
  29. package/dist/src/governor/decision-engine.test.js +629 -0
  30. package/dist/src/governor/event-bus.d.ts +43 -0
  31. package/dist/src/governor/event-bus.d.ts.map +1 -0
  32. package/dist/src/governor/event-bus.js +8 -0
  33. package/dist/src/governor/event-deduplicator.d.ts +43 -0
  34. package/dist/src/governor/event-deduplicator.d.ts.map +1 -0
  35. package/dist/src/governor/event-deduplicator.js +53 -0
  36. package/dist/src/governor/event-driven-governor.d.ts +131 -0
  37. package/dist/src/governor/event-driven-governor.d.ts.map +1 -0
  38. package/dist/src/governor/event-driven-governor.js +379 -0
  39. package/dist/src/governor/event-driven-governor.test.d.ts +2 -0
  40. package/dist/src/governor/event-driven-governor.test.d.ts.map +1 -0
  41. package/dist/src/governor/event-driven-governor.test.js +673 -0
  42. package/dist/src/governor/event-types.d.ts +78 -0
  43. package/dist/src/governor/event-types.d.ts.map +1 -0
  44. package/dist/src/governor/event-types.js +32 -0
  45. package/dist/src/governor/governor-types.d.ts +82 -0
  46. package/dist/src/governor/governor-types.d.ts.map +1 -0
  47. package/dist/src/governor/governor-types.js +21 -0
  48. package/dist/src/governor/governor.d.ts +100 -0
  49. package/dist/src/governor/governor.d.ts.map +1 -0
  50. package/dist/src/governor/governor.js +262 -0
  51. package/dist/src/governor/governor.test.d.ts +2 -0
  52. package/dist/src/governor/governor.test.d.ts.map +1 -0
  53. package/dist/src/governor/governor.test.js +514 -0
  54. package/dist/src/governor/human-touchpoints.d.ts +131 -0
  55. package/dist/src/governor/human-touchpoints.d.ts.map +1 -0
  56. package/dist/src/governor/human-touchpoints.js +251 -0
  57. package/dist/src/governor/human-touchpoints.test.d.ts +2 -0
  58. package/dist/src/governor/human-touchpoints.test.d.ts.map +1 -0
  59. package/dist/src/governor/human-touchpoints.test.js +366 -0
  60. package/dist/src/governor/in-memory-event-bus.d.ts +29 -0
  61. package/dist/src/governor/in-memory-event-bus.d.ts.map +1 -0
  62. package/dist/src/governor/in-memory-event-bus.js +79 -0
  63. package/dist/src/governor/index.d.ts +14 -0
  64. package/dist/src/governor/index.d.ts.map +1 -0
  65. package/dist/src/governor/index.js +13 -0
  66. package/dist/src/governor/override-parser.d.ts +60 -0
  67. package/dist/src/governor/override-parser.d.ts.map +1 -0
  68. package/dist/src/governor/override-parser.js +98 -0
  69. package/dist/src/governor/override-parser.test.d.ts +2 -0
  70. package/dist/src/governor/override-parser.test.d.ts.map +1 -0
  71. package/dist/src/governor/override-parser.test.js +312 -0
  72. package/dist/src/governor/platform-adapter.d.ts +69 -0
  73. package/dist/src/governor/platform-adapter.d.ts.map +1 -0
  74. package/dist/src/governor/platform-adapter.js +11 -0
  75. package/dist/src/governor/processing-state.d.ts +66 -0
  76. package/dist/src/governor/processing-state.d.ts.map +1 -0
  77. package/dist/src/governor/processing-state.js +43 -0
  78. package/dist/src/governor/processing-state.test.d.ts +2 -0
  79. package/dist/src/governor/processing-state.test.d.ts.map +1 -0
  80. package/dist/src/governor/processing-state.test.js +96 -0
  81. package/dist/src/governor/top-of-funnel.d.ts +118 -0
  82. package/dist/src/governor/top-of-funnel.d.ts.map +1 -0
  83. package/dist/src/governor/top-of-funnel.js +168 -0
  84. package/dist/src/governor/top-of-funnel.test.d.ts +2 -0
  85. package/dist/src/governor/top-of-funnel.test.d.ts.map +1 -0
  86. package/dist/src/governor/top-of-funnel.test.js +331 -0
  87. package/dist/src/index.d.ts +11 -0
  88. package/dist/src/index.d.ts.map +1 -0
  89. package/dist/src/index.js +10 -0
  90. package/dist/src/linear-cli.d.ts +38 -0
  91. package/dist/src/linear-cli.d.ts.map +1 -0
  92. package/dist/src/linear-cli.js +674 -0
  93. package/dist/src/logger.d.ts +117 -0
  94. package/dist/src/logger.d.ts.map +1 -0
  95. package/dist/src/logger.js +430 -0
  96. package/dist/src/manifest/generate.d.ts +20 -0
  97. package/dist/src/manifest/generate.d.ts.map +1 -0
  98. package/dist/src/manifest/generate.js +65 -0
  99. package/dist/src/manifest/index.d.ts +4 -0
  100. package/dist/src/manifest/index.d.ts.map +1 -0
  101. package/dist/src/manifest/index.js +2 -0
  102. package/dist/src/manifest/route-manifest.d.ts +34 -0
  103. package/dist/src/manifest/route-manifest.d.ts.map +1 -0
  104. package/dist/src/manifest/route-manifest.js +148 -0
  105. package/dist/src/orchestrator/activity-emitter.d.ts +119 -0
  106. package/dist/src/orchestrator/activity-emitter.d.ts.map +1 -0
  107. package/dist/src/orchestrator/activity-emitter.js +306 -0
  108. package/dist/src/orchestrator/api-activity-emitter.d.ts +167 -0
  109. package/dist/src/orchestrator/api-activity-emitter.d.ts.map +1 -0
  110. package/dist/src/orchestrator/api-activity-emitter.js +417 -0
  111. package/dist/src/orchestrator/heartbeat-writer.d.ts +57 -0
  112. package/dist/src/orchestrator/heartbeat-writer.d.ts.map +1 -0
  113. package/dist/src/orchestrator/heartbeat-writer.js +137 -0
  114. package/dist/src/orchestrator/index.d.ts +20 -0
  115. package/dist/src/orchestrator/index.d.ts.map +1 -0
  116. package/dist/src/orchestrator/index.js +22 -0
  117. package/dist/src/orchestrator/log-analyzer.d.ts +160 -0
  118. package/dist/src/orchestrator/log-analyzer.d.ts.map +1 -0
  119. package/dist/src/orchestrator/log-analyzer.js +572 -0
  120. package/dist/src/orchestrator/log-config.d.ts +39 -0
  121. package/dist/src/orchestrator/log-config.d.ts.map +1 -0
  122. package/dist/src/orchestrator/log-config.js +45 -0
  123. package/dist/src/orchestrator/orchestrator.d.ts +316 -0
  124. package/dist/src/orchestrator/orchestrator.d.ts.map +1 -0
  125. package/dist/src/orchestrator/orchestrator.js +3290 -0
  126. package/dist/src/orchestrator/parse-work-result.d.ts +16 -0
  127. package/dist/src/orchestrator/parse-work-result.d.ts.map +1 -0
  128. package/dist/src/orchestrator/parse-work-result.js +135 -0
  129. package/dist/src/orchestrator/parse-work-result.test.d.ts +2 -0
  130. package/dist/src/orchestrator/parse-work-result.test.d.ts.map +1 -0
  131. package/dist/src/orchestrator/parse-work-result.test.js +234 -0
  132. package/dist/src/orchestrator/progress-logger.d.ts +72 -0
  133. package/dist/src/orchestrator/progress-logger.d.ts.map +1 -0
  134. package/dist/src/orchestrator/progress-logger.js +135 -0
  135. package/dist/src/orchestrator/session-logger.d.ts +159 -0
  136. package/dist/src/orchestrator/session-logger.d.ts.map +1 -0
  137. package/dist/src/orchestrator/session-logger.js +275 -0
  138. package/dist/src/orchestrator/state-recovery.d.ts +96 -0
  139. package/dist/src/orchestrator/state-recovery.d.ts.map +1 -0
  140. package/dist/src/orchestrator/state-recovery.js +302 -0
  141. package/dist/src/orchestrator/state-types.d.ts +165 -0
  142. package/dist/src/orchestrator/state-types.d.ts.map +1 -0
  143. package/dist/src/orchestrator/state-types.js +7 -0
  144. package/dist/src/orchestrator/stream-parser.d.ts +151 -0
  145. package/dist/src/orchestrator/stream-parser.d.ts.map +1 -0
  146. package/dist/src/orchestrator/stream-parser.js +137 -0
  147. package/dist/src/orchestrator/types.d.ts +232 -0
  148. package/dist/src/orchestrator/types.d.ts.map +1 -0
  149. package/dist/src/orchestrator/types.js +4 -0
  150. package/dist/src/orchestrator/validate-git-remote.test.d.ts +2 -0
  151. package/dist/src/orchestrator/validate-git-remote.test.d.ts.map +1 -0
  152. package/dist/src/orchestrator/validate-git-remote.test.js +61 -0
  153. package/dist/src/providers/a2a-auth.d.ts +81 -0
  154. package/dist/src/providers/a2a-auth.d.ts.map +1 -0
  155. package/dist/src/providers/a2a-auth.js +188 -0
  156. package/dist/src/providers/a2a-auth.test.d.ts +2 -0
  157. package/dist/src/providers/a2a-auth.test.d.ts.map +1 -0
  158. package/dist/src/providers/a2a-auth.test.js +232 -0
  159. package/dist/src/providers/a2a-provider.d.ts +254 -0
  160. package/dist/src/providers/a2a-provider.d.ts.map +1 -0
  161. package/dist/src/providers/a2a-provider.integration.test.d.ts +9 -0
  162. package/dist/src/providers/a2a-provider.integration.test.d.ts.map +1 -0
  163. package/dist/src/providers/a2a-provider.integration.test.js +665 -0
  164. package/dist/src/providers/a2a-provider.js +811 -0
  165. package/dist/src/providers/a2a-provider.test.d.ts +2 -0
  166. package/dist/src/providers/a2a-provider.test.d.ts.map +1 -0
  167. package/dist/src/providers/a2a-provider.test.js +681 -0
  168. package/dist/src/providers/amp-provider.d.ts +20 -0
  169. package/dist/src/providers/amp-provider.d.ts.map +1 -0
  170. package/dist/src/providers/amp-provider.js +24 -0
  171. package/dist/src/providers/claude-provider.d.ts +18 -0
  172. package/dist/src/providers/claude-provider.d.ts.map +1 -0
  173. package/dist/src/providers/claude-provider.js +437 -0
  174. package/dist/src/providers/codex-provider.d.ts +133 -0
  175. package/dist/src/providers/codex-provider.d.ts.map +1 -0
  176. package/dist/src/providers/codex-provider.js +381 -0
  177. package/dist/src/providers/codex-provider.test.d.ts +2 -0
  178. package/dist/src/providers/codex-provider.test.d.ts.map +1 -0
  179. package/dist/src/providers/codex-provider.test.js +387 -0
  180. package/dist/src/providers/index.d.ts +44 -0
  181. package/dist/src/providers/index.d.ts.map +1 -0
  182. package/dist/src/providers/index.js +85 -0
  183. package/dist/src/providers/spring-ai-provider.d.ts +90 -0
  184. package/dist/src/providers/spring-ai-provider.d.ts.map +1 -0
  185. package/dist/src/providers/spring-ai-provider.integration.test.d.ts +13 -0
  186. package/dist/src/providers/spring-ai-provider.integration.test.d.ts.map +1 -0
  187. package/dist/src/providers/spring-ai-provider.integration.test.js +351 -0
  188. package/dist/src/providers/spring-ai-provider.js +317 -0
  189. package/dist/src/providers/spring-ai-provider.test.d.ts +2 -0
  190. package/dist/src/providers/spring-ai-provider.test.d.ts.map +1 -0
  191. package/dist/src/providers/spring-ai-provider.test.js +200 -0
  192. package/dist/src/providers/types.d.ts +165 -0
  193. package/dist/src/providers/types.d.ts.map +1 -0
  194. package/dist/src/providers/types.js +13 -0
  195. package/dist/src/templates/adapters.d.ts +51 -0
  196. package/dist/src/templates/adapters.d.ts.map +1 -0
  197. package/dist/src/templates/adapters.js +104 -0
  198. package/dist/src/templates/adapters.test.d.ts +2 -0
  199. package/dist/src/templates/adapters.test.d.ts.map +1 -0
  200. package/dist/src/templates/adapters.test.js +165 -0
  201. package/dist/src/templates/agent-definition.d.ts +85 -0
  202. package/dist/src/templates/agent-definition.d.ts.map +1 -0
  203. package/dist/src/templates/agent-definition.js +97 -0
  204. package/dist/src/templates/agent-definition.test.d.ts +2 -0
  205. package/dist/src/templates/agent-definition.test.d.ts.map +1 -0
  206. package/dist/src/templates/agent-definition.test.js +209 -0
  207. package/dist/src/templates/index.d.ts +14 -0
  208. package/dist/src/templates/index.d.ts.map +1 -0
  209. package/dist/src/templates/index.js +11 -0
  210. package/dist/src/templates/loader.d.ts +41 -0
  211. package/dist/src/templates/loader.d.ts.map +1 -0
  212. package/dist/src/templates/loader.js +114 -0
  213. package/dist/src/templates/registry.d.ts +80 -0
  214. package/dist/src/templates/registry.d.ts.map +1 -0
  215. package/dist/src/templates/registry.js +177 -0
  216. package/dist/src/templates/registry.test.d.ts +2 -0
  217. package/dist/src/templates/registry.test.d.ts.map +1 -0
  218. package/dist/src/templates/registry.test.js +198 -0
  219. package/dist/src/templates/renderer.d.ts +29 -0
  220. package/dist/src/templates/renderer.d.ts.map +1 -0
  221. package/dist/src/templates/renderer.js +35 -0
  222. package/dist/src/templates/strategy-templates.test.d.ts +2 -0
  223. package/dist/src/templates/strategy-templates.test.d.ts.map +1 -0
  224. package/dist/src/templates/strategy-templates.test.js +619 -0
  225. package/dist/src/templates/types.d.ts +233 -0
  226. package/dist/src/templates/types.d.ts.map +1 -0
  227. package/dist/src/templates/types.js +127 -0
  228. package/dist/src/templates/types.test.d.ts +2 -0
  229. package/dist/src/templates/types.test.d.ts.map +1 -0
  230. package/dist/src/templates/types.test.js +232 -0
  231. package/dist/src/tools/index.d.ts +6 -0
  232. package/dist/src/tools/index.d.ts.map +1 -0
  233. package/dist/src/tools/index.js +3 -0
  234. package/dist/src/tools/linear-runner.d.ts +34 -0
  235. package/dist/src/tools/linear-runner.d.ts.map +1 -0
  236. package/dist/src/tools/linear-runner.js +700 -0
  237. package/dist/src/tools/plugins/linear.d.ts +9 -0
  238. package/dist/src/tools/plugins/linear.d.ts.map +1 -0
  239. package/dist/src/tools/plugins/linear.js +138 -0
  240. package/dist/src/tools/registry.d.ts +9 -0
  241. package/dist/src/tools/registry.d.ts.map +1 -0
  242. package/dist/src/tools/registry.js +18 -0
  243. package/dist/src/tools/types.d.ts +18 -0
  244. package/dist/src/tools/types.d.ts.map +1 -0
  245. package/dist/src/tools/types.js +1 -0
  246. package/package.json +78 -0
@@ -0,0 +1,381 @@
1
+ /**
2
+ * OpenAI Codex Agent Provider
3
+ *
4
+ * Spawns the `codex` CLI (from @openai/codex) as a child process and parses
5
+ * its JSONL event stream into normalized AgentEvents.
6
+ *
7
+ * CLI invocation patterns:
8
+ * New session: codex exec --json --full-auto -C <cwd> "<prompt>"
9
+ * Resume: codex exec resume --json --full-auto <session_id> "<prompt>"
10
+ *
11
+ * JSONL event types:
12
+ * thread.started → init (sessionId)
13
+ * turn.started → system (turn_started)
14
+ * turn.completed → result (success, usage)
15
+ * turn.failed → result (failure)
16
+ * item.* → tool_use / tool_result / assistant_text / system
17
+ * error → error
18
+ */
19
+ import { spawn } from 'child_process';
20
+ import { createInterface } from 'readline';
21
+ /**
22
+ * Map a single Codex JSONL event to one or more normalized AgentEvents.
23
+ * Exported for unit testing — the AgentHandle uses this internally.
24
+ */
25
+ export function mapCodexEvent(event, state) {
26
+ switch (event.type) {
27
+ case 'thread.started':
28
+ state.sessionId = event.thread_id;
29
+ return [{
30
+ type: 'init',
31
+ sessionId: event.thread_id,
32
+ raw: event,
33
+ }];
34
+ case 'turn.started':
35
+ state.turnCount++;
36
+ return [{
37
+ type: 'system',
38
+ subtype: 'turn_started',
39
+ message: `Turn ${state.turnCount} started`,
40
+ raw: event,
41
+ }];
42
+ case 'turn.completed':
43
+ if (event.usage) {
44
+ state.totalInputTokens += event.usage.input_tokens ?? 0;
45
+ state.totalOutputTokens += event.usage.output_tokens ?? 0;
46
+ }
47
+ return [{
48
+ type: 'result',
49
+ success: true,
50
+ cost: {
51
+ inputTokens: state.totalInputTokens || undefined,
52
+ outputTokens: state.totalOutputTokens || undefined,
53
+ numTurns: state.turnCount || undefined,
54
+ },
55
+ raw: event,
56
+ }];
57
+ case 'turn.failed':
58
+ return [{
59
+ type: 'result',
60
+ success: false,
61
+ errors: [event.error?.message ?? 'Turn failed'],
62
+ errorSubtype: 'turn_failed',
63
+ raw: event,
64
+ }];
65
+ case 'item.started':
66
+ case 'item.updated':
67
+ case 'item.completed':
68
+ return mapCodexItemEvent(event);
69
+ case 'error':
70
+ return [{
71
+ type: 'error',
72
+ message: event.message ?? 'Unknown error',
73
+ raw: event,
74
+ }];
75
+ default:
76
+ return [{
77
+ type: 'system',
78
+ subtype: 'unknown',
79
+ message: `Unhandled Codex event type: ${event.type}`,
80
+ raw: event,
81
+ }];
82
+ }
83
+ }
84
+ /**
85
+ * Map a Codex item event to AgentEvents.
86
+ * Exported for unit testing.
87
+ */
88
+ export function mapCodexItemEvent(event) {
89
+ const item = event.item;
90
+ const eventType = event.type;
91
+ switch (item.type) {
92
+ case 'agent_message':
93
+ return [{
94
+ type: 'assistant_text',
95
+ text: item.text,
96
+ raw: event,
97
+ }];
98
+ case 'reasoning':
99
+ return [{
100
+ type: 'system',
101
+ subtype: 'reasoning',
102
+ message: item.text,
103
+ raw: event,
104
+ }];
105
+ case 'command_execution':
106
+ if (eventType === 'item.started') {
107
+ return [{
108
+ type: 'tool_use',
109
+ toolName: 'shell',
110
+ toolUseId: item.id,
111
+ input: { command: item.command },
112
+ raw: event,
113
+ }];
114
+ }
115
+ if (eventType === 'item.completed') {
116
+ return [{
117
+ type: 'tool_result',
118
+ toolName: 'shell',
119
+ toolUseId: item.id,
120
+ content: item.aggregated_output || '',
121
+ isError: item.status === 'failed' || (item.exit_code !== undefined && item.exit_code !== 0),
122
+ raw: event,
123
+ }];
124
+ }
125
+ return [{
126
+ type: 'system',
127
+ subtype: 'command_progress',
128
+ message: `Command: ${item.command} (${item.status})`,
129
+ raw: event,
130
+ }];
131
+ case 'file_change':
132
+ return [{
133
+ type: 'tool_result',
134
+ toolName: 'file_change',
135
+ toolUseId: item.id,
136
+ content: item.changes.map((c) => `${c.kind}: ${c.path}`).join('\n'),
137
+ isError: item.status === 'failed',
138
+ raw: event,
139
+ }];
140
+ case 'mcp_tool_call':
141
+ if (eventType === 'item.started') {
142
+ return [{
143
+ type: 'tool_use',
144
+ toolName: `mcp:${item.server}/${item.tool}`,
145
+ toolUseId: item.id,
146
+ input: (item.arguments ?? {}),
147
+ raw: event,
148
+ }];
149
+ }
150
+ if (eventType === 'item.completed') {
151
+ const isError = item.status === 'failed' || !!item.error;
152
+ const content = item.error?.message
153
+ ?? (item.result?.content ? JSON.stringify(item.result.content) : '');
154
+ return [{
155
+ type: 'tool_result',
156
+ toolName: `mcp:${item.server}/${item.tool}`,
157
+ toolUseId: item.id,
158
+ content,
159
+ isError,
160
+ raw: event,
161
+ }];
162
+ }
163
+ return [];
164
+ case 'todo_list':
165
+ return [{
166
+ type: 'system',
167
+ subtype: 'todo_list',
168
+ message: item.items.map((t) => `${t.completed ? '[x]' : '[ ]'} ${t.text}`).join('\n'),
169
+ raw: event,
170
+ }];
171
+ case 'error':
172
+ return [{
173
+ type: 'error',
174
+ message: item.message,
175
+ raw: event,
176
+ }];
177
+ default:
178
+ return [{
179
+ type: 'system',
180
+ subtype: 'unknown_item',
181
+ message: `Unhandled Codex item type: ${item.type}`,
182
+ raw: event,
183
+ }];
184
+ }
185
+ }
186
+ // ---------------------------------------------------------------------------
187
+ // Provider
188
+ // ---------------------------------------------------------------------------
189
+ export class CodexProvider {
190
+ name = 'codex';
191
+ spawn(config) {
192
+ return this.createHandle(config);
193
+ }
194
+ resume(sessionId, config) {
195
+ return this.createHandle(config, sessionId);
196
+ }
197
+ createHandle(config, resumeSessionId) {
198
+ const abortController = config.abortController;
199
+ // Resolve the codex binary — prefer CODEX_BIN env var, then fall back to 'codex'
200
+ const codexBin = config.env.CODEX_BIN || process.env.CODEX_BIN || 'codex';
201
+ // Build args
202
+ const args = ['exec'];
203
+ if (resumeSessionId) {
204
+ args.push('resume', '--json');
205
+ // Sandbox and approval mode
206
+ if (config.autonomous) {
207
+ args.push('--full-auto');
208
+ }
209
+ else {
210
+ // Non-autonomous: use suggest-equivalent approval mode
211
+ args.push('--approval-mode', 'untrusted');
212
+ if (config.sandboxEnabled) {
213
+ args.push('--sandbox', 'workspace-write');
214
+ }
215
+ }
216
+ args.push(resumeSessionId);
217
+ // Prompt is the final positional arg
218
+ if (config.prompt) {
219
+ args.push(config.prompt);
220
+ }
221
+ }
222
+ else {
223
+ args.push('--json');
224
+ // Sandbox and approval mode
225
+ if (config.autonomous) {
226
+ // --full-auto sets sandbox=workspace-write + approval=on-request
227
+ args.push('--full-auto');
228
+ }
229
+ else {
230
+ args.push('--approval-mode', 'untrusted');
231
+ if (config.sandboxEnabled) {
232
+ args.push('--sandbox', 'workspace-write');
233
+ }
234
+ }
235
+ // Working directory
236
+ args.push('-C', config.cwd);
237
+ // Prompt is the final positional arg
238
+ args.push(config.prompt);
239
+ }
240
+ // Spawn the codex process
241
+ const child = spawn(codexBin, args, {
242
+ cwd: config.cwd,
243
+ env: {
244
+ ...process.env,
245
+ ...config.env,
246
+ },
247
+ stdio: ['pipe', 'pipe', 'pipe'],
248
+ });
249
+ config.onProcessSpawned?.(child.pid);
250
+ // Wire up abort
251
+ const abortHandler = () => {
252
+ child.kill('SIGTERM');
253
+ };
254
+ abortController.signal.addEventListener('abort', abortHandler);
255
+ child.once('exit', () => {
256
+ abortController.signal.removeEventListener('abort', abortHandler);
257
+ });
258
+ child.on('error', (err) => {
259
+ console.error('[CodexProvider] Child process error:', err.message);
260
+ });
261
+ return new CodexAgentHandle(child, abortController);
262
+ }
263
+ }
264
+ // ---------------------------------------------------------------------------
265
+ // AgentHandle implementation
266
+ // ---------------------------------------------------------------------------
267
+ class CodexAgentHandle {
268
+ sessionId = null;
269
+ child;
270
+ abortController;
271
+ mapperState = {
272
+ sessionId: null,
273
+ totalInputTokens: 0,
274
+ totalOutputTokens: 0,
275
+ turnCount: 0,
276
+ };
277
+ constructor(child, abortController) {
278
+ this.child = child;
279
+ this.abortController = abortController;
280
+ }
281
+ get stream() {
282
+ return this.createEventStream();
283
+ }
284
+ async injectMessage(_text) {
285
+ // Codex exec mode doesn't support mid-session message injection.
286
+ // The prompt is provided at spawn time. Injection would require
287
+ // stopping and resuming with a new prompt.
288
+ throw new Error('Codex provider does not support mid-session message injection. ' +
289
+ 'Stop and resume with a new prompt instead.');
290
+ }
291
+ async stop() {
292
+ this.abortController.abort();
293
+ }
294
+ async *createEventStream() {
295
+ const stdout = this.child.stdout;
296
+ if (!stdout) {
297
+ yield {
298
+ type: 'error',
299
+ message: 'Codex process has no stdout',
300
+ raw: null,
301
+ };
302
+ return;
303
+ }
304
+ // Collect stderr for error reporting
305
+ let stderr = '';
306
+ this.child.stderr?.on('data', (chunk) => {
307
+ stderr += chunk.toString();
308
+ });
309
+ // Parse JSONL lines from stdout
310
+ const rl = createInterface({ input: stdout });
311
+ let hasResult = false;
312
+ for await (const line of rl) {
313
+ const trimmed = line.trim();
314
+ if (!trimmed)
315
+ continue;
316
+ let event;
317
+ try {
318
+ event = JSON.parse(trimmed);
319
+ }
320
+ catch {
321
+ // Non-JSON output — emit as system event
322
+ yield {
323
+ type: 'system',
324
+ subtype: 'raw_output',
325
+ message: trimmed,
326
+ raw: trimmed,
327
+ };
328
+ continue;
329
+ }
330
+ const mapped = mapCodexEvent(event, this.mapperState);
331
+ for (const agentEvent of mapped) {
332
+ if (agentEvent.type === 'init') {
333
+ this.sessionId = this.mapperState.sessionId;
334
+ }
335
+ if (agentEvent.type === 'result') {
336
+ hasResult = true;
337
+ }
338
+ yield agentEvent;
339
+ }
340
+ }
341
+ // Wait for process exit
342
+ const exitCode = await new Promise((resolve) => {
343
+ if (this.child.exitCode !== null) {
344
+ resolve(this.child.exitCode);
345
+ }
346
+ else {
347
+ this.child.once('exit', (code) => resolve(code));
348
+ }
349
+ });
350
+ // If we never got a result event, synthesize one from exit code
351
+ if (!hasResult) {
352
+ if (exitCode === 0) {
353
+ yield {
354
+ type: 'result',
355
+ success: true,
356
+ cost: {
357
+ inputTokens: this.mapperState.totalInputTokens || undefined,
358
+ outputTokens: this.mapperState.totalOutputTokens || undefined,
359
+ numTurns: this.mapperState.turnCount || undefined,
360
+ },
361
+ raw: { exitCode },
362
+ };
363
+ }
364
+ else {
365
+ yield {
366
+ type: 'result',
367
+ success: false,
368
+ errors: [stderr.trim() || `Codex process exited with code ${exitCode}`],
369
+ errorSubtype: 'process_exit',
370
+ raw: { exitCode, stderr },
371
+ };
372
+ }
373
+ }
374
+ }
375
+ }
376
+ /**
377
+ * Create a new Codex provider instance
378
+ */
379
+ export function createCodexProvider() {
380
+ return new CodexProvider();
381
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=codex-provider.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-provider.test.d.ts","sourceRoot":"","sources":["../../../src/providers/codex-provider.test.ts"],"names":[],"mappings":""}