@atolis-hq/wake 0.2.45 → 0.2.47
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/dist/src/adapters/claude/claude-runner.js +202 -192
- package/dist/src/adapters/codex/codex-runner.js +9 -1
- package/dist/src/adapters/cursor/cursor-runner.js +9 -1
- package/dist/src/adapters/fake/fake-runner.js +25 -1
- package/dist/src/adapters/runner/cli-command.js +17 -3
- package/dist/src/core/live-execution.js +81 -0
- package/dist/src/core/tick-runner.js +124 -11
- package/dist/src/domain/schema.js +4 -0
- package/dist/src/version.js +1 -1
- package/package.json +1 -1
|
@@ -3,6 +3,7 @@ import { runAgentCliCommand } from '../runner/cli-command.js';
|
|
|
3
3
|
import { buildStagePrompt } from '../runner/stage-prompt.js';
|
|
4
4
|
import { emitRuntimeEvent, runnerRuntimeEvent } from '../runner/runtime-events.js';
|
|
5
5
|
import { writeRunnerTranscript } from '../runner/transcripts.js';
|
|
6
|
+
import { createAgentExecution } from '../../core/live-execution.js';
|
|
6
7
|
export { buildStagePrompt } from '../runner/stage-prompt.js';
|
|
7
8
|
function slugify(value, maxLength = 40) {
|
|
8
9
|
return value
|
|
@@ -152,182 +153,109 @@ function readSandboxLogBreadcrumb() {
|
|
|
152
153
|
};
|
|
153
154
|
}
|
|
154
155
|
export function createClaudeRunner(options) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
runId: input.runId,
|
|
230
|
-
projection: input.projection,
|
|
231
|
-
routing: input.routing,
|
|
232
|
-
cli: CLAUDE_CLI_NAME,
|
|
233
|
-
model,
|
|
234
|
-
payload: { pid: identity.pid, processStartedAt: identity.processStartedAt },
|
|
235
|
-
}));
|
|
236
|
-
},
|
|
237
|
-
});
|
|
238
|
-
const responseTranscriptPath = await writeRunnerTranscript({
|
|
239
|
-
config: input.config,
|
|
240
|
-
projection: input.projection,
|
|
241
|
-
runId: input.runId,
|
|
242
|
-
action: input.action,
|
|
243
|
-
cli: CLAUDE_CLI_NAME,
|
|
244
|
-
kind: 'response',
|
|
245
|
-
text: result.stdout,
|
|
246
|
-
});
|
|
247
|
-
if (result.exitCode !== 0 || result.timedOut || result.stdout.trim().length === 0) {
|
|
248
|
-
const sandboxLog = readSandboxLogBreadcrumb();
|
|
249
|
-
const failureClass = classifyClaudeCliFailure({
|
|
250
|
-
stdout: result.stdout,
|
|
251
|
-
stderr: result.stderr,
|
|
252
|
-
timedOut: result.timedOut,
|
|
253
|
-
});
|
|
254
|
-
console.error(formatClaudeRunLogLine({
|
|
255
|
-
phase: 'failure',
|
|
256
|
-
runId: input.runId,
|
|
257
|
-
action: input.action,
|
|
258
|
-
issueNumber: input.projection.issue.number,
|
|
259
|
-
repo: input.projection.issue.repo,
|
|
260
|
-
recentEventIds: input.recentEvents.map((event) => event.eventId),
|
|
261
|
-
model,
|
|
262
|
-
...(input.workspacePath === undefined ? {} : { workspacePath: input.workspacePath }),
|
|
263
|
-
exitCode: result.exitCode,
|
|
264
|
-
}));
|
|
156
|
+
async function executeRun(input) {
|
|
157
|
+
const sessionName = buildWakeSessionName({
|
|
158
|
+
sessionName: options.settings.sessionName,
|
|
159
|
+
issueNumber: input.projection.issue.number,
|
|
160
|
+
title: input.projection.issue.title,
|
|
161
|
+
runId: input.runId,
|
|
162
|
+
});
|
|
163
|
+
// Resume an in-progress session when the projection carries a session ID
|
|
164
|
+
// that was created by this same CLI. This happens when the previous run
|
|
165
|
+
// ended with BLOCKED and the same action is being retried after a human
|
|
166
|
+
// reply. Any forward-stage transition or FAILED run clears the stored
|
|
167
|
+
// session ID so that the next action always starts fresh.
|
|
168
|
+
const priorSessionId = input.projection.wake.sessionId;
|
|
169
|
+
const priorSessionCli = input.projection.wake.sessionCli;
|
|
170
|
+
const isResume = priorSessionId !== undefined && priorSessionCli === CLAUDE_CLI_NAME;
|
|
171
|
+
const stagePrompt = await buildStagePrompt({
|
|
172
|
+
action: input.action,
|
|
173
|
+
projection: input.projection,
|
|
174
|
+
mode: isResume ? 'resume' : 'start',
|
|
175
|
+
config: input.config,
|
|
176
|
+
...(input.promptContextOverrides === undefined
|
|
177
|
+
? {}
|
|
178
|
+
: { contextOverrides: input.promptContextOverrides }),
|
|
179
|
+
...(input.mergeConflictDetected === true ? { mergeConflictDetected: true } : {}),
|
|
180
|
+
...(input.upstreamChanges === undefined ? {} : { upstreamChanges: input.upstreamChanges }),
|
|
181
|
+
});
|
|
182
|
+
const model = resolveModel({
|
|
183
|
+
action: input.action,
|
|
184
|
+
settings: options.settings,
|
|
185
|
+
});
|
|
186
|
+
const args = buildClaudePrintArgs({
|
|
187
|
+
model,
|
|
188
|
+
prompt: stagePrompt.prompt,
|
|
189
|
+
systemPrompt: stagePrompt.harnessPrompt,
|
|
190
|
+
sessionName,
|
|
191
|
+
allowedTools: stagePrompt.allowedTools,
|
|
192
|
+
extraArgs: stagePrompt.extraArgs,
|
|
193
|
+
maxTurns: stagePrompt.maxTurns,
|
|
194
|
+
...(stagePrompt.permissionMode === undefined
|
|
195
|
+
? {}
|
|
196
|
+
: { permissionMode: stagePrompt.permissionMode }),
|
|
197
|
+
...(options.settings.remoteControl.enabled ? { remoteControlName: sessionName } : {}),
|
|
198
|
+
...(options.settings.effort === undefined ? {} : { effort: options.settings.effort }),
|
|
199
|
+
...(isResume ? { resumeSessionId: priorSessionId } : {}),
|
|
200
|
+
});
|
|
201
|
+
const promptTranscriptPath = await writeRunnerTranscript({
|
|
202
|
+
config: input.config,
|
|
203
|
+
projection: input.projection,
|
|
204
|
+
runId: input.runId,
|
|
205
|
+
action: input.action,
|
|
206
|
+
cli: CLAUDE_CLI_NAME,
|
|
207
|
+
kind: 'prompt',
|
|
208
|
+
text: stagePrompt.prompt,
|
|
209
|
+
});
|
|
210
|
+
console.log(formatClaudeRunLogLine({
|
|
211
|
+
phase: 'start',
|
|
212
|
+
runId: input.runId,
|
|
213
|
+
action: input.action,
|
|
214
|
+
issueNumber: input.projection.issue.number,
|
|
215
|
+
repo: input.projection.issue.repo,
|
|
216
|
+
recentEventIds: input.recentEvents.map((event) => event.eventId),
|
|
217
|
+
model,
|
|
218
|
+
...(input.workspacePath === undefined ? {} : { workspacePath: input.workspacePath }),
|
|
219
|
+
}));
|
|
220
|
+
const result = await runClaudeCommand({
|
|
221
|
+
command: options.command,
|
|
222
|
+
args,
|
|
223
|
+
cwd: input.workspacePath ?? options.cwd,
|
|
224
|
+
timeoutMs: options.settings.timeoutMs,
|
|
225
|
+
...(input.cancellationSignal === undefined
|
|
226
|
+
? {}
|
|
227
|
+
: { cancellationSignal: input.cancellationSignal }),
|
|
228
|
+
onProcessStart: async (identity) => {
|
|
229
|
+
await input.onProcessStart?.(identity);
|
|
265
230
|
await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
|
|
266
|
-
type: 'agent.process.
|
|
231
|
+
type: 'agent.process.started',
|
|
267
232
|
runId: input.runId,
|
|
268
233
|
projection: input.projection,
|
|
269
234
|
routing: input.routing,
|
|
270
235
|
cli: CLAUDE_CLI_NAME,
|
|
271
236
|
model,
|
|
272
|
-
payload: {
|
|
237
|
+
payload: { pid: identity.pid, processStartedAt: identity.processStartedAt },
|
|
273
238
|
}));
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
return {
|
|
288
|
-
result: [
|
|
289
|
-
result.timedOut
|
|
290
|
-
? `Claude runner timed out after ${options.settings.timeoutMs}ms and was killed`
|
|
291
|
-
: trimmedStdout.length === 0
|
|
292
|
-
? 'Claude runner produced no output'
|
|
293
|
-
: parsedReason !== undefined
|
|
294
|
-
? `Claude runner failed: ${parsedReason}`
|
|
295
|
-
: 'Claude runner failed',
|
|
296
|
-
result.stderr,
|
|
297
|
-
stdoutFailureDetail,
|
|
298
|
-
sandboxLog?.text,
|
|
299
|
-
'FAILED',
|
|
300
|
-
]
|
|
301
|
-
.filter((part) => part !== undefined && part.length > 0)
|
|
302
|
-
.join('\n'),
|
|
303
|
-
model,
|
|
304
|
-
cli: CLAUDE_CLI_NAME,
|
|
305
|
-
failureClass,
|
|
306
|
-
metadata: {
|
|
307
|
-
stdout: result.stdout,
|
|
308
|
-
stderr: result.stderr,
|
|
309
|
-
exitCode: result.exitCode,
|
|
310
|
-
failureClass,
|
|
311
|
-
...(promptTranscriptPath === undefined ? {} : { promptTranscriptPath }),
|
|
312
|
-
...(responseTranscriptPath === undefined ? {} : { responseTranscriptPath }),
|
|
313
|
-
...(sandboxLog?.metadata ?? {}),
|
|
314
|
-
},
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
const parsed = parseClaudePrintOutput(result.stdout);
|
|
239
|
+
},
|
|
240
|
+
});
|
|
241
|
+
const responseTranscriptPath = await writeRunnerTranscript({
|
|
242
|
+
config: input.config,
|
|
243
|
+
projection: input.projection,
|
|
244
|
+
runId: input.runId,
|
|
245
|
+
action: input.action,
|
|
246
|
+
cli: CLAUDE_CLI_NAME,
|
|
247
|
+
kind: 'response',
|
|
248
|
+
text: result.stdout,
|
|
249
|
+
});
|
|
250
|
+
if (result.exitCode !== 0 || result.timedOut || result.stdout.trim().length === 0) {
|
|
318
251
|
const sandboxLog = readSandboxLogBreadcrumb();
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
...(parsed.session_id === undefined ? {} : { sessionId: parsed.session_id }),
|
|
327
|
-
payload: { message: 'Claude print result received', raw: parsed },
|
|
328
|
-
}));
|
|
329
|
-
console.log(formatClaudeRunLogLine({
|
|
330
|
-
phase: 'success',
|
|
252
|
+
const failureClass = classifyClaudeCliFailure({
|
|
253
|
+
stdout: result.stdout,
|
|
254
|
+
stderr: result.stderr,
|
|
255
|
+
timedOut: result.timedOut,
|
|
256
|
+
});
|
|
257
|
+
console.error(formatClaudeRunLogLine({
|
|
258
|
+
phase: 'failure',
|
|
331
259
|
runId: input.runId,
|
|
332
260
|
action: input.action,
|
|
333
261
|
issueNumber: input.projection.issue.number,
|
|
@@ -335,21 +263,8 @@ export function createClaudeRunner(options) {
|
|
|
335
263
|
recentEventIds: input.recentEvents.map((event) => event.eventId),
|
|
336
264
|
model,
|
|
337
265
|
...(input.workspacePath === undefined ? {} : { workspacePath: input.workspacePath }),
|
|
338
|
-
|
|
266
|
+
exitCode: result.exitCode,
|
|
339
267
|
}));
|
|
340
|
-
const tokenUsage = extractTokenUsage(parsed);
|
|
341
|
-
if (tokenUsage !== undefined) {
|
|
342
|
-
await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
|
|
343
|
-
type: 'agent.usage.updated',
|
|
344
|
-
runId: input.runId,
|
|
345
|
-
projection: input.projection,
|
|
346
|
-
routing: input.routing,
|
|
347
|
-
cli: CLAUDE_CLI_NAME,
|
|
348
|
-
model,
|
|
349
|
-
...(parsed.session_id === undefined ? {} : { sessionId: parsed.session_id }),
|
|
350
|
-
payload: { tokenUsage },
|
|
351
|
-
}));
|
|
352
|
-
}
|
|
353
268
|
await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
|
|
354
269
|
type: 'agent.process.exited',
|
|
355
270
|
runId: input.runId,
|
|
@@ -357,29 +272,124 @@ export function createClaudeRunner(options) {
|
|
|
357
272
|
routing: input.routing,
|
|
358
273
|
cli: CLAUDE_CLI_NAME,
|
|
359
274
|
model,
|
|
360
|
-
...(parsed.session_id === undefined ? {} : { sessionId: parsed.session_id }),
|
|
361
275
|
payload: { exitCode: result.exitCode, timedOut: result.timedOut },
|
|
362
276
|
}));
|
|
277
|
+
let parsedReason;
|
|
278
|
+
let stdoutFailureDetail;
|
|
279
|
+
const trimmedStdout = result.stdout.trim();
|
|
280
|
+
try {
|
|
281
|
+
if (trimmedStdout.length > 0) {
|
|
282
|
+
parsedReason = parseClaudePrintOutput(result.stdout).result;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
catch {
|
|
286
|
+
// stdout wasn't valid JSON, so it is likely a CLI-level error
|
|
287
|
+
// message rather than a Claude print result.
|
|
288
|
+
stdoutFailureDetail = trimmedStdout;
|
|
289
|
+
}
|
|
363
290
|
return {
|
|
364
|
-
result:
|
|
291
|
+
result: [
|
|
292
|
+
result.timedOut
|
|
293
|
+
? `Claude runner timed out after ${options.settings.timeoutMs}ms and was killed`
|
|
294
|
+
: trimmedStdout.length === 0
|
|
295
|
+
? 'Claude runner produced no output'
|
|
296
|
+
: parsedReason !== undefined
|
|
297
|
+
? `Claude runner failed: ${parsedReason}`
|
|
298
|
+
: 'Claude runner failed',
|
|
299
|
+
result.stderr,
|
|
300
|
+
stdoutFailureDetail,
|
|
301
|
+
sandboxLog?.text,
|
|
302
|
+
'FAILED',
|
|
303
|
+
]
|
|
304
|
+
.filter((part) => part !== undefined && part.length > 0)
|
|
305
|
+
.join('\n'),
|
|
365
306
|
model,
|
|
366
307
|
cli: CLAUDE_CLI_NAME,
|
|
367
|
-
|
|
368
|
-
? { failureClass: 'task' }
|
|
369
|
-
: {}),
|
|
370
|
-
...(parsed.session_id === undefined ? {} : { session_id: parsed.session_id }),
|
|
371
|
-
...(tokenUsage === undefined ? {} : { tokenUsage }),
|
|
308
|
+
failureClass,
|
|
372
309
|
metadata: {
|
|
373
310
|
stdout: result.stdout,
|
|
374
311
|
stderr: result.stderr,
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
allowAutoApproval: stagePrompt.allowAutoApproval,
|
|
312
|
+
exitCode: result.exitCode,
|
|
313
|
+
failureClass,
|
|
378
314
|
...(promptTranscriptPath === undefined ? {} : { promptTranscriptPath }),
|
|
379
315
|
...(responseTranscriptPath === undefined ? {} : { responseTranscriptPath }),
|
|
380
316
|
...(sandboxLog?.metadata ?? {}),
|
|
381
317
|
},
|
|
382
318
|
};
|
|
319
|
+
}
|
|
320
|
+
const parsed = parseClaudePrintOutput(result.stdout);
|
|
321
|
+
const sandboxLog = readSandboxLogBreadcrumb();
|
|
322
|
+
await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
|
|
323
|
+
type: 'agent.progress',
|
|
324
|
+
runId: input.runId,
|
|
325
|
+
projection: input.projection,
|
|
326
|
+
routing: input.routing,
|
|
327
|
+
cli: CLAUDE_CLI_NAME,
|
|
328
|
+
model,
|
|
329
|
+
...(parsed.session_id === undefined ? {} : { sessionId: parsed.session_id }),
|
|
330
|
+
payload: { message: 'Claude print result received', raw: parsed },
|
|
331
|
+
}));
|
|
332
|
+
console.log(formatClaudeRunLogLine({
|
|
333
|
+
phase: 'success',
|
|
334
|
+
runId: input.runId,
|
|
335
|
+
action: input.action,
|
|
336
|
+
issueNumber: input.projection.issue.number,
|
|
337
|
+
repo: input.projection.issue.repo,
|
|
338
|
+
recentEventIds: input.recentEvents.map((event) => event.eventId),
|
|
339
|
+
model,
|
|
340
|
+
...(input.workspacePath === undefined ? {} : { workspacePath: input.workspacePath }),
|
|
341
|
+
...(parsed.session_id === undefined ? {} : { sessionId: parsed.session_id }),
|
|
342
|
+
}));
|
|
343
|
+
const tokenUsage = extractTokenUsage(parsed);
|
|
344
|
+
if (tokenUsage !== undefined) {
|
|
345
|
+
await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
|
|
346
|
+
type: 'agent.usage.updated',
|
|
347
|
+
runId: input.runId,
|
|
348
|
+
projection: input.projection,
|
|
349
|
+
routing: input.routing,
|
|
350
|
+
cli: CLAUDE_CLI_NAME,
|
|
351
|
+
model,
|
|
352
|
+
...(parsed.session_id === undefined ? {} : { sessionId: parsed.session_id }),
|
|
353
|
+
payload: { tokenUsage },
|
|
354
|
+
}));
|
|
355
|
+
}
|
|
356
|
+
await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
|
|
357
|
+
type: 'agent.process.exited',
|
|
358
|
+
runId: input.runId,
|
|
359
|
+
projection: input.projection,
|
|
360
|
+
routing: input.routing,
|
|
361
|
+
cli: CLAUDE_CLI_NAME,
|
|
362
|
+
model,
|
|
363
|
+
...(parsed.session_id === undefined ? {} : { sessionId: parsed.session_id }),
|
|
364
|
+
payload: { exitCode: result.exitCode, timedOut: result.timedOut },
|
|
365
|
+
}));
|
|
366
|
+
return {
|
|
367
|
+
result: parsed.result,
|
|
368
|
+
model,
|
|
369
|
+
cli: CLAUDE_CLI_NAME,
|
|
370
|
+
...(parseRunnerResult(parsed.result).status === 'FAILED'
|
|
371
|
+
? { failureClass: 'task' }
|
|
372
|
+
: {}),
|
|
373
|
+
...(parsed.session_id === undefined ? {} : { session_id: parsed.session_id }),
|
|
374
|
+
...(tokenUsage === undefined ? {} : { tokenUsage }),
|
|
375
|
+
metadata: {
|
|
376
|
+
stdout: result.stdout,
|
|
377
|
+
stderr: result.stderr,
|
|
378
|
+
raw: parsed,
|
|
379
|
+
skipApproval: stagePrompt.skipApproval,
|
|
380
|
+
allowAutoApproval: stagePrompt.allowAutoApproval,
|
|
381
|
+
...(promptTranscriptPath === undefined ? {} : { promptTranscriptPath }),
|
|
382
|
+
...(responseTranscriptPath === undefined ? {} : { responseTranscriptPath }),
|
|
383
|
+
...(sandboxLog?.metadata ?? {}),
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
return {
|
|
388
|
+
async start(input) {
|
|
389
|
+
return createAgentExecution(input, executeRun);
|
|
390
|
+
},
|
|
391
|
+
async run(input) {
|
|
392
|
+
return (await this.start(input)).result;
|
|
383
393
|
},
|
|
384
394
|
async smoke() {
|
|
385
395
|
const args = buildClaudePrintArgs({
|
|
@@ -2,6 +2,7 @@ import { buildStagePrompt } from '../runner/stage-prompt.js';
|
|
|
2
2
|
import { runAgentCliCommand } from '../runner/cli-command.js';
|
|
3
3
|
import { emitRuntimeEvent, runnerRuntimeEvent } from '../runner/runtime-events.js';
|
|
4
4
|
import { writeRunnerTranscript } from '../runner/transcripts.js';
|
|
5
|
+
import { createAgentExecution } from '../../core/live-execution.js';
|
|
5
6
|
import { parseRunnerResult } from '../../domain/schema.js';
|
|
6
7
|
const CODEX_CLI_NAME = 'Codex';
|
|
7
8
|
export function buildCodexExecArgs(input) {
|
|
@@ -201,7 +202,10 @@ export function buildCodexToolCapabilityNote(input) {
|
|
|
201
202
|
return input.mode === 'resume' ? `Reminder: this is still a planning-only stage. ${note}` : note;
|
|
202
203
|
}
|
|
203
204
|
export function createCodexRunner(options) {
|
|
204
|
-
|
|
205
|
+
const runner = {
|
|
206
|
+
async start(input) {
|
|
207
|
+
return createAgentExecution(input, (liveInput) => runner.run(liveInput));
|
|
208
|
+
},
|
|
205
209
|
async run(input) {
|
|
206
210
|
const runMode = 'start';
|
|
207
211
|
const toolCapabilityNote = buildCodexToolCapabilityNote({
|
|
@@ -269,6 +273,9 @@ export function createCodexRunner(options) {
|
|
|
269
273
|
}),
|
|
270
274
|
cwd,
|
|
271
275
|
timeoutMs: options.settings.timeoutMs,
|
|
276
|
+
...(input.cancellationSignal === undefined
|
|
277
|
+
? {}
|
|
278
|
+
: { cancellationSignal: input.cancellationSignal }),
|
|
272
279
|
onProcessStart: async (identity) => {
|
|
273
280
|
await input.onProcessStart?.(identity);
|
|
274
281
|
await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
|
|
@@ -474,4 +481,5 @@ export function createCodexRunner(options) {
|
|
|
474
481
|
};
|
|
475
482
|
},
|
|
476
483
|
};
|
|
484
|
+
return runner;
|
|
477
485
|
}
|
|
@@ -3,6 +3,7 @@ import { buildStagePrompt } from '../runner/stage-prompt.js';
|
|
|
3
3
|
import { runAgentCliCommand } from '../runner/cli-command.js';
|
|
4
4
|
import { emitRuntimeEvent, runnerRuntimeEvent } from '../runner/runtime-events.js';
|
|
5
5
|
import { writeRunnerTranscript } from '../runner/transcripts.js';
|
|
6
|
+
import { createAgentExecution } from '../../core/live-execution.js';
|
|
6
7
|
const CURSOR_CLI_NAME = 'Cursor';
|
|
7
8
|
export function buildCursorAgentArgs(input) {
|
|
8
9
|
const fullPrompt = buildCursorPromptText(input);
|
|
@@ -154,7 +155,10 @@ function readSandboxLogBreadcrumb() {
|
|
|
154
155
|
};
|
|
155
156
|
}
|
|
156
157
|
export function createCursorRunner(options) {
|
|
157
|
-
|
|
158
|
+
const runner = {
|
|
159
|
+
async start(input) {
|
|
160
|
+
return createAgentExecution(input, (liveInput) => runner.run(liveInput));
|
|
161
|
+
},
|
|
158
162
|
async run(input) {
|
|
159
163
|
const priorSessionId = input.projection.wake.sessionId;
|
|
160
164
|
const priorSessionCli = input.projection.wake.sessionCli;
|
|
@@ -220,6 +224,9 @@ export function createCursorRunner(options) {
|
|
|
220
224
|
}),
|
|
221
225
|
cwd,
|
|
222
226
|
timeoutMs: options.settings.timeoutMs,
|
|
227
|
+
...(input.cancellationSignal === undefined
|
|
228
|
+
? {}
|
|
229
|
+
: { cancellationSignal: input.cancellationSignal }),
|
|
223
230
|
onProcessStart: async (identity) => {
|
|
224
231
|
await input.onProcessStart?.(identity);
|
|
225
232
|
await emitRuntimeEvent(input.onRuntimeEvent, runnerRuntimeEvent({
|
|
@@ -412,4 +419,5 @@ export function createCursorRunner(options) {
|
|
|
412
419
|
};
|
|
413
420
|
},
|
|
414
421
|
};
|
|
422
|
+
return runner;
|
|
415
423
|
}
|
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
import { emitRuntimeEvent, runnerRuntimeEvent } from '../runner/runtime-events.js';
|
|
2
|
+
import { createAgentExecution } from '../../core/live-execution.js';
|
|
2
3
|
export function createFakeRunner(result, options) {
|
|
3
|
-
|
|
4
|
+
const runner = {
|
|
5
|
+
async start(input) {
|
|
6
|
+
return createAgentExecution(input, (liveInput) => runner.run(liveInput));
|
|
7
|
+
},
|
|
4
8
|
async run(_) {
|
|
5
9
|
const cli = options?.cli ?? 'Fake';
|
|
10
|
+
const isCanceled = () => _.cancellationSignal?.aborted === true;
|
|
11
|
+
if (isCanceled()) {
|
|
12
|
+
return {
|
|
13
|
+
result: 'Fake runner canceled\nFAILED',
|
|
14
|
+
model: 'fake',
|
|
15
|
+
cli,
|
|
16
|
+
failureClass: 'infra',
|
|
17
|
+
metadata: { source: 'fake-runner', canceled: true },
|
|
18
|
+
};
|
|
19
|
+
}
|
|
6
20
|
await emitRuntimeEvent(_.onRuntimeEvent, runnerRuntimeEvent({
|
|
7
21
|
type: 'agent.process.started',
|
|
8
22
|
runId: _.runId,
|
|
@@ -32,6 +46,15 @@ export function createFakeRunner(result, options) {
|
|
|
32
46
|
sessionId: 'fake-session-1',
|
|
33
47
|
payload: { exitCode: 0, synthetic: true },
|
|
34
48
|
}));
|
|
49
|
+
if (isCanceled()) {
|
|
50
|
+
return {
|
|
51
|
+
result: 'Fake runner canceled\nFAILED',
|
|
52
|
+
model: 'fake',
|
|
53
|
+
cli,
|
|
54
|
+
failureClass: 'infra',
|
|
55
|
+
metadata: { source: 'fake-runner', canceled: true },
|
|
56
|
+
};
|
|
57
|
+
}
|
|
35
58
|
return (result ?? {
|
|
36
59
|
result: [
|
|
37
60
|
'Fake runner completed',
|
|
@@ -50,4 +73,5 @@ export function createFakeRunner(result, options) {
|
|
|
50
73
|
});
|
|
51
74
|
},
|
|
52
75
|
};
|
|
76
|
+
return runner;
|
|
53
77
|
}
|
|
@@ -11,6 +11,7 @@ export function runAgentCliCommand(input) {
|
|
|
11
11
|
let stdout = '';
|
|
12
12
|
let stderr = '';
|
|
13
13
|
let timedOut = false;
|
|
14
|
+
let canceled = false;
|
|
14
15
|
let killTimer;
|
|
15
16
|
let startNotification = Promise.resolve();
|
|
16
17
|
let startNotificationError;
|
|
@@ -22,13 +23,24 @@ export function runAgentCliCommand(input) {
|
|
|
22
23
|
});
|
|
23
24
|
}
|
|
24
25
|
}
|
|
26
|
+
const terminate = () => {
|
|
27
|
+
child.kill('SIGTERM');
|
|
28
|
+
killTimer = setTimeout(() => child.kill('SIGKILL'), TIMEOUT_KILL_GRACE_MS);
|
|
29
|
+
};
|
|
25
30
|
const timeoutTimer = input.timeoutMs === undefined
|
|
26
31
|
? undefined
|
|
27
32
|
: setTimeout(() => {
|
|
28
33
|
timedOut = true;
|
|
29
|
-
|
|
30
|
-
killTimer = setTimeout(() => child.kill('SIGKILL'), TIMEOUT_KILL_GRACE_MS);
|
|
34
|
+
terminate();
|
|
31
35
|
}, input.timeoutMs);
|
|
36
|
+
const abortListener = () => {
|
|
37
|
+
canceled = true;
|
|
38
|
+
terminate();
|
|
39
|
+
};
|
|
40
|
+
input.cancellationSignal?.addEventListener('abort', abortListener, { once: true });
|
|
41
|
+
if (input.cancellationSignal?.aborted === true) {
|
|
42
|
+
abortListener();
|
|
43
|
+
}
|
|
32
44
|
child.stdout.on('data', (chunk) => {
|
|
33
45
|
stdout += chunk.toString();
|
|
34
46
|
});
|
|
@@ -38,11 +50,13 @@ export function runAgentCliCommand(input) {
|
|
|
38
50
|
child.on('error', (error) => {
|
|
39
51
|
clearTimeout(timeoutTimer);
|
|
40
52
|
clearTimeout(killTimer);
|
|
53
|
+
input.cancellationSignal?.removeEventListener('abort', abortListener);
|
|
41
54
|
reject(error);
|
|
42
55
|
});
|
|
43
56
|
child.on('close', async (exitCode) => {
|
|
44
57
|
clearTimeout(timeoutTimer);
|
|
45
58
|
clearTimeout(killTimer);
|
|
59
|
+
input.cancellationSignal?.removeEventListener('abort', abortListener);
|
|
46
60
|
await startNotification;
|
|
47
61
|
if (startNotificationError !== undefined) {
|
|
48
62
|
reject(startNotificationError);
|
|
@@ -52,7 +66,7 @@ export function runAgentCliCommand(input) {
|
|
|
52
66
|
stdout,
|
|
53
67
|
stderr,
|
|
54
68
|
exitCode: exitCode ?? 1,
|
|
55
|
-
timedOut,
|
|
69
|
+
timedOut: timedOut || canceled,
|
|
56
70
|
});
|
|
57
71
|
});
|
|
58
72
|
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { currentProcessIdentity } from '../lib/process-identity.js';
|
|
2
|
+
function createEventQueue() {
|
|
3
|
+
const queue = [];
|
|
4
|
+
const waiters = [];
|
|
5
|
+
let closed = false;
|
|
6
|
+
function emit(value) {
|
|
7
|
+
const waiter = waiters.shift();
|
|
8
|
+
if (waiter !== undefined) {
|
|
9
|
+
waiter(value);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
queue.push(value);
|
|
13
|
+
}
|
|
14
|
+
async function nextQueued() {
|
|
15
|
+
const value = queue.shift();
|
|
16
|
+
if (value !== undefined)
|
|
17
|
+
return value;
|
|
18
|
+
if (closed)
|
|
19
|
+
return { kind: 'done' };
|
|
20
|
+
return new Promise((resolve) => waiters.push(resolve));
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
push(event) {
|
|
24
|
+
if (!closed)
|
|
25
|
+
emit({ kind: 'event', event });
|
|
26
|
+
},
|
|
27
|
+
close() {
|
|
28
|
+
if (closed)
|
|
29
|
+
return;
|
|
30
|
+
closed = true;
|
|
31
|
+
emit({ kind: 'done' });
|
|
32
|
+
},
|
|
33
|
+
fail(error) {
|
|
34
|
+
if (closed)
|
|
35
|
+
return;
|
|
36
|
+
closed = true;
|
|
37
|
+
emit({ kind: 'error', error });
|
|
38
|
+
},
|
|
39
|
+
iterable: {
|
|
40
|
+
async *[Symbol.asyncIterator]() {
|
|
41
|
+
while (true) {
|
|
42
|
+
const value = await nextQueued();
|
|
43
|
+
if (value.kind === 'done')
|
|
44
|
+
return;
|
|
45
|
+
if (value.kind === 'error')
|
|
46
|
+
throw value.error;
|
|
47
|
+
yield value.event;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
export function createAgentExecution(input, execute) {
|
|
54
|
+
const controller = new AbortController();
|
|
55
|
+
const events = createEventQueue();
|
|
56
|
+
const result = Promise.resolve()
|
|
57
|
+
.then(() => execute({
|
|
58
|
+
...input,
|
|
59
|
+
cancellationSignal: controller.signal,
|
|
60
|
+
onRuntimeEvent: async (event) => {
|
|
61
|
+
await input.onRuntimeEvent?.(event);
|
|
62
|
+
events.push(event);
|
|
63
|
+
},
|
|
64
|
+
}))
|
|
65
|
+
.then((value) => {
|
|
66
|
+
events.close();
|
|
67
|
+
return value;
|
|
68
|
+
}, (error) => {
|
|
69
|
+
events.fail(error);
|
|
70
|
+
throw error;
|
|
71
|
+
});
|
|
72
|
+
return {
|
|
73
|
+
runId: input.runId,
|
|
74
|
+
processIdentity: currentProcessIdentity(),
|
|
75
|
+
events: events.iterable,
|
|
76
|
+
async cancel(reason) {
|
|
77
|
+
controller.abort(reason);
|
|
78
|
+
},
|
|
79
|
+
result,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -18,12 +18,14 @@ import { createOutbox } from './outbox.js';
|
|
|
18
18
|
import { createEventResolver } from './event-resolver.js';
|
|
19
19
|
import { createStaleRunReconciler } from './stale-run-reconciler.js';
|
|
20
20
|
import { createWorkspaceCleanup } from './workspace-cleanup.js';
|
|
21
|
+
import { createAgentExecution } from './live-execution.js';
|
|
21
22
|
import { createAutonomousDecisionAuditEvent, workflowRevision as computeWorkflowRevision, } from './audit-events.js';
|
|
22
23
|
import { createRunLease, isRunLeaseExpired, renewRunLease, runLeaseRenewalIntervalMs, } from './run-lease.js';
|
|
23
24
|
import { currentProcessIdentity, processIdentityMatches } from '../lib/process-identity.js';
|
|
24
25
|
import { readJsonFile, writeJsonFile } from '../lib/json-file.js';
|
|
25
26
|
import { isMissingPathError } from '../lib/state-health.js';
|
|
26
27
|
const prReviewApprovalMarker = '<!-- wake:pr-review-approved -->';
|
|
28
|
+
const activeRunSourceRefreshIntervalMs = 1_000;
|
|
27
29
|
function latestHumanCommentId(candidate) {
|
|
28
30
|
const human = candidate.comments.filter((c) => !c.isBotAuthored);
|
|
29
31
|
return human.at(-1)?.id;
|
|
@@ -400,7 +402,17 @@ export function createTickRunner(deps) {
|
|
|
400
402
|
return watch;
|
|
401
403
|
}
|
|
402
404
|
async function markPendingActionableIssues(projections) {
|
|
405
|
+
const activeRunWorkItemKeys = new Set();
|
|
406
|
+
const now = deps.clock.now();
|
|
407
|
+
for (const record of await deps.stateStore.listRunRecords()) {
|
|
408
|
+
if (record.status === 'running' && (await isRunningRecordActive(record, now))) {
|
|
409
|
+
activeRunWorkItemKeys.add(record.workItemKey);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
403
412
|
for (const projection of projections) {
|
|
413
|
+
if (activeRunWorkItemKeys.has(projection.workItemKey)) {
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
404
416
|
const statusLabel = statusLabelForStage(projection.wake.stage);
|
|
405
417
|
const stageLabel = stageLabelForStage(projection.wake.stage);
|
|
406
418
|
const workflowLabel = workflowLabelForWorkflowName(workflowNameForProjection(projection, deps.config));
|
|
@@ -423,6 +435,21 @@ export function createTickRunner(deps) {
|
|
|
423
435
|
function runnerTimeoutMs() {
|
|
424
436
|
return maxConfiguredRunnerTimeoutMs(deps.config);
|
|
425
437
|
}
|
|
438
|
+
function cancellationReasonForIneligibleProjection(projection) {
|
|
439
|
+
if (projection === null || projection.issue.state !== 'open') {
|
|
440
|
+
return 'CANCELED_BY_SOURCE_CLOSED';
|
|
441
|
+
}
|
|
442
|
+
const requiredAssignees = deps.config.sources.github.policy.requiredAssignees;
|
|
443
|
+
if (requiredAssignees.length > 0 &&
|
|
444
|
+
!requiredAssignees.some((login) => projection.issue.assignees.includes(login))) {
|
|
445
|
+
return 'CANCELED_BY_UNASSIGNMENT';
|
|
446
|
+
}
|
|
447
|
+
const workflow = workflowForProjection(projection, deps.config);
|
|
448
|
+
if (workflow === null || !isKnownWorkflowStage(projection.wake.stage, workflow)) {
|
|
449
|
+
return 'CANCELED_BY_WORKFLOW_CHANGE';
|
|
450
|
+
}
|
|
451
|
+
return 'CANCELED_BY_SUPERSEDING_EVENT';
|
|
452
|
+
}
|
|
426
453
|
async function isRunningRecordActive(record, now) {
|
|
427
454
|
if (record.lease !== undefined && !isRunLeaseExpired(record, now)) {
|
|
428
455
|
return true;
|
|
@@ -1161,6 +1188,12 @@ export function createTickRunner(deps) {
|
|
|
1161
1188
|
});
|
|
1162
1189
|
}, runLeaseRenewalIntervalMs);
|
|
1163
1190
|
}
|
|
1191
|
+
function delayActiveRunRefresh() {
|
|
1192
|
+
return new Promise((resolve) => {
|
|
1193
|
+
const timer = setTimeout(resolve, activeRunSourceRefreshIntervalMs);
|
|
1194
|
+
timer.unref?.();
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1164
1197
|
try {
|
|
1165
1198
|
await transitionRunLifecycle('PREPARING');
|
|
1166
1199
|
const prepareResult = workspaceMode === 'branch'
|
|
@@ -1192,17 +1225,20 @@ export function createTickRunner(deps) {
|
|
|
1192
1225
|
const recentEvents = await deps.stateStore.listEventEnvelopesForWorkItem(candidate.workItemKey, 6);
|
|
1193
1226
|
await transitionRunLifecycle('RUNNING');
|
|
1194
1227
|
startLeaseRenewal();
|
|
1228
|
+
const activeCandidate = candidate;
|
|
1195
1229
|
const runnerProjection = watcherRun
|
|
1196
1230
|
? {
|
|
1197
|
-
...
|
|
1231
|
+
...activeCandidate,
|
|
1198
1232
|
wake: {
|
|
1199
|
-
...
|
|
1233
|
+
...activeCandidate.wake,
|
|
1200
1234
|
sessionId: undefined,
|
|
1201
1235
|
sessionCli: undefined,
|
|
1202
1236
|
},
|
|
1203
1237
|
}
|
|
1204
|
-
:
|
|
1205
|
-
|
|
1238
|
+
: activeCandidate;
|
|
1239
|
+
let executionFinished = false;
|
|
1240
|
+
let cancellationReason = null;
|
|
1241
|
+
const runnerInput = {
|
|
1206
1242
|
action,
|
|
1207
1243
|
projection: runnerProjection,
|
|
1208
1244
|
recentEvents,
|
|
@@ -1227,7 +1263,79 @@ export function createTickRunner(deps) {
|
|
|
1227
1263
|
});
|
|
1228
1264
|
},
|
|
1229
1265
|
onRuntimeEvent: appendRuntimeEvent,
|
|
1230
|
-
}
|
|
1266
|
+
};
|
|
1267
|
+
const execution = deps.runner.start === undefined
|
|
1268
|
+
? createAgentExecution(runnerInput, (liveInput) => deps.runner.run(liveInput))
|
|
1269
|
+
: await deps.runner.start(runnerInput);
|
|
1270
|
+
async function persistCancellationRequest(reason) {
|
|
1271
|
+
const requestedAt = deps.clock.now().toISOString();
|
|
1272
|
+
await deps.stateStore.updateRunRecordIf(runId, {
|
|
1273
|
+
expect: (record) => record.status === 'running' &&
|
|
1274
|
+
record.lease?.leaseId === lease.leaseId &&
|
|
1275
|
+
record.lease.ownerInstanceId === ownerInstanceId,
|
|
1276
|
+
update: (record) => ({
|
|
1277
|
+
...record,
|
|
1278
|
+
metadata: {
|
|
1279
|
+
...record.metadata,
|
|
1280
|
+
cancellation: {
|
|
1281
|
+
reason,
|
|
1282
|
+
requestedAt,
|
|
1283
|
+
source: 'active-source-reconciliation',
|
|
1284
|
+
},
|
|
1285
|
+
},
|
|
1286
|
+
}),
|
|
1287
|
+
});
|
|
1288
|
+
}
|
|
1289
|
+
async function superviseActiveSource() {
|
|
1290
|
+
if (deps.workSource.refreshForDispatch === undefined) {
|
|
1291
|
+
return null;
|
|
1292
|
+
}
|
|
1293
|
+
while (!executionFinished) {
|
|
1294
|
+
await delayActiveRunRefresh();
|
|
1295
|
+
if (executionFinished) {
|
|
1296
|
+
return null;
|
|
1297
|
+
}
|
|
1298
|
+
let activeRefresh;
|
|
1299
|
+
try {
|
|
1300
|
+
activeRefresh = await deps.workSource.refreshForDispatch({
|
|
1301
|
+
projection: activeCandidate,
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
catch {
|
|
1305
|
+
continue;
|
|
1306
|
+
}
|
|
1307
|
+
if (activeRefresh === null) {
|
|
1308
|
+
continue;
|
|
1309
|
+
}
|
|
1310
|
+
if (activeRefresh.events.length > 0) {
|
|
1311
|
+
await ingestInboundEvents(activeRefresh.events);
|
|
1312
|
+
}
|
|
1313
|
+
const refreshedProjection = (await deps.stateStore.readIssueState(activeCandidate.workItemKey)) ??
|
|
1314
|
+
activeCandidate;
|
|
1315
|
+
const ineligible = activeRefresh.sourceExists === false ||
|
|
1316
|
+
!policy.isEligible(refreshedProjection, deps.config);
|
|
1317
|
+
if (!ineligible) {
|
|
1318
|
+
continue;
|
|
1319
|
+
}
|
|
1320
|
+
const reason = cancellationReasonForIneligibleProjection(activeRefresh.sourceExists === false ? null : refreshedProjection);
|
|
1321
|
+
cancellationReason = reason;
|
|
1322
|
+
await persistCancellationRequest(reason);
|
|
1323
|
+
await execution.cancel(reason);
|
|
1324
|
+
return reason;
|
|
1325
|
+
}
|
|
1326
|
+
return null;
|
|
1327
|
+
}
|
|
1328
|
+
const runnerResult = await Promise.race([
|
|
1329
|
+
execution.result.finally(() => {
|
|
1330
|
+
executionFinished = true;
|
|
1331
|
+
}),
|
|
1332
|
+
superviseActiveSource().then(async (reason) => {
|
|
1333
|
+
if (reason === null) {
|
|
1334
|
+
return execution.result;
|
|
1335
|
+
}
|
|
1336
|
+
return execution.result;
|
|
1337
|
+
}),
|
|
1338
|
+
]);
|
|
1231
1339
|
clearInterval(leaseRenewalTimer);
|
|
1232
1340
|
leaseRenewalTimer = undefined;
|
|
1233
1341
|
const parsedRunnerResult = parseRunnerResult(runnerResult.result);
|
|
@@ -1333,16 +1441,19 @@ export function createTickRunner(deps) {
|
|
|
1333
1441
|
const resultMetadata = {
|
|
1334
1442
|
...runnerResult.metadata,
|
|
1335
1443
|
envelope: parsedRunnerResult.envelope,
|
|
1444
|
+
...(cancellationReason === null ? {} : { cancellationReason }),
|
|
1336
1445
|
...(runnerResult.failureClass === undefined
|
|
1337
1446
|
? {}
|
|
1338
1447
|
: { failureClass: runnerResult.failureClass }),
|
|
1339
1448
|
...(runnerResult.routing === undefined ? {} : { routing: runnerResult.routing }),
|
|
1340
1449
|
};
|
|
1341
|
-
const executionOutcome =
|
|
1342
|
-
?
|
|
1343
|
-
: runnerResult.failureClass === '
|
|
1344
|
-
? '
|
|
1345
|
-
: '
|
|
1450
|
+
const executionOutcome = cancellationReason !== null
|
|
1451
|
+
? cancellationReason
|
|
1452
|
+
: runnerResult.failureClass === 'quota'
|
|
1453
|
+
? 'QUOTA_EXHAUSTED'
|
|
1454
|
+
: runnerResult.failureClass === 'infra'
|
|
1455
|
+
? 'PROCESS_FAILED'
|
|
1456
|
+
: 'COMPLETED';
|
|
1346
1457
|
const workflowOutcome = sentinel === 'DONE'
|
|
1347
1458
|
? 'DONE'
|
|
1348
1459
|
: sentinel === 'BLOCKED'
|
|
@@ -1400,7 +1511,9 @@ export function createTickRunner(deps) {
|
|
|
1400
1511
|
sessionId: runnerResult.session_id,
|
|
1401
1512
|
sessionCli: runnerResult.cli,
|
|
1402
1513
|
workspacePath,
|
|
1403
|
-
reason:
|
|
1514
|
+
reason: cancellationReason === null
|
|
1515
|
+
? `runner:${sentinel.toLowerCase()}`
|
|
1516
|
+
: `runner:${String(cancellationReason).toLowerCase()}`,
|
|
1404
1517
|
...(runnerResult.routing === undefined ? {} : { routing: runnerResult.routing }),
|
|
1405
1518
|
...(runnerResult.failureClass === undefined
|
|
1406
1519
|
? {}
|
|
@@ -24,6 +24,10 @@ export const executionOutcomeValues = [
|
|
|
24
24
|
'TIMED_OUT',
|
|
25
25
|
'STALLED',
|
|
26
26
|
'CANCELED_BY_RECONCILIATION',
|
|
27
|
+
'CANCELED_BY_SOURCE_CLOSED',
|
|
28
|
+
'CANCELED_BY_UNASSIGNMENT',
|
|
29
|
+
'CANCELED_BY_SUPERSEDING_EVENT',
|
|
30
|
+
'CANCELED_BY_WORKFLOW_CHANGE',
|
|
27
31
|
'CANCELED_BY_OPERATOR',
|
|
28
32
|
'QUOTA_EXHAUSTED',
|
|
29
33
|
'MALFORMED_OUTPUT',
|
package/dist/src/version.js
CHANGED