@atolis-hq/wake 0.1.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.
- package/LICENSE +201 -0
- package/README.md +140 -0
- package/dist/src/adapters/claude/claude-runner.js +388 -0
- package/dist/src/adapters/claude/prompt-templates.js +57 -0
- package/dist/src/adapters/codex/codex-runner.js +391 -0
- package/dist/src/adapters/cursor/cursor-runner.js +352 -0
- package/dist/src/adapters/docker/docker-cli.js +97 -0
- package/dist/src/adapters/fake/fake-artifact-verifier.js +14 -0
- package/dist/src/adapters/fake/fake-github-pull-request-activity-source.js +73 -0
- package/dist/src/adapters/fake/fake-resource-index.js +21 -0
- package/dist/src/adapters/fake/fake-runner.js +22 -0
- package/dist/src/adapters/fake/fake-ticketing-system.js +166 -0
- package/dist/src/adapters/fake/fake-workspace-manager.js +27 -0
- package/dist/src/adapters/fs/resource-index.js +84 -0
- package/dist/src/adapters/fs/self-update-ledger.js +17 -0
- package/dist/src/adapters/fs/state-store.js +364 -0
- package/dist/src/adapters/git/git-workspace-manager.js +168 -0
- package/dist/src/adapters/github/github-artifact-verifier.js +38 -0
- package/dist/src/adapters/github/github-auth.js +16 -0
- package/dist/src/adapters/github/github-client.js +100 -0
- package/dist/src/adapters/github/github-issues-work-source.js +410 -0
- package/dist/src/adapters/github/github-pull-request-activity-source.js +263 -0
- package/dist/src/adapters/http/ui-assets.js +302 -0
- package/dist/src/adapters/http/ui-data.js +389 -0
- package/dist/src/adapters/http/ui-server.js +151 -0
- package/dist/src/adapters/runner/cli-command.js +43 -0
- package/dist/src/adapters/runner/prompt-templates.js +76 -0
- package/dist/src/adapters/runner/runner-cli-adapter.js +112 -0
- package/dist/src/adapters/runner/runner-registry.js +141 -0
- package/dist/src/adapters/runner/stage-prompt.js +256 -0
- package/dist/src/adapters/runner/transcripts.js +25 -0
- package/dist/src/cli/correlate-command.js +62 -0
- package/dist/src/cli/init-command.js +11 -0
- package/dist/src/cli/locks-command.js +19 -0
- package/dist/src/cli/sandbox-command.js +191 -0
- package/dist/src/cli/sandbox-logging.js +30 -0
- package/dist/src/cli/sandbox-resume.js +77 -0
- package/dist/src/cli/scaffold-assets.js +173 -0
- package/dist/src/cli/self-update-command.js +158 -0
- package/dist/src/cli/startup-preflight.js +127 -0
- package/dist/src/cli/stop-command.js +42 -0
- package/dist/src/cli/ui-command.js +27 -0
- package/dist/src/config/defaults.js +11 -0
- package/dist/src/config/load-config.js +26 -0
- package/dist/src/core/contracts.js +1 -0
- package/dist/src/core/control-plane.js +127 -0
- package/dist/src/core/lifecycle-service.js +8 -0
- package/dist/src/core/policy-engine.js +200 -0
- package/dist/src/core/projection-updater.js +438 -0
- package/dist/src/core/quota-backoff.js +69 -0
- package/dist/src/core/sink-router.js +85 -0
- package/dist/src/core/tick-runner.js +1347 -0
- package/dist/src/domain/branch-naming.js +14 -0
- package/dist/src/domain/resource-uri.js +38 -0
- package/dist/src/domain/runner-routing.js +108 -0
- package/dist/src/domain/schema.js +685 -0
- package/dist/src/domain/sources.js +16 -0
- package/dist/src/domain/stages.js +39 -0
- package/dist/src/domain/types.js +1 -0
- package/dist/src/domain/workflows.js +83 -0
- package/dist/src/lib/clock.js +5 -0
- package/dist/src/lib/event-log.js +21 -0
- package/dist/src/lib/json-file.js +23 -0
- package/dist/src/lib/lock.js +118 -0
- package/dist/src/lib/paths.js +44 -0
- package/dist/src/lib/work-id.js +19 -0
- package/dist/src/main.js +523 -0
- package/dist/src/version.js +1 -0
- package/docker/Dockerfile +54 -0
- package/docker/entrypoint.sh +75 -0
- package/docker/log-command.sh +107 -0
- package/docker/setup.sh +72 -0
- package/package.json +52 -0
- package/prompts/implement.md +49 -0
- package/prompts/refine.md +44 -0
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
import { buildStagePrompt } from '../runner/stage-prompt.js';
|
|
2
|
+
import { runAgentCliCommand } from '../runner/cli-command.js';
|
|
3
|
+
import { writeRunnerTranscript } from '../runner/transcripts.js';
|
|
4
|
+
import { parseRunnerResult } from '../../domain/schema.js';
|
|
5
|
+
const CODEX_CLI_NAME = 'Codex';
|
|
6
|
+
export function buildCodexExecArgs(input) {
|
|
7
|
+
const prompt = buildCodexPromptText(input);
|
|
8
|
+
return [
|
|
9
|
+
'--ask-for-approval',
|
|
10
|
+
'never',
|
|
11
|
+
...(input.reasoningEffort === undefined
|
|
12
|
+
? []
|
|
13
|
+
: ['-c', `model_reasoning_effort="${input.reasoningEffort}"`]),
|
|
14
|
+
'exec',
|
|
15
|
+
'--json',
|
|
16
|
+
'--skip-git-repo-check',
|
|
17
|
+
'--sandbox',
|
|
18
|
+
input.sandboxMode,
|
|
19
|
+
'--cd',
|
|
20
|
+
input.cwd,
|
|
21
|
+
'--model',
|
|
22
|
+
input.model,
|
|
23
|
+
prompt,
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
export function buildCodexPromptText(input) {
|
|
27
|
+
return input.harnessPrompt === undefined
|
|
28
|
+
? input.prompt
|
|
29
|
+
: `${input.harnessPrompt}\n\n${input.prompt}`;
|
|
30
|
+
}
|
|
31
|
+
export function buildCodexResumeArgs(input) {
|
|
32
|
+
return ['resume', input.sessionId];
|
|
33
|
+
}
|
|
34
|
+
function compactLogValue(value) {
|
|
35
|
+
return value.replace(/\s+/g, ' ').trim();
|
|
36
|
+
}
|
|
37
|
+
export function formatCodexRunLogLine(input) {
|
|
38
|
+
const parts = [
|
|
39
|
+
'[codex-run]',
|
|
40
|
+
`phase=${input.phase}`,
|
|
41
|
+
`runId=${input.runId}`,
|
|
42
|
+
`cli=Codex`,
|
|
43
|
+
...(input.model === undefined ? [] : [`model=${input.model}`]),
|
|
44
|
+
`repo=${input.repo}`,
|
|
45
|
+
`issueNumber=${input.issueNumber}`,
|
|
46
|
+
`action=${input.action}`,
|
|
47
|
+
`recentEventIds=${input.recentEventIds.length > 0 ? input.recentEventIds.join(',') : '(none)'}`,
|
|
48
|
+
...(input.workspacePath === undefined
|
|
49
|
+
? []
|
|
50
|
+
: [`workspacePath=${compactLogValue(input.workspacePath)}`]),
|
|
51
|
+
...(input.sessionId === undefined ? [] : [`sessionId=${input.sessionId}`]),
|
|
52
|
+
...(input.exitCode === undefined ? [] : [`exitCode=${input.exitCode}`]),
|
|
53
|
+
];
|
|
54
|
+
return parts.join(' ');
|
|
55
|
+
}
|
|
56
|
+
export function extractCodexExecResult(stdout) {
|
|
57
|
+
let result;
|
|
58
|
+
let sessionId;
|
|
59
|
+
let turns = 0;
|
|
60
|
+
let inputTokens = 0;
|
|
61
|
+
let outputTokens = 0;
|
|
62
|
+
let cachedInputTokens = 0;
|
|
63
|
+
let sawUsage = false;
|
|
64
|
+
for (const line of stdout.split(/\r?\n/).filter((entry) => entry.trim().length > 0)) {
|
|
65
|
+
const event = JSON.parse(line);
|
|
66
|
+
if (event.type === 'thread.started' && typeof event.thread_id === 'string') {
|
|
67
|
+
sessionId = event.thread_id;
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (event.type === 'item.completed') {
|
|
71
|
+
const item = event.item;
|
|
72
|
+
if (item?.type === 'agent_message' && typeof item.text === 'string') {
|
|
73
|
+
result = item.text;
|
|
74
|
+
}
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (event.type === 'turn.completed') {
|
|
78
|
+
const usage = event.usage;
|
|
79
|
+
if (usage !== undefined) {
|
|
80
|
+
sawUsage = true;
|
|
81
|
+
turns += 1;
|
|
82
|
+
// Each `turn.completed` reports that turn's own usage (an exec run can
|
|
83
|
+
// make several model turns via tool calls), so accumulate across turns
|
|
84
|
+
// rather than keeping only the last one - otherwise a multi-turn run's
|
|
85
|
+
// reported usage undercounts the actual spend (#135).
|
|
86
|
+
inputTokens += typeof usage.input_tokens === 'number' ? usage.input_tokens : 0;
|
|
87
|
+
outputTokens += typeof usage.output_tokens === 'number' ? usage.output_tokens : 0;
|
|
88
|
+
// OpenAI's Responses API reports cached prompt tokens nested under
|
|
89
|
+
// input_tokens_details.cached_tokens; unverified against a live Codex
|
|
90
|
+
// success response (this environment's Codex quota was exhausted while
|
|
91
|
+
// this adapter was written), so it is read defensively and simply
|
|
92
|
+
// omitted if absent rather than assumed to exist.
|
|
93
|
+
const inputTokensDetails = usage.input_tokens_details;
|
|
94
|
+
if (typeof inputTokensDetails?.cached_tokens === 'number') {
|
|
95
|
+
cachedInputTokens += inputTokensDetails.cached_tokens;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (result === undefined) {
|
|
101
|
+
throw new Error('Codex exec JSONL stream did not include a final agent message.');
|
|
102
|
+
}
|
|
103
|
+
const tokenUsage = sawUsage
|
|
104
|
+
? {
|
|
105
|
+
inputTokens,
|
|
106
|
+
outputTokens,
|
|
107
|
+
turns,
|
|
108
|
+
...(cachedInputTokens > 0 ? { cacheReadInputTokens: cachedInputTokens } : {}),
|
|
109
|
+
}
|
|
110
|
+
: undefined;
|
|
111
|
+
return {
|
|
112
|
+
result,
|
|
113
|
+
...(sessionId === undefined ? {} : { sessionId }),
|
|
114
|
+
...(tokenUsage === undefined ? {} : { tokenUsage }),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
// Codex exec emits a JSONL stream even on failure (unlike a bare CLI crash,
|
|
118
|
+
// which produces no JSON at all). Reading the structured `message` field off
|
|
119
|
+
// `error`/`turn.failed` events is more reliable than grepping the raw stdout
|
|
120
|
+
// blob, and it is also the string that carries the actual reset-time hint
|
|
121
|
+
// (e.g. "...or try again at 2:29 PM") that quota-backoff needs.
|
|
122
|
+
export function extractCodexErrorMessage(stdout) {
|
|
123
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
124
|
+
const trimmed = line.trim();
|
|
125
|
+
if (trimmed.length === 0) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
let event;
|
|
129
|
+
try {
|
|
130
|
+
event = JSON.parse(trimmed);
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (event.type === 'error' && typeof event.message === 'string') {
|
|
136
|
+
return event.message;
|
|
137
|
+
}
|
|
138
|
+
if (event.type === 'turn.failed') {
|
|
139
|
+
const error = event.error;
|
|
140
|
+
if (typeof error?.message === 'string') {
|
|
141
|
+
return error.message;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
export function classifyCodexCliFailure(input) {
|
|
148
|
+
if (input.timedOut) {
|
|
149
|
+
return 'infra';
|
|
150
|
+
}
|
|
151
|
+
const structuredMessage = extractCodexErrorMessage(input.stdout);
|
|
152
|
+
const text = (structuredMessage ?? `${input.stderr}\n${input.stdout}`).toLowerCase();
|
|
153
|
+
if (text.includes('usage limit') ||
|
|
154
|
+
text.includes('rate limit') ||
|
|
155
|
+
text.includes('quota') ||
|
|
156
|
+
text.includes('billing') ||
|
|
157
|
+
text.includes('credit') ||
|
|
158
|
+
text.includes('too many requests') ||
|
|
159
|
+
text.includes('unauthorized') ||
|
|
160
|
+
text.includes('authentication')) {
|
|
161
|
+
return 'quota';
|
|
162
|
+
}
|
|
163
|
+
return 'infra';
|
|
164
|
+
}
|
|
165
|
+
function resolveModel(input) {
|
|
166
|
+
const { models, model } = input.settings;
|
|
167
|
+
const actionSpecificModel = models[input.action];
|
|
168
|
+
if (actionSpecificModel !== undefined) {
|
|
169
|
+
return actionSpecificModel;
|
|
170
|
+
}
|
|
171
|
+
if (models.default !== undefined) {
|
|
172
|
+
return models.default;
|
|
173
|
+
}
|
|
174
|
+
return model;
|
|
175
|
+
}
|
|
176
|
+
function readSandboxLogBreadcrumb() {
|
|
177
|
+
const containerName = process.env.WAKE_SANDBOX_CONTAINER_NAME;
|
|
178
|
+
if (containerName === undefined || containerName.length === 0) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
text: `Sandbox logs: docker logs --tail 200 ${containerName}`,
|
|
183
|
+
metadata: {
|
|
184
|
+
sandboxContainerName: containerName,
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function resolveSandboxMode(input) {
|
|
189
|
+
return input.workspaceMode === 'branch' ? 'danger-full-access' : 'workspace-write';
|
|
190
|
+
}
|
|
191
|
+
// Codex uses shell execution rather than Claude Code's named tools (Read/Glob/Grep).
|
|
192
|
+
// For read-only stages, override the tool capability note so the agent is told what it
|
|
193
|
+
// can actually use instead of Claude-specific tool names it does not have.
|
|
194
|
+
export function buildCodexToolCapabilityNote(input) {
|
|
195
|
+
if (input.workspaceMode !== 'read-only') {
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
const note = 'You may read the repository using standard shell commands (cat, ls, find, grep, head, tail) and git status. ' +
|
|
199
|
+
'The workspace-write sandbox prevents write and edit operations — do not attempt to modify files.';
|
|
200
|
+
return input.mode === 'resume' ? `Reminder: this is still a planning-only stage. ${note}` : note;
|
|
201
|
+
}
|
|
202
|
+
export function createCodexRunner(options) {
|
|
203
|
+
return {
|
|
204
|
+
async run(input) {
|
|
205
|
+
const runMode = 'start';
|
|
206
|
+
const toolCapabilityNote = buildCodexToolCapabilityNote({
|
|
207
|
+
...(input.workspaceMode === undefined ? {} : { workspaceMode: input.workspaceMode }),
|
|
208
|
+
mode: runMode,
|
|
209
|
+
});
|
|
210
|
+
const stagePrompt = await buildStagePrompt({
|
|
211
|
+
action: input.action,
|
|
212
|
+
projection: input.projection,
|
|
213
|
+
mode: runMode,
|
|
214
|
+
config: input.config,
|
|
215
|
+
...(input.workspaceMode === undefined ? {} : { workspaceMode: input.workspaceMode }),
|
|
216
|
+
...(input.mergeConflictDetected === true ? { mergeConflictDetected: true } : {}),
|
|
217
|
+
...(input.upstreamChanges === undefined ? {} : { upstreamChanges: input.upstreamChanges }),
|
|
218
|
+
...(toolCapabilityNote !== undefined ? { contextOverrides: { toolCapabilityNote } } : {}),
|
|
219
|
+
});
|
|
220
|
+
const model = resolveModel({
|
|
221
|
+
action: input.action,
|
|
222
|
+
settings: options.settings,
|
|
223
|
+
});
|
|
224
|
+
const cwd = input.workspacePath ?? options.cwd;
|
|
225
|
+
const sandboxMode = resolveSandboxMode({
|
|
226
|
+
...(input.workspaceMode === undefined ? {} : { workspaceMode: input.workspaceMode }),
|
|
227
|
+
});
|
|
228
|
+
const promptText = buildCodexPromptText({
|
|
229
|
+
prompt: stagePrompt.prompt,
|
|
230
|
+
harnessPrompt: stagePrompt.harnessPrompt,
|
|
231
|
+
});
|
|
232
|
+
const promptTranscriptPath = await writeRunnerTranscript({
|
|
233
|
+
config: input.config,
|
|
234
|
+
projection: input.projection,
|
|
235
|
+
runId: input.runId,
|
|
236
|
+
action: input.action,
|
|
237
|
+
cli: CODEX_CLI_NAME,
|
|
238
|
+
kind: 'prompt',
|
|
239
|
+
text: promptText,
|
|
240
|
+
});
|
|
241
|
+
console.log(formatCodexRunLogLine({
|
|
242
|
+
phase: 'start',
|
|
243
|
+
runId: input.runId,
|
|
244
|
+
action: input.action,
|
|
245
|
+
issueNumber: input.projection.issue.number,
|
|
246
|
+
repo: input.projection.issue.repo,
|
|
247
|
+
recentEventIds: input.recentEvents.map((event) => event.eventId),
|
|
248
|
+
model,
|
|
249
|
+
...(input.workspacePath === undefined
|
|
250
|
+
? {}
|
|
251
|
+
: { workspacePath: input.workspacePath }),
|
|
252
|
+
}));
|
|
253
|
+
const result = await runAgentCliCommand({
|
|
254
|
+
command: options.command,
|
|
255
|
+
args: buildCodexExecArgs({
|
|
256
|
+
model,
|
|
257
|
+
prompt: promptText,
|
|
258
|
+
cwd,
|
|
259
|
+
sandboxMode,
|
|
260
|
+
...(options.settings.reasoningEffort === undefined
|
|
261
|
+
? {}
|
|
262
|
+
: { reasoningEffort: options.settings.reasoningEffort }),
|
|
263
|
+
}),
|
|
264
|
+
cwd,
|
|
265
|
+
timeoutMs: options.settings.timeoutMs,
|
|
266
|
+
});
|
|
267
|
+
const responseTranscriptPath = await writeRunnerTranscript({
|
|
268
|
+
config: input.config,
|
|
269
|
+
projection: input.projection,
|
|
270
|
+
runId: input.runId,
|
|
271
|
+
action: input.action,
|
|
272
|
+
cli: CODEX_CLI_NAME,
|
|
273
|
+
kind: 'response',
|
|
274
|
+
text: result.stdout,
|
|
275
|
+
});
|
|
276
|
+
if (result.exitCode !== 0 || result.timedOut || result.stdout.trim().length === 0) {
|
|
277
|
+
const sandboxLog = readSandboxLogBreadcrumb();
|
|
278
|
+
const failureClass = classifyCodexCliFailure({
|
|
279
|
+
stdout: result.stdout,
|
|
280
|
+
stderr: result.stderr,
|
|
281
|
+
timedOut: result.timedOut,
|
|
282
|
+
});
|
|
283
|
+
const structuredMessage = result.timedOut
|
|
284
|
+
? undefined
|
|
285
|
+
: extractCodexErrorMessage(result.stdout);
|
|
286
|
+
console.error(formatCodexRunLogLine({
|
|
287
|
+
phase: 'failure',
|
|
288
|
+
runId: input.runId,
|
|
289
|
+
action: input.action,
|
|
290
|
+
issueNumber: input.projection.issue.number,
|
|
291
|
+
repo: input.projection.issue.repo,
|
|
292
|
+
recentEventIds: input.recentEvents.map((event) => event.eventId),
|
|
293
|
+
model,
|
|
294
|
+
...(input.workspacePath === undefined
|
|
295
|
+
? {}
|
|
296
|
+
: { workspacePath: input.workspacePath }),
|
|
297
|
+
exitCode: result.exitCode,
|
|
298
|
+
}));
|
|
299
|
+
return {
|
|
300
|
+
result: [
|
|
301
|
+
result.timedOut
|
|
302
|
+
? `Codex runner timed out after ${options.settings.timeoutMs}ms and was killed`
|
|
303
|
+
: structuredMessage !== undefined
|
|
304
|
+
? `Codex runner failed: ${structuredMessage}`
|
|
305
|
+
: result.stdout.trim().length === 0 ? 'Codex runner produced no output'
|
|
306
|
+
: 'Codex runner failed',
|
|
307
|
+
result.stderr,
|
|
308
|
+
sandboxLog?.text,
|
|
309
|
+
'FAILED',
|
|
310
|
+
]
|
|
311
|
+
.filter((part) => part !== undefined && part.length > 0)
|
|
312
|
+
.join('\n'),
|
|
313
|
+
model,
|
|
314
|
+
cli: CODEX_CLI_NAME,
|
|
315
|
+
failureClass,
|
|
316
|
+
metadata: {
|
|
317
|
+
stdout: result.stdout,
|
|
318
|
+
stderr: result.stderr,
|
|
319
|
+
exitCode: result.exitCode,
|
|
320
|
+
failureClass,
|
|
321
|
+
...(promptTranscriptPath === undefined ? {} : { promptTranscriptPath }),
|
|
322
|
+
...(responseTranscriptPath === undefined ? {} : { responseTranscriptPath }),
|
|
323
|
+
...(sandboxLog?.metadata ?? {}),
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
const parsed = extractCodexExecResult(result.stdout);
|
|
328
|
+
const sandboxLog = readSandboxLogBreadcrumb();
|
|
329
|
+
console.log(formatCodexRunLogLine({
|
|
330
|
+
phase: 'success',
|
|
331
|
+
runId: input.runId,
|
|
332
|
+
action: input.action,
|
|
333
|
+
issueNumber: input.projection.issue.number,
|
|
334
|
+
repo: input.projection.issue.repo,
|
|
335
|
+
recentEventIds: input.recentEvents.map((event) => event.eventId),
|
|
336
|
+
model,
|
|
337
|
+
...(input.workspacePath === undefined
|
|
338
|
+
? {}
|
|
339
|
+
: { workspacePath: input.workspacePath }),
|
|
340
|
+
...(parsed.sessionId === undefined ? {} : { sessionId: parsed.sessionId }),
|
|
341
|
+
}));
|
|
342
|
+
return {
|
|
343
|
+
result: parsed.result,
|
|
344
|
+
model,
|
|
345
|
+
cli: CODEX_CLI_NAME,
|
|
346
|
+
...(parseRunnerResult(parsed.result).status === 'FAILED'
|
|
347
|
+
? { failureClass: 'task' }
|
|
348
|
+
: {}),
|
|
349
|
+
...(parsed.sessionId === undefined ? {} : { session_id: parsed.sessionId }),
|
|
350
|
+
...(parsed.tokenUsage === undefined ? {} : { tokenUsage: parsed.tokenUsage }),
|
|
351
|
+
metadata: {
|
|
352
|
+
stdout: result.stdout,
|
|
353
|
+
stderr: result.stderr,
|
|
354
|
+
raw: result.stdout
|
|
355
|
+
.split(/\r?\n/)
|
|
356
|
+
.filter((line) => line.trim().length > 0)
|
|
357
|
+
.map((line) => JSON.parse(line)),
|
|
358
|
+
skipApproval: stagePrompt.skipApproval,
|
|
359
|
+
...(promptTranscriptPath === undefined ? {} : { promptTranscriptPath }),
|
|
360
|
+
...(responseTranscriptPath === undefined ? {} : { responseTranscriptPath }),
|
|
361
|
+
...(sandboxLog?.metadata ?? {}),
|
|
362
|
+
},
|
|
363
|
+
};
|
|
364
|
+
},
|
|
365
|
+
async smoke() {
|
|
366
|
+
const result = await runAgentCliCommand({
|
|
367
|
+
command: options.command,
|
|
368
|
+
args: buildCodexExecArgs({
|
|
369
|
+
model: options.settings.smokeModel,
|
|
370
|
+
prompt: options.settings.smokePrompt,
|
|
371
|
+
cwd: options.cwd,
|
|
372
|
+
sandboxMode: 'danger-full-access',
|
|
373
|
+
...(options.settings.reasoningEffort === undefined
|
|
374
|
+
? {}
|
|
375
|
+
: { reasoningEffort: options.settings.reasoningEffort }),
|
|
376
|
+
}),
|
|
377
|
+
cwd: options.cwd,
|
|
378
|
+
});
|
|
379
|
+
const parsed = result.exitCode === 0 && result.stdout.trim().length > 0
|
|
380
|
+
? extractCodexExecResult(result.stdout)
|
|
381
|
+
: undefined;
|
|
382
|
+
return {
|
|
383
|
+
text: parsed?.result ?? '',
|
|
384
|
+
...(parsed?.sessionId === undefined ? {} : { sessionId: parsed.sessionId }),
|
|
385
|
+
stdout: result.stdout,
|
|
386
|
+
stderr: result.stderr,
|
|
387
|
+
exitCode: result.exitCode,
|
|
388
|
+
};
|
|
389
|
+
},
|
|
390
|
+
};
|
|
391
|
+
}
|