@cliangdev/conductor 0.6.1 → 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 (43) hide show
  1. package/assets/claude/commands/conductor/workflow.md +95 -12
  2. package/dist/commands/config.d.ts.map +1 -1
  3. package/dist/commands/config.js +38 -0
  4. package/dist/commands/config.js.map +1 -1
  5. package/dist/daemon/job-runner.d.ts +81 -0
  6. package/dist/daemon/job-runner.d.ts.map +1 -0
  7. package/dist/daemon/job-runner.js +533 -0
  8. package/dist/daemon/job-runner.js.map +1 -0
  9. package/dist/daemon/run-lifecycle.d.ts +7 -0
  10. package/dist/daemon/run-lifecycle.d.ts.map +1 -1
  11. package/dist/daemon/run-lifecycle.js +26 -0
  12. package/dist/daemon/run-lifecycle.js.map +1 -1
  13. package/dist/daemon/run-queue.d.ts +6 -1
  14. package/dist/daemon/run-queue.d.ts.map +1 -1
  15. package/dist/daemon/run-queue.js +42 -3
  16. package/dist/daemon/run-queue.js.map +1 -1
  17. package/dist/daemon/runner.d.ts +16 -0
  18. package/dist/daemon/runner.d.ts.map +1 -1
  19. package/dist/daemon/runner.js +25 -19
  20. package/dist/daemon/runner.js.map +1 -1
  21. package/dist/daemon/watcher.d.ts.map +1 -1
  22. package/dist/daemon/watcher.js +7 -1
  23. package/dist/daemon/watcher.js.map +1 -1
  24. package/dist/lib/config.d.ts +4 -0
  25. package/dist/lib/config.d.ts.map +1 -1
  26. package/dist/lib/config.js +5 -1
  27. package/dist/lib/config.js.map +1 -1
  28. package/dist/mcp/index.d.ts.map +1 -1
  29. package/dist/mcp/index.js +65 -6
  30. package/dist/mcp/index.js.map +1 -1
  31. package/dist/mcp/tools/documents.d.ts +11 -0
  32. package/dist/mcp/tools/documents.d.ts.map +1 -1
  33. package/dist/mcp/tools/documents.js +22 -2
  34. package/dist/mcp/tools/documents.js.map +1 -1
  35. package/dist/mcp/tools/integrations.d.ts +1 -0
  36. package/dist/mcp/tools/integrations.d.ts.map +1 -1
  37. package/dist/mcp/tools/integrations.js +3 -0
  38. package/dist/mcp/tools/integrations.js.map +1 -1
  39. package/dist/mcp/tools/workflows.d.ts +12 -0
  40. package/dist/mcp/tools/workflows.d.ts.map +1 -1
  41. package/dist/mcp/tools/workflows.js +21 -0
  42. package/dist/mcp/tools/workflows.js.map +1 -1
  43. package/package.json +1 -1
@@ -0,0 +1,533 @@
1
+ import * as fs from 'fs';
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+ import { randomUUID } from 'crypto';
5
+ import { spawnAndWait, buildEnvArgs } from './runner.js';
6
+ import { acknowledgeEvent, completeJob } from './run-lifecycle.js';
7
+ // ─── Constants ───────────────────────────────────────────────────────────────
8
+ export const DEFAULT_RUNNER_IMAGE = 'ghcr.io/cliangdev/conductor-runner:3';
9
+ export const DEFAULT_TIMEOUT_MINUTES = 30;
10
+ const LOG_BATCH_INTERVAL_MS = 2000;
11
+ /** Fixed in-container path consumed artifacts are made available at — mirrors
12
+ * ClaudeCodeStepExecutor's CONDUCTOR_ARTIFACTS_DIR value for the Cloud Run path, so the same
13
+ * entrypoint contract works regardless of which launcher runs it. */
14
+ const ARTIFACTS_CONTAINER_DIR = '/conductor/artifacts';
15
+ /** Workspace-relative root a producing step's declared `path:` is resolved against, inside the
16
+ * container — matches the claude-code entrypoint's WORKSPACE_DIR. */
17
+ const WORKSPACE_CONTAINER_DIR = '/conductor/workspace';
18
+ /** Extra headroom for the daemon's kill backstop on claude-code steps: the
19
+ * entrypoint enforces the real timeout itself (SIGTERM→SIGKILL, then
20
+ * self-reports CLAUDE_TIMEOUT); killing at exactly the same moment would race
21
+ * that self-report. */
22
+ const CLAUDE_TIMEOUT_GRACE_MS = 2 * 60000;
23
+ /** conductor-claude-entrypoint exit taxonomy → job-level errorReason. */
24
+ const CLAUDE_EXIT_ERROR_REASONS = {
25
+ 10: 'CLAUDE_AGENT_ERROR',
26
+ 11: 'CLAUDE_AUTH_ERROR',
27
+ 12: 'CLAUDE_RATE_LIMITED',
28
+ 13: 'CLAUDE_TIMEOUT',
29
+ 20: 'CLAUDE_CONFIG_ERROR',
30
+ };
31
+ /** Env keys that must never appear in `docker run -e KEY=VALUE` argv — visible to any local user
32
+ * via `ps`/procfs. These go into a `--env-file` instead (see {@link splitSecretEnv}). */
33
+ const DOCKER_ARGV_SECRET_KEYS = [
34
+ 'CLAUDE_CODE_OAUTH_TOKEN',
35
+ 'CONDUCTOR_API_KEY',
36
+ 'CONDUCTOR_RUN_TOKEN',
37
+ 'ANTHROPIC_API_KEY',
38
+ ];
39
+ // ─── Helpers ─────────────────────────────────────────────────────────────────
40
+ /** Fills a `{workerJobId}` placeholder in a callback URL template. Templates
41
+ * with no placeholder (e.g. a run-scoped log-chunk URL) are returned as-is. */
42
+ export function fillTemplate(template, workerJobId) {
43
+ return template.replace(/\{workerJobId\}/g, workerJobId);
44
+ }
45
+ /**
46
+ * Assembles the container env contract for a single step: job-level payload
47
+ * env, overridden by step-level env, overridden by the CONDUCTOR_* contract
48
+ * vars. `ANTHROPIC_API_KEY` is stripped unconditionally — self-hosted jobs
49
+ * must never carry it, even if it leaked into the payload's env — since it
50
+ * silently overrides subscription auth in `claude -p`.
51
+ */
52
+ export function buildStepEnv(payload, step, event, config, stepCompleteUrl, logChunkUrl) {
53
+ const baseEnv = { ...payload.env, ...(step.env ?? {}) };
54
+ delete baseEnv['ANTHROPIC_API_KEY'];
55
+ const contractEnv = {
56
+ CONDUCTOR_API_URL: config.apiUrl,
57
+ CONDUCTOR_PROJECT_ID: event.projectId,
58
+ CONDUCTOR_WORKFLOW_RUN_ID: event.workflowRunId,
59
+ CONDUCTOR_JOB_ID: event.jobId,
60
+ CONDUCTOR_WORKER_JOB_ID: step.workerJobId,
61
+ CONDUCTOR_RUN_TOKEN: payload.runToken,
62
+ CONDUCTOR_LOG_CHUNK_URL: logChunkUrl,
63
+ CONDUCTOR_STEP_COMPLETE_URL: stepCompleteUrl,
64
+ CONDUCTOR_TIMEOUT_MINUTES: String(step.timeoutMinutes ?? DEFAULT_TIMEOUT_MINUTES),
65
+ CONDUCTOR_MCP_ENABLED: step.conductorMcp ? 'true' : 'false',
66
+ };
67
+ if (step.conductorMcp) {
68
+ contractEnv.CONDUCTOR_API_KEY = config.apiKey;
69
+ }
70
+ if (step.stepType === 'claude-code') {
71
+ contractEnv.CONDUCTOR_STEP_PROMPT = step.prompt ?? '';
72
+ if (step.inputsJson !== undefined)
73
+ contractEnv.CONDUCTOR_STEP_INPUTS_JSON = step.inputsJson;
74
+ if (step.allowedTools !== undefined)
75
+ contractEnv.CONDUCTOR_ALLOWED_TOOLS = step.allowedTools;
76
+ if (step.maxTurns !== undefined)
77
+ contractEnv.CONDUCTOR_MAX_TURNS = String(step.maxTurns);
78
+ if (step.outputSchemaJson !== undefined)
79
+ contractEnv.CONDUCTOR_OUTPUT_SCHEMA_JSON = step.outputSchemaJson;
80
+ // Caller (runStep) guarantees this is present before reaching here.
81
+ contractEnv.CLAUDE_CODE_OAUTH_TOKEN = config.claudeCodeOauthToken ?? '';
82
+ if (step.artifacts && step.artifacts.length > 0 && payload.artifactsUrl) {
83
+ contractEnv.CONDUCTOR_ARTIFACTS_URL = payload.artifactsUrl;
84
+ contractEnv.CONDUCTOR_STEP_ARTIFACTS_JSON = JSON.stringify(step.artifacts);
85
+ }
86
+ if (payload.consumedArtifacts && payload.consumedArtifacts.length > 0) {
87
+ contractEnv.CONDUCTOR_CONSUMED_ARTIFACTS_JSON = JSON.stringify(payload.consumedArtifacts);
88
+ contractEnv.CONDUCTOR_ARTIFACTS_DIR = ARTIFACTS_CONTAINER_DIR;
89
+ }
90
+ }
91
+ const merged = { ...baseEnv, ...contractEnv };
92
+ delete merged['ANTHROPIC_API_KEY'];
93
+ return merged;
94
+ }
95
+ /** Redacts secret values (OAuth token, API key, run token) from a log line
96
+ * before it's posted upstream. */
97
+ function redactSecrets(line, secrets) {
98
+ let out = line;
99
+ for (const secret of secrets) {
100
+ if (!secret)
101
+ continue;
102
+ out = out.split(secret).join('***REDACTED***');
103
+ }
104
+ return out;
105
+ }
106
+ /** Batches log lines and POSTs them to the log-chunk callback as `{lines}`
107
+ * with the per-run token — the protocol-2 shape, distinct from the legacy
108
+ * `{chunk}` + apiKey shape in runner.ts's streamLogChunk. */
109
+ function createLogBatcher(logChunkUrl, runToken, secrets) {
110
+ let buffer = [];
111
+ let timer = null;
112
+ async function flush() {
113
+ if (buffer.length === 0)
114
+ return;
115
+ const lines = buffer;
116
+ buffer = [];
117
+ try {
118
+ await fetch(logChunkUrl, {
119
+ method: 'POST',
120
+ headers: {
121
+ 'Content-Type': 'application/json',
122
+ Authorization: `Bearer ${runToken}`,
123
+ },
124
+ body: JSON.stringify({ lines }),
125
+ });
126
+ }
127
+ catch (err) {
128
+ console.error('[job-runner] Failed to stream log chunk:', err);
129
+ }
130
+ }
131
+ function push(rawChunk) {
132
+ const redacted = redactSecrets(rawChunk, secrets);
133
+ for (const line of redacted.split('\n')) {
134
+ if (line.length > 0)
135
+ buffer.push(line);
136
+ }
137
+ }
138
+ function start() {
139
+ timer = setInterval(() => {
140
+ void flush();
141
+ }, LOG_BATCH_INTERVAL_MS);
142
+ }
143
+ function stop() {
144
+ if (timer !== null) {
145
+ clearInterval(timer);
146
+ timer = null;
147
+ }
148
+ }
149
+ return { push, flush, start, stop };
150
+ }
151
+ async function fetchDispatchPayload(event, config) {
152
+ const url = `${config.apiUrl}/api/v1/workflow-runs/${event.workflowRunId}/jobs/${event.jobId}/dispatch-payload`;
153
+ try {
154
+ const response = await fetch(url, {
155
+ headers: {
156
+ Authorization: `Bearer ${config.apiKey}`,
157
+ 'Content-Type': 'application/json',
158
+ },
159
+ });
160
+ if (response.status === 404 || response.status === 410) {
161
+ return 'not-found';
162
+ }
163
+ if (!response.ok) {
164
+ console.error(`[job-runner] dispatch-payload fetch failed with status ${response.status}`);
165
+ return null;
166
+ }
167
+ return (await response.json());
168
+ }
169
+ catch (err) {
170
+ console.error('[job-runner] Failed to fetch dispatch payload:', err);
171
+ return null;
172
+ }
173
+ }
174
+ /**
175
+ * Splits a step's container env into secret keys (never argv/procfs, see
176
+ * {@link DOCKER_ARGV_SECRET_KEYS}) and everything else, which still goes through `-e` args —
177
+ * `docker run --env-file` can't carry multiline values, and non-secret env is never multiline in
178
+ * practice (the claude-code prompt, which can be, is a secret-adjacent CONDUCTOR_STEP_PROMPT var
179
+ * that isn't in the secret list and stays on argv; only the four listed keys are ever redirected).
180
+ */
181
+ function splitSecretEnv(env) {
182
+ const fileEnv = {};
183
+ const argEnv = {};
184
+ for (const [key, value] of Object.entries(env)) {
185
+ if (!DOCKER_ARGV_SECRET_KEYS.includes(key)) {
186
+ argEnv[key] = value;
187
+ continue;
188
+ }
189
+ if (value.includes('\n')) {
190
+ console.error(`[job-runner] ${key} contains a newline, which docker --env-file cannot carry; ` +
191
+ 'omitting it from the container env');
192
+ continue;
193
+ }
194
+ fileEnv[key] = value;
195
+ }
196
+ return { fileEnv, argEnv };
197
+ }
198
+ /** Writes secret env vars to a mode-0600 temp file for `docker run --env-file`, keeping them out
199
+ * of process argv. Caller is responsible for deleting the returned path once the container exits. */
200
+ function writeSecretEnvFile(fileEnv) {
201
+ const filePath = path.join(os.tmpdir(), `conductor-env-${randomUUID()}.env`);
202
+ const contents = Object.entries(fileEnv)
203
+ .map(([key, value]) => `${key}=${value}`)
204
+ .join('\n');
205
+ fs.writeFileSync(filePath, contents + '\n', { mode: 0o600 });
206
+ return filePath;
207
+ }
208
+ /**
209
+ * Downloads every consumed artifact into a fresh per-job temp directory, once per job (not per
210
+ * step) — the same directory is bind-mounted at {@link ARTIFACTS_CONTAINER_DIR} into every
211
+ * container this job runs, so any step (not just claude-code, whose entrypoint additionally gets
212
+ * `CONDUCTOR_CONSUMED_ARTIFACTS_JSON`) can read the files directly.
213
+ *
214
+ * A failed download (non-OK response or a network error) fails fast with a named reason — mirrors
215
+ * conductor-claude-entrypoint.mjs's materializeConsumedArtifacts, which throws a ConfigError on the
216
+ * same condition: a consumer job that can't get a file it declared `consumes:` on has nothing
217
+ * sensible to fall back to, and silently running steps against a missing file is exactly the
218
+ * silent-absence failure mode artifact passing exists to prevent.
219
+ */
220
+ async function downloadConsumedArtifacts(payload, jobRunId) {
221
+ if (!payload.consumedArtifacts || payload.consumedArtifacts.length === 0)
222
+ return { ok: true, dir: null };
223
+ const dir = path.join(os.tmpdir(), `conductor-artifacts-${jobRunId}`);
224
+ fs.mkdirSync(dir, { recursive: true });
225
+ for (const artifact of payload.consumedArtifacts) {
226
+ let res;
227
+ try {
228
+ res = await fetch(artifact.downloadUrl);
229
+ }
230
+ catch (err) {
231
+ cleanupDir(dir);
232
+ return {
233
+ ok: false,
234
+ errorReason: `ARTIFACT_DOWNLOAD_FAILED: failed to download consumed artifact '${artifact.name}': ${String(err)}`,
235
+ };
236
+ }
237
+ if (!res.ok) {
238
+ cleanupDir(dir);
239
+ return {
240
+ ok: false,
241
+ errorReason: `ARTIFACT_DOWNLOAD_FAILED: failed to download consumed artifact '${artifact.name}': HTTP ${res.status}`,
242
+ };
243
+ }
244
+ const buf = Buffer.from(await res.arrayBuffer());
245
+ fs.writeFileSync(path.join(dir, artifact.name), buf);
246
+ }
247
+ return { ok: true, dir };
248
+ }
249
+ /** Best-effort recursive removal — used to clean up the per-job artifacts dir when a partial
250
+ * download fails partway through, since the caller never gets a handle to it in that case. */
251
+ function cleanupDir(dir) {
252
+ try {
253
+ fs.rmSync(dir, { recursive: true, force: true });
254
+ }
255
+ catch (err) {
256
+ console.error('[job-runner] Failed to remove consumed-artifacts dir after a failed download:', err);
257
+ }
258
+ }
259
+ /** Declares one artifact (`POST {artifactsUrl}`) and returns its upload target, or null on failure. */
260
+ async function createArtifact(artifactsUrl, jobId, name, runToken) {
261
+ try {
262
+ const res = await fetch(artifactsUrl, {
263
+ method: 'POST',
264
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${runToken}` },
265
+ body: JSON.stringify({ jobId, name }),
266
+ });
267
+ if (!res.ok)
268
+ return null;
269
+ return (await res.json());
270
+ }
271
+ catch (err) {
272
+ console.error(`[job-runner] Failed to create artifact '${name}':`, err);
273
+ return null;
274
+ }
275
+ }
276
+ /**
277
+ * PUTs the artifact's raw bytes to its upload URL. A signed GCS URL is self-contained and must NOT
278
+ * carry an Authorization header (it would invalidate the signature); the local-profile passthrough
279
+ * URL is backend-relative (starts with `apiUrl`) and DOES need the run-token bearer header — that's
280
+ * the only signal available to tell the two apart.
281
+ */
282
+ async function putArtifactContent(uploadUrl, content, runToken, apiUrl) {
283
+ const headers = {};
284
+ if (uploadUrl.startsWith(apiUrl)) {
285
+ headers['Authorization'] = `Bearer ${runToken}`;
286
+ }
287
+ try {
288
+ const res = await fetch(uploadUrl, { method: 'PUT', headers, body: content });
289
+ return res.ok;
290
+ }
291
+ catch (err) {
292
+ console.error('[job-runner] Failed to PUT artifact content:', err);
293
+ return false;
294
+ }
295
+ }
296
+ async function completeArtifact(artifactsUrl, artifactId, runToken) {
297
+ try {
298
+ const res = await fetch(`${artifactsUrl}/${artifactId}/complete`, {
299
+ method: 'POST',
300
+ headers: { Authorization: `Bearer ${runToken}` },
301
+ });
302
+ return res.ok;
303
+ }
304
+ catch (err) {
305
+ console.error(`[job-runner] Failed to complete artifact ${artifactId}:`, err);
306
+ return false;
307
+ }
308
+ }
309
+ /**
310
+ * Uploads a `docker` step's declared artifacts after it exits successfully — `claude-code` steps
311
+ * never reach here (the entrypoint uploads its own artifacts over the network, from inside the
312
+ * container, before exiting). Requires the container to still exist (caller must not have used
313
+ * `--rm`): each declared `path:` is `docker cp`'d out of {@link WORKSPACE_CONTAINER_DIR} before the
314
+ * create/PUT/complete sequence. Returns a FAILED StepResult on the first problem (missing file or
315
+ * any HTTP step failing) — no partial credit for a job that promised an artifact it didn't deliver.
316
+ */
317
+ async function uploadDockerStepArtifacts(payload, event, step, containerName, config) {
318
+ if (!step.artifacts || step.artifacts.length === 0)
319
+ return null;
320
+ if (!payload.artifactsUrl) {
321
+ return { status: 'FAILED', errorReason: 'ARTIFACTS_URL_MISSING' };
322
+ }
323
+ for (const artifact of step.artifacts) {
324
+ const tmpFile = path.join(os.tmpdir(), `conductor-artifact-${randomUUID()}`);
325
+ const containerPath = `${containerName}:${WORKSPACE_CONTAINER_DIR}/${artifact.path}`;
326
+ const cpCode = await spawnAndWait('docker', ['cp', containerPath, tmpFile]);
327
+ if (cpCode !== 0 || !fs.existsSync(tmpFile)) {
328
+ return {
329
+ status: 'FAILED',
330
+ errorReason: `ARTIFACT_MISSING: declared artifact '${artifact.name}' not found at ${artifact.path}`,
331
+ };
332
+ }
333
+ const content = fs.readFileSync(tmpFile);
334
+ try {
335
+ fs.unlinkSync(tmpFile);
336
+ }
337
+ catch {
338
+ // best-effort cleanup
339
+ }
340
+ const created = await createArtifact(payload.artifactsUrl, event.jobId, artifact.name, payload.runToken);
341
+ if (!created) {
342
+ return { status: 'FAILED', errorReason: `ARTIFACT_UPLOAD_FAILED: could not declare artifact '${artifact.name}'` };
343
+ }
344
+ const putOk = await putArtifactContent(created.uploadUrl, content, payload.runToken, config.apiUrl);
345
+ if (!putOk) {
346
+ return { status: 'FAILED', errorReason: `ARTIFACT_UPLOAD_FAILED: upload failed for '${artifact.name}'` };
347
+ }
348
+ const completedOk = await completeArtifact(payload.artifactsUrl, created.artifactId, payload.runToken);
349
+ if (!completedOk) {
350
+ return { status: 'FAILED', errorReason: `ARTIFACT_UPLOAD_FAILED: complete failed for '${artifact.name}'` };
351
+ }
352
+ }
353
+ return null;
354
+ }
355
+ async function postStepComplete(stepCompleteUrl, runToken, body) {
356
+ try {
357
+ await fetch(stepCompleteUrl, {
358
+ method: 'POST',
359
+ headers: {
360
+ 'Content-Type': 'application/json',
361
+ Authorization: `Bearer ${runToken}`,
362
+ },
363
+ body: JSON.stringify(body),
364
+ });
365
+ }
366
+ catch (err) {
367
+ console.error('[job-runner] Failed to post step-complete:', err);
368
+ }
369
+ }
370
+ // ─── Step execution ─────────────────────────────────────────────────────────
371
+ async function runStep(event, payload, step, config, artifactsDir) {
372
+ const stepCompleteUrl = fillTemplate(payload.callbacks.stepCompleteUrlTemplate, step.workerJobId);
373
+ const logChunkUrl = fillTemplate(payload.callbacks.logChunkUrlTemplate, step.workerJobId);
374
+ const isClaudeCode = step.stepType === 'claude-code';
375
+ if (isClaudeCode && !config.claudeCodeOauthToken) {
376
+ const result = { status: 'FAILED', errorReason: 'CLAUDE_SUBSCRIPTION_NOT_CONFIGURED' };
377
+ await postStepComplete(stepCompleteUrl, payload.runToken, result);
378
+ return result;
379
+ }
380
+ const env = buildStepEnv(payload, step, event, config, stepCompleteUrl, logChunkUrl);
381
+ const { fileEnv, argEnv } = splitSecretEnv(env);
382
+ const envFilePath = Object.keys(fileEnv).length > 0 ? writeSecretEnvFile(fileEnv) : null;
383
+ const image = payload.image ?? DEFAULT_RUNNER_IMAGE;
384
+ const containerName = `conductor-job-${payload.jobRunId}-${step.stepIndex}`;
385
+ const command = isClaudeCode ? ['conductor-claude-entrypoint'] : [];
386
+ // `claude-code` steps self-upload their declared artifacts over the network before exiting, so
387
+ // `--rm` is always safe for them. A `docker` step's produced files must be `docker cp`'d out
388
+ // AFTER it exits (see uploadDockerStepArtifacts), so its container is kept around and removed
389
+ // explicitly further down instead.
390
+ const hasProducerArtifacts = !isClaudeCode && (step.artifacts?.length ?? 0) > 0;
391
+ const runArgs = [
392
+ 'run',
393
+ ...(hasProducerArtifacts ? [] : ['--rm']),
394
+ '--name',
395
+ containerName,
396
+ ...(artifactsDir ? ['-v', `${artifactsDir}:${ARTIFACTS_CONTAINER_DIR}`] : []),
397
+ ...(envFilePath ? ['--env-file', envFilePath] : []),
398
+ ...buildEnvArgs(argEnv),
399
+ image,
400
+ ...command,
401
+ ];
402
+ const secrets = [payload.runToken, config.apiKey, config.claudeCodeOauthToken ?? ''];
403
+ const logBatcher = createLogBatcher(logChunkUrl, payload.runToken, secrets);
404
+ logBatcher.start();
405
+ let timedOut = false;
406
+ const timeoutMs = (step.timeoutMinutes ?? DEFAULT_TIMEOUT_MINUTES) * 60000 +
407
+ (isClaudeCode ? CLAUDE_TIMEOUT_GRACE_MS : 0);
408
+ const timeoutTimer = setTimeout(() => {
409
+ timedOut = true;
410
+ void spawnAndWait('docker', ['kill', containerName]);
411
+ }, timeoutMs);
412
+ let spawnFailed = false;
413
+ let exitCode;
414
+ try {
415
+ exitCode = await spawnAndWait('docker', runArgs, {
416
+ onLine: logBatcher.push,
417
+ onSpawnError: () => {
418
+ spawnFailed = true;
419
+ },
420
+ });
421
+ }
422
+ finally {
423
+ if (envFilePath) {
424
+ try {
425
+ fs.unlinkSync(envFilePath);
426
+ }
427
+ catch (err) {
428
+ console.error('[job-runner] Failed to remove secret env file:', err);
429
+ }
430
+ }
431
+ }
432
+ clearTimeout(timeoutTimer);
433
+ logBatcher.stop();
434
+ await logBatcher.flush();
435
+ if (timedOut) {
436
+ const result = { status: 'FAILED', errorReason: 'STEP_TIMEOUT', exitCode };
437
+ await postStepComplete(stepCompleteUrl, payload.runToken, result);
438
+ return result;
439
+ }
440
+ if (spawnFailed) {
441
+ const result = { status: 'FAILED', errorReason: 'STEP_LAUNCH_FAILED', exitCode };
442
+ await postStepComplete(stepCompleteUrl, payload.runToken, result);
443
+ return result;
444
+ }
445
+ if (isClaudeCode) {
446
+ // The container self-reports success/failure to CONDUCTOR_STEP_COMPLETE_URL
447
+ // as part of its own contract — the daemon must not double-post here.
448
+ // The exit code is only used to decide whether the job continues.
449
+ return exitCode === 0
450
+ ? { status: 'SUCCESS' }
451
+ : {
452
+ status: 'FAILED',
453
+ errorReason: CLAUDE_EXIT_ERROR_REASONS[exitCode] ?? 'CLAUDE_AGENT_ERROR',
454
+ exitCode,
455
+ };
456
+ }
457
+ // Non-claude-code steps don't self-report; the daemon posts on their behalf.
458
+ let result = exitCode === 0 ? { status: 'SUCCESS' } : { status: 'FAILED', errorReason: 'STEP_FAILED', exitCode };
459
+ if (exitCode === 0 && hasProducerArtifacts) {
460
+ const artifactFailure = await uploadDockerStepArtifacts(payload, event, step, containerName, config);
461
+ if (artifactFailure)
462
+ result = artifactFailure;
463
+ }
464
+ if (hasProducerArtifacts) {
465
+ // Container was kept alive (no --rm) so uploadDockerStepArtifacts could `docker cp` out of it —
466
+ // remove it now regardless of outcome.
467
+ await spawnAndWait('docker', ['rm', containerName]);
468
+ }
469
+ await postStepComplete(stepCompleteUrl, payload.runToken, result);
470
+ return result;
471
+ }
472
+ // ─── Main ────────────────────────────────────────────────────────────────────
473
+ /**
474
+ * Handles a single `workflow.job` event end-to-end: fetches the interpolated
475
+ * dispatch payload, runs each step sequentially (stopping at the first
476
+ * failure), posts the job-level completion, then acks the event.
477
+ */
478
+ export async function runWorkflowJob(event, config) {
479
+ const payload = await fetchDispatchPayload(event, config);
480
+ if (payload === 'not-found') {
481
+ // Job/run no longer exists server-side (e.g. cancelled) — nothing to
482
+ // report back to; just drop it.
483
+ await acknowledgeEvent(event.projectId, event.eventId, config);
484
+ return;
485
+ }
486
+ if (payload === null) {
487
+ // Transient failure — leave the event un-acked so the poller redelivers it.
488
+ return;
489
+ }
490
+ const image = payload.image ?? DEFAULT_RUNNER_IMAGE;
491
+ let jobStatus = 'SUCCESS';
492
+ let jobErrorReason;
493
+ let jobExitCode;
494
+ // Downloaded once per job (not per step) and bind-mounted into every step's container — see
495
+ // downloadConsumedArtifacts. A failed download fails the whole job before any step (or even the
496
+ // image pull) runs — no step should ever start against a consumed artifact that's silently missing.
497
+ const artifactsResult = await downloadConsumedArtifacts(payload, payload.jobRunId);
498
+ let artifactsDir = null;
499
+ if (!artifactsResult.ok) {
500
+ jobStatus = 'FAILED';
501
+ jobErrorReason = artifactsResult.errorReason;
502
+ }
503
+ else {
504
+ artifactsDir = artifactsResult.dir;
505
+ const pullCode = await spawnAndWait('docker', ['pull', image]);
506
+ if (pullCode !== 0) {
507
+ jobStatus = 'FAILED';
508
+ jobErrorReason = 'IMAGE_PULL_FAILED';
509
+ }
510
+ else {
511
+ for (const step of payload.steps) {
512
+ const result = await runStep(event, payload, step, config, artifactsDir);
513
+ if (result.status === 'FAILED') {
514
+ jobStatus = 'FAILED';
515
+ jobErrorReason = result.errorReason;
516
+ jobExitCode = result.exitCode;
517
+ break;
518
+ }
519
+ }
520
+ }
521
+ }
522
+ if (artifactsDir) {
523
+ try {
524
+ fs.rmSync(artifactsDir, { recursive: true, force: true });
525
+ }
526
+ catch (err) {
527
+ console.error('[job-runner] Failed to remove consumed-artifacts dir:', err);
528
+ }
529
+ }
530
+ await completeJob(event.workflowRunId, event.jobId, jobStatus, config, jobErrorReason, jobExitCode);
531
+ await acknowledgeEvent(event.projectId, event.eventId, config);
532
+ }
533
+ //# sourceMappingURL=job-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"job-runner.js","sourceRoot":"","sources":["../../src/daemon/job-runner.ts"],"names":[],"mappings":"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"}
@@ -18,4 +18,11 @@ export declare function acknowledgeEvent(projectId: string, eventId: string, con
18
18
  * Used by the run queue orchestrator.
19
19
  */
20
20
  export declare function completeRun(event: WorkflowTriggerEvent, status: 'SUCCESS' | 'FAILED', config: Config): Promise<void>;
21
+ /**
22
+ * POST /api/v1/workflow-runs/{runId}/jobs/{jobId}/complete
23
+ * Finalises a single self-hosted job under the per-job dispatch protocol.
24
+ * Errors are swallowed and logged — the caller acks the daemon event
25
+ * regardless, matching completeRun's fire-and-forget shape.
26
+ */
27
+ export declare function completeJob(runId: string, jobId: string, status: 'SUCCESS' | 'FAILED', config: Config, errorReason?: string, exitCode?: number): Promise<void>;
21
28
  //# sourceMappingURL=run-lifecycle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-lifecycle.d.ts","sourceRoot":"","sources":["../../src/daemon/run-lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAIvD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,GAAG,QAAQ,EAC5B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAaf;AAID;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAaf;AAID;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,oBAAoB,EAC3B,MAAM,EAAE,SAAS,GAAG,QAAQ,EAC5B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAGf"}
1
+ {"version":3,"file":"run-lifecycle.d.ts","sourceRoot":"","sources":["../../src/daemon/run-lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAIvD;;;GAGG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,GAAG,QAAQ,EAC5B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAaf;AAID;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAaf;AAID;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,oBAAoB,EAC3B,MAAM,EAAE,SAAS,GAAG,QAAQ,EAC5B,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAGf;AAID;;;;;GAKG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,SAAS,GAAG,QAAQ,EAC5B,MAAM,EAAE,MAAM,EACd,WAAW,CAAC,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAiBf"}
@@ -50,4 +50,30 @@ export async function completeRun(event, status, config) {
50
50
  await updateRunStatus(event.workflowRunId, status, config);
51
51
  await acknowledgeEvent(event.projectId, event.eventId, config);
52
52
  }
53
+ // ─── completeJob (protocol 2) ──────────────────────────────────────────────────
54
+ /**
55
+ * POST /api/v1/workflow-runs/{runId}/jobs/{jobId}/complete
56
+ * Finalises a single self-hosted job under the per-job dispatch protocol.
57
+ * Errors are swallowed and logged — the caller acks the daemon event
58
+ * regardless, matching completeRun's fire-and-forget shape.
59
+ */
60
+ export async function completeJob(runId, jobId, status, config, errorReason, exitCode) {
61
+ try {
62
+ await fetch(`${config.apiUrl}/api/v1/workflow-runs/${runId}/jobs/${jobId}/complete`, {
63
+ method: 'POST',
64
+ headers: {
65
+ 'Content-Type': 'application/json',
66
+ Authorization: `Bearer ${config.apiKey}`,
67
+ },
68
+ body: JSON.stringify({
69
+ status,
70
+ ...(errorReason !== undefined ? { errorReason } : {}),
71
+ ...(exitCode !== undefined ? { exitCode } : {}),
72
+ }),
73
+ });
74
+ }
75
+ catch (err) {
76
+ console.error('[run-lifecycle] Failed to complete job:', err);
77
+ }
78
+ }
53
79
  //# sourceMappingURL=run-lifecycle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-lifecycle.js","sourceRoot":"","sources":["../../src/daemon/run-lifecycle.ts"],"names":[],"mappings":"AAGA,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAa,EACb,MAA4B,EAC5B,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,yBAAyB,KAAK,EAAE,EAAE;YAC5D,MAAM,EAAE,OAAO;YACf,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE;aACzC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;SACjC,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,GAAG,CAAC,CAAA;IACpE,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,OAAe,EACf,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,oBAAoB,SAAS,oBAAoB,EAAE;YAC7E,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE;aACzC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;SAC9C,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,GAAG,CAAC,CAAA;IACpE,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAA2B,EAC3B,MAA4B,EAC5B,MAAc;IAEd,MAAM,eAAe,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1D,MAAM,gBAAgB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AAChE,CAAC"}
1
+ {"version":3,"file":"run-lifecycle.js","sourceRoot":"","sources":["../../src/daemon/run-lifecycle.ts"],"names":[],"mappings":"AAGA,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAa,EACb,MAA4B,EAC5B,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,yBAAyB,KAAK,EAAE,EAAE;YAC5D,MAAM,EAAE,OAAO;YACf,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE;aACzC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;SACjC,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,GAAG,CAAC,CAAA;IACpE,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,OAAe,EACf,MAAc;IAEd,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,oBAAoB,SAAS,oBAAoB,EAAE;YAC7E,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE;aACzC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;SAC9C,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,GAAG,CAAC,CAAA;IACpE,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAA2B,EAC3B,MAA4B,EAC5B,MAAc;IAEd,MAAM,eAAe,CAAC,KAAK,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAC1D,MAAM,gBAAgB,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;AAChE,CAAC;AAED,kFAAkF;AAElF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAa,EACb,KAAa,EACb,MAA4B,EAC5B,MAAc,EACd,WAAoB,EACpB,QAAiB;IAEjB,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,yBAAyB,KAAK,SAAS,KAAK,WAAW,EAAE;YACnF,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE;aACzC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,MAAM;gBACN,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACrD,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAChD,CAAC;SACH,CAAC,CAAA;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,GAAG,CAAC,CAAA;IAC/D,CAAC;AACH,CAAC"}
@@ -1,12 +1,17 @@
1
1
  import type { Config } from '../lib/config.js';
2
2
  import { type WorkflowTriggerEvent } from './runner.js';
3
+ import { type WorkflowJobEvent } from './job-runner.js';
3
4
  export declare class RunQueue {
4
5
  private maxConcurrent;
5
6
  private activeCount;
6
7
  private queue;
7
8
  constructor(maxConcurrent?: number);
9
+ /** Legacy `workflow.trigger` path: one event carries the whole run's jobs. */
8
10
  enqueue(event: WorkflowTriggerEvent, getConfig: () => Config): void;
11
+ /** Protocol-2 `workflow.job` path: one event per self-hosted job. */
12
+ enqueueJob(event: WorkflowJobEvent, getConfig: () => Config): void;
9
13
  private processNext;
10
- private runItem;
14
+ private runTriggerItem;
15
+ private runJobItem;
11
16
  }
12
17
  //# sourceMappingURL=run-queue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run-queue.d.ts","sourceRoot":"","sources":["../../src/daemon/run-queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAU,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAI/D,qBAAa,QAAQ;IACnB,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,KAAK,CAAsE;gBAEvE,aAAa,GAAE,MAAU;IAIrC,OAAO,CAAC,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI;IAKnE,OAAO,CAAC,WAAW;YAUL,OAAO;CAqCtB"}
1
+ {"version":3,"file":"run-queue.d.ts","sourceRoot":"","sources":["../../src/daemon/run-queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAU,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAG/D,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAMvE,qBAAa,QAAQ;IACnB,OAAO,CAAC,aAAa,CAAQ;IAC7B,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,KAAK,CAAkB;gBAEnB,aAAa,GAAE,MAAU;IAIrC,8EAA8E;IAC9E,OAAO,CAAC,KAAK,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI;IAKnE,qEAAqE;IACrE,UAAU,CAAC,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI;IAKlE,OAAO,CAAC,WAAW;YAWL,cAAc;YAsCd,UAAU;CAkCzB"}