@agimon-ai/po-workflow 0.0.0-alpha.90 → 0.0.0-alpha.92
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/{RecoverWorkflowService-3K1OgTtI.cjs → RecoverWorkflowService-DH-0c4wb.cjs} +156 -422
- package/dist/RecoverWorkflowService-DH-0c4wb.cjs.map +1 -0
- package/dist/{RecoverWorkflowService-CJLGM3FH.mjs → RecoverWorkflowService-VSaDiC-G.mjs} +157 -423
- package/dist/RecoverWorkflowService-VSaDiC-G.mjs.map +1 -0
- package/dist/cli.cjs +37 -39
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +37 -39
- package/dist/cli.mjs.map +1 -1
- package/dist/extensions/server.cjs +52 -27
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.mjs +52 -27
- package/dist/extensions/server.mjs.map +1 -1
- package/package.json +8 -8
- package/src/prompts/codemode-how-to-workflow/SKILL.md +5 -5
- package/src/prompts/help-how-to-workflow/SKILL.md +2 -2
- package/dist/RecoverWorkflowService-3K1OgTtI.cjs.map +0 -1
- package/dist/RecoverWorkflowService-CJLGM3FH.mjs.map +0 -1
|
@@ -316,13 +316,6 @@ const RepairTriageSchema = JobSchema.omit({
|
|
|
316
316
|
needs: true
|
|
317
317
|
}).describe("Workflow-defined repair triage that runs before jobs in an active repair.");
|
|
318
318
|
const AgentDecisionTriggerSchema = zod.z.object({ steps: zod.z.array(StepSchema) });
|
|
319
|
-
const WorktreeHookSchema = zod.z.object({ steps: zod.z.array(StepSchema) });
|
|
320
|
-
const WorktreeConfigSchema = zod.z.object({
|
|
321
|
-
beforeCreate: WorktreeHookSchema.optional(),
|
|
322
|
-
afterCreate: WorktreeHookSchema.optional(),
|
|
323
|
-
beforeCompleted: WorktreeHookSchema.optional(),
|
|
324
|
-
afterCompleted: WorktreeHookSchema.optional()
|
|
325
|
-
});
|
|
326
319
|
const WorkflowKeybindingsSchema = zod.z.object({ STOP: zod.z.string().optional() });
|
|
327
320
|
const RUN_DIRECTORY_BUILT_IN_PATHS = /* @__PURE__ */ new Set([
|
|
328
321
|
"run.json",
|
|
@@ -403,7 +396,7 @@ const WorkflowDefinitionSchema = zod.z.object({
|
|
|
403
396
|
pre: PreBlockSchema.optional(),
|
|
404
397
|
post: PreBlockSchema.optional(),
|
|
405
398
|
repair: RepairTriageSchema.optional(),
|
|
406
|
-
|
|
399
|
+
isolation: zod.z.enum(["checkout"]).optional().describe("Run in its own checkout. Reported to launchers only; the engine never creates one."),
|
|
407
400
|
jobs: zod.z.record(zod.z.string(), JobSchema),
|
|
408
401
|
"child-jobs": zod.z.record(zod.z.string().min(1), JobSchema).optional()
|
|
409
402
|
});
|
|
@@ -682,9 +675,7 @@ const WorkflowRunRecordSchema = zod.z.object({
|
|
|
682
675
|
fixLoopCycle: zod.z.number().int().positive().optional(),
|
|
683
676
|
inputs: zod.z.record(zod.z.string(), zod.z.string()).optional(),
|
|
684
677
|
job: zod.z.string().optional(),
|
|
685
|
-
keepWorktree: zod.z.boolean().optional(),
|
|
686
678
|
launcher: WorkflowLauncherMetadataSchema.optional(),
|
|
687
|
-
originalRepoPath: zod.z.string().optional(),
|
|
688
679
|
outcome: WorkflowOutcomeSchema.optional(),
|
|
689
680
|
pid: zod.z.number().int().positive().optional(),
|
|
690
681
|
prompt: zod.z.string().optional(),
|
|
@@ -712,6 +703,7 @@ const WorkflowRunRecordSchema = zod.z.object({
|
|
|
712
703
|
*/
|
|
713
704
|
terminalSocket: zod.z.string().optional(),
|
|
714
705
|
failureReason: zod.z.string().optional(),
|
|
706
|
+
/** Read-only legacy metadata from engine-owned worktrees, kept for display. Recovery refuses such runs. */
|
|
715
707
|
worktreeBranch: zod.z.string().optional(),
|
|
716
708
|
worktreePath: zod.z.string().optional(),
|
|
717
709
|
workflowPath: zod.z.string(),
|
|
@@ -1425,7 +1417,6 @@ var WorkflowRegistryService = class {
|
|
|
1425
1417
|
env: input.env,
|
|
1426
1418
|
inputs: input.inputs,
|
|
1427
1419
|
job: input.job,
|
|
1428
|
-
keepWorktree: input.keepWorktree,
|
|
1429
1420
|
launcher: input.launcher,
|
|
1430
1421
|
runKey,
|
|
1431
1422
|
prompt: input.prompt,
|
|
@@ -1489,12 +1480,9 @@ var WorkflowRegistryService = class {
|
|
|
1489
1480
|
failureReason: input.failureReason,
|
|
1490
1481
|
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1491
1482
|
fixLoopCycle: input.fixLoopCycle,
|
|
1492
|
-
originalRepoPath: input.originalRepoPath ?? currentRecord.originalRepoPath,
|
|
1493
1483
|
outcome: input.outcome,
|
|
1494
1484
|
pid: currentRecord.pid,
|
|
1495
|
-
stage: input.stage
|
|
1496
|
-
worktreeBranch: input.worktreeBranch ?? currentRecord.worktreeBranch,
|
|
1497
|
-
worktreePath: input.worktreePath ?? currentRecord.worktreePath
|
|
1485
|
+
stage: input.stage
|
|
1498
1486
|
};
|
|
1499
1487
|
await this.removeFileIfExists((0, node_path.resolve)(handle.runDir, PAUSE_REQUEST_FILENAME$1));
|
|
1500
1488
|
await this.writeRunRecord(handle.recordPath, finalRecord);
|
|
@@ -1692,7 +1680,6 @@ var WorkflowRegistryService = class {
|
|
|
1692
1680
|
});
|
|
1693
1681
|
});
|
|
1694
1682
|
}
|
|
1695
|
-
/** Save worktree identity as soon as it exists, including for a later interrupted run. */
|
|
1696
1683
|
async updateConfiguration(handle, configuration) {
|
|
1697
1684
|
await this.withRunLock(handle.recordPath, async () => {
|
|
1698
1685
|
const record = await this.readRunRecord(handle.recordPath);
|
|
@@ -1703,16 +1690,6 @@ var WorkflowRegistryService = class {
|
|
|
1703
1690
|
});
|
|
1704
1691
|
});
|
|
1705
1692
|
}
|
|
1706
|
-
async updateWorktree(handle, metadata) {
|
|
1707
|
-
return this.withRunLock(handle.recordPath, async () => {
|
|
1708
|
-
const current = await this.readRunRecord(handle.recordPath);
|
|
1709
|
-
if (current.stage !== RUNNING_STAGE || current.runId !== handle.runId) throw new Error(`Workflow run is no longer controllable: ${handle.workspace}/${handle.runKey}`);
|
|
1710
|
-
await this.writeRunRecord(handle.recordPath, {
|
|
1711
|
-
...current,
|
|
1712
|
-
...metadata
|
|
1713
|
-
});
|
|
1714
|
-
});
|
|
1715
|
-
}
|
|
1716
1693
|
async clearPauseRequest(handle) {
|
|
1717
1694
|
await this.removeFileIfExists(handle.pauseRequestPath ?? (0, node_path.resolve)(handle.runDir, PAUSE_REQUEST_FILENAME$1));
|
|
1718
1695
|
}
|
|
@@ -2803,6 +2780,12 @@ const CHOICE_SETTING_KEYS = new Set(Object.keys(ChoiceSettingsSchema.shape));
|
|
|
2803
2780
|
/** A prompt printed raw would be split and expanded by the shell, so templates must quote it. */
|
|
2804
2781
|
const UNQUOTED_PROMPT_PATTERN = /\{\{-?\s*(prompt|systemPrompt)\s*-?\}\}/;
|
|
2805
2782
|
const LEGACY_INTERPOLATION_MARKER = "${{";
|
|
2783
|
+
const REMOVED_WORKTREE_KEY = "worktree";
|
|
2784
|
+
const REMOVED_WORKTREE_MESSAGE = "`worktree:` was removed. Declare `isolation: checkout` and start the run with an isolating launcher such as po-sparo `worktrees.startWorkflow`; move hook steps into jobs.";
|
|
2785
|
+
/** The schema strips unknown keys, so a removed block must fail before it can be silently ignored. */
|
|
2786
|
+
function rejectRemovedKeys(definition, path) {
|
|
2787
|
+
if (definition && typeof definition === "object" && Object.hasOwn(definition, REMOVED_WORKTREE_KEY)) throw new Error(`${REMOVED_WORKTREE_MESSAGE} (${path})`);
|
|
2788
|
+
}
|
|
2806
2789
|
/**
|
|
2807
2790
|
* A declared command's template and host options, whichever form it was written
|
|
2808
2791
|
* in. `run` is undefined for an in-process command with no shell form.
|
|
@@ -2920,7 +2903,9 @@ var WorkflowParserService = class {
|
|
|
2920
2903
|
} catch {
|
|
2921
2904
|
this.githubSha = "local";
|
|
2922
2905
|
}
|
|
2923
|
-
const
|
|
2906
|
+
const definition = (0, js_yaml.load)(content);
|
|
2907
|
+
rejectRemovedKeys(definition, resolved);
|
|
2908
|
+
const workflow = WorkflowDefinitionSchema.parse(definition);
|
|
2924
2909
|
this.resolveToolsPaths(workflow, resolved);
|
|
2925
2910
|
if (workflow.imports) await this.resolveImports(workflow, resolved);
|
|
2926
2911
|
if ((!workflow.jobs || Object.keys(workflow.jobs).length === 0) && !Object.keys(workflow["child-jobs"] ?? {}).length) throw new Error("No jobs found in workflow file");
|
|
@@ -2939,6 +2924,7 @@ var WorkflowParserService = class {
|
|
|
2939
2924
|
if (!await (0, _agimon_ai_po_core_platform.pathExists)(this.runtime.fs, resolved, this.runtime.ioContext)) throw new Error(`Workflow file not found: ${resolved}`);
|
|
2940
2925
|
const content = (0, _agimon_ai_po_core_platform.getOrThrow)(await this.runtime.fs.readTextFile(resolved, this.runtime.ioContext));
|
|
2941
2926
|
const parsed = (0, js_yaml.load)(content);
|
|
2927
|
+
rejectRemovedKeys(parsed, resolved);
|
|
2942
2928
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`Workflow template must be a YAML object: ${resolved}`);
|
|
2943
2929
|
const workflow = parsed;
|
|
2944
2930
|
this.resolveToolsPaths(workflow, resolved);
|
|
@@ -3032,7 +3018,6 @@ var WorkflowParserService = class {
|
|
|
3032
3018
|
checkSteps(workflow.pre?.steps, "pre", false);
|
|
3033
3019
|
checkSteps(workflow.post?.steps, "post", false);
|
|
3034
3020
|
checkSteps(workflow.on?.agent_decision?.steps, "agent_decision", false);
|
|
3035
|
-
for (const [hook, block] of Object.entries(workflow.worktree ?? {})) checkSteps(block?.steps, `worktree ${hook}`, false);
|
|
3036
3021
|
if (problems.length > 0) throw new Error(`Invalid workflow:\n - ${problems.join("\n - ")}`);
|
|
3037
3022
|
}
|
|
3038
3023
|
/** Child references are checked after imports and extends, never before their definitions arrive. */
|
|
@@ -3093,7 +3078,7 @@ var WorkflowParserService = class {
|
|
|
3093
3078
|
*
|
|
3094
3079
|
* A runner declared under `runners` lays its `runConfig` over the one of
|
|
3095
3080
|
* every step that has a `customRun`, wherever the step sits: jobs, hooks,
|
|
3096
|
-
* triage and
|
|
3081
|
+
* triage and trigger steps alike. Any other runner, including a command
|
|
3097
3082
|
* map's key, leaves the workflow as parsed.
|
|
3098
3083
|
*/
|
|
3099
3084
|
selectRunner(workflow, runner) {
|
|
@@ -3124,7 +3109,7 @@ var WorkflowParserService = class {
|
|
|
3124
3109
|
* - pre.services: imported services prepended before main services
|
|
3125
3110
|
* - post.steps: imported steps prepended before main steps
|
|
3126
3111
|
* - post.services: imported services prepended before main services
|
|
3127
|
-
* -
|
|
3112
|
+
* - isolation: scalar default (main wins, otherwise first imported declaration)
|
|
3128
3113
|
* - jobs: imported template jobs (dot-prefixed) merged in, main overrides
|
|
3129
3114
|
* - system-prompt: concatenated (imported + main)
|
|
3130
3115
|
* - commands, choices: merged per name (main overrides imported)
|
|
@@ -3143,10 +3128,12 @@ var WorkflowParserService = class {
|
|
|
3143
3128
|
if (!await (0, _agimon_ai_po_core_platform.pathExists)(this.runtime.fs, resolvedImport, this.runtime.ioContext)) throw new Error(`Imported workflow file not found: ${resolvedImport} (from ${normalizedPath})`);
|
|
3144
3129
|
const importContent = (0, _agimon_ai_po_core_platform.getOrThrow)(await this.runtime.fs.readTextFile(resolvedImport, this.runtime.ioContext));
|
|
3145
3130
|
const imported = (0, js_yaml.load)(importContent);
|
|
3131
|
+
rejectRemovedKeys(imported, resolvedImport);
|
|
3146
3132
|
this.resolveToolsPaths(imported, resolvedImport);
|
|
3147
3133
|
if (imported.imports) await this.resolveImports(imported, resolvedImport, visited);
|
|
3148
3134
|
workflow.tools ??= imported.tools;
|
|
3149
3135
|
workflow.instructions ??= imported.instructions;
|
|
3136
|
+
workflow.isolation ??= imported.isolation;
|
|
3150
3137
|
if (imported.env) workflow.env = {
|
|
3151
3138
|
...imported.env,
|
|
3152
3139
|
...workflow.env
|
|
@@ -3161,15 +3148,6 @@ var WorkflowParserService = class {
|
|
|
3161
3148
|
if (imported.post.services) workflow.post.services = [...imported.post.services, ...workflow.post.services ?? []];
|
|
3162
3149
|
if (imported.post.steps) workflow.post.steps = [...imported.post.steps, ...workflow.post.steps ?? []];
|
|
3163
3150
|
}
|
|
3164
|
-
if (imported.worktree) {
|
|
3165
|
-
if (!workflow.worktree) workflow.worktree = {};
|
|
3166
|
-
for (const hook of [
|
|
3167
|
-
"beforeCreate",
|
|
3168
|
-
"afterCreate",
|
|
3169
|
-
"beforeCompleted",
|
|
3170
|
-
"afterCompleted"
|
|
3171
|
-
]) if (imported.worktree[hook] && !workflow.worktree[hook]) workflow.worktree[hook] = imported.worktree[hook];
|
|
3172
|
-
}
|
|
3173
3151
|
if (imported["max-workflows"] && !workflow["max-workflows"]) workflow["max-workflows"] = imported["max-workflows"];
|
|
3174
3152
|
if (imported["launch-command"] && !workflow["launch-command"]) workflow["launch-command"] = imported["launch-command"];
|
|
3175
3153
|
if (imported.launcher && !workflow.launcher) workflow.launcher = imported.launcher;
|
|
@@ -3907,11 +3885,11 @@ function runWorkflowSpan(logger, name, attributes, work) {
|
|
|
3907
3885
|
* - Mixing concerns (keep focused on single domain)
|
|
3908
3886
|
* - Direct tool implementation (services should be tool-agnostic)
|
|
3909
3887
|
*/
|
|
3910
|
-
const RESET$
|
|
3888
|
+
const RESET$4 = "\x1B[0m";
|
|
3911
3889
|
const BOLD$3 = "\x1B[1m";
|
|
3912
|
-
const DIM$
|
|
3890
|
+
const DIM$4 = "\x1B[2m";
|
|
3913
3891
|
const GREEN$4 = "\x1B[32m";
|
|
3914
|
-
const YELLOW$
|
|
3892
|
+
const YELLOW$2 = "\x1B[33m";
|
|
3915
3893
|
const RED$4 = "\x1B[31m";
|
|
3916
3894
|
const MAGENTA = "\x1B[35m";
|
|
3917
3895
|
const WORKFLOW_JOB_ID_ENV_KEY = "WORKFLOW_JOB_ID";
|
|
@@ -4001,8 +3979,8 @@ var JobRunnerService = class {
|
|
|
4001
3979
|
const maxRetries = managedCompletion ? 1 : options.maxRetries;
|
|
4002
3980
|
for (const [matrixIndex, matrix] of matrixCombos.entries()) {
|
|
4003
3981
|
const jobExecutionId = (0, node_crypto.randomUUID)();
|
|
4004
|
-
const matrixLabel = Object.keys(matrix).length > 0 ? ` ${DIM$
|
|
4005
|
-
this.logger.info(`\n ${MAGENTA}${BOLD$3}job${RESET$
|
|
3982
|
+
const matrixLabel = Object.keys(matrix).length > 0 ? ` ${DIM$4}(${Object.entries(matrix).map(([k, v]) => `${k}=${v}`).join(", ")})${RESET$4}` : "";
|
|
3983
|
+
this.logger.info(`\n ${MAGENTA}${BOLD$3}job${RESET$4} ${BOLD$3}${jobName}${RESET$4}${matrixLabel}`);
|
|
4006
3984
|
this.logger.info(` ${"─".repeat(50)}`);
|
|
4007
3985
|
const jobEnv = {
|
|
4008
3986
|
...context.workflowEnv,
|
|
@@ -4044,7 +4022,7 @@ var JobRunnerService = class {
|
|
|
4044
4022
|
this.logger.error(reason);
|
|
4045
4023
|
return false;
|
|
4046
4024
|
}
|
|
4047
|
-
this.logger.info(` ${DIM$
|
|
4025
|
+
this.logger.info(` ${DIM$4}jobid${RESET$4} ${jobExecutionId}`);
|
|
4048
4026
|
const fixLoopDisabled = managedCompletion || envFlagEnabled$1(jobEnv[WORKFLOW_FIX_LOOP_DISABLED_ENV_KEY]);
|
|
4049
4027
|
const fixFileContract = usesFixFileContract(job);
|
|
4050
4028
|
const currentJobIndex = context.jobOrder.indexOf(jobName);
|
|
@@ -4119,7 +4097,7 @@ var JobRunnerService = class {
|
|
|
4119
4097
|
matrix,
|
|
4120
4098
|
prompt
|
|
4121
4099
|
});
|
|
4122
|
-
this.logger.info(` ${DIM$
|
|
4100
|
+
this.logger.info(` ${DIM$4}prompt${RESET$4} ${prompt.split("\n")[0].slice(0, 80)}${prompt.includes("\n") ? "..." : ""}`);
|
|
4123
4101
|
}
|
|
4124
4102
|
const contextPath = job.context ? this.parser.interpolate(job.context, {
|
|
4125
4103
|
inputs: context.inputs,
|
|
@@ -4132,8 +4110,8 @@ var JobRunnerService = class {
|
|
|
4132
4110
|
if (await (0, _agimon_ai_po_core_platform.pathExists)(this.runtime.fs, resolvedPath, this.runtime.ioContext)) {
|
|
4133
4111
|
jobEnv.WORKFLOW_CONTEXT = resolvedPath;
|
|
4134
4112
|
jobEnv.WORKFLOW_CONTEXT_FILE = resolvedPath;
|
|
4135
|
-
this.logger.info(` ${DIM$
|
|
4136
|
-
} else if (!options.dryRun) this.logger.warn(` ${YELLOW$
|
|
4113
|
+
this.logger.info(` ${DIM$4}ctx ${RESET$4} ${contextPath}`);
|
|
4114
|
+
} else if (!options.dryRun) this.logger.warn(` ${YELLOW$2}warn${RESET$4} context file not found: ${contextPath}`);
|
|
4137
4115
|
}
|
|
4138
4116
|
if (jobEnv.CHANGELOG_FILE) {
|
|
4139
4117
|
const changelogPath = (0, node_path.resolve)(this.runtime.cwd, options.workflowDir, jobEnv.CHANGELOG_FILE);
|
|
@@ -4141,7 +4119,7 @@ var JobRunnerService = class {
|
|
|
4141
4119
|
if (!await (0, _agimon_ai_po_core_platform.pathExists)(this.runtime.fs, changelogDir, this.runtime.ioContext)) (0, _agimon_ai_po_core_platform.getOrThrow)(await this.runtime.fs.createDir(changelogDir, { recursive: true }, this.runtime.ioContext));
|
|
4142
4120
|
if (!await (0, _agimon_ai_po_core_platform.pathExists)(this.runtime.fs, changelogPath, this.runtime.ioContext)) (0, _agimon_ai_po_core_platform.getOrThrow)(await this.runtime.fs.writeFile(changelogPath, "# Changelog\n", this.runtime.ioContext));
|
|
4143
4121
|
jobEnv.WORKFLOW_CHANGELOG = changelogPath;
|
|
4144
|
-
this.logger.info(` ${DIM$
|
|
4122
|
+
this.logger.info(` ${DIM$4}log ${RESET$4} changelog at ${jobEnv.CHANGELOG_FILE}`);
|
|
4145
4123
|
}
|
|
4146
4124
|
const stepContext = {
|
|
4147
4125
|
inputs: context.inputs,
|
|
@@ -4159,7 +4137,7 @@ var JobRunnerService = class {
|
|
|
4159
4137
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
4160
4138
|
unwrittenOutputs = void 0;
|
|
4161
4139
|
if (attempt > 1) {
|
|
4162
|
-
this.logger.info(`\n ${YELLOW$
|
|
4140
|
+
this.logger.info(`\n ${YELLOW$2}retry${RESET$4} ${BOLD$3}${jobName}${RESET$4}${matrixLabel} (attempt ${attempt}/${maxRetries})`);
|
|
4163
4141
|
this.logger.info(` ${"─".repeat(50)}`);
|
|
4164
4142
|
}
|
|
4165
4143
|
const baseline = writesRunDir ? await this.runDirectoryService.recordWrites(writesRunDir, declaredEntries) : void 0;
|
|
@@ -4182,7 +4160,7 @@ var JobRunnerService = class {
|
|
|
4182
4160
|
unwrittenOutputs = describeUnwritten(await this.runDirectoryService.readWrites(writesRunDir), jobName, writes.produced);
|
|
4183
4161
|
if (unwrittenOutputs) {
|
|
4184
4162
|
allStepsPassed = false;
|
|
4185
|
-
this.logger.error(` ${RED$4}error${RESET$
|
|
4163
|
+
this.logger.error(` ${RED$4}error${RESET$4} ${unwrittenOutputs}`);
|
|
4186
4164
|
await this.logger.event?.("error", "workflow.job.outputs_unwritten", { attributes: this.buildLifecycleAttributes(jobEnv, {
|
|
4187
4165
|
"workflow.job.attempt": attempt,
|
|
4188
4166
|
"workflow.job.failure_reason": unwrittenOutputs
|
|
@@ -4201,7 +4179,7 @@ var JobRunnerService = class {
|
|
|
4201
4179
|
break;
|
|
4202
4180
|
}
|
|
4203
4181
|
const restartFrom = await writeFixRequest(this.runtime, jobEnv.WORKFLOW_RUN_DIR, context.jobOrder, jobName, fixes);
|
|
4204
|
-
this.logger.warn(` ${YELLOW$
|
|
4182
|
+
this.logger.warn(` ${YELLOW$2}Job "${jobName}" requested ${fixes.length} fix${fixes.length === 1 ? "" : "es"}; restarting from "${restartFrom}"${RESET$4}`);
|
|
4205
4183
|
jobPassed = true;
|
|
4206
4184
|
fixRequested = true;
|
|
4207
4185
|
break;
|
|
@@ -4216,22 +4194,22 @@ var JobRunnerService = class {
|
|
|
4216
4194
|
jobPassed = true;
|
|
4217
4195
|
break;
|
|
4218
4196
|
}
|
|
4219
|
-
if (attempt < maxRetries) this.logger.warn(` ${YELLOW$
|
|
4197
|
+
if (attempt < maxRetries) this.logger.warn(` ${YELLOW$2}Job "${jobName}" failed, retrying...${RESET$4}`);
|
|
4220
4198
|
}
|
|
4221
4199
|
if (decidedFailure) {
|
|
4222
4200
|
context.onFailed?.(decidedFailure);
|
|
4223
|
-
this.logger.error(`\n ${RED$4}${decidedFailure}${RESET$
|
|
4201
|
+
this.logger.error(`\n ${RED$4}${decidedFailure}${RESET$4}`);
|
|
4224
4202
|
}
|
|
4225
4203
|
if (!jobPassed) {
|
|
4226
4204
|
if (!decidedFailure && unwrittenOutputs) context.onFailed?.(unwrittenOutputs);
|
|
4227
|
-
this.logger.error(`\n ${RED$4}Job "${jobName}" failed after ${maxRetries} attempts${RESET$
|
|
4205
|
+
this.logger.error(`\n ${RED$4}Job "${jobName}" failed after ${maxRetries} attempts${RESET$4}`);
|
|
4228
4206
|
await this.logger.event?.("error", "workflow.job.finished", { attributes: this.buildLifecycleAttributes(jobEnv, {
|
|
4229
4207
|
"workflow.job.duration_ms": Date.now() - jobStartedAt,
|
|
4230
4208
|
"workflow.job.outcome": "failed"
|
|
4231
4209
|
}) });
|
|
4232
4210
|
if (decidedFailure || job.strategy?.["fail-fast"] !== false) return false;
|
|
4233
4211
|
} else {
|
|
4234
|
-
this.logger.info(` ${GREEN$4}Job "${jobName}" completed${RESET$
|
|
4212
|
+
this.logger.info(` ${GREEN$4}Job "${jobName}" completed${RESET$4}${matrixLabel}`);
|
|
4235
4213
|
await this.logger.event?.("info", "workflow.job.finished", { attributes: this.buildLifecycleAttributes(jobEnv, {
|
|
4236
4214
|
"workflow.job.duration_ms": Date.now() - jobStartedAt,
|
|
4237
4215
|
"workflow.job.outcome": fixRequested ? "fix" : "success"
|
|
@@ -4499,11 +4477,11 @@ const StepTimeoutRetriesSchema = zod.z.number().int().min(0).max(STEP_TIMEOUT_RE
|
|
|
4499
4477
|
* - Mixing concerns (keep focused on single domain)
|
|
4500
4478
|
* - Direct tool implementation (services should be tool-agnostic)
|
|
4501
4479
|
*/
|
|
4502
|
-
const RESET$
|
|
4503
|
-
const DIM$
|
|
4504
|
-
const CYAN$
|
|
4480
|
+
const RESET$3 = "\x1B[0m";
|
|
4481
|
+
const DIM$3 = "\x1B[2m";
|
|
4482
|
+
const CYAN$1 = "\x1B[36m";
|
|
4505
4483
|
const GREEN$3 = "\x1B[32m";
|
|
4506
|
-
const YELLOW$
|
|
4484
|
+
const YELLOW$1 = "\x1B[33m";
|
|
4507
4485
|
const RED$3 = "\x1B[31m";
|
|
4508
4486
|
const INTERRUPT_EXIT_CODE = 130;
|
|
4509
4487
|
const TERMINATE_EXIT_CODE = 143;
|
|
@@ -4589,7 +4567,7 @@ function outputDrained(child) {
|
|
|
4589
4567
|
}
|
|
4590
4568
|
/** A logger whose lines name the parallel step they came from. */
|
|
4591
4569
|
function labelledLogger(logger, label) {
|
|
4592
|
-
const prefix = `${DIM$
|
|
4570
|
+
const prefix = `${DIM$3}[${label}]${RESET$3} `;
|
|
4593
4571
|
return {
|
|
4594
4572
|
info: (message) => logger.info(`${prefix}${message}`),
|
|
4595
4573
|
error: (message) => logger.error(`${prefix}${message}`),
|
|
@@ -4782,23 +4760,23 @@ var StepRunnerService = class StepRunnerService {
|
|
|
4782
4760
|
}
|
|
4783
4761
|
if (this.activeExternal) {
|
|
4784
4762
|
if (this.activeExternal.stopSignal) {
|
|
4785
|
-
this.logger.info(` ${DIM$
|
|
4763
|
+
this.logger.info(` ${DIM$3}${STATUS_SKIP}${RESET$3} ${this.activeExternal.stepName} ${ALREADY_STOPPING_SUFFIX}`);
|
|
4786
4764
|
return;
|
|
4787
4765
|
}
|
|
4788
|
-
this.logger.info(` ${YELLOW$
|
|
4766
|
+
this.logger.info(` ${YELLOW$1}${STATUS_INTERRUPTED}${RESET$3} stopping ${this.activeExternal.stepName} (${signal})`);
|
|
4789
4767
|
this.stopExternal(this.activeExternal, signal);
|
|
4790
4768
|
return;
|
|
4791
4769
|
}
|
|
4792
4770
|
if (!this.activeStep) {
|
|
4793
|
-
this.logger.info(` ${DIM$
|
|
4771
|
+
this.logger.info(` ${DIM$3}${STATUS_SKIP}${RESET$3} ${NO_ACTIVE_STEP_MESSAGE}`);
|
|
4794
4772
|
return;
|
|
4795
4773
|
}
|
|
4796
4774
|
if (this.activeStep.process.killed) {
|
|
4797
|
-
this.logger.info(` ${DIM$
|
|
4775
|
+
this.logger.info(` ${DIM$3}${STATUS_SKIP}${RESET$3} ${this.activeStep.stepName} ${ALREADY_STOPPING_SUFFIX}`);
|
|
4798
4776
|
return;
|
|
4799
4777
|
}
|
|
4800
|
-
this.logger.info(` ${YELLOW$
|
|
4801
|
-
if (!this.killActiveStep(signal)) this.logger.warn(` ${YELLOW$
|
|
4778
|
+
this.logger.info(` ${YELLOW$1}${STATUS_INTERRUPTED}${RESET$3} sending ${signal} to ${this.activeStep.stepName}`);
|
|
4779
|
+
if (!this.killActiveStep(signal)) this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${FAILED_TO_SIGNAL_MESSAGE} ${this.activeStep.stepName}`);
|
|
4802
4780
|
}
|
|
4803
4781
|
/**
|
|
4804
4782
|
* Execute a single workflow step and stream its output to the workflow logger.
|
|
@@ -4833,7 +4811,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
4833
4811
|
}
|
|
4834
4812
|
}
|
|
4835
4813
|
const fail = (reason) => {
|
|
4836
|
-
this.logger.error(` ${RED$3}${STATUS_ERROR}${RESET$
|
|
4814
|
+
this.logger.error(` ${RED$3}${STATUS_ERROR}${RESET$3} ${reason}`);
|
|
4837
4815
|
report.reason = reason;
|
|
4838
4816
|
};
|
|
4839
4817
|
if (step.customRun) step = {
|
|
@@ -4856,38 +4834,38 @@ var StepRunnerService = class StepRunnerService {
|
|
|
4856
4834
|
if (step.uses) {
|
|
4857
4835
|
const action = this.parser.interpolate(step.uses, stepContext);
|
|
4858
4836
|
if (this.parser.isActionSkipped(action)) {
|
|
4859
|
-
this.logger.info(` ${DIM$
|
|
4837
|
+
this.logger.info(` ${DIM$3}${STATUS_SKIP}${RESET$3} ${action}`);
|
|
4860
4838
|
return true;
|
|
4861
4839
|
}
|
|
4862
|
-
this.logger.warn(` ${YELLOW$
|
|
4840
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${UNSUPPORTED_ACTION_PREFIX} ${action} ${UNSUPPORTED_ACTION_SUFFIX}`);
|
|
4863
4841
|
return true;
|
|
4864
4842
|
}
|
|
4865
4843
|
if (!resolvedStepCommand) {
|
|
4866
4844
|
if (!step.customRun) return true;
|
|
4867
4845
|
fail(`${CUSTOM_RUN_UNSUPPORTED_MESSAGE} "${stepName}"`);
|
|
4868
4846
|
if (step["continue-on-error"] || options.continueOnError) {
|
|
4869
|
-
this.logger.warn(` ${YELLOW$
|
|
4847
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_FAIL}${RESET$3} ${stepName} ${CONTINUE_ON_ERROR_SUFFIX}\n`);
|
|
4870
4848
|
return true;
|
|
4871
4849
|
}
|
|
4872
|
-
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$
|
|
4850
|
+
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$3} ${stepName}\n`);
|
|
4873
4851
|
return false;
|
|
4874
4852
|
}
|
|
4875
4853
|
if (resolvedStepCommand.missingRunner) {
|
|
4876
4854
|
fail(`${EXPLICIT_RUNNER_MISSING_PREFIX} "${resolvedStepCommand.missingRunner.runner}" ${EXPLICIT_RUNNER_MISSING_MIDDLE} "${stepName}" (${EXPLICIT_RUNNER_AVAILABLE_PREFIX} ${resolvedStepCommand.missingRunner.availableKeys.join(", ")})`);
|
|
4877
4855
|
if (step["continue-on-error"] || options.continueOnError) {
|
|
4878
|
-
this.logger.warn(` ${YELLOW$
|
|
4856
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_FAIL}${RESET$3} ${stepName} ${CONTINUE_ON_ERROR_SUFFIX}\n`);
|
|
4879
4857
|
return true;
|
|
4880
4858
|
}
|
|
4881
|
-
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$
|
|
4859
|
+
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$3} ${stepName}\n`);
|
|
4882
4860
|
return false;
|
|
4883
4861
|
}
|
|
4884
4862
|
if (resolvedStepCommand.templateError) {
|
|
4885
4863
|
fail(`step "${stepName}": ${resolvedStepCommand.templateError}`);
|
|
4886
4864
|
if (step["continue-on-error"] || options.continueOnError) {
|
|
4887
|
-
this.logger.warn(` ${YELLOW$
|
|
4865
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_FAIL}${RESET$3} ${stepName} ${CONTINUE_ON_ERROR_SUFFIX}\n`);
|
|
4888
4866
|
return true;
|
|
4889
4867
|
}
|
|
4890
|
-
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$
|
|
4868
|
+
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$3} ${stepName}\n`);
|
|
4891
4869
|
return false;
|
|
4892
4870
|
}
|
|
4893
4871
|
const { command, custom, inProcessOnly, interactive, template } = resolvedStepCommand;
|
|
@@ -4899,10 +4877,10 @@ var StepRunnerService = class StepRunnerService {
|
|
|
4899
4877
|
if (!(error instanceof WorkflowStepTimeoutConfigError)) throw error;
|
|
4900
4878
|
fail(`invalid ${error.context.configKey} for "${stepName}": ${String(error.context.timeoutValue)}`);
|
|
4901
4879
|
if (shouldContinue) {
|
|
4902
|
-
this.logger.warn(` ${YELLOW$
|
|
4880
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_FAIL}${RESET$3} ${stepName} ${CONTINUE_ON_ERROR_SUFFIX}\n`);
|
|
4903
4881
|
return true;
|
|
4904
4882
|
}
|
|
4905
|
-
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$
|
|
4883
|
+
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$3} ${stepName}\n`);
|
|
4906
4884
|
return false;
|
|
4907
4885
|
}
|
|
4908
4886
|
const workDir = step["working-directory"] ? (0, node_path.resolve)(this.runtime.cwd, options.workflowDir, this.parser.interpolate(step["working-directory"], stepContext)) : (0, node_path.resolve)(this.runtime.cwd, options.workflowDir);
|
|
@@ -4983,9 +4961,9 @@ var StepRunnerService = class StepRunnerService {
|
|
|
4983
4961
|
await this.logStepLifecycle("info", "workflow.step.started", stepEnv, { "workflow.step.interactive": interactive });
|
|
4984
4962
|
delete stepEnv[STATUS_FILE_ENV_KEY];
|
|
4985
4963
|
if (options.dryRun) {
|
|
4986
|
-
this.logger.info(` ${CYAN$
|
|
4987
|
-
this.logger.info(`${COMMAND_LOG_INDENT}${DIM$
|
|
4988
|
-
if (step.secrets !== void 0 && step.secrets.length > 0) this.logger.info(`${COMMAND_LOG_INDENT}${DIM$
|
|
4964
|
+
this.logger.info(` ${CYAN$1}${STATUS_DRY}${RESET$3} ${stepName}`);
|
|
4965
|
+
this.logger.info(`${COMMAND_LOG_INDENT}${DIM$3}${COMMAND_LOG_PROMPT}${command.split(COMMAND_LINE_BREAK).join(COMMAND_LOG_CONTINUATION)}${RESET$3}`);
|
|
4966
|
+
if (step.secrets !== void 0 && step.secrets.length > 0) this.logger.info(`${COMMAND_LOG_INDENT}${DIM$3}${SECRETS_LOG_PREFIX}${step.secrets.join(", ")}${RESET$3}`);
|
|
4989
4967
|
await this.logStepLifecycle("info", "workflow.step.finished", stepEnv, {
|
|
4990
4968
|
"workflow.step.duration_ms": Date.now() - stepStartedAt,
|
|
4991
4969
|
"workflow.step.outcome": "dry-run"
|
|
@@ -5012,10 +4990,10 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5012
4990
|
if (!(error instanceof WorkflowStepTimeoutConfigError)) throw error;
|
|
5013
4991
|
fail(`invalid ${error.context.configKey} for "${stepName}": ${String(error.context.timeoutValue)}`);
|
|
5014
4992
|
if (shouldContinue) {
|
|
5015
|
-
this.logger.warn(` ${YELLOW$
|
|
4993
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_FAIL}${RESET$3} ${stepName} ${CONTINUE_ON_ERROR_SUFFIX}\n`);
|
|
5016
4994
|
return true;
|
|
5017
4995
|
}
|
|
5018
|
-
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$
|
|
4996
|
+
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$3} ${stepName}\n`);
|
|
5019
4997
|
return false;
|
|
5020
4998
|
}
|
|
5021
4999
|
let secretEnv;
|
|
@@ -5024,20 +5002,20 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5024
5002
|
if (secretEnv === void 0) {
|
|
5025
5003
|
fail(`${SECRETS_UNAVAILABLE_MESSAGE} "${stepName}"`);
|
|
5026
5004
|
if (shouldContinue) {
|
|
5027
|
-
this.logger.warn(` ${YELLOW$
|
|
5005
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_FAIL}${RESET$3} ${stepName} ${CONTINUE_ON_ERROR_SUFFIX}\n`);
|
|
5028
5006
|
return true;
|
|
5029
5007
|
}
|
|
5030
|
-
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$
|
|
5008
|
+
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$3} ${stepName}\n`);
|
|
5031
5009
|
return false;
|
|
5032
5010
|
}
|
|
5033
5011
|
}
|
|
5034
5012
|
for (let attempt = 0; attempt <= maxTimeoutRetries; attempt++) {
|
|
5035
5013
|
if (decisionFilePath && decisionIdentity) await resetDecisionFile(this.runtime, decisionFilePath, decisionIdentity);
|
|
5036
|
-
if (attempt > 0) this.logger.warn(` ${YELLOW$
|
|
5037
|
-
else this.logger.info(` ${CYAN$
|
|
5038
|
-
this.logger.info(`${COMMAND_LOG_INDENT}${DIM$
|
|
5014
|
+
if (attempt > 0) this.logger.warn(` ${YELLOW$1}${STATUS_RETRY}${RESET$3} ${STEP_TIMEOUT_RETRY_PREFIX} "${stepName}" (attempt ${attempt + 1}/${maxTimeoutRetries + 1})`);
|
|
5015
|
+
else this.logger.info(` ${CYAN$1}${STATUS_RUN}${RESET$3} ${stepName}`);
|
|
5016
|
+
this.logger.info(`${COMMAND_LOG_INDENT}${DIM$3}${COMMAND_LOG_PROMPT}${command.split(COMMAND_LINE_BREAK)[0]}${command.includes(COMMAND_LINE_BREAK) ? " ..." : ""}${RESET$3}`);
|
|
5039
5017
|
if (options.stopRequestPath && await this.hasCurrentStopRequest(options.stopRequestPath)) {
|
|
5040
|
-
this.logger.info(`\n ${YELLOW$
|
|
5018
|
+
this.logger.info(`\n ${YELLOW$1}${STATUS_INTERRUPTED}${RESET$3} ${stepName} (${STATUS_STOP})`);
|
|
5041
5019
|
throw new WorkflowInterruptedError(TERMINATE_SIGNAL$1, {
|
|
5042
5020
|
cause: /* @__PURE__ */ new Error(`Workflow stop requested before "${stepName}"`),
|
|
5043
5021
|
context: this.createInterruptContext(stepName, command)
|
|
@@ -5083,14 +5061,14 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5083
5061
|
return this.executeStep(step, stepContext, options, report);
|
|
5084
5062
|
}
|
|
5085
5063
|
if (executionResult.status === "stop_requested") {
|
|
5086
|
-
this.logger.info(`\n ${YELLOW$
|
|
5064
|
+
this.logger.info(`\n ${YELLOW$1}${STATUS_INTERRUPTED}${RESET$3} ${stepName} (${STATUS_STOP})`);
|
|
5087
5065
|
throw new WorkflowInterruptedError(TERMINATE_SIGNAL$1, {
|
|
5088
5066
|
cause: /* @__PURE__ */ new Error(`Workflow stop requested during "${stepName}"`),
|
|
5089
5067
|
context: this.createInterruptContext(stepName, command)
|
|
5090
5068
|
});
|
|
5091
5069
|
}
|
|
5092
5070
|
if (executionResult.status === "signaled") {
|
|
5093
|
-
this.logger.info(`\n ${YELLOW$
|
|
5071
|
+
this.logger.info(`\n ${YELLOW$1}${STATUS_INTERRUPTED}${RESET$3} ${stepName}`);
|
|
5094
5072
|
throw new WorkflowInterruptedError(executionResult.signal, {
|
|
5095
5073
|
cause: /* @__PURE__ */ new Error(`Step process ended with ${executionResult.signal}`),
|
|
5096
5074
|
context: this.createInterruptContext(stepName, command)
|
|
@@ -5098,7 +5076,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5098
5076
|
}
|
|
5099
5077
|
if (executionResult.status === "completed" && (executionResult.exitCode === INTERRUPT_EXIT_CODE || executionResult.exitCode === TERMINATE_EXIT_CODE)) {
|
|
5100
5078
|
const interruptSignal = executionResult.exitCode === INTERRUPT_EXIT_CODE ? INTERRUPT_SIGNAL$2 : TERMINATE_SIGNAL$1;
|
|
5101
|
-
this.logger.info(`\n ${YELLOW$
|
|
5079
|
+
this.logger.info(`\n ${YELLOW$1}${STATUS_INTERRUPTED}${RESET$3} ${stepName}`);
|
|
5102
5080
|
throw new WorkflowInterruptedError(interruptSignal, {
|
|
5103
5081
|
cause: /* @__PURE__ */ new Error(`Step process exited with ${executionResult.exitCode}`),
|
|
5104
5082
|
context: this.createInterruptContext(stepName, command)
|
|
@@ -5111,10 +5089,10 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5111
5089
|
"workflow.step.duration_ms": Date.now() - stepStartedAt,
|
|
5112
5090
|
"workflow.step.outcome": "continued"
|
|
5113
5091
|
});
|
|
5114
|
-
this.logger.warn(` ${YELLOW$
|
|
5092
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_FAIL}${RESET$3} ${stepName} ${CONTINUE_ON_ERROR_SUFFIX}\n`);
|
|
5115
5093
|
return true;
|
|
5116
5094
|
}
|
|
5117
|
-
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$
|
|
5095
|
+
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$3} ${stepName}\n`);
|
|
5118
5096
|
await this.logStepLifecycle("error", "workflow.step.finished", stepEnv, {
|
|
5119
5097
|
"workflow.step.duration_ms": Date.now() - stepStartedAt,
|
|
5120
5098
|
"workflow.step.outcome": "failed",
|
|
@@ -5131,7 +5109,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5131
5109
|
if (decision.decision === "complete") {
|
|
5132
5110
|
const artifactProblem = artifactSnapshots ? await this.describeArtifactWarnings(stepEnv, artifactSnapshots) : void 0;
|
|
5133
5111
|
if (!artifactProblem) {
|
|
5134
|
-
this.logger.info(`\n ${GREEN$3}${STATUS_PASS}${RESET$
|
|
5112
|
+
this.logger.info(`\n ${GREEN$3}${STATUS_PASS}${RESET$3} ${stepName}${decision.summary ? ` (${decision.summary})` : ""}\n`);
|
|
5135
5113
|
await this.logStepLifecycle("info", "workflow.step.finished", stepEnv, {
|
|
5136
5114
|
"workflow.step.duration_ms": Date.now() - stepStartedAt,
|
|
5137
5115
|
"workflow.step.outcome": "success"
|
|
@@ -5140,7 +5118,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5140
5118
|
}
|
|
5141
5119
|
fail(`step "${stepName}" ${artifactProblem}`);
|
|
5142
5120
|
} else if (decision.decision === "fix" && options.onDecision) {
|
|
5143
|
-
this.logger.warn(`\n ${YELLOW$
|
|
5121
|
+
this.logger.warn(`\n ${YELLOW$1}fix${RESET$3} ${stepName} asks to restart from "${decision.restartFrom}": ${firstLine(decision.reason)}\n`);
|
|
5144
5122
|
options.onDecision({
|
|
5145
5123
|
...decision,
|
|
5146
5124
|
step: stepName
|
|
@@ -5167,10 +5145,10 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5167
5145
|
"workflow.step.duration_ms": Date.now() - stepStartedAt,
|
|
5168
5146
|
"workflow.step.outcome": "continued"
|
|
5169
5147
|
});
|
|
5170
|
-
this.logger.warn(` ${YELLOW$
|
|
5148
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_FAIL}${RESET$3} ${stepName} ${CONTINUE_ON_ERROR_SUFFIX}\n`);
|
|
5171
5149
|
return true;
|
|
5172
5150
|
}
|
|
5173
|
-
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$
|
|
5151
|
+
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$3} ${stepName}\n`);
|
|
5174
5152
|
await this.logStepLifecycle("error", "workflow.step.finished", stepEnv, {
|
|
5175
5153
|
"workflow.step.duration_ms": Date.now() - stepStartedAt,
|
|
5176
5154
|
"workflow.step.outcome": "timed-out",
|
|
@@ -5187,7 +5165,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5187
5165
|
const tail = executionResult.outputTail?.trim();
|
|
5188
5166
|
const ended = executionResult.failure ? `failed: ${executionResult.failure}` : `exited with code ${executionResult.exitCode}.`;
|
|
5189
5167
|
const reason = `\`${command.split(COMMAND_LINE_BREAK)[0]}\` ${ended}${tail ? `\n\nLast output:\n\n\`\`\`\n${tail}\n\`\`\`` : ""}`;
|
|
5190
|
-
this.logger.warn(`\n ${YELLOW$
|
|
5168
|
+
this.logger.warn(`\n ${YELLOW$1}fix${RESET$3} ${stepName} failed; restarting from "${restartFrom}"\n`);
|
|
5191
5169
|
options.onDecision({
|
|
5192
5170
|
decision: "fix",
|
|
5193
5171
|
restartFrom,
|
|
@@ -5203,7 +5181,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5203
5181
|
if (executionResult.status === "completed" && executionResult.exitCode === 0) {
|
|
5204
5182
|
const artifactProblem = artifactSnapshots ? await this.describeArtifactWarnings(stepEnv, artifactSnapshots) : void 0;
|
|
5205
5183
|
if (!artifactProblem) {
|
|
5206
|
-
this.logger.info(`\n ${GREEN$3}${STATUS_PASS}${RESET$
|
|
5184
|
+
this.logger.info(`\n ${GREEN$3}${STATUS_PASS}${RESET$3} ${stepName}\n`);
|
|
5207
5185
|
await this.logStepLifecycle("info", "workflow.step.finished", stepEnv, {
|
|
5208
5186
|
"workflow.step.duration_ms": Date.now() - stepStartedAt,
|
|
5209
5187
|
"workflow.step.outcome": "success"
|
|
@@ -5218,10 +5196,10 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5218
5196
|
"workflow.step.duration_ms": Date.now() - stepStartedAt,
|
|
5219
5197
|
"workflow.step.outcome": "continued"
|
|
5220
5198
|
});
|
|
5221
|
-
this.logger.warn(` ${YELLOW$
|
|
5199
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_FAIL}${RESET$3} ${stepName} ${CONTINUE_ON_ERROR_SUFFIX}\n`);
|
|
5222
5200
|
return true;
|
|
5223
5201
|
}
|
|
5224
|
-
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$
|
|
5202
|
+
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$3} ${stepName}\n`);
|
|
5225
5203
|
await this.logStepLifecycle("error", "workflow.step.finished", stepEnv, {
|
|
5226
5204
|
"workflow.step.duration_ms": Date.now() - stepStartedAt,
|
|
5227
5205
|
"workflow.step.outcome": "failed",
|
|
@@ -5238,10 +5216,10 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5238
5216
|
"workflow.step.duration_ms": Date.now() - stepStartedAt,
|
|
5239
5217
|
"workflow.step.outcome": "continued"
|
|
5240
5218
|
});
|
|
5241
|
-
this.logger.warn(` ${YELLOW$
|
|
5219
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_FAIL}${RESET$3} ${stepName} ${CONTINUE_ON_ERROR_SUFFIX}\n`);
|
|
5242
5220
|
return true;
|
|
5243
5221
|
}
|
|
5244
|
-
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$
|
|
5222
|
+
this.logger.error(` ${RED$3}${STATUS_FAIL}${RESET$3} ${stepName}\n`);
|
|
5245
5223
|
await this.logStepLifecycle("error", "workflow.step.finished", stepEnv, {
|
|
5246
5224
|
"workflow.step.duration_ms": Date.now() - stepStartedAt,
|
|
5247
5225
|
"workflow.step.outcome": "failed",
|
|
@@ -5281,7 +5259,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5281
5259
|
});
|
|
5282
5260
|
if (result.status === "completed" && result.exitCode === 0) return { run: true };
|
|
5283
5261
|
if (result.status === "completed" && result.exitCode === 1) {
|
|
5284
|
-
this.logger.info(` ${DIM$
|
|
5262
|
+
this.logger.info(` ${DIM$3}${STATUS_SKIP}${RESET$3} ${stepName} (condition is false)`);
|
|
5285
5263
|
await this.logStepLifecycle("info", "workflow.step.skipped", stepEnv, { "workflow.step.outcome": "skipped" });
|
|
5286
5264
|
return { run: false };
|
|
5287
5265
|
}
|
|
@@ -5315,7 +5293,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5315
5293
|
*/
|
|
5316
5294
|
async executeCommand(command, workDir, stepEnv, stepName, interactive, timeoutMs, secretEnv) {
|
|
5317
5295
|
const redact = secretEnv === void 0 ? void 0 : secretRedactor(Object.values(secretEnv));
|
|
5318
|
-
if (interactive) this.logger.info(` ${DIM$
|
|
5296
|
+
if (interactive) this.logger.info(` ${DIM$3}${INTERACTIVE_OUTPUT_NOTICE}${RESET$3}`);
|
|
5319
5297
|
return await new Promise((resolveResult) => {
|
|
5320
5298
|
const terminalState = interactive ? this.captureTerminalState() : null;
|
|
5321
5299
|
const child = interactive ? this.runtime.workflowHost.spawn(command, [], {
|
|
@@ -5393,7 +5371,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5393
5371
|
if (this.killActiveStep(TERMINATE_SIGNAL$1)) {
|
|
5394
5372
|
forceKillTimer = setTimeout(() => {
|
|
5395
5373
|
if (!settled) {
|
|
5396
|
-
this.logger.warn(` ${YELLOW$
|
|
5374
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${stepName} ${STEP_TIMEOUT_FORCE_KILL_SUFFIX}`);
|
|
5397
5375
|
this.killActiveStep(TERMINATE_FORCE_KILL_SIGNAL);
|
|
5398
5376
|
}
|
|
5399
5377
|
}, FORCE_KILL_GRACE_PERIOD_MS);
|
|
@@ -5612,7 +5590,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5612
5590
|
}, timeoutMs);
|
|
5613
5591
|
try {
|
|
5614
5592
|
if (execution.ref) {
|
|
5615
|
-
this.logger.info(` ${DIM$
|
|
5593
|
+
this.logger.info(` ${DIM$3}${execution.ref.kind}${RESET$3} ${execution.ref.label ?? execution.ref.id}`);
|
|
5616
5594
|
await onExecutionStarted?.(execution.ref);
|
|
5617
5595
|
}
|
|
5618
5596
|
const outcome = await execution.completion.catch((error) => ({ error: error instanceof Error ? error : new Error(String(error)) }));
|
|
@@ -5649,7 +5627,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5649
5627
|
if (active.stopSignal) return;
|
|
5650
5628
|
active.stopSignal = signal;
|
|
5651
5629
|
active.execution.stop().catch((error) => {
|
|
5652
|
-
this.logger.warn(` ${YELLOW$
|
|
5630
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${FAILED_TO_SIGNAL_MESSAGE} ${active.stepName} (${error instanceof Error ? error.message : String(error)})`);
|
|
5653
5631
|
});
|
|
5654
5632
|
}
|
|
5655
5633
|
definedEnv(env) {
|
|
@@ -5961,17 +5939,17 @@ var StepRunnerService = class StepRunnerService {
|
|
|
5961
5939
|
this.runtime.workflowHost.signal(-processGroupId, TERMINATE_SIGNAL$1);
|
|
5962
5940
|
} catch (error) {
|
|
5963
5941
|
const errorCode = error.code;
|
|
5964
|
-
if (errorCode !== ESRCH_ERROR_CODE) this.logger.warn(` ${YELLOW$
|
|
5965
|
-
else this.logger.info(` ${DIM$
|
|
5942
|
+
if (errorCode !== ESRCH_ERROR_CODE) this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${FAILED_TO_CLEANUP_PROCESS_GROUP_MESSAGE} ${stepName} (pgid=${processGroupId}, error=${errorCode})`);
|
|
5943
|
+
else this.logger.info(` ${DIM$3}cleanup${RESET$3} process group ${processGroupId} already exited (ESRCH)`);
|
|
5966
5944
|
return;
|
|
5967
5945
|
}
|
|
5968
5946
|
await this.waitForProcessGroupToExit(processGroupId, FORCE_KILL_GRACE_PERIOD_MS);
|
|
5969
5947
|
if (!this.isProcessGroupAlive(processGroupId)) return;
|
|
5970
|
-
this.logger.warn(` ${YELLOW$
|
|
5948
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${stepName} process group did not exit after SIGTERM, forcing SIGKILL`);
|
|
5971
5949
|
try {
|
|
5972
5950
|
this.runtime.workflowHost.signal(-processGroupId, TERMINATE_FORCE_KILL_SIGNAL);
|
|
5973
5951
|
} catch (error) {
|
|
5974
|
-
if (error.code !== ESRCH_ERROR_CODE) this.logger.warn(` ${YELLOW$
|
|
5952
|
+
if (error.code !== ESRCH_ERROR_CODE) this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${FAILED_TO_CLEANUP_PROCESS_GROUP_MESSAGE} ${stepName} (pgid=${processGroupId}, error=${error.code})`);
|
|
5975
5953
|
return;
|
|
5976
5954
|
}
|
|
5977
5955
|
await this.waitForProcessGroupToExit(processGroupId, PROCESS_EXIT_WAIT_TIMEOUT_MS);
|
|
@@ -6007,7 +5985,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6007
5985
|
return false;
|
|
6008
5986
|
}
|
|
6009
5987
|
const initialProcessGroupIds = [.../* @__PURE__ */ new Set([...this.activeStep.trackedProcessGroupIds, ...this.collectInteractiveProcessGroupIds(initialProcessIds)])];
|
|
6010
|
-
this.logger.info(` ${DIM$
|
|
5988
|
+
this.logger.info(` ${DIM$3}cleanup${RESET$3} reaping ${stepName} interactive pids [${initialProcessIds.join(", ")}]${initialProcessGroupIds.length > 0 ? ` groups [${initialProcessGroupIds.join(", ")}]` : ""}`);
|
|
6011
5989
|
const graceMs = this.interactiveKillGraceMs();
|
|
6012
5990
|
if (signal !== TERMINATE_FORCE_KILL_SIGNAL) await this.reapInteractiveTree(signal, graceMs);
|
|
6013
5991
|
const sigkillEscalated = this.collectInteractiveProcessIds().length > 0;
|
|
@@ -6020,7 +5998,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6020
5998
|
survivors,
|
|
6021
5999
|
sigkillEscalated
|
|
6022
6000
|
};
|
|
6023
|
-
if (survivors.length > 0) this.logger.warn(` ${YELLOW$
|
|
6001
|
+
if (survivors.length > 0) this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${stepName} interactive processes survived termination: ${survivors.map((entry) => `${entry.pid} (${entry.command})`).join(", ")}`);
|
|
6024
6002
|
return true;
|
|
6025
6003
|
}
|
|
6026
6004
|
/**
|
|
@@ -6087,7 +6065,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6087
6065
|
(0, _agimon_ai_po_core_platform.getOrThrow)(await this.runtime.fs.createDir((0, node_path.dirname)(logPath), { recursive: true }, this.runtime.ioContext));
|
|
6088
6066
|
(0, _agimon_ai_po_core_platform.getOrThrow)(await this.runtime.fs.writeFile(logPath, `${JSON.stringify(entries.slice(-50), null, 2)}\n`, this.runtime.ioContext));
|
|
6089
6067
|
} catch (error) {
|
|
6090
|
-
this.logger.warn(` ${YELLOW$
|
|
6068
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} interactive-reap log write failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
6091
6069
|
}
|
|
6092
6070
|
}
|
|
6093
6071
|
async interactiveReapLogPath() {
|
|
@@ -6142,7 +6120,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6142
6120
|
try {
|
|
6143
6121
|
processRows = this.runtime.workflowHost.inspectProcesses("parents");
|
|
6144
6122
|
} catch (error) {
|
|
6145
|
-
this.logger.warn(` ${YELLOW$
|
|
6123
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} unable to inspect process tree for [${rootProcessIds.join(", ")}] (${error instanceof Error ? error.message : String(error)})`);
|
|
6146
6124
|
return rootProcessIds.filter((pid) => this.isProcessAlive(pid)).map((pid) => ({
|
|
6147
6125
|
depth: 0,
|
|
6148
6126
|
pid
|
|
@@ -6183,7 +6161,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6183
6161
|
signaled = true;
|
|
6184
6162
|
} catch (error) {
|
|
6185
6163
|
const code = error.code;
|
|
6186
|
-
if (code !== ESRCH_ERROR_CODE) this.logger.warn(` ${YELLOW$
|
|
6164
|
+
if (code !== ESRCH_ERROR_CODE) this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${FAILED_TO_SIGNAL_MESSAGE} pid ${processId} (${code ?? error.message})`);
|
|
6187
6165
|
}
|
|
6188
6166
|
}
|
|
6189
6167
|
return signaled;
|
|
@@ -6203,7 +6181,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6203
6181
|
try {
|
|
6204
6182
|
processRows = this.runtime.workflowHost.inspectProcesses("groups");
|
|
6205
6183
|
} catch (error) {
|
|
6206
|
-
this.logger.warn(` ${YELLOW$
|
|
6184
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} unable to inspect process groups (${error instanceof Error ? error.message : String(error)})`);
|
|
6207
6185
|
return [];
|
|
6208
6186
|
}
|
|
6209
6187
|
const processGroupByPid = /* @__PURE__ */ new Map();
|
|
@@ -6231,7 +6209,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6231
6209
|
signaled = true;
|
|
6232
6210
|
} catch (error) {
|
|
6233
6211
|
const code = error.code;
|
|
6234
|
-
if (code !== ESRCH_ERROR_CODE) this.logger.warn(` ${YELLOW$
|
|
6212
|
+
if (code !== ESRCH_ERROR_CODE) this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${FAILED_TO_SIGNAL_MESSAGE} process group ${processGroupId} (${code ?? error.message})`);
|
|
6235
6213
|
}
|
|
6236
6214
|
return signaled;
|
|
6237
6215
|
}
|
|
@@ -6288,13 +6266,13 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6288
6266
|
this.runtime.workflowHost.signal(-processGroupId, signal);
|
|
6289
6267
|
return true;
|
|
6290
6268
|
} catch (error) {
|
|
6291
|
-
if (error.code !== ESRCH_ERROR_CODE) this.logger.warn(` ${YELLOW$
|
|
6292
|
-
else this.logger.info(` ${DIM$
|
|
6269
|
+
if (error.code !== ESRCH_ERROR_CODE) this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${FAILED_TO_SIGNAL_MESSAGE} process group for ${this.activeStep.stepName}`);
|
|
6270
|
+
else this.logger.info(` ${DIM$3}signal${RESET$3} process group for ${this.activeStep.stepName} already exited (ESRCH)`);
|
|
6293
6271
|
}
|
|
6294
6272
|
try {
|
|
6295
6273
|
return child.kill(signal);
|
|
6296
6274
|
} catch (error) {
|
|
6297
|
-
this.logger.warn(` ${YELLOW$
|
|
6275
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${FAILED_TO_SIGNAL_MESSAGE} ${this.activeStep.stepName} (${error.message})`);
|
|
6298
6276
|
return false;
|
|
6299
6277
|
}
|
|
6300
6278
|
}
|
|
@@ -6377,7 +6355,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6377
6355
|
survivors,
|
|
6378
6356
|
sigkillEscalated: true
|
|
6379
6357
|
};
|
|
6380
|
-
this.logger.warn(` ${YELLOW$
|
|
6358
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${stepName} signalled completion but ${survivors.length} process(es) survived termination; proceeding to the next step: ${survivors.map((entry) => `${entry.pid} (${entry.command})`).join(", ")}`);
|
|
6381
6359
|
}
|
|
6382
6360
|
settle(result);
|
|
6383
6361
|
}, delayMs);
|
|
@@ -6390,14 +6368,14 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6390
6368
|
const graceMs = this.stepCompletionKillGraceMs();
|
|
6391
6369
|
signalDelivered = this.killActiveStep(TERMINATE_SIGNAL$1);
|
|
6392
6370
|
if (!signalDelivered) {
|
|
6393
|
-
this.logger.warn(` ${YELLOW$
|
|
6371
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${stepName} stop request: SIGTERM could not be delivered, process may have already exited`);
|
|
6394
6372
|
scheduleAbsoluteSettle({ status: RESULT_STATUS_STOP_REQUESTED }, PROCESS_EXIT_WAIT_TIMEOUT_MS);
|
|
6395
6373
|
return;
|
|
6396
6374
|
}
|
|
6397
6375
|
forceKillTimer = setTimeout(() => {
|
|
6398
6376
|
if (settled) return;
|
|
6399
6377
|
sigkillEscalated = true;
|
|
6400
|
-
this.logger.warn(` ${YELLOW$
|
|
6378
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${stepName} did not exit after stop-request SIGTERM, forcing SIGKILL`);
|
|
6401
6379
|
this.killActiveStep(TERMINATE_FORCE_KILL_SIGNAL);
|
|
6402
6380
|
}, graceMs);
|
|
6403
6381
|
scheduleAbsoluteSettle({ status: RESULT_STATUS_STOP_REQUESTED }, graceMs + PROCESS_EXIT_WAIT_TIMEOUT_MS);
|
|
@@ -6409,14 +6387,14 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6409
6387
|
const graceMs = this.stepCompletionKillGraceMs();
|
|
6410
6388
|
signalDelivered = this.killActiveStep(TERMINATE_SIGNAL$1);
|
|
6411
6389
|
if (!signalDelivered) {
|
|
6412
|
-
this.logger.warn(` ${YELLOW$
|
|
6390
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${stepName} pause request: SIGTERM could not be delivered, process may have already exited`);
|
|
6413
6391
|
scheduleAbsoluteSettle({ status: RESULT_STATUS_PAUSE_REQUESTED }, PROCESS_EXIT_WAIT_TIMEOUT_MS);
|
|
6414
6392
|
return;
|
|
6415
6393
|
}
|
|
6416
6394
|
forceKillTimer = setTimeout(() => {
|
|
6417
6395
|
if (settled) return;
|
|
6418
6396
|
sigkillEscalated = true;
|
|
6419
|
-
this.logger.warn(` ${YELLOW$
|
|
6397
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${stepName} did not exit after pause-request SIGTERM, forcing SIGKILL`);
|
|
6420
6398
|
this.killActiveStep(TERMINATE_FORCE_KILL_SIGNAL);
|
|
6421
6399
|
}, graceMs);
|
|
6422
6400
|
scheduleAbsoluteSettle({ status: RESULT_STATUS_PAUSE_REQUESTED }, graceMs + PROCESS_EXIT_WAIT_TIMEOUT_MS);
|
|
@@ -6431,7 +6409,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6431
6409
|
else stopWatcher = admitted;
|
|
6432
6410
|
}).catch((error) => this.logger.warn(`Workflow stop-request watcher unavailable, polling instead: ${String(error)}`));
|
|
6433
6411
|
} catch (error) {
|
|
6434
|
-
if (error.code !== "ENOENT") this.logger.warn(` ${YELLOW$
|
|
6412
|
+
if (error.code !== "ENOENT") this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} stop-request watcher setup failed for ${stepName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
6435
6413
|
}
|
|
6436
6414
|
stopPollTimer = setInterval(() => {
|
|
6437
6415
|
checkStopRequest().catch((error) => this.logger.warn(`Workflow control check failed: ${String(error)}`));
|
|
@@ -6447,7 +6425,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6447
6425
|
else pauseWatcher = admitted;
|
|
6448
6426
|
}).catch((error) => this.logger.warn(`Workflow pause-request watcher unavailable, polling instead: ${String(error)}`));
|
|
6449
6427
|
} catch (error) {
|
|
6450
|
-
if (error.code !== "ENOENT") this.logger.warn(` ${YELLOW$
|
|
6428
|
+
if (error.code !== "ENOENT") this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} pause-request watcher setup failed for ${stepName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
6451
6429
|
}
|
|
6452
6430
|
pausePollTimer = setInterval(() => {
|
|
6453
6431
|
checkPauseRequest().catch((error) => this.logger.warn(`Workflow control check failed: ${String(error)}`));
|
|
@@ -6457,7 +6435,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6457
6435
|
checkPauseRequest().catch((error) => this.logger.warn(`Workflow control check failed: ${String(error)}`));
|
|
6458
6436
|
executionPromise.then(async (result) => {
|
|
6459
6437
|
if (stopRequestTriggered) {
|
|
6460
|
-
if (sigkillEscalated) this.logger.warn(` ${YELLOW$
|
|
6438
|
+
if (sigkillEscalated) this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} ${stepName} required SIGKILL escalation after stop request`);
|
|
6461
6439
|
settle({ status: RESULT_STATUS_STOP_REQUESTED });
|
|
6462
6440
|
return;
|
|
6463
6441
|
}
|
|
@@ -6520,7 +6498,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6520
6498
|
else watcher = admitted;
|
|
6521
6499
|
}).catch((error) => this.logger.warn(`Workflow stop-request watcher unavailable, polling instead: ${String(error)}`));
|
|
6522
6500
|
} catch (error) {
|
|
6523
|
-
if (error.code !== "ENOENT") this.logger.warn(` ${YELLOW$
|
|
6501
|
+
if (error.code !== "ENOENT") this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} stop-request watcher setup failed for ${stepName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
6524
6502
|
}
|
|
6525
6503
|
pollTimer = setInterval(() => {
|
|
6526
6504
|
checkStopRequest().catch((error) => this.logger.warn(`Workflow control check failed: ${String(error)}`));
|
|
@@ -6585,7 +6563,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6585
6563
|
};
|
|
6586
6564
|
await this.writeControlRecord(recordPath, record);
|
|
6587
6565
|
} catch (error) {
|
|
6588
|
-
this.logger.warn(` ${YELLOW$
|
|
6566
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} could not persist paused state: ${String(error)}`);
|
|
6589
6567
|
throw error;
|
|
6590
6568
|
}
|
|
6591
6569
|
}
|
|
@@ -6593,7 +6571,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6593
6571
|
if (!stopRequestPath) return {};
|
|
6594
6572
|
const pauseRequestPath = (0, node_path.join)((0, node_path.dirname)(stopRequestPath), PAUSE_REQUEST_FILENAME);
|
|
6595
6573
|
const recordPath = (0, node_path.join)((0, node_path.dirname)(stopRequestPath), RUN_RECORD_FILENAME);
|
|
6596
|
-
this.logger.info(` ${YELLOW$
|
|
6574
|
+
this.logger.info(` ${YELLOW$1}${STATUS_WAIT}${RESET$3} ${stepName} paused; waiting for resume`);
|
|
6597
6575
|
while (true) {
|
|
6598
6576
|
if (this.interruptedSignal) throw new WorkflowInterruptedError(this.interruptedSignal, {
|
|
6599
6577
|
cause: /* @__PURE__ */ new Error(`Workflow interrupted while paused: ${stepName}`),
|
|
@@ -6642,7 +6620,7 @@ var StepRunnerService = class StepRunnerService {
|
|
|
6642
6620
|
try {
|
|
6643
6621
|
this.runtime.workflowHost.restoreTerminalState(terminalState ?? void 0);
|
|
6644
6622
|
} catch (error) {
|
|
6645
|
-
this.logger.warn(` ${YELLOW$
|
|
6623
|
+
this.logger.warn(` ${YELLOW$1}${STATUS_WARN}${RESET$3} failed to restore terminal state: ${String(error)}`);
|
|
6646
6624
|
}
|
|
6647
6625
|
}
|
|
6648
6626
|
};
|
|
@@ -8025,7 +8003,6 @@ async function diagnoseWorkflowBindings(workflow, options) {
|
|
|
8025
8003
|
if (input.command) env.WORKFLOW_COMMAND = input.command;
|
|
8026
8004
|
if (input.choice) env.WORKFLOW_CHOICE = input.choice;
|
|
8027
8005
|
if (input.prompt !== void 0) later("trigger.prompt", "Trigger admission and its prompt-dependent result require execution.");
|
|
8028
|
-
if (workflow.worktree) env.WORKTREE_PATH = env.WORKTREE_BRANCH = DEFERRED;
|
|
8029
8006
|
const steps = new StepRunnerService(options.runtime, parser, {
|
|
8030
8007
|
info() {},
|
|
8031
8008
|
warn() {},
|
|
@@ -8105,7 +8082,6 @@ async function diagnoseWorkflowBindings(workflow, options) {
|
|
|
8105
8082
|
walk(workflow.pre?.steps, base, "pre");
|
|
8106
8083
|
walk(workflow.post?.steps, base, "post");
|
|
8107
8084
|
walk(workflow.on?.agent_decision?.steps, base, "agent_decision");
|
|
8108
|
-
for (const [name, hook] of Object.entries(workflow.worktree ?? {})) walk(hook?.steps, base, `worktree.${name}`);
|
|
8109
8085
|
for (const [catalog, jobs] of [
|
|
8110
8086
|
["jobs", workflow.jobs],
|
|
8111
8087
|
["child-jobs", workflow["child-jobs"] ?? {}],
|
|
@@ -8182,8 +8158,6 @@ function collectSteps(workflow) {
|
|
|
8182
8158
|
walk(workflow.pre?.steps, "pre");
|
|
8183
8159
|
walk(workflow.post?.steps, "post");
|
|
8184
8160
|
walk(workflow.repair?.steps, "repair");
|
|
8185
|
-
walk(workflow.worktree?.beforeCreate?.steps, "worktree.beforeCreate");
|
|
8186
|
-
walk(workflow.worktree?.afterCreate?.steps, "worktree.afterCreate");
|
|
8187
8161
|
for (const catalog of ["jobs", "child-jobs"]) for (const [name, job] of Object.entries(workflow[catalog] ?? {})) {
|
|
8188
8162
|
walk(job.preJob?.steps, `${catalog}.${name}.preJob`);
|
|
8189
8163
|
walk(job.steps, `${catalog}.${name}`);
|
|
@@ -8351,18 +8325,21 @@ async function diagnoseWorkflow(workflowPath, options) {
|
|
|
8351
8325
|
});
|
|
8352
8326
|
}
|
|
8353
8327
|
options.signal?.throwIfAborted();
|
|
8328
|
+
const isolation = workflow.isolation ? { isolation: workflow.isolation } : {};
|
|
8354
8329
|
if (options.bindings) {
|
|
8355
8330
|
const bindings = await diagnoseWorkflowBindings(workflow, options);
|
|
8356
8331
|
options.signal?.throwIfAborted();
|
|
8357
8332
|
return {
|
|
8358
8333
|
path,
|
|
8359
8334
|
diagnostics: [...diagnostics, ...bindings.diagnostics],
|
|
8360
|
-
deferred: bindings.deferred
|
|
8335
|
+
deferred: bindings.deferred,
|
|
8336
|
+
...isolation
|
|
8361
8337
|
};
|
|
8362
8338
|
}
|
|
8363
8339
|
return {
|
|
8364
8340
|
path,
|
|
8365
|
-
diagnostics
|
|
8341
|
+
diagnostics,
|
|
8342
|
+
...isolation
|
|
8366
8343
|
};
|
|
8367
8344
|
}
|
|
8368
8345
|
/**
|
|
@@ -10685,9 +10662,9 @@ async function registryOperation(options, operation, request) {
|
|
|
10685
10662
|
* - Mixing concerns (keep focused on single domain)
|
|
10686
10663
|
* - Direct tool implementation (services should be tool-agnostic)
|
|
10687
10664
|
*/
|
|
10688
|
-
const RESET$
|
|
10665
|
+
const RESET$2 = "\x1B[0m";
|
|
10689
10666
|
const BOLD$2 = "\x1B[1m";
|
|
10690
|
-
const DIM$
|
|
10667
|
+
const DIM$2 = "\x1B[2m";
|
|
10691
10668
|
const GREEN$2 = "\x1B[32m";
|
|
10692
10669
|
const RED$2 = "\x1B[31m";
|
|
10693
10670
|
const BLUE$2 = "\x1B[34m";
|
|
@@ -10758,12 +10735,12 @@ var BackgroundServiceManager = class {
|
|
|
10758
10735
|
async startService(service, baseEnv, workflowDir, dryRun) {
|
|
10759
10736
|
const command = service.run;
|
|
10760
10737
|
if (dryRun) {
|
|
10761
|
-
this.logger.info(` ${BLUE$2}dry ${RESET$
|
|
10762
|
-
this.logger.info(` ${DIM$
|
|
10738
|
+
this.logger.info(` ${BLUE$2}dry ${RESET$2} ${service.name}`);
|
|
10739
|
+
this.logger.info(` ${DIM$2}$ ${command}${RESET$2}`);
|
|
10763
10740
|
return null;
|
|
10764
10741
|
}
|
|
10765
|
-
this.logger.info(` ${BLUE$2}start${RESET$
|
|
10766
|
-
this.logger.info(` ${DIM$
|
|
10742
|
+
this.logger.info(` ${BLUE$2}start${RESET$2} ${service.name}`);
|
|
10743
|
+
this.logger.info(` ${DIM$2}$ ${command}${RESET$2}`);
|
|
10767
10744
|
const serviceEnv = {
|
|
10768
10745
|
...this.runtime.baseEnvironment,
|
|
10769
10746
|
...baseEnv
|
|
@@ -10858,7 +10835,7 @@ var BackgroundServiceManager = class {
|
|
|
10858
10835
|
});
|
|
10859
10836
|
throw error;
|
|
10860
10837
|
}
|
|
10861
|
-
const prefix = `${BLUE$2}[${service.name}]${RESET$
|
|
10838
|
+
const prefix = `${BLUE$2}[${service.name}]${RESET$2}`;
|
|
10862
10839
|
child.stdout?.on("data", (data) => {
|
|
10863
10840
|
for (const line of data.toString().split("\n")) if (line.trim()) this.logger.info(`${prefix} ${line}`);
|
|
10864
10841
|
});
|
|
@@ -10945,7 +10922,7 @@ var BackgroundServiceManager = class {
|
|
|
10945
10922
|
...this.runtime.baseEnvironment,
|
|
10946
10923
|
...baseEnv
|
|
10947
10924
|
};
|
|
10948
|
-
this.logger.info(` ${DIM$
|
|
10925
|
+
this.logger.info(` ${DIM$2}wait${RESET$2} Waiting for ${service.name} to be ready...`);
|
|
10949
10926
|
while (Date.now() - start < timeout) {
|
|
10950
10927
|
if (shouldAbort?.()) return false;
|
|
10951
10928
|
try {
|
|
@@ -10954,7 +10931,7 @@ var BackgroundServiceManager = class {
|
|
|
10954
10931
|
environment: readyEnv,
|
|
10955
10932
|
timeoutMs: 5e3
|
|
10956
10933
|
});
|
|
10957
|
-
this.logger.info(` ${GREEN$2}ready${RESET$
|
|
10934
|
+
this.logger.info(` ${GREEN$2}ready${RESET$2} ${service.name}`);
|
|
10958
10935
|
return true;
|
|
10959
10936
|
} catch {
|
|
10960
10937
|
if (shouldAbort?.()) return false;
|
|
@@ -10964,20 +10941,20 @@ var BackgroundServiceManager = class {
|
|
|
10964
10941
|
});
|
|
10965
10942
|
}
|
|
10966
10943
|
if (shouldAbort?.()) return false;
|
|
10967
|
-
this.logger.error(` ${RED$2}timeout${RESET$
|
|
10944
|
+
this.logger.error(` ${RED$2}timeout${RESET$2} ${service.name} not ready after ${service["ready-timeout"] || 30}s`);
|
|
10968
10945
|
return false;
|
|
10969
10946
|
}
|
|
10970
10947
|
async stopAll() {
|
|
10971
10948
|
if (this.runningServices.length === 0) return;
|
|
10972
|
-
this.logger.info(`\n ${BLUE$2}${BOLD$2}pre${RESET$
|
|
10949
|
+
this.logger.info(`\n ${BLUE$2}${BOLD$2}pre${RESET$2} ${BOLD$2}Stopping services${RESET$2}`);
|
|
10973
10950
|
this.logger.info(` ${"─".repeat(50)}`);
|
|
10974
10951
|
for (const svc of this.runningServices) {
|
|
10975
|
-
if (!svc.process.killed && svc.process.pid) this.logger.info(` ${DIM$
|
|
10952
|
+
if (!svc.process.killed && svc.process.pid) this.logger.info(` ${DIM$2}stop${RESET$2} ${svc.name} (pid ${svc.process.pid})`);
|
|
10976
10953
|
if (svc.release) try {
|
|
10977
10954
|
await svc.release();
|
|
10978
10955
|
continue;
|
|
10979
10956
|
} catch (error) {
|
|
10980
|
-
this.logger.warn(` ${RED$2}warn${RESET$
|
|
10957
|
+
this.logger.warn(` ${RED$2}warn${RESET$2} Failed registry cleanup for ${svc.name}: ${error instanceof Error ? error.message : String(error)}`);
|
|
10981
10958
|
}
|
|
10982
10959
|
if (!svc.process.killed && svc.process.pid) try {
|
|
10983
10960
|
this.runtime.workflowHost.signal(-svc.process.pid, "SIGTERM");
|
|
@@ -11024,10 +11001,10 @@ var WorkflowCapacityError = class extends Error {
|
|
|
11024
11001
|
* - Mixing concerns (keep focused on single domain)
|
|
11025
11002
|
* - Direct tool implementation (services should be tool-agnostic)
|
|
11026
11003
|
*/
|
|
11027
|
-
const RESET$
|
|
11004
|
+
const RESET$1 = "\x1B[0m";
|
|
11028
11005
|
const BOLD$1 = "\x1B[1m";
|
|
11029
|
-
const DIM$
|
|
11030
|
-
const CYAN
|
|
11006
|
+
const DIM$1 = "\x1B[2m";
|
|
11007
|
+
const CYAN = "\x1B[36m";
|
|
11031
11008
|
const GREEN$1 = "\x1B[32m";
|
|
11032
11009
|
const RED$1 = "\x1B[31m";
|
|
11033
11010
|
const BLUE$1 = "\x1B[34m";
|
|
@@ -11088,7 +11065,7 @@ var TriggerService = class {
|
|
|
11088
11065
|
*/
|
|
11089
11066
|
async handleUserPrompt(workflow, cliPrompt, workflowEnv, workflowDir, dryRun) {
|
|
11090
11067
|
if (!workflow.on || !(USER_PROMPT_EVENT in workflow.on)) return true;
|
|
11091
|
-
this.logger.info(`\n ${BLUE$1}${BOLD$1}trigger${RESET$
|
|
11068
|
+
this.logger.info(`\n ${BLUE$1}${BOLD$1}trigger${RESET$1} ${BOLD$1}user_prompt${RESET$1}`);
|
|
11092
11069
|
this.logger.info(` ${"─".repeat(SEPARATOR_WIDTH)}`);
|
|
11093
11070
|
let userInput = cliPrompt;
|
|
11094
11071
|
const contextFile = workflowEnv.CONTEXT_FILE;
|
|
@@ -11096,15 +11073,15 @@ var TriggerService = class {
|
|
|
11096
11073
|
const contextPath = (0, node_path.resolve)(workflowDir, contextFile);
|
|
11097
11074
|
if (await this.pathExists(contextPath)) {
|
|
11098
11075
|
userInput = (0, _agimon_ai_po_core_platform.getOrThrow)(await this.runtime.fs.readTextFile(contextPath, this.runtime.ioContext)).trim();
|
|
11099
|
-
if (userInput) this.logger.info(` ${GREEN$1}found${RESET$
|
|
11076
|
+
if (userInput) this.logger.info(` ${GREEN$1}found${RESET$1} Existing context.md -> ${contextFile}`);
|
|
11100
11077
|
}
|
|
11101
11078
|
}
|
|
11102
11079
|
if (!userInput) {
|
|
11103
11080
|
if (dryRun) {
|
|
11104
|
-
this.logger.info(` ${CYAN
|
|
11081
|
+
this.logger.info(` ${CYAN}dry ${RESET$1} Would prompt user for input`);
|
|
11105
11082
|
userInput = DRY_RUN_PROMPT_TEXT;
|
|
11106
11083
|
} else {
|
|
11107
|
-
this.logger.info(` ${CYAN
|
|
11084
|
+
this.logger.info(` ${CYAN}input${RESET$1} Enter your prompt (press Enter twice to finish):\n`);
|
|
11108
11085
|
const lines = [];
|
|
11109
11086
|
const rl = this.runtime.workflowHost.createPrompt();
|
|
11110
11087
|
const promptResult = new Promise((res, rej) => {
|
|
@@ -11140,7 +11117,7 @@ var TriggerService = class {
|
|
|
11140
11117
|
}
|
|
11141
11118
|
}
|
|
11142
11119
|
if (!userInput) {
|
|
11143
|
-
this.logger.error(` ${RED$1}fail${RESET$
|
|
11120
|
+
this.logger.error(` ${RED$1}fail${RESET$1} No prompt provided. Aborting.`);
|
|
11144
11121
|
return false;
|
|
11145
11122
|
}
|
|
11146
11123
|
if (contextFile) {
|
|
@@ -11148,10 +11125,10 @@ var TriggerService = class {
|
|
|
11148
11125
|
const contextDir = (0, node_path.dirname)(contextPath);
|
|
11149
11126
|
(0, _agimon_ai_po_core_platform.getOrThrow)(await this.runtime.fs.createDir(contextDir, { recursive: true }, this.runtime.ioContext));
|
|
11150
11127
|
(0, _agimon_ai_po_core_platform.getOrThrow)(await this.runtime.fs.writeFile(contextPath, userInput, this.runtime.ioContext));
|
|
11151
|
-
this.logger.info(` ${GREEN$1}saved${RESET$
|
|
11128
|
+
this.logger.info(` ${GREEN$1}saved${RESET$1} ${userInput.split("\n").length} line(s) -> ${contextFile}`);
|
|
11152
11129
|
}
|
|
11153
11130
|
workflowEnv.USER_PROMPT = userInput;
|
|
11154
|
-
this.logger.info(` ${DIM$
|
|
11131
|
+
this.logger.info(` ${DIM$1}prompt${RESET$1} ${userInput.split("\n")[0].slice(0, PROMPT_PREVIEW_MAX_CHARS)}${userInput.includes("\n") ? "..." : ""}`);
|
|
11155
11132
|
return true;
|
|
11156
11133
|
}
|
|
11157
11134
|
/**
|
|
@@ -11163,11 +11140,11 @@ var TriggerService = class {
|
|
|
11163
11140
|
async handleAgentDecision(workflow, workflowEnv, inputs, secrets, options, prompt) {
|
|
11164
11141
|
const trigger = workflow.on?.[AGENT_DECISION_EVENT];
|
|
11165
11142
|
if (!trigger?.steps) return true;
|
|
11166
|
-
this.logger.info(`\n ${BLUE$1}${BOLD$1}trigger${RESET$
|
|
11143
|
+
this.logger.info(`\n ${BLUE$1}${BOLD$1}trigger${RESET$1} ${BOLD$1}agent_decision${RESET$1}`);
|
|
11167
11144
|
this.logger.info(` ${"─".repeat(SEPARATOR_WIDTH)}`);
|
|
11168
11145
|
if (prompt) {
|
|
11169
11146
|
workflowEnv.HEARTBEAT_PROMPT = prompt;
|
|
11170
|
-
this.logger.info(` ${DIM$
|
|
11147
|
+
this.logger.info(` ${DIM$1}prompt${RESET$1} ${prompt.split("\n")[0].slice(0, PROMPT_PREVIEW_MAX_CHARS)}${prompt.includes("\n") ? "..." : ""}`);
|
|
11171
11148
|
}
|
|
11172
11149
|
const contextFile = workflowEnv.CONTEXT_FILE;
|
|
11173
11150
|
if (contextFile) {
|
|
@@ -11184,22 +11161,22 @@ var TriggerService = class {
|
|
|
11184
11161
|
const stepName = step.name ?? `step ${index + 1}`;
|
|
11185
11162
|
await options.onStepStarted?.(stepName, index, trigger.steps.length);
|
|
11186
11163
|
if (!await this.stepRunner.runStep(step, stepContext, options)) {
|
|
11187
|
-
this.logger.error(`\n ${RED$1}Agent decision aborted workflow${RESET$
|
|
11164
|
+
this.logger.error(`\n ${RED$1}Agent decision aborted workflow${RESET$1}`);
|
|
11188
11165
|
return false;
|
|
11189
11166
|
}
|
|
11190
11167
|
}
|
|
11191
11168
|
if (contextFile && !options.dryRun) {
|
|
11192
11169
|
const contextPath = (0, node_path.resolve)(options.workflowDir, contextFile);
|
|
11193
11170
|
if (!await this.pathExists(contextPath)) {
|
|
11194
|
-
this.logger.error(` ${RED$1}fail${RESET$
|
|
11171
|
+
this.logger.error(` ${RED$1}fail${RESET$1} Context file not created: ${contextFile}`);
|
|
11195
11172
|
return false;
|
|
11196
11173
|
}
|
|
11197
11174
|
const content = (0, _agimon_ai_po_core_platform.getOrThrow)(await this.runtime.fs.readTextFile(contextPath, this.runtime.ioContext)).trim();
|
|
11198
11175
|
if (!content) {
|
|
11199
|
-
this.logger.error(` ${RED$1}fail${RESET$
|
|
11176
|
+
this.logger.error(` ${RED$1}fail${RESET$1} Context file is empty: ${contextFile}`);
|
|
11200
11177
|
return false;
|
|
11201
11178
|
}
|
|
11202
|
-
this.logger.info(` ${GREEN$1}ready${RESET$
|
|
11179
|
+
this.logger.info(` ${GREEN$1}ready${RESET$1} context has ${content.split("\n").length} line(s)`);
|
|
11203
11180
|
}
|
|
11204
11181
|
return true;
|
|
11205
11182
|
}
|
|
@@ -11456,103 +11433,6 @@ var WorkflowRepairService = class {
|
|
|
11456
11433
|
}
|
|
11457
11434
|
};
|
|
11458
11435
|
//#endregion
|
|
11459
|
-
//#region src/services/WorktreeService/index.ts
|
|
11460
|
-
/**
|
|
11461
|
-
* WorktreeService
|
|
11462
|
-
*
|
|
11463
|
-
* DESIGN PATTERNS:
|
|
11464
|
-
* - Service pattern for business logic encapsulation
|
|
11465
|
-
* - Single responsibility principle
|
|
11466
|
-
*
|
|
11467
|
-
* CODING STANDARDS:
|
|
11468
|
-
* - Use async/await for asynchronous operations
|
|
11469
|
-
* - Throw descriptive errors for error cases
|
|
11470
|
-
* - Keep methods focused and well-named
|
|
11471
|
-
*
|
|
11472
|
-
* AVOID:
|
|
11473
|
-
* - Mixing concerns (keep focused on single domain)
|
|
11474
|
-
* - Direct tool implementation (services should be tool-agnostic)
|
|
11475
|
-
*/
|
|
11476
|
-
const RESET$1 = "\x1B[0m";
|
|
11477
|
-
const DIM$1 = "\x1B[2m";
|
|
11478
|
-
const CYAN = "\x1B[36m";
|
|
11479
|
-
const YELLOW$1 = "\x1B[33m";
|
|
11480
|
-
var WorktreeService = class {
|
|
11481
|
-
runtime;
|
|
11482
|
-
stepRunner;
|
|
11483
|
-
logger;
|
|
11484
|
-
constructor(runtime, stepRunner, logger) {
|
|
11485
|
-
this.runtime = runtime;
|
|
11486
|
-
this.stepRunner = stepRunner;
|
|
11487
|
-
this.logger = logger;
|
|
11488
|
-
}
|
|
11489
|
-
getWorktreeBranchName(workflowName) {
|
|
11490
|
-
return `worktree/${workflowName.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-|-$/g, "")}`;
|
|
11491
|
-
}
|
|
11492
|
-
async createWorktree(repoRoot, workflowName) {
|
|
11493
|
-
repoRoot = (0, node_path.resolve)(this.runtime.cwd, repoRoot);
|
|
11494
|
-
const branchName = this.getWorktreeBranchName(workflowName);
|
|
11495
|
-
const safeName = branchName.slice(9);
|
|
11496
|
-
const parentDir = (0, node_path.dirname)(repoRoot);
|
|
11497
|
-
const folderName = (0, node_path.basename)(repoRoot);
|
|
11498
|
-
const worktreeBase = (0, node_path.resolve)(parentDir, `${folderName}-worktree`);
|
|
11499
|
-
const worktreePath = (0, node_path.resolve)(worktreeBase, safeName);
|
|
11500
|
-
if (!await (0, _agimon_ai_po_core_platform.pathExists)(this.runtime.fs, worktreeBase, this.runtime.ioContext)) (0, _agimon_ai_po_core_platform.getOrThrow)(await this.runtime.fs.createDir(worktreeBase, { recursive: true }, this.runtime.ioContext));
|
|
11501
|
-
if (await (0, _agimon_ai_po_core_platform.pathExists)(this.runtime.fs, worktreePath, this.runtime.ioContext)) {
|
|
11502
|
-
this.logger.info(` ${DIM$1}clean${RESET$1} Removing stale worktree at ${worktreePath}`);
|
|
11503
|
-
await this.cleanupWorktreePath(repoRoot, worktreePath);
|
|
11504
|
-
}
|
|
11505
|
-
try {
|
|
11506
|
-
await workflowShellOutput(this.runtime, `git branch -D "${branchName}"`, { cwd: repoRoot });
|
|
11507
|
-
} catch {}
|
|
11508
|
-
this.logger.info(` ${CYAN}create${RESET$1} Worktree at ${worktreePath} (branch: ${branchName})`);
|
|
11509
|
-
await workflowShellOutput(this.runtime, `git worktree add -b "${branchName}" "${worktreePath}" HEAD`, { cwd: repoRoot });
|
|
11510
|
-
return worktreePath;
|
|
11511
|
-
}
|
|
11512
|
-
async removeWorktree(repoRoot, worktreePath) {
|
|
11513
|
-
repoRoot = (0, node_path.resolve)(this.runtime.cwd, repoRoot);
|
|
11514
|
-
worktreePath = (0, node_path.resolve)(this.runtime.cwd, worktreePath);
|
|
11515
|
-
if (!await (0, _agimon_ai_po_core_platform.pathExists)(this.runtime.fs, worktreePath, this.runtime.ioContext)) return;
|
|
11516
|
-
this.logger.info(` ${DIM$1}remove${RESET$1} Worktree at ${worktreePath}`);
|
|
11517
|
-
try {
|
|
11518
|
-
await this.cleanupWorktreePath(repoRoot, worktreePath);
|
|
11519
|
-
} catch {
|
|
11520
|
-
this.logger.warn(` ${YELLOW$1}warn${RESET$1} Failed to remove worktree (may need manual cleanup)`);
|
|
11521
|
-
}
|
|
11522
|
-
}
|
|
11523
|
-
async cleanupWorktreePath(repoRoot, worktreePath) {
|
|
11524
|
-
if (await this.isRegisteredWorktree(repoRoot, worktreePath)) {
|
|
11525
|
-
await workflowShellOutput(this.runtime, `git worktree remove --force "${worktreePath}"`, { cwd: repoRoot });
|
|
11526
|
-
return;
|
|
11527
|
-
}
|
|
11528
|
-
await (0, _agimon_ai_po_core_platform.removePath)(this.runtime.fs, worktreePath, this.runtime.ioContext);
|
|
11529
|
-
}
|
|
11530
|
-
async isRegisteredWorktree(repoRoot, worktreePath) {
|
|
11531
|
-
try {
|
|
11532
|
-
return (await workflowShellOutput(this.runtime, "git worktree list --porcelain", { cwd: repoRoot })).split("\n").some((line) => line.startsWith("worktree ") && (0, node_path.resolve)(this.runtime.cwd, line.slice(9)) === worktreePath);
|
|
11533
|
-
} catch {
|
|
11534
|
-
return false;
|
|
11535
|
-
}
|
|
11536
|
-
}
|
|
11537
|
-
async runHook(hook, cwd, baseEnv, inputs, secrets, options) {
|
|
11538
|
-
const stepContext = {
|
|
11539
|
-
inputs,
|
|
11540
|
-
matrix: {},
|
|
11541
|
-
secrets,
|
|
11542
|
-
env: baseEnv
|
|
11543
|
-
};
|
|
11544
|
-
for (const [index, step] of hook.steps.entries()) {
|
|
11545
|
-
const stepName = step.name ?? `step ${index + 1}`;
|
|
11546
|
-
await options.onStepStarted?.(stepName, index, hook.steps.length);
|
|
11547
|
-
if (!await this.stepRunner.runStep(step, stepContext, {
|
|
11548
|
-
...options,
|
|
11549
|
-
workflowDir: cwd
|
|
11550
|
-
})) return false;
|
|
11551
|
-
}
|
|
11552
|
-
return true;
|
|
11553
|
-
}
|
|
11554
|
-
};
|
|
11555
|
-
//#endregion
|
|
11556
11436
|
//#region src/services/RunWorkflowService/index.ts
|
|
11557
11437
|
/**
|
|
11558
11438
|
* RunWorkflowService
|
|
@@ -11598,7 +11478,6 @@ const DRY_RUN_ARTIFACT_FILENAME = "assembled-workflow.yml";
|
|
|
11598
11478
|
const TRIGGER_USER_PROMPT = "user_prompt";
|
|
11599
11479
|
const TRIGGER_AGENT_DECISION = "agent_decision";
|
|
11600
11480
|
const TRIGGER_WORKFLOW_DISPATCH = "workflow_dispatch";
|
|
11601
|
-
const WORKTREE_DRY_RUN_MESSAGE = "Would create at";
|
|
11602
11481
|
const SERVICE_STARTUP_DELAY_MS = 2e3;
|
|
11603
11482
|
const DEFAULT_WORKSPACE = "default";
|
|
11604
11483
|
const WORKFLOW_SUCCESS_TEXT = "Workflow completed successfully";
|
|
@@ -11606,8 +11485,6 @@ const WORKFLOW_SKIPPED_TEXT = "Workflow skipped: agent decided nothing to do";
|
|
|
11606
11485
|
const WORKFLOW_ABORTED_PROMPT_TEXT = "Workflow aborted: no prompt provided";
|
|
11607
11486
|
const WORKFLOW_ABORTED_PRECONDITIONS_TEXT = "Workflow aborted: pre-conditions failed";
|
|
11608
11487
|
const WORKFLOW_POST_FAILED_TEXT = "Workflow post-cleanup failed";
|
|
11609
|
-
const WORKFLOW_ABORTED_WORKTREE_BEFORE_CREATE_TEXT = "Workflow aborted: worktree beforeCreate hook failed";
|
|
11610
|
-
const WORKFLOW_ABORTED_WORKTREE_AFTER_CREATE_TEXT = "Workflow aborted: worktree afterCreate hook failed";
|
|
11611
11488
|
const WORKFLOW_FAILED_AT_JOB_PREFIX = "Workflow failed at job";
|
|
11612
11489
|
const COMPLETED_STAGE = "completed";
|
|
11613
11490
|
const ERROR_STAGE$1 = "error";
|
|
@@ -11672,7 +11549,7 @@ function envFlagEnabled(value) {
|
|
|
11672
11549
|
}
|
|
11673
11550
|
/**
|
|
11674
11551
|
* Orchestrates local workflow execution, including triggers, jobs, services,
|
|
11675
|
-
*
|
|
11552
|
+
* and graceful interruption handling. Checkout isolation belongs to launchers.
|
|
11676
11553
|
*/
|
|
11677
11554
|
var RunWorkflowService = class {
|
|
11678
11555
|
runtime;
|
|
@@ -11683,7 +11560,6 @@ var RunWorkflowService = class {
|
|
|
11683
11560
|
stepRunner;
|
|
11684
11561
|
jobRunner;
|
|
11685
11562
|
triggerService;
|
|
11686
|
-
worktreeService;
|
|
11687
11563
|
registry;
|
|
11688
11564
|
repairService;
|
|
11689
11565
|
runDirectoryService;
|
|
@@ -11733,7 +11609,6 @@ var RunWorkflowService = class {
|
|
|
11733
11609
|
this.runDirectoryService = dependencies.runDirectoryService ?? new RunDirectoryService(this.runtime, this.registry.writeCoordinator);
|
|
11734
11610
|
this.jobRunner = dependencies.jobRunner ?? new JobRunnerService(this.runtime, this.parser, this.stepRunner, this.logger, this.runDirectoryService);
|
|
11735
11611
|
this.triggerService = dependencies.triggerService ?? new TriggerService(this.runtime, this.stepRunner, this.logger);
|
|
11736
|
-
this.worktreeService = dependencies.worktreeService ?? new WorktreeService(this.runtime, this.stepRunner, this.logger);
|
|
11737
11612
|
this.repairService = dependencies.repairService ?? new WorkflowRepairService(this.runtime);
|
|
11738
11613
|
}
|
|
11739
11614
|
/**
|
|
@@ -11762,7 +11637,7 @@ var RunWorkflowService = class {
|
|
|
11762
11637
|
this.runtime.workflowHost.onSignal(HANGUP_SIGNAL, handleSighup)
|
|
11763
11638
|
] : [];
|
|
11764
11639
|
try {
|
|
11765
|
-
return await runWorkflowSpan(this.logger, "workflow.run", {}, () => this.executeWorkflow(input, dryRun, continueOnError
|
|
11640
|
+
return await runWorkflowSpan(this.logger, "workflow.run", {}, () => this.executeWorkflow(input, dryRun, continueOnError));
|
|
11766
11641
|
} catch (error) {
|
|
11767
11642
|
if (error instanceof WorkflowInterruptedError || this.isInterrupted()) {
|
|
11768
11643
|
await this.serviceManager.stopAll();
|
|
@@ -11933,7 +11808,7 @@ var RunWorkflowService = class {
|
|
|
11933
11808
|
/**
|
|
11934
11809
|
* Execute the workflow after signal handlers are installed.
|
|
11935
11810
|
*/
|
|
11936
|
-
async executeWorkflow(input, dryRun, continueOnError
|
|
11811
|
+
async executeWorkflow(input, dryRun, continueOnError) {
|
|
11937
11812
|
if (input.statusFile) input = {
|
|
11938
11813
|
...input,
|
|
11939
11814
|
statusFile: (0, node_path.resolve)(input.statusFile)
|
|
@@ -11953,8 +11828,8 @@ var RunWorkflowService = class {
|
|
|
11953
11828
|
*
|
|
11954
11829
|
* The delegating process returns from inside the `try`, so the `finally`
|
|
11955
11830
|
* still fires for it. Most of that block is already inert here, keyed off
|
|
11956
|
-
* state delegation never creates: no run record
|
|
11957
|
-
*
|
|
11831
|
+
* state delegation never creates: no run record and no completion
|
|
11832
|
+
* record. `post:` is the exception, and it is not a harmless one.
|
|
11958
11833
|
*/
|
|
11959
11834
|
let delegated = false;
|
|
11960
11835
|
let policyAuthorized = input.admission?.binding === void 0;
|
|
@@ -11962,18 +11837,12 @@ var RunWorkflowService = class {
|
|
|
11962
11837
|
let result = null;
|
|
11963
11838
|
let runError = null;
|
|
11964
11839
|
let workflowDir = (0, node_path.dirname)(workflowPath);
|
|
11965
|
-
let originalDir = workflowDir;
|
|
11966
|
-
let worktreePath = null;
|
|
11967
|
-
let worktreeBranch = null;
|
|
11968
|
-
let shouldRunSuccessCompletionHooks = false;
|
|
11969
|
-
let shouldRemoveWorktreeOnExit = false;
|
|
11970
11840
|
let failedJob;
|
|
11971
11841
|
let failureReason;
|
|
11972
11842
|
let persistedFixLoopCycle;
|
|
11973
11843
|
let activeJob;
|
|
11974
11844
|
let activeRepair = null;
|
|
11975
11845
|
const dryRunPromptAssemblies = [];
|
|
11976
|
-
const useWorktree = !!workflow.worktree;
|
|
11977
11846
|
const inputs = /* @__PURE__ */ new Map();
|
|
11978
11847
|
const secrets = input.secretFile ? await this.parser.loadSecrets(input.secretFile) : /* @__PURE__ */ new Map();
|
|
11979
11848
|
const workflowEnv = {};
|
|
@@ -12070,7 +11939,6 @@ var RunWorkflowService = class {
|
|
|
12070
11939
|
env: input.env,
|
|
12071
11940
|
inputs: input.inputs,
|
|
12072
11941
|
job: input.recovery ? input.recovery.originalJob : input.job,
|
|
12073
|
-
keepWorktree: input.keepWorktree,
|
|
12074
11942
|
launcher: this.launcherMetadata ?? await this.resolveLauncherMetadata(),
|
|
12075
11943
|
prompt: input.prompt,
|
|
12076
11944
|
recoveryClaimId: input.recovery?.claimId,
|
|
@@ -12142,7 +12010,6 @@ var RunWorkflowService = class {
|
|
|
12142
12010
|
const stepCount = workflow.post.steps?.length || 0;
|
|
12143
12011
|
this.logger.info(` Post: ${svcCount} service(s), ${stepCount} cleanup step(s)`);
|
|
12144
12012
|
}
|
|
12145
|
-
if (useWorktree) this.logger.info(` Worktree: enabled${keepWorktree ? " (keep on completion)" : ""}`);
|
|
12146
12013
|
const triggerType = workflow.on && TRIGGER_USER_PROMPT in workflow.on ? TRIGGER_USER_PROMPT : workflow.on?.[TRIGGER_AGENT_DECISION] ? TRIGGER_AGENT_DECISION : TRIGGER_WORKFLOW_DISPATCH;
|
|
12147
12014
|
this.logger.info(` Trigger: ${triggerType}`);
|
|
12148
12015
|
this.logger.info(` Mode: ${dryRun ? "dry-run" : "execute"}`);
|
|
@@ -12179,87 +12046,6 @@ var RunWorkflowService = class {
|
|
|
12179
12046
|
};
|
|
12180
12047
|
return result;
|
|
12181
12048
|
}
|
|
12182
|
-
originalDir = workflowDir;
|
|
12183
|
-
if (useWorktree && input.recovery) {
|
|
12184
|
-
if (!input.recovery.worktreePath || !await this.pathExists(input.recovery.worktreePath)) throw new Error(`Recoverable worktree not found: ${input.recovery.worktreePath ?? "(missing)"}`);
|
|
12185
|
-
originalDir = input.recovery.originalRepoPath ?? originalDir;
|
|
12186
|
-
worktreePath = input.recovery.worktreePath;
|
|
12187
|
-
worktreeBranch = input.recovery.worktreeBranch ?? this.worktreeService.getWorktreeBranchName(registryRun.displayName);
|
|
12188
|
-
workflowDir = worktreePath;
|
|
12189
|
-
workflowEnv.WORKTREE_PATH = worktreePath;
|
|
12190
|
-
workflowEnv.WORKTREE_BRANCH = worktreeBranch;
|
|
12191
|
-
workflowEnv.ORIGINAL_REPO_PATH = originalDir;
|
|
12192
|
-
this.logger.info(`\n ${BLUE}${BOLD}worktree${RESET} ${BOLD}Reusing worktree${RESET}`);
|
|
12193
|
-
this.logger.info(` ${"─".repeat(50)}`);
|
|
12194
|
-
this.logger.info(` ${DIM}path ${RESET} ${worktreePath}`);
|
|
12195
|
-
} else if (useWorktree && !dryRun) {
|
|
12196
|
-
if (workflow.worktree?.beforeCreate) {
|
|
12197
|
-
workflowEnv[WORKFLOW_PHASE_ENV] = "worktree-before-create";
|
|
12198
|
-
this.logger.info(`\n ${BLUE}${BOLD}worktree${RESET} ${BOLD}beforeCreate${RESET}`);
|
|
12199
|
-
this.logger.info(` ${"─".repeat(50)}`);
|
|
12200
|
-
if (!await this.worktreeService.runHook(workflow.worktree.beforeCreate, workflowDir, workflowEnv, inputs, secrets, {
|
|
12201
|
-
runner,
|
|
12202
|
-
dryRun,
|
|
12203
|
-
continueOnError,
|
|
12204
|
-
stopRequestPath: registryRun.stopRequestPath,
|
|
12205
|
-
onStepStarted,
|
|
12206
|
-
onExecutionStateChange
|
|
12207
|
-
})) {
|
|
12208
|
-
if (this.isInterrupted()) result = this.createInterruptedResult();
|
|
12209
|
-
else {
|
|
12210
|
-
this.logger.error(`\n${RED}${BOLD}${WORKFLOW_ABORTED_WORKTREE_BEFORE_CREATE_TEXT}${RESET}`);
|
|
12211
|
-
result = {
|
|
12212
|
-
exitCode: WORKFLOW_FAILED_EXIT_CODE,
|
|
12213
|
-
output: this.outputLines.join("\n")
|
|
12214
|
-
};
|
|
12215
|
-
}
|
|
12216
|
-
}
|
|
12217
|
-
}
|
|
12218
|
-
if (!result) {
|
|
12219
|
-
this.logger.info(`\n ${BLUE}${BOLD}worktree${RESET} ${BOLD}Creating worktree${RESET}`);
|
|
12220
|
-
this.logger.info(` ${"─".repeat(50)}`);
|
|
12221
|
-
worktreeBranch = this.worktreeService.getWorktreeBranchName(registryRun.displayName);
|
|
12222
|
-
worktreePath = await this.worktreeService.createWorktree(workflowDir, registryRun.displayName);
|
|
12223
|
-
await this.registry.updateWorktree(registryRun, {
|
|
12224
|
-
originalRepoPath: originalDir,
|
|
12225
|
-
worktreeBranch,
|
|
12226
|
-
worktreePath
|
|
12227
|
-
});
|
|
12228
|
-
workflowDir = worktreePath;
|
|
12229
|
-
workflowEnv.WORKTREE_PATH = worktreePath;
|
|
12230
|
-
workflowEnv.WORKTREE_BRANCH = worktreeBranch;
|
|
12231
|
-
workflowEnv.ORIGINAL_REPO_PATH = originalDir;
|
|
12232
|
-
if (workflow.worktree?.afterCreate) {
|
|
12233
|
-
workflowEnv[WORKFLOW_PHASE_ENV] = "worktree-after-create";
|
|
12234
|
-
this.logger.info(`\n ${BLUE}${BOLD}worktree${RESET} ${BOLD}afterCreate${RESET}`);
|
|
12235
|
-
this.logger.info(` ${"─".repeat(50)}`);
|
|
12236
|
-
if (!await this.worktreeService.runHook(workflow.worktree.afterCreate, worktreePath, workflowEnv, inputs, secrets, {
|
|
12237
|
-
runner,
|
|
12238
|
-
dryRun,
|
|
12239
|
-
continueOnError,
|
|
12240
|
-
stopRequestPath: registryRun.stopRequestPath,
|
|
12241
|
-
onStepStarted,
|
|
12242
|
-
onExecutionStateChange
|
|
12243
|
-
})) {
|
|
12244
|
-
if (this.isInterrupted()) result = this.createInterruptedResult();
|
|
12245
|
-
else {
|
|
12246
|
-
this.logger.error(`\n${RED}${BOLD}${WORKFLOW_ABORTED_WORKTREE_AFTER_CREATE_TEXT}${RESET}`);
|
|
12247
|
-
result = {
|
|
12248
|
-
exitCode: WORKFLOW_FAILED_EXIT_CODE,
|
|
12249
|
-
output: this.outputLines.join("\n")
|
|
12250
|
-
};
|
|
12251
|
-
}
|
|
12252
|
-
shouldRemoveWorktreeOnExit = !keepWorktree;
|
|
12253
|
-
}
|
|
12254
|
-
}
|
|
12255
|
-
}
|
|
12256
|
-
} else if (useWorktree && dryRun) {
|
|
12257
|
-
const parentDir = (0, node_path.dirname)(workflowDir);
|
|
12258
|
-
const folderName = (0, node_path.basename)(workflowDir);
|
|
12259
|
-
const safeName = registryRun.displayName.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-|-$/g, "");
|
|
12260
|
-
const dryWorktreePath = (0, node_path.resolve)(parentDir, `${folderName}-worktree`, safeName);
|
|
12261
|
-
this.logger.info(`\n ${BLUE}${BOLD}worktree${RESET} ${BOLD}(dry-run)${RESET} ${WORKTREE_DRY_RUN_MESSAGE} ${dryWorktreePath}`);
|
|
12262
|
-
}
|
|
12263
12049
|
progress = new WorkflowProgressService(this.runtime, registryRun.runDir);
|
|
12264
12050
|
if (!result && workflow.pre) {
|
|
12265
12051
|
workflowEnv[WORKFLOW_PHASE_ENV] = "pre";
|
|
@@ -12283,7 +12069,6 @@ var RunWorkflowService = class {
|
|
|
12283
12069
|
output: this.outputLines.join("\n")
|
|
12284
12070
|
};
|
|
12285
12071
|
}
|
|
12286
|
-
shouldRemoveWorktreeOnExit = Boolean(worktreePath && !keepWorktree);
|
|
12287
12072
|
}
|
|
12288
12073
|
}
|
|
12289
12074
|
const maxRetries = parsePositiveIntegerEnv(workflowEnv.MAX_RETRIES, DEFAULT_MAX_RETRIES);
|
|
@@ -12631,11 +12416,9 @@ var RunWorkflowService = class {
|
|
|
12631
12416
|
const artifactPath = await this.writeDryRunWorkflowArtifact(workflow, jobOrder, dryRunPromptAssemblies);
|
|
12632
12417
|
this.logger.info(`\n ${DIM}Assembled workflow: ${artifactPath}${RESET}`);
|
|
12633
12418
|
}
|
|
12634
|
-
shouldRunSuccessCompletionHooks = true;
|
|
12635
12419
|
this.logger.info(`\n${BOLD}${"═".repeat(60)}${RESET}`);
|
|
12636
12420
|
this.logger.info(` ${GREEN}${BOLD}${WORKFLOW_SUCCESS_TEXT}${RESET}`);
|
|
12637
12421
|
this.logger.info(` Jobs run: ${[...completedJobs].join(", ")}`);
|
|
12638
|
-
if (worktreePath) this.logger.info(` Worktree: ${worktreePath}`);
|
|
12639
12422
|
this.logger.info(`${BOLD}${"═".repeat(60)}${RESET}\n`);
|
|
12640
12423
|
result = {
|
|
12641
12424
|
exitCode: 0,
|
|
@@ -12655,25 +12438,6 @@ var RunWorkflowService = class {
|
|
|
12655
12438
|
} else throw error;
|
|
12656
12439
|
} finally {
|
|
12657
12440
|
if (registryRun && !(dryRun && input.recovery)) await this.registry.markFinalizing(registryRun);
|
|
12658
|
-
if (shouldRunSuccessCompletionHooks && result?.exitCode === 0 && useWorktree && workflow.worktree?.beforeCompleted && !dryRun && worktreePath) {
|
|
12659
|
-
workflowEnv[WORKFLOW_PHASE_ENV] = "worktree-before-completed";
|
|
12660
|
-
this.logger.info(`\n ${BLUE}${BOLD}worktree${RESET} ${BOLD}beforeCompleted${RESET}`);
|
|
12661
|
-
this.logger.info(` ${"─".repeat(50)}`);
|
|
12662
|
-
if (!await this.worktreeService.runHook(workflow.worktree.beforeCompleted, worktreePath, workflowEnv, inputs, secrets, {
|
|
12663
|
-
runner,
|
|
12664
|
-
dryRun,
|
|
12665
|
-
continueOnError
|
|
12666
|
-
})) {
|
|
12667
|
-
if (this.isInterrupted()) result = this.createInterruptedResult();
|
|
12668
|
-
else {
|
|
12669
|
-
this.logger.error(`\n${RED}${BOLD}worktree beforeCompleted hook failed${RESET}`);
|
|
12670
|
-
result = {
|
|
12671
|
-
exitCode: WORKFLOW_FAILED_EXIT_CODE,
|
|
12672
|
-
output: this.outputLines.join("\n")
|
|
12673
|
-
};
|
|
12674
|
-
}
|
|
12675
|
-
}
|
|
12676
|
-
}
|
|
12677
12441
|
if (workflow.post && !delegated && policyAuthorized) {
|
|
12678
12442
|
this.stepRunner.resetInterruption();
|
|
12679
12443
|
const settled = this.resolveRunOutcome(result, runError);
|
|
@@ -12705,28 +12469,6 @@ var RunWorkflowService = class {
|
|
|
12705
12469
|
};
|
|
12706
12470
|
}
|
|
12707
12471
|
}
|
|
12708
|
-
if (shouldRunSuccessCompletionHooks && result?.exitCode === 0 && useWorktree && workflow.worktree?.afterCompleted && !dryRun && !keepWorktree) {
|
|
12709
|
-
workflowEnv[WORKFLOW_PHASE_ENV] = "worktree-after-completed";
|
|
12710
|
-
this.logger.info(`\n ${BLUE}${BOLD}worktree${RESET} ${BOLD}afterCompleted${RESET}`);
|
|
12711
|
-
this.logger.info(` ${"─".repeat(50)}`);
|
|
12712
|
-
if (!await this.worktreeService.runHook(workflow.worktree.afterCompleted, originalDir, workflowEnv, inputs, secrets, {
|
|
12713
|
-
runner,
|
|
12714
|
-
dryRun,
|
|
12715
|
-
continueOnError
|
|
12716
|
-
})) {
|
|
12717
|
-
if (this.isInterrupted()) result = this.createInterruptedResult();
|
|
12718
|
-
else {
|
|
12719
|
-
this.logger.error(`\n${RED}${BOLD}worktree afterCompleted hook failed${RESET}`);
|
|
12720
|
-
result = {
|
|
12721
|
-
exitCode: WORKFLOW_FAILED_EXIT_CODE,
|
|
12722
|
-
output: this.outputLines.join("\n")
|
|
12723
|
-
};
|
|
12724
|
-
}
|
|
12725
|
-
}
|
|
12726
|
-
}
|
|
12727
|
-
if (shouldRemoveWorktreeOnExit && worktreePath) {
|
|
12728
|
-
if (!(registryRun && (await this.registry.readRunRecord(registryRun.recordPath)).resume)) await this.worktreeService.removeWorktree(originalDir, worktreePath);
|
|
12729
|
-
}
|
|
12730
12472
|
if (result) result = {
|
|
12731
12473
|
...result,
|
|
12732
12474
|
output: this.outputLines.join("\n")
|
|
@@ -12735,10 +12477,7 @@ var RunWorkflowService = class {
|
|
|
12735
12477
|
const finalizedRecord = await this.finalizeRegistryRun(registryRun, result, runError, {
|
|
12736
12478
|
failedJob,
|
|
12737
12479
|
failureReason,
|
|
12738
|
-
fixLoopCycle: persistedFixLoopCycle
|
|
12739
|
-
originalRepoPath: worktreePath ? originalDir : void 0,
|
|
12740
|
-
worktreeBranch: worktreeBranch ?? void 0,
|
|
12741
|
-
worktreePath: worktreePath ?? void 0
|
|
12480
|
+
fixLoopCycle: persistedFixLoopCycle
|
|
12742
12481
|
});
|
|
12743
12482
|
workflowEnv[WORKFLOW_PHASE_ENV] = "terminal";
|
|
12744
12483
|
await this.logger.event?.(finalizedRecord.stage === ERROR_STAGE$1 ? "error" : "info", "workflow.run.finished", {
|
|
@@ -13076,7 +12815,6 @@ var RunWorkflowService = class {
|
|
|
13076
12815
|
if (input.profile) parts.push("--profile", require_workflowCommandTemplate.escapeShellArg(input.profile));
|
|
13077
12816
|
if (input.dryRun) parts.push("--dry-run");
|
|
13078
12817
|
if (input.continueOnError) parts.push("--continue-on-error");
|
|
13079
|
-
if (input.keepWorktree) parts.push("--keep-worktree");
|
|
13080
12818
|
if (input.prompt) parts.push("--prompt", require_workflowCommandTemplate.escapeShellArg(input.prompt));
|
|
13081
12819
|
if (input.name) parts.push("--name", require_workflowCommandTemplate.escapeShellArg(input.name));
|
|
13082
12820
|
if (input.workspace) parts.push("--workspace", require_workflowCommandTemplate.escapeShellArg(input.workspace));
|
|
@@ -13400,6 +13138,7 @@ var RecoverWorkflowService = class {
|
|
|
13400
13138
|
const record = failedRecord ?? await this.registry.readRunByKey(input.workspace, ERROR_STAGE, input.runKey);
|
|
13401
13139
|
const activeRepair = record.activeRepairId ? await this.registry.readRunRepair(record.workspace, ERROR_STAGE, record.runKey, record.activeRepairId) : void 0;
|
|
13402
13140
|
if (activeRepair && !["pending", "active"].includes(activeRepair.status)) throw new Error(`Workflow run "${record.workspace}/${record.runKey}" points to non-active repair ${activeRepair.repairId} (${activeRepair.status})`);
|
|
13141
|
+
if (record.worktreePath) throw new Error(`Workflow run "${record.workspace}/${record.runKey}" ran in an engine-owned worktree, which is no longer supported. Launch it fresh.`);
|
|
13403
13142
|
const workflow = await this.parser.parseWorkflowFile(record.workflowPath);
|
|
13404
13143
|
const repairTriageFailed = record.failedJob === REPAIR_TRIAGE_JOB_NAME && Boolean(workflow.repair);
|
|
13405
13144
|
const fallbackRepairFailed = Boolean(activeRepair && !workflow.repair && record.failedJob && activeRepair.scopeJobs.includes(record.failedJob));
|
|
@@ -13411,7 +13150,6 @@ var RecoverWorkflowService = class {
|
|
|
13411
13150
|
const fixRestartFrom = terminalFix.restartFrom;
|
|
13412
13151
|
const recoveredJob = activeRepair ? this.repairService.resolveRecoveryStart(activeRepair) : fixRestartFrom ?? record.failedJob;
|
|
13413
13152
|
if (!recoveredJob) throw new Error(`Workflow run "${record.workspace}/${record.runKey}" does not include a recoverable failed job`);
|
|
13414
|
-
if (record.worktreePath && !await (0, _agimon_ai_po_core_platform.pathExists)(this.runtime.fs, record.worktreePath, this.runtime.ioContext)) throw new Error(`Recoverable worktree not found: ${record.worktreePath}`);
|
|
13415
13153
|
const runner = input.runner ?? record.runner ?? record.cliAgent;
|
|
13416
13154
|
if ([runner, record.command].some((value) => value !== void 0 && [
|
|
13417
13155
|
"claude",
|
|
@@ -13458,7 +13196,6 @@ var RecoverWorkflowService = class {
|
|
|
13458
13196
|
secretFile: record.secretFile,
|
|
13459
13197
|
dryRun: input.dryRun ?? record.dryRun,
|
|
13460
13198
|
continueOnError: record.continueOnError,
|
|
13461
|
-
keepWorktree: record.keepWorktree,
|
|
13462
13199
|
prompt: record.prompt,
|
|
13463
13200
|
name: record.displayName,
|
|
13464
13201
|
workspace: record.workspace,
|
|
@@ -13467,11 +13204,8 @@ var RecoverWorkflowService = class {
|
|
|
13467
13204
|
activeRepairId: activeRepair?.repairId,
|
|
13468
13205
|
claimId: recoveryClaimId,
|
|
13469
13206
|
originalJob,
|
|
13470
|
-
originalRepoPath: record.originalRepoPath,
|
|
13471
13207
|
runKey: record.runKey,
|
|
13472
|
-
startJob: recoveredJob
|
|
13473
|
-
worktreeBranch: record.worktreeBranch,
|
|
13474
|
-
worktreePath: record.worktreePath
|
|
13208
|
+
startJob: recoveredJob
|
|
13475
13209
|
}
|
|
13476
13210
|
};
|
|
13477
13211
|
}
|
|
@@ -13783,4 +13517,4 @@ Object.defineProperty(exports, "workflowShellOutput", {
|
|
|
13783
13517
|
}
|
|
13784
13518
|
});
|
|
13785
13519
|
|
|
13786
|
-
//# sourceMappingURL=RecoverWorkflowService-
|
|
13520
|
+
//# sourceMappingURL=RecoverWorkflowService-DH-0c4wb.cjs.map
|