@wizdear/atlas-code 0.2.4 → 0.2.6
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/README.md +1 -1
- package/dist/agent-factory.d.ts +10 -5
- package/dist/agent-factory.d.ts.map +1 -1
- package/dist/agent-factory.js +50 -13
- package/dist/agent-factory.js.map +1 -1
- package/dist/cli.d.ts +7 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +72 -16
- package/dist/cli.js.map +1 -1
- package/dist/discovery.d.ts +9 -2
- package/dist/discovery.d.ts.map +1 -1
- package/dist/discovery.js +4 -5
- package/dist/discovery.js.map +1 -1
- package/dist/extension.d.ts +9 -2
- package/dist/extension.d.ts.map +1 -1
- package/dist/extension.js +1103 -381
- package/dist/extension.js.map +1 -1
- package/dist/gate.d.ts +1 -1
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/orchestrator.d.ts +0 -4
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +0 -2
- package/dist/orchestrator.js.map +1 -1
- package/dist/pipeline-editor.d.ts +2 -0
- package/dist/pipeline-editor.d.ts.map +1 -1
- package/dist/pipeline-editor.js +36 -5
- package/dist/pipeline-editor.js.map +1 -1
- package/dist/pipeline.d.ts +2 -10
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +4 -6
- package/dist/pipeline.js.map +1 -1
- package/dist/planner.d.ts +9 -2
- package/dist/planner.d.ts.map +1 -1
- package/dist/planner.js +15 -11
- package/dist/planner.js.map +1 -1
- package/dist/roles/architect.d.ts +1 -1
- package/dist/roles/architect.d.ts.map +1 -1
- package/dist/roles/architect.js +1 -1
- package/dist/roles/architect.js.map +1 -1
- package/dist/roles/cicd.d.ts +1 -1
- package/dist/roles/cicd.d.ts.map +1 -1
- package/dist/roles/cicd.js +5 -0
- package/dist/roles/cicd.js.map +1 -1
- package/dist/roles/documenter.d.ts +1 -1
- package/dist/roles/documenter.d.ts.map +1 -1
- package/dist/roles/documenter.js +11 -0
- package/dist/roles/documenter.js.map +1 -1
- package/dist/roles/index.d.ts +1 -0
- package/dist/roles/index.d.ts.map +1 -1
- package/dist/roles/index.js +3 -0
- package/dist/roles/index.js.map +1 -1
- package/dist/roles/recover.d.ts +5 -0
- package/dist/roles/recover.d.ts.map +1 -0
- package/dist/roles/recover.js +82 -0
- package/dist/roles/recover.js.map +1 -0
- package/dist/roles/reviewer.d.ts +1 -1
- package/dist/roles/reviewer.d.ts.map +1 -1
- package/dist/roles/reviewer.js +7 -1
- package/dist/roles/reviewer.js.map +1 -1
- package/dist/roles/standards-enricher.d.ts +1 -1
- package/dist/roles/standards-enricher.d.ts.map +1 -1
- package/dist/roles/standards-enricher.js +8 -0
- package/dist/roles/standards-enricher.js.map +1 -1
- package/dist/roles/tester.d.ts +1 -1
- package/dist/roles/tester.d.ts.map +1 -1
- package/dist/roles/tester.js +7 -0
- package/dist/roles/tester.js.map +1 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +6 -6
- package/dist/router.js.map +1 -1
- package/dist/standards.d.ts +37 -11
- package/dist/standards.d.ts.map +1 -1
- package/dist/standards.js +71 -89
- package/dist/standards.js.map +1 -1
- package/dist/step-executor.d.ts +15 -2
- package/dist/step-executor.d.ts.map +1 -1
- package/dist/step-executor.js +138 -30
- package/dist/step-executor.js.map +1 -1
- package/dist/store.d.ts +3 -10
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +45 -57
- package/dist/store.js.map +1 -1
- package/dist/system-architect.d.ts +9 -2
- package/dist/system-architect.d.ts.map +1 -1
- package/dist/system-architect.js +6 -10
- package/dist/system-architect.js.map +1 -1
- package/dist/telegram/bridge.d.ts +39 -0
- package/dist/telegram/bridge.d.ts.map +1 -0
- package/dist/telegram/bridge.js +380 -0
- package/dist/telegram/bridge.js.map +1 -0
- package/dist/telegram/formatter.d.ts +15 -0
- package/dist/telegram/formatter.d.ts.map +1 -0
- package/dist/telegram/formatter.js +86 -0
- package/dist/telegram/formatter.js.map +1 -0
- package/dist/telegram/renderer.d.ts +45 -0
- package/dist/telegram/renderer.d.ts.map +1 -0
- package/dist/telegram/renderer.js +150 -0
- package/dist/telegram/renderer.js.map +1 -0
- package/dist/telegram/telegram-api.d.ts +84 -0
- package/dist/telegram/telegram-api.d.ts.map +1 -0
- package/dist/telegram/telegram-api.js +134 -0
- package/dist/telegram/telegram-api.js.map +1 -0
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/ui.d.ts +1 -1
- package/dist/ui.d.ts.map +1 -1
- package/dist/ui.js +2 -0
- package/dist/ui.js.map +1 -1
- package/package.json +1 -1
package/dist/pipeline-editor.js
CHANGED
|
@@ -86,6 +86,16 @@ export class PipelineEditorComponent {
|
|
|
86
86
|
}
|
|
87
87
|
this.tui.requestRender();
|
|
88
88
|
}
|
|
89
|
+
/** Replaces the last activity entry, or adds if empty. Used for streaming text in-place updates. */
|
|
90
|
+
updateLastActivity(text) {
|
|
91
|
+
if (this.activityLog.length > 0) {
|
|
92
|
+
this.activityLog[this.activityLog.length - 1] = text;
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
this.activityLog.push(text);
|
|
96
|
+
}
|
|
97
|
+
this.tui.requestRender();
|
|
98
|
+
}
|
|
89
99
|
/** Returns a read-only snapshot of the current activity log. */
|
|
90
100
|
getActivityLog() {
|
|
91
101
|
return this.activityLog;
|
|
@@ -185,11 +195,32 @@ export class PipelineEditorComponent {
|
|
|
185
195
|
else {
|
|
186
196
|
// Single-state mode (Discovery, Planning, etc.)
|
|
187
197
|
const spinner = ansi(ANSI.cyan, SPINNER_FRAMES[this.spinnerFrame]);
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
198
|
+
const phaseLine = `${spinner} ${ansi(ANSI.bold, this.phase)}${this.detail ? ":" : "..."}`;
|
|
199
|
+
contentLines.push(this.wrapLine(bc, truncateToWidth(phaseLine, innerWidth), innerWidth));
|
|
200
|
+
// Show detail lines (streaming text) — fill available space
|
|
201
|
+
if (this.detail) {
|
|
202
|
+
const detailLines = this.detail.split("\n");
|
|
203
|
+
// Reserve space for activity log + padding
|
|
204
|
+
const maxDetailLines = MAX_ACTIVITY_LINES;
|
|
205
|
+
const visibleDetailLines = detailLines.slice(-maxDetailLines);
|
|
206
|
+
for (const line of visibleDetailLines) {
|
|
207
|
+
const truncated = truncateToWidth(line, innerWidth);
|
|
208
|
+
contentLines.push(this.wrapLine(bc, truncated, innerWidth));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// Show activity log in single-state mode
|
|
212
|
+
if (this.activityLog.length > 0) {
|
|
213
|
+
contentLines.push(this.wrapLine(bc, "", innerWidth));
|
|
214
|
+
for (const activity of this.activityLog) {
|
|
215
|
+
const activityText = ansi(ANSI.dim, ` ↳ ${activity}`);
|
|
216
|
+
contentLines.push(this.wrapLine(bc, truncateToWidth(activityText, innerWidth), innerWidth));
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Pad to minimum height so the editor doesn't look too small
|
|
220
|
+
const minContentLines = MAX_ACTIVITY_LINES + 2; // phase + blank + activity slots
|
|
221
|
+
while (contentLines.length < minContentLines) {
|
|
222
|
+
contentLines.push(this.wrapLine(bc, "", innerWidth));
|
|
223
|
+
}
|
|
193
224
|
}
|
|
194
225
|
// Hint row
|
|
195
226
|
const expandKey = this.keybindings?.getKeys("expandTools")[0] ?? "ctrl+o";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline-editor.js","sourceRoot":"","sources":["../src/pipeline-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { KeybindingsManager } from \"@mariozechner/pi-coding-agent\";\nimport {\n\tCURSOR_MARKER,\n\ttype EditorComponent,\n\ttype EditorTheme,\n\ttype TUI,\n\ttruncateToWidth,\n\tvisibleWidth,\n} from \"@mariozechner/pi-tui\";\n\n// ─── ANSI Helpers ────────────────────────────────────────────────────────────\n\nconst ANSI = {\n\treset: \"\\x1b[0m\",\n\tbold: \"\\x1b[1m\",\n\tdim: \"\\x1b[2m\",\n\tgreen: \"\\x1b[32m\",\n\tyellow: \"\\x1b[33m\",\n\tred: \"\\x1b[31m\",\n\tcyan: \"\\x1b[36m\",\n\tgray: \"\\x1b[90m\",\n} as const;\n\nfunction ansi(style: string, text: string): string {\n\treturn `${style}${text}${ANSI.reset}`;\n}\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Step info for rendering (lightweight subset of PipelineStep). */\nexport interface PipelineStepInfo {\n\tagent: string;\n\taction: string;\n\tstatus: \"done\" | \"running\" | \"pending\" | \"skipped\";\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\n/** Braille spinner frames. */\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n\n/** Max visible rows for step list. */\nconst MAX_VISIBLE_STEPS = 8;\n\n/** Max visible rows for activity log. */\nconst MAX_ACTIVITY_LINES = 6;\n\n/** Role label mapping. */\nexport const ROLE_LABELS: Record<string, string> = {\n\tplanner: \"Planner\",\n\tarchitect: \"Architect\",\n\tdeveloper: \"Developer\",\n\ttester: \"Tester\",\n\treviewer: \"Reviewer\",\n\tcicd: \"CI/CD\",\n\tanalyzer: \"Analyzer\",\n\tdiagnostician: \"Diagnostician\",\n\tdiscovery: \"Discovery\",\n\tprojectAnalyzer: \"Project Analyzer\",\n\tsystemArchitect: \"System Architect\",\n};\n\n// ─── PipelineEditorComponent ─────────────────────────────────────────────────\n\n/**\n * Read-only component that replaces the default editor during pipeline execution.\n * Shows current step and tool activity, ignoring normal input.\n * Supports Esc for abort and expandTools key for expand/collapse.\n */\nexport class PipelineEditorComponent implements EditorComponent {\n\tprivate phase = \"\";\n\tprivate detail = \"\";\n\tprivate tui: TUI;\n\tprivate keybindings: KeybindingsManager | undefined;\n\tprivate steps: PipelineStepInfo[] = [];\n\tprivate currentStepIndex = -1;\n\tprivate title = \" Vibe Pipeline \";\n\tprivate spinnerFrame = 0;\n\tprivate spinnerInterval: ReturnType<typeof setInterval> | null = null;\n\tprivate activityLog: string[] = [];\n\n\t/** Callbacks set by pi. */\n\tonSubmit?: (text: string) => void;\n\tonChange?: (text: string) => void;\n\n\t/** Border color function (set by pi). */\n\tborderColor?: (str: string) => string;\n\n\t/** Abort callback (set by vibe). */\n\tonAbort?: () => void;\n\n\t/** Toggle expand/collapse callback (set by vibe). */\n\tonToggleExpand?: () => void;\n\n\tconstructor(tui: TUI, _theme: EditorTheme, keybindings?: KeybindingsManager) {\n\t\tthis.tui = tui;\n\t\tthis.keybindings = keybindings;\n\t}\n\n\t/** Sets the current phase. */\n\tsetPhase(phase: string): void {\n\t\tif (this.phase !== phase) {\n\t\t\tthis.phase = phase;\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\t/** Sets the detail progress info. */\n\tsetDetail(detail: string): void {\n\t\tif (this.detail !== detail) {\n\t\t\tthis.detail = detail;\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\t/** Adds an entry to the activity log. Removes oldest when exceeding MAX_ACTIVITY_LINES. */\n\taddActivity(text: string): void {\n\t\tthis.activityLog.push(text);\n\t\tif (this.activityLog.length > MAX_ACTIVITY_LINES) {\n\t\t\tthis.activityLog.splice(0, this.activityLog.length - MAX_ACTIVITY_LINES);\n\t\t}\n\t\tthis.tui.requestRender();\n\t}\n\n\t/** Returns a read-only snapshot of the current activity log. */\n\tgetActivityLog(): readonly string[] {\n\t\treturn this.activityLog;\n\t}\n\n\t/** Clears the activity log. */\n\tclearActivity(): void {\n\t\tif (this.activityLog.length > 0) {\n\t\t\tthis.activityLog = [];\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\t/** Sets the pipeline step list. */\n\tsetSteps(steps: PipelineStepInfo[]): void {\n\t\tthis.steps = steps;\n\t\tthis.tui.requestRender();\n\t}\n\n\t/** Sets the currently running step index. */\n\tsetCurrentStep(index: number): void {\n\t\tif (this.currentStepIndex !== index) {\n\t\t\tthis.currentStepIndex = index;\n\t\t\tthis.activityLog = [];\n\t\t\t// Update step states: previous steps → done, current → running\n\t\t\tfor (let i = 0; i < this.steps.length; i++) {\n\t\t\t\tif (this.steps[i].status === \"skipped\") continue;\n\t\t\t\tif (i < index) {\n\t\t\t\t\tthis.steps[i].status = \"done\";\n\t\t\t\t} else if (i === index) {\n\t\t\t\t\tthis.steps[i].status = \"running\";\n\t\t\t\t} else {\n\t\t\t\t\tif (this.steps[i].status !== \"skipped\") {\n\t\t\t\t\t\tthis.steps[i].status = \"pending\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\t/** Sets the title. */\n\tsetTitle(title: string): void {\n\t\tconst formatted = ` ${title} `;\n\t\tif (this.title !== formatted) {\n\t\t\tthis.title = formatted;\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\t/** Starts automatic spinner rotation at 80ms intervals. */\n\tstartSpinner(): void {\n\t\tif (this.spinnerInterval) return;\n\t\tthis.spinnerInterval = setInterval(() => {\n\t\t\tthis.spinnerFrame = (this.spinnerFrame + 1) % SPINNER_FRAMES.length;\n\t\t\tthis.tui.requestRender();\n\t\t}, 80);\n\t}\n\n\t/** Stops automatic spinner rotation. */\n\tstopSpinner(): void {\n\t\tif (this.spinnerInterval) {\n\t\t\tclearInterval(this.spinnerInterval);\n\t\t\tthis.spinnerInterval = null;\n\t\t}\n\t}\n\n\t// ─── EditorComponent Implementation ─────────────────────────────────\n\n\trender(width: number): string[] {\n\t\tconst bc = this.borderColor ?? ((s: string) => s);\n\t\tconst innerWidth = Math.max(width - 4, 10); // border + padding\n\n\t\t// Top border: ┌ + ─ + title + ─ + ┐ = innerWidth + 4 = width\n\t\tconst titleText = this.title;\n\t\tconst topBarWidth = Math.max(innerWidth + 2 - visibleWidth(titleText), 0);\n\t\tconst topLeft = Math.floor(topBarWidth / 2);\n\t\tconst topRight = topBarWidth - topLeft;\n\t\tconst top = bc(`┌${\"─\".repeat(topLeft)}${titleText}${\"─\".repeat(topRight)}┐`);\n\n\t\tconst contentLines: string[] = [];\n\n\t\tif (this.steps.length > 0) {\n\t\t\t// Step list mode\n\t\t\tif (this.phase) {\n\t\t\t\tconst phaseHeader = ansi(ANSI.bold, this.phase);\n\t\t\t\tcontentLines.push(this.wrapLine(bc, phaseHeader, innerWidth));\n\t\t\t}\n\t\t\tconst { start, end } = this.computeVisibleRange();\n\t\t\tfor (let i = start; i < end; i++) {\n\t\t\t\tconst step = this.steps[i];\n\t\t\t\tconst line = this.renderStepLine(step, i);\n\t\t\t\tcontentLines.push(this.wrapLine(bc, line, innerWidth));\n\n\t\t\t\t// Show activity log below the running step\n\t\t\t\tif (step.status === \"running\" && this.activityLog.length > 0) {\n\t\t\t\t\tfor (const activity of this.activityLog) {\n\t\t\t\t\t\tconst activityText = ansi(ANSI.dim, ` ↳ ${activity}`);\n\t\t\t\t\t\tconst truncated = truncateToWidth(activityText, innerWidth);\n\t\t\t\t\t\tcontentLines.push(this.wrapLine(bc, truncated, innerWidth));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Single-state mode (Discovery, Planning, etc.)\n\t\t\tconst spinner = ansi(ANSI.cyan, SPINNER_FRAMES[this.spinnerFrame]);\n\t\t\tconst statusText = this.detail\n\t\t\t\t? `${spinner} ${ansi(ANSI.bold, this.phase)}: ${this.detail}`\n\t\t\t\t: `${spinner} ${ansi(ANSI.bold, this.phase)}...`;\n\t\t\tconst truncated = truncateToWidth(statusText, innerWidth);\n\t\t\tcontentLines.push(this.wrapLine(bc, truncated, innerWidth));\n\t\t}\n\n\t\t// Hint row\n\t\tconst expandKey = this.keybindings?.getKeys(\"expandTools\")[0] ?? \"ctrl+o\";\n\t\tconst hint = ansi(ANSI.dim, `Esc: abort ${expandKey}: expand/collapse`);\n\t\tconst hintPad = Math.max(innerWidth - visibleWidth(hint), 0);\n\t\tconst hintLine = `${bc(\"│\")} ${\" \".repeat(hintPad)}${hint} ${bc(\"│\")}`;\n\t\tcontentLines.push(hintLine);\n\n\t\t// Bottom border\n\t\tconst bottom = bc(`└${\"─\".repeat(innerWidth + 2)}┘`);\n\n\t\treturn [`${CURSOR_MARKER}${top}`, ...contentLines, bottom];\n\t}\n\n\tgetText(): string {\n\t\treturn \"\";\n\t}\n\n\tsetText(_text: string): void {\n\t\t// no-op: read-only\n\t}\n\n\thandleInput(data: string): void {\n\t\t// Detect Esc key\n\t\tif (data === \"\\x1b\" || data === \"\\x1b\\x1b\") {\n\t\t\tthis.onAbort?.();\n\t\t\treturn;\n\t\t}\n\t\t// Detect expandTools key (Ctrl+O by default)\n\t\tif (this.keybindings?.matches(data, \"expandTools\")) {\n\t\t\tthis.onToggleExpand?.();\n\t\t\treturn;\n\t\t}\n\t\t// Ignore all other input\n\t}\n\n\tinvalidate(): void {\n\t\t// Cache invalidation. Next render() will use the latest state.\n\t}\n\n\t// ─── Private Helpers ─────────────────────────────────────────────────\n\n\t/** Computes visible range. Windows around the currently running step. */\n\tprivate computeVisibleRange(): { start: number; end: number } {\n\t\tconst total = this.steps.length;\n\t\tif (total <= MAX_VISIBLE_STEPS) {\n\t\t\treturn { start: 0, end: total };\n\t\t}\n\n\t\tconst center = Math.max(0, this.currentStepIndex);\n\t\tconst half = Math.floor(MAX_VISIBLE_STEPS / 2);\n\t\tlet start = Math.max(0, center - half);\n\t\tlet end = start + MAX_VISIBLE_STEPS;\n\n\t\tif (end > total) {\n\t\t\tend = total;\n\t\t\tstart = Math.max(0, end - MAX_VISIBLE_STEPS);\n\t\t}\n\n\t\treturn { start, end };\n\t}\n\n\t/** Renders a single step line. */\n\tprivate renderStepLine(step: PipelineStepInfo, index: number): string {\n\t\tconst label = ROLE_LABELS[step.agent] ?? step.agent;\n\t\tconst num = `${index + 1}`.padStart(2);\n\n\t\tswitch (step.status) {\n\t\t\tcase \"done\": {\n\t\t\t\tconst marker = ansi(ANSI.green, \"✓\");\n\t\t\t\treturn ansi(ANSI.dim, `${marker} ${ansi(ANSI.dim, `${num}. ${label}: ${step.action}`)}`);\n\t\t\t}\n\t\t\tcase \"running\": {\n\t\t\t\tconst spinner = ansi(`${ANSI.cyan}${ANSI.bold}`, SPINNER_FRAMES[this.spinnerFrame]);\n\t\t\t\treturn `${spinner} ${ansi(ANSI.bold, `${num}. ${label}: ${step.action}`)}`;\n\t\t\t}\n\t\t\tcase \"skipped\": {\n\t\t\t\tconst marker = ansi(ANSI.gray, \"⊘\");\n\t\t\t\treturn ansi(ANSI.dim, `${marker} ${ansi(ANSI.dim, `${num}. ${label}: ${step.action}`)}`);\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconst marker = ansi(ANSI.gray, \"○\");\n\t\t\t\treturn ansi(ANSI.dim, `${marker} ${ansi(ANSI.dim, `${num}. ${label}: ${step.action}`)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Wraps content text as a box row. */\n\tprivate wrapLine(bc: (s: string) => string, content: string, innerWidth: number): string {\n\t\tconst truncated = truncateToWidth(content, innerWidth);\n\t\tconst pad = Math.max(innerWidth - visibleWidth(truncated), 0);\n\t\treturn `${bc(\"│\")} ${truncated}${\" \".repeat(pad)} ${bc(\"│\")}`;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pipeline-editor.js","sourceRoot":"","sources":["../src/pipeline-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import type { KeybindingsManager } from \"@mariozechner/pi-coding-agent\";\nimport {\n\tCURSOR_MARKER,\n\ttype EditorComponent,\n\ttype EditorTheme,\n\ttype TUI,\n\ttruncateToWidth,\n\tvisibleWidth,\n} from \"@mariozechner/pi-tui\";\n\n// ─── ANSI Helpers ────────────────────────────────────────────────────────────\n\nconst ANSI = {\n\treset: \"\\x1b[0m\",\n\tbold: \"\\x1b[1m\",\n\tdim: \"\\x1b[2m\",\n\tgreen: \"\\x1b[32m\",\n\tyellow: \"\\x1b[33m\",\n\tred: \"\\x1b[31m\",\n\tcyan: \"\\x1b[36m\",\n\tgray: \"\\x1b[90m\",\n} as const;\n\nfunction ansi(style: string, text: string): string {\n\treturn `${style}${text}${ANSI.reset}`;\n}\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Step info for rendering (lightweight subset of PipelineStep). */\nexport interface PipelineStepInfo {\n\tagent: string;\n\taction: string;\n\tstatus: \"done\" | \"running\" | \"pending\" | \"skipped\";\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\n/** Braille spinner frames. */\nconst SPINNER_FRAMES = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\n\n/** Max visible rows for step list. */\nconst MAX_VISIBLE_STEPS = 8;\n\n/** Max visible rows for activity log. */\nconst MAX_ACTIVITY_LINES = 6;\n\n/** Role label mapping. */\nexport const ROLE_LABELS: Record<string, string> = {\n\tplanner: \"Planner\",\n\tarchitect: \"Architect\",\n\tdeveloper: \"Developer\",\n\ttester: \"Tester\",\n\treviewer: \"Reviewer\",\n\tcicd: \"CI/CD\",\n\tanalyzer: \"Analyzer\",\n\tdiagnostician: \"Diagnostician\",\n\tdiscovery: \"Discovery\",\n\tprojectAnalyzer: \"Project Analyzer\",\n\tsystemArchitect: \"System Architect\",\n};\n\n// ─── PipelineEditorComponent ─────────────────────────────────────────────────\n\n/**\n * Read-only component that replaces the default editor during pipeline execution.\n * Shows current step and tool activity, ignoring normal input.\n * Supports Esc for abort and expandTools key for expand/collapse.\n */\nexport class PipelineEditorComponent implements EditorComponent {\n\tprivate phase = \"\";\n\tprivate detail = \"\";\n\tprivate tui: TUI;\n\tprivate keybindings: KeybindingsManager | undefined;\n\tprivate steps: PipelineStepInfo[] = [];\n\tprivate currentStepIndex = -1;\n\tprivate title = \" Vibe Pipeline \";\n\tprivate spinnerFrame = 0;\n\tprivate spinnerInterval: ReturnType<typeof setInterval> | null = null;\n\tprivate activityLog: string[] = [];\n\n\t/** Callbacks set by pi. */\n\tonSubmit?: (text: string) => void;\n\tonChange?: (text: string) => void;\n\n\t/** Border color function (set by pi). */\n\tborderColor?: (str: string) => string;\n\n\t/** Abort callback (set by vibe). */\n\tonAbort?: () => void;\n\n\t/** Toggle expand/collapse callback (set by vibe). */\n\tonToggleExpand?: () => void;\n\n\tconstructor(tui: TUI, _theme: EditorTheme, keybindings?: KeybindingsManager) {\n\t\tthis.tui = tui;\n\t\tthis.keybindings = keybindings;\n\t}\n\n\t/** Sets the current phase. */\n\tsetPhase(phase: string): void {\n\t\tif (this.phase !== phase) {\n\t\t\tthis.phase = phase;\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\t/** Sets the detail progress info. */\n\tsetDetail(detail: string): void {\n\t\tif (this.detail !== detail) {\n\t\t\tthis.detail = detail;\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\t/** Adds an entry to the activity log. Removes oldest when exceeding MAX_ACTIVITY_LINES. */\n\taddActivity(text: string): void {\n\t\tthis.activityLog.push(text);\n\t\tif (this.activityLog.length > MAX_ACTIVITY_LINES) {\n\t\t\tthis.activityLog.splice(0, this.activityLog.length - MAX_ACTIVITY_LINES);\n\t\t}\n\t\tthis.tui.requestRender();\n\t}\n\n\t/** Replaces the last activity entry, or adds if empty. Used for streaming text in-place updates. */\n\tupdateLastActivity(text: string): void {\n\t\tif (this.activityLog.length > 0) {\n\t\t\tthis.activityLog[this.activityLog.length - 1] = text;\n\t\t} else {\n\t\t\tthis.activityLog.push(text);\n\t\t}\n\t\tthis.tui.requestRender();\n\t}\n\n\t/** Returns a read-only snapshot of the current activity log. */\n\tgetActivityLog(): readonly string[] {\n\t\treturn this.activityLog;\n\t}\n\n\t/** Clears the activity log. */\n\tclearActivity(): void {\n\t\tif (this.activityLog.length > 0) {\n\t\t\tthis.activityLog = [];\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\t/** Sets the pipeline step list. */\n\tsetSteps(steps: PipelineStepInfo[]): void {\n\t\tthis.steps = steps;\n\t\tthis.tui.requestRender();\n\t}\n\n\t/** Sets the currently running step index. */\n\tsetCurrentStep(index: number): void {\n\t\tif (this.currentStepIndex !== index) {\n\t\t\tthis.currentStepIndex = index;\n\t\t\tthis.activityLog = [];\n\t\t\t// Update step states: previous steps → done, current → running\n\t\t\tfor (let i = 0; i < this.steps.length; i++) {\n\t\t\t\tif (this.steps[i].status === \"skipped\") continue;\n\t\t\t\tif (i < index) {\n\t\t\t\t\tthis.steps[i].status = \"done\";\n\t\t\t\t} else if (i === index) {\n\t\t\t\t\tthis.steps[i].status = \"running\";\n\t\t\t\t} else {\n\t\t\t\t\tif (this.steps[i].status !== \"skipped\") {\n\t\t\t\t\t\tthis.steps[i].status = \"pending\";\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\t/** Sets the title. */\n\tsetTitle(title: string): void {\n\t\tconst formatted = ` ${title} `;\n\t\tif (this.title !== formatted) {\n\t\t\tthis.title = formatted;\n\t\t\tthis.tui.requestRender();\n\t\t}\n\t}\n\n\t/** Starts automatic spinner rotation at 80ms intervals. */\n\tstartSpinner(): void {\n\t\tif (this.spinnerInterval) return;\n\t\tthis.spinnerInterval = setInterval(() => {\n\t\t\tthis.spinnerFrame = (this.spinnerFrame + 1) % SPINNER_FRAMES.length;\n\t\t\tthis.tui.requestRender();\n\t\t}, 80);\n\t}\n\n\t/** Stops automatic spinner rotation. */\n\tstopSpinner(): void {\n\t\tif (this.spinnerInterval) {\n\t\t\tclearInterval(this.spinnerInterval);\n\t\t\tthis.spinnerInterval = null;\n\t\t}\n\t}\n\n\t// ─── EditorComponent Implementation ─────────────────────────────────\n\n\trender(width: number): string[] {\n\t\tconst bc = this.borderColor ?? ((s: string) => s);\n\t\tconst innerWidth = Math.max(width - 4, 10); // border + padding\n\n\t\t// Top border: ┌ + ─ + title + ─ + ┐ = innerWidth + 4 = width\n\t\tconst titleText = this.title;\n\t\tconst topBarWidth = Math.max(innerWidth + 2 - visibleWidth(titleText), 0);\n\t\tconst topLeft = Math.floor(topBarWidth / 2);\n\t\tconst topRight = topBarWidth - topLeft;\n\t\tconst top = bc(`┌${\"─\".repeat(topLeft)}${titleText}${\"─\".repeat(topRight)}┐`);\n\n\t\tconst contentLines: string[] = [];\n\n\t\tif (this.steps.length > 0) {\n\t\t\t// Step list mode\n\t\t\tif (this.phase) {\n\t\t\t\tconst phaseHeader = ansi(ANSI.bold, this.phase);\n\t\t\t\tcontentLines.push(this.wrapLine(bc, phaseHeader, innerWidth));\n\t\t\t}\n\t\t\tconst { start, end } = this.computeVisibleRange();\n\t\t\tfor (let i = start; i < end; i++) {\n\t\t\t\tconst step = this.steps[i];\n\t\t\t\tconst line = this.renderStepLine(step, i);\n\t\t\t\tcontentLines.push(this.wrapLine(bc, line, innerWidth));\n\n\t\t\t\t// Show activity log below the running step\n\t\t\t\tif (step.status === \"running\" && this.activityLog.length > 0) {\n\t\t\t\t\tfor (const activity of this.activityLog) {\n\t\t\t\t\t\tconst activityText = ansi(ANSI.dim, ` ↳ ${activity}`);\n\t\t\t\t\t\tconst truncated = truncateToWidth(activityText, innerWidth);\n\t\t\t\t\t\tcontentLines.push(this.wrapLine(bc, truncated, innerWidth));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Single-state mode (Discovery, Planning, etc.)\n\t\t\tconst spinner = ansi(ANSI.cyan, SPINNER_FRAMES[this.spinnerFrame]);\n\t\t\tconst phaseLine = `${spinner} ${ansi(ANSI.bold, this.phase)}${this.detail ? \":\" : \"...\"}`;\n\t\t\tcontentLines.push(this.wrapLine(bc, truncateToWidth(phaseLine, innerWidth), innerWidth));\n\n\t\t\t// Show detail lines (streaming text) — fill available space\n\t\t\tif (this.detail) {\n\t\t\t\tconst detailLines = this.detail.split(\"\\n\");\n\t\t\t\t// Reserve space for activity log + padding\n\t\t\t\tconst maxDetailLines = MAX_ACTIVITY_LINES;\n\t\t\t\tconst visibleDetailLines = detailLines.slice(-maxDetailLines);\n\t\t\t\tfor (const line of visibleDetailLines) {\n\t\t\t\t\tconst truncated = truncateToWidth(line, innerWidth);\n\t\t\t\t\tcontentLines.push(this.wrapLine(bc, truncated, innerWidth));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Show activity log in single-state mode\n\t\t\tif (this.activityLog.length > 0) {\n\t\t\t\tcontentLines.push(this.wrapLine(bc, \"\", innerWidth));\n\t\t\t\tfor (const activity of this.activityLog) {\n\t\t\t\t\tconst activityText = ansi(ANSI.dim, ` ↳ ${activity}`);\n\t\t\t\t\tcontentLines.push(this.wrapLine(bc, truncateToWidth(activityText, innerWidth), innerWidth));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Pad to minimum height so the editor doesn't look too small\n\t\t\tconst minContentLines = MAX_ACTIVITY_LINES + 2; // phase + blank + activity slots\n\t\t\twhile (contentLines.length < minContentLines) {\n\t\t\t\tcontentLines.push(this.wrapLine(bc, \"\", innerWidth));\n\t\t\t}\n\t\t}\n\n\t\t// Hint row\n\t\tconst expandKey = this.keybindings?.getKeys(\"expandTools\")[0] ?? \"ctrl+o\";\n\t\tconst hint = ansi(ANSI.dim, `Esc: abort ${expandKey}: expand/collapse`);\n\t\tconst hintPad = Math.max(innerWidth - visibleWidth(hint), 0);\n\t\tconst hintLine = `${bc(\"│\")} ${\" \".repeat(hintPad)}${hint} ${bc(\"│\")}`;\n\t\tcontentLines.push(hintLine);\n\n\t\t// Bottom border\n\t\tconst bottom = bc(`└${\"─\".repeat(innerWidth + 2)}┘`);\n\n\t\treturn [`${CURSOR_MARKER}${top}`, ...contentLines, bottom];\n\t}\n\n\tgetText(): string {\n\t\treturn \"\";\n\t}\n\n\tsetText(_text: string): void {\n\t\t// no-op: read-only\n\t}\n\n\thandleInput(data: string): void {\n\t\t// Detect Esc key\n\t\tif (data === \"\\x1b\" || data === \"\\x1b\\x1b\") {\n\t\t\tthis.onAbort?.();\n\t\t\treturn;\n\t\t}\n\t\t// Detect expandTools key (Ctrl+O by default)\n\t\tif (this.keybindings?.matches(data, \"expandTools\")) {\n\t\t\tthis.onToggleExpand?.();\n\t\t\treturn;\n\t\t}\n\t\t// Ignore all other input\n\t}\n\n\tinvalidate(): void {\n\t\t// Cache invalidation. Next render() will use the latest state.\n\t}\n\n\t// ─── Private Helpers ─────────────────────────────────────────────────\n\n\t/** Computes visible range. Windows around the currently running step. */\n\tprivate computeVisibleRange(): { start: number; end: number } {\n\t\tconst total = this.steps.length;\n\t\tif (total <= MAX_VISIBLE_STEPS) {\n\t\t\treturn { start: 0, end: total };\n\t\t}\n\n\t\tconst center = Math.max(0, this.currentStepIndex);\n\t\tconst half = Math.floor(MAX_VISIBLE_STEPS / 2);\n\t\tlet start = Math.max(0, center - half);\n\t\tlet end = start + MAX_VISIBLE_STEPS;\n\n\t\tif (end > total) {\n\t\t\tend = total;\n\t\t\tstart = Math.max(0, end - MAX_VISIBLE_STEPS);\n\t\t}\n\n\t\treturn { start, end };\n\t}\n\n\t/** Renders a single step line. */\n\tprivate renderStepLine(step: PipelineStepInfo, index: number): string {\n\t\tconst label = ROLE_LABELS[step.agent] ?? step.agent;\n\t\tconst num = `${index + 1}`.padStart(2);\n\n\t\tswitch (step.status) {\n\t\t\tcase \"done\": {\n\t\t\t\tconst marker = ansi(ANSI.green, \"✓\");\n\t\t\t\treturn ansi(ANSI.dim, `${marker} ${ansi(ANSI.dim, `${num}. ${label}: ${step.action}`)}`);\n\t\t\t}\n\t\t\tcase \"running\": {\n\t\t\t\tconst spinner = ansi(`${ANSI.cyan}${ANSI.bold}`, SPINNER_FRAMES[this.spinnerFrame]);\n\t\t\t\treturn `${spinner} ${ansi(ANSI.bold, `${num}. ${label}: ${step.action}`)}`;\n\t\t\t}\n\t\t\tcase \"skipped\": {\n\t\t\t\tconst marker = ansi(ANSI.gray, \"⊘\");\n\t\t\t\treturn ansi(ANSI.dim, `${marker} ${ansi(ANSI.dim, `${num}. ${label}: ${step.action}`)}`);\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tconst marker = ansi(ANSI.gray, \"○\");\n\t\t\t\treturn ansi(ANSI.dim, `${marker} ${ansi(ANSI.dim, `${num}. ${label}: ${step.action}`)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Wraps content text as a box row. */\n\tprivate wrapLine(bc: (s: string) => string, content: string, innerWidth: number): string {\n\t\tconst truncated = truncateToWidth(content, innerWidth);\n\t\tconst pad = Math.max(innerWidth - visibleWidth(truncated), 0);\n\t\treturn `${bc(\"│\")} ${truncated}${\" \".repeat(pad)} ${bc(\"│\")}`;\n\t}\n}\n"]}
|
package/dist/pipeline.d.ts
CHANGED
|
@@ -29,12 +29,10 @@ export interface StepContext {
|
|
|
29
29
|
onAgentFinished?: () => void;
|
|
30
30
|
/** Logger. Uses noop if not specified. */
|
|
31
31
|
logger?: VibeLogger;
|
|
32
|
-
/** Lightweight skill index. Included in the agent system prompt. */
|
|
33
|
-
availableSkills?: string;
|
|
34
|
-
/** Project context (from project-context.md). Injected into system prompt for project awareness. */
|
|
35
|
-
projectContext?: string;
|
|
36
32
|
/** Mutable. Set by StepExecutor after agent completion. Read by PipelineRunner for event data. */
|
|
37
33
|
lastStepUsage?: StepUsage;
|
|
34
|
+
/** Mutable. Set by StepExecutor after agent completion. Last assistant response text. */
|
|
35
|
+
lastStepResponseText?: string;
|
|
38
36
|
}
|
|
39
37
|
/** Step execution function. Called by the pipeline engine for each step. */
|
|
40
38
|
export type StepExecutor = (step: PipelineStep, featureId: string, context: StepContext) => Promise<void>;
|
|
@@ -54,10 +52,6 @@ export interface PipelineRunnerOptions {
|
|
|
54
52
|
onAgentFinished?: () => void;
|
|
55
53
|
/** Logger. Uses noop if not specified. */
|
|
56
54
|
logger?: VibeLogger;
|
|
57
|
-
/** Lightweight skill index. Included in the agent system prompt. */
|
|
58
|
-
availableSkills?: string;
|
|
59
|
-
/** Project context (from project-context.md). Injected into system prompt for project awareness. */
|
|
60
|
-
projectContext?: string;
|
|
61
55
|
/** Custom retry delay function for step execution retries. Defaults to exponential backoff. */
|
|
62
56
|
retryDelayFn?: RetryDelayFn;
|
|
63
57
|
}
|
|
@@ -87,8 +81,6 @@ export declare class PipelineRunner {
|
|
|
87
81
|
private readonly onAgentFinished?;
|
|
88
82
|
private readonly log;
|
|
89
83
|
private readonly logger?;
|
|
90
|
-
private readonly availableSkills?;
|
|
91
|
-
private readonly projectContext?;
|
|
92
84
|
private readonly retryDelayFn;
|
|
93
85
|
private paused;
|
|
94
86
|
private aborted;
|
package/dist/pipeline.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Agent } from \"@mariozechner/pi-agent-core\";\nimport type { Model } from \"@mariozechner/pi-ai\";\nimport type { GetApiKeyFn } from \"./agent-factory.js\";\nimport type { ApprovalRequestFn } from \"./gate.js\";\nimport { GateChecker } from \"./gate.js\";\nimport { createModuleLogger, type ModuleLogger, noopLogger, type VibeLogger } from \"./logger.js\";\nimport { defaultStepExecutor } from \"./step-executor.js\";\nimport type { VibeStore } from \"./store.js\";\nimport type {\n\tAgentRole,\n\tFeaturePipeline,\n\tFeatureStatusValue,\n\tPersistedPipeline,\n\tPipelineStep,\n\tVibeConfig,\n\tVibeEvent,\n} from \"./types.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Aggregated token usage for a single pipeline step. */\nexport interface StepUsage {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\ttotalTokens: number;\n\t/** Total cost in USD. */\n\tcost: number;\n}\n\n/** Context required for step execution */\nexport interface StepContext {\n\tstore: VibeStore;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Model to use. Uses the Agent's default model if not specified. */\n\tmodel?: Model<any>;\n\t/** Called immediately after agent creation. Allows external code to acquire an Agent reference. */\n\tonAgentCreated?: (agent: Agent) => void;\n\t/** Called after agent execution completes (success/error). Allows releasing the Agent reference. */\n\tonAgentFinished?: () => void;\n\t/** Logger. Uses noop if not specified. */\n\tlogger?: VibeLogger;\n\t/** Lightweight skill index. Included in the agent system prompt. */\n\tavailableSkills?: string;\n\t/** Project context (from project-context.md). Injected into system prompt for project awareness. */\n\tprojectContext?: string;\n\t/** Mutable. Set by StepExecutor after agent completion. Read by PipelineRunner for event data. */\n\tlastStepUsage?: StepUsage;\n}\n\n/** Step execution function. Called by the pipeline engine for each step. */\nexport type StepExecutor = (step: PipelineStep, featureId: string, context: StepContext) => Promise<void>;\n\n/** Pipeline execution options */\nexport interface PipelineRunnerOptions {\n\tstore: VibeStore;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\trequestApproval?: ApprovalRequestFn;\n\tstepExecutor?: StepExecutor;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Model to use. Uses the Agent's default model if not specified. */\n\tmodel?: Model<any>;\n\t/** Called immediately after agent creation. Allows acquiring an Agent reference during execution. */\n\tonAgentCreated?: (agent: Agent) => void;\n\t/** Called after agent execution completes. Allows releasing the Agent reference. */\n\tonAgentFinished?: () => void;\n\t/** Logger. Uses noop if not specified. */\n\tlogger?: VibeLogger;\n\t/** Lightweight skill index. Included in the agent system prompt. */\n\tavailableSkills?: string;\n\t/** Project context (from project-context.md). Injected into system prompt for project awareness. */\n\tprojectContext?: string;\n\t/** Custom retry delay function for step execution retries. Defaults to exponential backoff. */\n\tretryDelayFn?: RetryDelayFn;\n}\n\n// ─── Status Mapping ──────────────────────────────────────────────────────────\n\n/** Maps agent role (+ optional action) to FeatureStatusValue */\nexport function agentRoleToFeatureStatus(role: AgentRole, action?: string): FeatureStatusValue {\n\tswitch (role) {\n\t\tcase \"planner\":\n\t\t\treturn \"planned\";\n\t\tcase \"architect\":\n\t\t\treturn \"designing\";\n\t\tcase \"developer\":\n\t\t\treturn \"implementing\";\n\t\tcase \"tester\":\n\t\t\treturn \"testing\";\n\t\tcase \"reviewer\":\n\t\t\treturn \"reviewing\";\n\t\tcase \"cicd\":\n\t\t\treturn action === \"merge\" ? \"merging\" : \"branching\";\n\t\tcase \"analyzer\":\n\t\t\treturn \"designing\";\n\t\tcase \"diagnostician\":\n\t\t\treturn \"designing\";\n\t\tcase \"discovery\":\n\t\t\treturn \"planned\";\n\t\tcase \"projectAnalyzer\":\n\t\t\treturn \"planned\";\n\t\tcase \"documenter\":\n\t\t\treturn \"done\";\n\t\tcase \"standardsEnricher\":\n\t\t\treturn \"planned\";\n\t\tcase \"systemArchitect\":\n\t\t\treturn \"designing\";\n\t}\n}\n\n// ─── Retry Helpers ───────────────────────────────────────────────────────────\n\n/**\n * Pattern matching transient errors that should be retried.\n * Covers: undici fetch \"terminated\", HTTP 5xx, rate limits, connection errors.\n */\nconst RETRYABLE_ERROR_PATTERN =\n\t/terminated|overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|retry delay|ECONNRESET|ETIMEDOUT|EPIPE|EAI_AGAIN/i;\n\n/** Returns true if the error message indicates a transient failure worth retrying. */\nexport function isRetryableStepError(errorMessage: string): boolean {\n\treturn RETRYABLE_ERROR_PATTERN.test(errorMessage);\n}\n\n/** Default exponential backoff delay in ms: base * 2^attempt, capped at 60s. */\nexport function defaultRetryDelay(attempt: number): number {\n\tconst base = 5000;\n\tconst maxDelay = 60000;\n\treturn Math.min(base * 2 ** attempt, maxDelay);\n}\n\n/** Retry delay function signature. */\nexport type RetryDelayFn = (attempt: number) => number;\n\n// ─── Helper ──────────────────────────────────────────────────────────────────\n\nfunction createEvent(\n\ttype: VibeEvent[\"type\"],\n\tfeatureId: string,\n\tstep?: PipelineStep,\n\tdata?: Record<string, unknown>,\n): VibeEvent {\n\treturn {\n\t\ttype,\n\t\tfeatureId,\n\t\ttimestamp: new Date().toISOString(),\n\t\tstep,\n\t\tdata,\n\t};\n}\n\n// ─── Persistence Helpers ─────────────────────────────────────────────────────\n\n/** Creates a PersistedPipeline from a FeaturePipeline. */\nexport function toPersisted(pipeline: FeaturePipeline): PersistedPipeline {\n\treturn {\n\t\tfeatureId: pipeline.featureId,\n\t\tworkflowType: pipeline.workflowType,\n\t\tcurrentStep: pipeline.currentStep,\n\t\tstatus: pipeline.status,\n\t\tretryCount: pipeline.retryCount,\n\t\tmaxRetries: pipeline.maxRetries,\n\t\tparentFeatureId: pipeline.parentFeatureId,\n\t\tissueRef: pipeline.issueRef,\n\t};\n}\n\n// ─── PipelineRunner ──────────────────────────────────────────────────────────\n\n/**\n * Pipeline runner. Sequentially executes FeaturePipeline steps and emits events.\n */\nexport class PipelineRunner {\n\tprivate readonly store: VibeStore;\n\tprivate readonly config: VibeConfig;\n\tprivate readonly projectRoot: string;\n\tprivate readonly requestApproval?: ApprovalRequestFn;\n\tprivate readonly stepExecutor: StepExecutor;\n\tprivate readonly gateChecker: GateChecker;\n\tprivate readonly getApiKey?: GetApiKeyFn;\n\tprivate readonly model?: Model<any>;\n\tprivate readonly onAgentCreated?: (agent: Agent) => void;\n\tprivate readonly onAgentFinished?: () => void;\n\tprivate readonly log: ModuleLogger;\n\tprivate readonly logger?: VibeLogger;\n\tprivate readonly availableSkills?: string;\n\tprivate readonly projectContext?: string;\n\tprivate readonly retryDelayFn: RetryDelayFn;\n\n\tprivate paused = false;\n\tprivate aborted = false;\n\n\tconstructor(options: PipelineRunnerOptions) {\n\t\tthis.store = options.store;\n\t\tthis.config = options.config;\n\t\tthis.projectRoot = options.projectRoot;\n\t\tthis.requestApproval = options.requestApproval;\n\t\tthis.stepExecutor = options.stepExecutor ?? defaultStepExecutor;\n\t\tthis.getApiKey = options.getApiKey;\n\t\tthis.model = options.model;\n\t\tthis.onAgentCreated = options.onAgentCreated;\n\t\tthis.onAgentFinished = options.onAgentFinished;\n\t\tthis.logger = options.logger;\n\t\tthis.availableSkills = options.availableSkills;\n\t\tthis.projectContext = options.projectContext;\n\t\tthis.retryDelayFn = options.retryDelayFn ?? defaultRetryDelay;\n\t\tthis.log = createModuleLogger(options.logger ?? noopLogger, \"pipeline\");\n\t\tthis.gateChecker = new GateChecker(this.store, this.config, this.model, options.logger);\n\t}\n\n\t/**\n\t * Runs the pipeline and yields events.\n\t */\n\tasync *run(pipeline: FeaturePipeline): AsyncGenerator<VibeEvent> {\n\t\tthis.paused = false;\n\t\tthis.aborted = false;\n\t\tpipeline.status = \"running\";\n\t\tthis.log.info(`Pipeline started: ${pipeline.featureId}`, {\n\t\t\tfeatureId: pipeline.featureId,\n\t\t\tworkflowType: pipeline.workflowType,\n\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\tcurrentStep: pipeline.currentStep,\n\t\t});\n\n\t\tconst context: StepContext = {\n\t\t\tstore: this.store,\n\t\t\tconfig: this.config,\n\t\t\tprojectRoot: this.projectRoot,\n\t\t\tgetApiKey: this.getApiKey,\n\t\t\tmodel: this.model,\n\t\t\tonAgentCreated: this.onAgentCreated,\n\t\t\tonAgentFinished: this.onAgentFinished,\n\t\t\tlogger: this.logger,\n\t\t\tavailableSkills: this.availableSkills,\n\t\t\tprojectContext: this.projectContext,\n\t\t};\n\n\t\tfor (let i = pipeline.currentStep; i < pipeline.steps.length; i++) {\n\t\t\tif (this.aborted) {\n\t\t\t\tthis.log.warn(\"Pipeline aborted\", { featureId: pipeline.featureId, step: i });\n\t\t\t\tpipeline.status = \"failed\";\n\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\tyield createEvent(\"step_failed\", pipeline.featureId, pipeline.steps[i], {\n\t\t\t\t\treason: \"aborted\",\n\t\t\t\t\tstepIndex: i,\n\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.paused) {\n\t\t\t\tthis.log.info(\"Pipeline paused\", { featureId: pipeline.featureId, step: i });\n\t\t\t\tpipeline.status = \"blocked\";\n\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\tyield createEvent(\"blocked\", pipeline.featureId, pipeline.steps[i], { reason: \"paused\" });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst step = pipeline.steps[i];\n\n\t\t\t// Handle skip\n\t\t\tif (step.skip) {\n\t\t\t\tpipeline.currentStep = i + 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// step_start event\n\t\t\tyield createEvent(\"step_start\", pipeline.featureId, step, {\n\t\t\t\tagent: step.agent,\n\t\t\t\tinputs: step.inputs,\n\t\t\t\tstepIndex: i,\n\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t});\n\n\t\t\t// Update status\n\t\t\tconst featureStatus = agentRoleToFeatureStatus(step.agent, step.action);\n\t\t\ttry {\n\t\t\t\tawait this.store.updateFeatureStatus(pipeline.featureId, featureStatus);\n\t\t\t} catch {\n\t\t\t\t// Ignore status transition failure (may already be in this state)\n\t\t\t}\n\n\t\t\t// Execute step (with retry for transient errors)\n\t\t\tthis.log.info(`Step executing: ${step.agent}:${step.action}`, { featureId: pipeline.featureId, step: i });\n\t\t\tconst maxStepRetries = this.config.retry.maxStepRetries ?? 2;\n\t\t\tlet stepAttempt = 0;\n\t\t\tconst startTime = Date.now();\n\n\t\t\twhile (stepAttempt <= maxStepRetries) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.stepExecutor(step, pipeline.featureId, context);\n\t\t\t\t\tbreak;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\tconst errorStack = error instanceof Error ? error.stack : undefined;\n\t\t\t\t\tconst errorCause = error instanceof Error ? error.cause : undefined;\n\n\t\t\t\t\tif (stepAttempt < maxStepRetries && isRetryableStepError(errorMsg)) {\n\t\t\t\t\t\tstepAttempt++;\n\t\t\t\t\t\tconst delay = this.retryDelayFn(stepAttempt - 1);\n\t\t\t\t\t\tthis.log.warn(\n\t\t\t\t\t\t\t`Step error (retryable), retry ${stepAttempt}/${maxStepRetries} after ${delay}ms: ${step.agent}:${step.action}: ${errorMsg}`,\n\t\t\t\t\t\t\t{ featureId: pipeline.featureId, step: i, attempt: stepAttempt, cause: errorCause },\n\t\t\t\t\t\t);\n\t\t\t\t\t\tyield createEvent(\"step_retry\", pipeline.featureId, step, {\n\t\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t\t\tattempt: stepAttempt,\n\t\t\t\t\t\t\tmaxRetries: maxStepRetries,\n\t\t\t\t\t\t\tdelayMs: delay,\n\t\t\t\t\t\t\tstepIndex: i,\n\t\t\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.log.error(`Step failed: ${step.agent}:${step.action}: ${errorMsg}`, {\n\t\t\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\t\t\tstep: i,\n\t\t\t\t\t\tstack: errorStack,\n\t\t\t\t\t\tcause: errorCause,\n\t\t\t\t\t\tattempts: stepAttempt + 1,\n\t\t\t\t\t});\n\t\t\t\t\tpipeline.status = \"failed\";\n\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\tyield createEvent(\"step_failed\", pipeline.featureId, step, {\n\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t\tstepIndex: i,\n\t\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t\t\tattempts: stepAttempt + 1,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst elapsed = Date.now() - startTime;\n\t\t\tthis.log.info(`Step completed: ${step.agent}:${step.action} (${elapsed}ms)`, {\n\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\tstep: i,\n\t\t\t});\n\n\t\t\t// Gate validation\n\t\t\tif (step.gate) {\n\t\t\t\tconst gateResult = await this.gateChecker.evaluate(step, pipeline.featureId, this.requestApproval);\n\n\t\t\t\tif (!gateResult.passed) {\n\t\t\t\t\tif (gateResult.action === \"abort\") {\n\t\t\t\t\t\tthis.log.warn(`Gate abort: ${step.gate.type}`, { featureId: pipeline.featureId });\n\t\t\t\t\t\tpipeline.status = \"aborted\";\n\t\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\t\t// Delete feature artifacts\n\t\t\t\t\t\tawait this.store.clearFeatureDir(pipeline.featureId);\n\t\t\t\t\t\tyield createEvent(\"feature_aborted\", pipeline.featureId, step, {\n\t\t\t\t\t\t\taction: gateResult.action,\n\t\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.log.warn(\n\t\t\t\t\t\t`Gate rejected: ${step.gate.type}, retry ${pipeline.retryCount + 1}/${pipeline.maxRetries}`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tpipeline.status = \"blocked\";\n\t\t\t\t\tpipeline.retryCount++;\n\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\tyield createEvent(\"gate_rejected\", pipeline.featureId, step, {\n\t\t\t\t\t\taction: gateResult.action,\n\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (pipeline.retryCount >= pipeline.maxRetries) {\n\t\t\t\t\t\tyield createEvent(\"blocked\", pipeline.featureId, step, {\n\t\t\t\t\t\t\treason: \"max retries exceeded\",\n\t\t\t\t\t\t\tretryCount: pipeline.retryCount,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// On gate failure, do not increment currentStep so this step is re-executed\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Distinguish Skip vs Approve\n\t\t\t\tif (gateResult.action === \"skip\") {\n\t\t\t\t\tyield createEvent(\"gate_skipped\", pipeline.featureId, step);\n\t\t\t\t} else {\n\t\t\t\t\tyield createEvent(\"gate_approved\", pipeline.featureId, step);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// step_complete event\n\t\t\tyield createEvent(\"step_complete\", pipeline.featureId, step, {\n\t\t\t\toutputs: step.outputs,\n\t\t\t\telapsed,\n\t\t\t\tstepIndex: i,\n\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\tusage: context.lastStepUsage,\n\t\t\t});\n\t\t\tcontext.lastStepUsage = undefined;\n\n\t\t\tpipeline.currentStep = i + 1;\n\n\t\t\t// Persist pipeline state on step completion\n\t\t\tawait this.persistPipeline(pipeline);\n\t\t}\n\n\t\t// All steps completed\n\t\tthis.log.info(`Pipeline completed: ${pipeline.featureId}`, { featureId: pipeline.featureId });\n\t\tpipeline.status = \"done\";\n\t\tawait this.persistPipeline(pipeline);\n\t\ttry {\n\t\t\tawait this.store.updateFeatureStatus(pipeline.featureId, \"done\");\n\t\t} catch {\n\t\t\t// Ignore status transition failure\n\t\t}\n\t\tyield createEvent(\"pipeline_complete\", pipeline.featureId);\n\t}\n\n\t/**\n\t * Resumes the pipeline. Continues execution from currentStep.\n\t */\n\tasync *resume(pipeline: FeaturePipeline): AsyncGenerator<VibeEvent> {\n\t\tyield* this.run(pipeline);\n\t}\n\n\t/** Pauses after the current step completes. */\n\tpause(): void {\n\t\tthis.paused = true;\n\t}\n\n\t/** Aborts immediately. */\n\tabort(): void {\n\t\tthis.aborted = true;\n\t}\n\n\t/** Persists the pipeline state to disk. */\n\tprivate async persistPipeline(pipeline: FeaturePipeline): Promise<void> {\n\t\ttry {\n\t\t\tawait this.store.savePipelineState(pipeline.featureId, toPersisted(pipeline));\n\t\t\tthis.log.debug(\"Pipeline state persisted\", {\n\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\tstatus: pipeline.status,\n\t\t\t\tcurrentStep: pipeline.currentStep,\n\t\t\t});\n\t\t} catch {\n\t\t\tthis.log.warn(\"Pipeline state persistence failed\", { featureId: pipeline.featureId });\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Agent } from \"@mariozechner/pi-agent-core\";\nimport type { Model } from \"@mariozechner/pi-ai\";\nimport type { GetApiKeyFn } from \"./agent-factory.js\";\nimport type { ApprovalRequestFn } from \"./gate.js\";\nimport { GateChecker } from \"./gate.js\";\nimport { createModuleLogger, type ModuleLogger, noopLogger, type VibeLogger } from \"./logger.js\";\nimport { defaultStepExecutor } from \"./step-executor.js\";\nimport type { VibeStore } from \"./store.js\";\nimport type {\n\tAgentRole,\n\tFeaturePipeline,\n\tFeatureStatusValue,\n\tPersistedPipeline,\n\tPipelineStep,\n\tVibeConfig,\n\tVibeEvent,\n} from \"./types.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Aggregated token usage for a single pipeline step. */\nexport interface StepUsage {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\ttotalTokens: number;\n\t/** Total cost in USD. */\n\tcost: number;\n}\n\n/** Context required for step execution */\nexport interface StepContext {\n\tstore: VibeStore;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Model to use. Uses the Agent's default model if not specified. */\n\tmodel?: Model<any>;\n\t/** Called immediately after agent creation. Allows external code to acquire an Agent reference. */\n\tonAgentCreated?: (agent: Agent) => void;\n\t/** Called after agent execution completes (success/error). Allows releasing the Agent reference. */\n\tonAgentFinished?: () => void;\n\t/** Logger. Uses noop if not specified. */\n\tlogger?: VibeLogger;\n\t/** Mutable. Set by StepExecutor after agent completion. Read by PipelineRunner for event data. */\n\tlastStepUsage?: StepUsage;\n\t/** Mutable. Set by StepExecutor after agent completion. Last assistant response text. */\n\tlastStepResponseText?: string;\n}\n\n/** Step execution function. Called by the pipeline engine for each step. */\nexport type StepExecutor = (step: PipelineStep, featureId: string, context: StepContext) => Promise<void>;\n\n/** Pipeline execution options */\nexport interface PipelineRunnerOptions {\n\tstore: VibeStore;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\trequestApproval?: ApprovalRequestFn;\n\tstepExecutor?: StepExecutor;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Model to use. Uses the Agent's default model if not specified. */\n\tmodel?: Model<any>;\n\t/** Called immediately after agent creation. Allows acquiring an Agent reference during execution. */\n\tonAgentCreated?: (agent: Agent) => void;\n\t/** Called after agent execution completes. Allows releasing the Agent reference. */\n\tonAgentFinished?: () => void;\n\t/** Logger. Uses noop if not specified. */\n\tlogger?: VibeLogger;\n\t/** Custom retry delay function for step execution retries. Defaults to exponential backoff. */\n\tretryDelayFn?: RetryDelayFn;\n}\n\n// ─── Status Mapping ──────────────────────────────────────────────────────────\n\n/** Maps agent role (+ optional action) to FeatureStatusValue */\nexport function agentRoleToFeatureStatus(role: AgentRole, action?: string): FeatureStatusValue {\n\tswitch (role) {\n\t\tcase \"planner\":\n\t\t\treturn \"planned\";\n\t\tcase \"architect\":\n\t\t\treturn \"designing\";\n\t\tcase \"developer\":\n\t\t\treturn \"implementing\";\n\t\tcase \"tester\":\n\t\t\treturn \"testing\";\n\t\tcase \"reviewer\":\n\t\t\treturn \"reviewing\";\n\t\tcase \"cicd\":\n\t\t\treturn action === \"merge\" ? \"merging\" : \"branching\";\n\t\tcase \"analyzer\":\n\t\t\treturn \"designing\";\n\t\tcase \"diagnostician\":\n\t\t\treturn \"designing\";\n\t\tcase \"discovery\":\n\t\t\treturn \"planned\";\n\t\tcase \"projectAnalyzer\":\n\t\t\treturn \"planned\";\n\t\tcase \"documenter\":\n\t\t\treturn \"done\";\n\t\tcase \"standardsEnricher\":\n\t\t\treturn \"planned\";\n\t\tcase \"systemArchitect\":\n\t\t\treturn \"designing\";\n\t\tcase \"recover\":\n\t\t\treturn \"planned\";\n\t}\n}\n\n// ─── Retry Helpers ───────────────────────────────────────────────────────────\n\n/**\n * Pattern matching transient errors that should be retried.\n * Covers: undici fetch \"terminated\", HTTP 5xx, rate limits, connection errors.\n */\nconst RETRYABLE_ERROR_PATTERN =\n\t/terminated|overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|retry delay|ECONNRESET|ETIMEDOUT|EPIPE|EAI_AGAIN/i;\n\n/** Returns true if the error message indicates a transient failure worth retrying. */\nexport function isRetryableStepError(errorMessage: string): boolean {\n\treturn RETRYABLE_ERROR_PATTERN.test(errorMessage);\n}\n\n/** Default exponential backoff delay in ms: base * 2^attempt, capped at 60s. */\nexport function defaultRetryDelay(attempt: number): number {\n\tconst base = 5000;\n\tconst maxDelay = 60000;\n\treturn Math.min(base * 2 ** attempt, maxDelay);\n}\n\n/** Retry delay function signature. */\nexport type RetryDelayFn = (attempt: number) => number;\n\n// ─── Helper ──────────────────────────────────────────────────────────────────\n\nfunction createEvent(\n\ttype: VibeEvent[\"type\"],\n\tfeatureId: string,\n\tstep?: PipelineStep,\n\tdata?: Record<string, unknown>,\n): VibeEvent {\n\treturn {\n\t\ttype,\n\t\tfeatureId,\n\t\ttimestamp: new Date().toISOString(),\n\t\tstep,\n\t\tdata,\n\t};\n}\n\n// ─── Persistence Helpers ─────────────────────────────────────────────────────\n\n/** Creates a PersistedPipeline from a FeaturePipeline. */\nexport function toPersisted(pipeline: FeaturePipeline): PersistedPipeline {\n\treturn {\n\t\tfeatureId: pipeline.featureId,\n\t\tworkflowType: pipeline.workflowType,\n\t\tcurrentStep: pipeline.currentStep,\n\t\tstatus: pipeline.status,\n\t\tretryCount: pipeline.retryCount,\n\t\tmaxRetries: pipeline.maxRetries,\n\t\tparentFeatureId: pipeline.parentFeatureId,\n\t\tissueRef: pipeline.issueRef,\n\t};\n}\n\n// ─── PipelineRunner ──────────────────────────────────────────────────────────\n\n/**\n * Pipeline runner. Sequentially executes FeaturePipeline steps and emits events.\n */\nexport class PipelineRunner {\n\tprivate readonly store: VibeStore;\n\tprivate readonly config: VibeConfig;\n\tprivate readonly projectRoot: string;\n\tprivate readonly requestApproval?: ApprovalRequestFn;\n\tprivate readonly stepExecutor: StepExecutor;\n\tprivate readonly gateChecker: GateChecker;\n\tprivate readonly getApiKey?: GetApiKeyFn;\n\tprivate readonly model?: Model<any>;\n\tprivate readonly onAgentCreated?: (agent: Agent) => void;\n\tprivate readonly onAgentFinished?: () => void;\n\tprivate readonly log: ModuleLogger;\n\tprivate readonly logger?: VibeLogger;\n\tprivate readonly retryDelayFn: RetryDelayFn;\n\n\tprivate paused = false;\n\tprivate aborted = false;\n\n\tconstructor(options: PipelineRunnerOptions) {\n\t\tthis.store = options.store;\n\t\tthis.config = options.config;\n\t\tthis.projectRoot = options.projectRoot;\n\t\tthis.requestApproval = options.requestApproval;\n\t\tthis.stepExecutor = options.stepExecutor ?? defaultStepExecutor;\n\t\tthis.getApiKey = options.getApiKey;\n\t\tthis.model = options.model;\n\t\tthis.onAgentCreated = options.onAgentCreated;\n\t\tthis.onAgentFinished = options.onAgentFinished;\n\t\tthis.logger = options.logger;\n\t\tthis.retryDelayFn = options.retryDelayFn ?? defaultRetryDelay;\n\t\tthis.log = createModuleLogger(options.logger ?? noopLogger, \"pipeline\");\n\t\tthis.gateChecker = new GateChecker(this.store, this.config, this.model, options.logger);\n\t}\n\n\t/**\n\t * Runs the pipeline and yields events.\n\t */\n\tasync *run(pipeline: FeaturePipeline): AsyncGenerator<VibeEvent> {\n\t\tthis.paused = false;\n\t\tthis.aborted = false;\n\t\tpipeline.status = \"running\";\n\t\tthis.log.info(`Pipeline started: ${pipeline.featureId}`, {\n\t\t\tfeatureId: pipeline.featureId,\n\t\t\tworkflowType: pipeline.workflowType,\n\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\tcurrentStep: pipeline.currentStep,\n\t\t});\n\n\t\tconst context: StepContext = {\n\t\t\tstore: this.store,\n\t\t\tconfig: this.config,\n\t\t\tprojectRoot: this.projectRoot,\n\t\t\tgetApiKey: this.getApiKey,\n\t\t\tmodel: this.model,\n\t\t\tonAgentCreated: this.onAgentCreated,\n\t\t\tonAgentFinished: this.onAgentFinished,\n\t\t\tlogger: this.logger,\n\t\t};\n\n\t\tfor (let i = pipeline.currentStep; i < pipeline.steps.length; i++) {\n\t\t\tif (this.aborted) {\n\t\t\t\tthis.log.warn(\"Pipeline aborted\", { featureId: pipeline.featureId, step: i });\n\t\t\t\tpipeline.status = \"failed\";\n\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\tyield createEvent(\"step_failed\", pipeline.featureId, pipeline.steps[i], {\n\t\t\t\t\treason: \"aborted\",\n\t\t\t\t\tstepIndex: i,\n\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.paused) {\n\t\t\t\tthis.log.info(\"Pipeline paused\", { featureId: pipeline.featureId, step: i });\n\t\t\t\tpipeline.status = \"blocked\";\n\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\tyield createEvent(\"blocked\", pipeline.featureId, pipeline.steps[i], { reason: \"paused\" });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst step = pipeline.steps[i];\n\n\t\t\t// Handle skip\n\t\t\tif (step.skip) {\n\t\t\t\tpipeline.currentStep = i + 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// step_start event\n\t\t\tyield createEvent(\"step_start\", pipeline.featureId, step, {\n\t\t\t\tagent: step.agent,\n\t\t\t\tinputs: step.inputs,\n\t\t\t\tstepIndex: i,\n\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t});\n\n\t\t\t// Update status\n\t\t\tconst featureStatus = agentRoleToFeatureStatus(step.agent, step.action);\n\t\t\ttry {\n\t\t\t\tawait this.store.updateFeatureStatus(pipeline.featureId, featureStatus);\n\t\t\t} catch {\n\t\t\t\t// Ignore status transition failure (may already be in this state)\n\t\t\t}\n\n\t\t\t// Execute step (with retry for transient errors)\n\t\t\tthis.log.info(`Step executing: ${step.agent}:${step.action}`, { featureId: pipeline.featureId, step: i });\n\t\t\tconst maxStepRetries = this.config.retry.maxStepRetries ?? 2;\n\t\t\tlet stepAttempt = 0;\n\t\t\tconst startTime = Date.now();\n\n\t\t\twhile (stepAttempt <= maxStepRetries) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.stepExecutor(step, pipeline.featureId, context);\n\t\t\t\t\tbreak;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\tconst errorStack = error instanceof Error ? error.stack : undefined;\n\t\t\t\t\tconst errorCause = error instanceof Error ? error.cause : undefined;\n\n\t\t\t\t\tif (stepAttempt < maxStepRetries && isRetryableStepError(errorMsg)) {\n\t\t\t\t\t\tstepAttempt++;\n\t\t\t\t\t\tconst delay = this.retryDelayFn(stepAttempt - 1);\n\t\t\t\t\t\tthis.log.warn(\n\t\t\t\t\t\t\t`Step error (retryable), retry ${stepAttempt}/${maxStepRetries} after ${delay}ms: ${step.agent}:${step.action}: ${errorMsg}`,\n\t\t\t\t\t\t\t{ featureId: pipeline.featureId, step: i, attempt: stepAttempt, cause: errorCause },\n\t\t\t\t\t\t);\n\t\t\t\t\t\tyield createEvent(\"step_retry\", pipeline.featureId, step, {\n\t\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t\t\tattempt: stepAttempt,\n\t\t\t\t\t\t\tmaxRetries: maxStepRetries,\n\t\t\t\t\t\t\tdelayMs: delay,\n\t\t\t\t\t\t\tstepIndex: i,\n\t\t\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.log.error(`Step failed: ${step.agent}:${step.action}: ${errorMsg}`, {\n\t\t\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\t\t\tstep: i,\n\t\t\t\t\t\tstack: errorStack,\n\t\t\t\t\t\tcause: errorCause,\n\t\t\t\t\t\tattempts: stepAttempt + 1,\n\t\t\t\t\t});\n\t\t\t\t\tpipeline.status = \"failed\";\n\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\tyield createEvent(\"step_failed\", pipeline.featureId, step, {\n\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t\tstepIndex: i,\n\t\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t\t\tattempts: stepAttempt + 1,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst elapsed = Date.now() - startTime;\n\t\t\tthis.log.info(`Step completed: ${step.agent}:${step.action} (${elapsed}ms)`, {\n\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\tstep: i,\n\t\t\t});\n\n\t\t\t// Gate validation\n\t\t\tif (step.gate) {\n\t\t\t\tconst gateResult = await this.gateChecker.evaluate(step, pipeline.featureId, this.requestApproval);\n\n\t\t\t\tif (!gateResult.passed) {\n\t\t\t\t\tif (gateResult.action === \"abort\") {\n\t\t\t\t\t\tthis.log.warn(`Gate abort: ${step.gate.type}`, { featureId: pipeline.featureId });\n\t\t\t\t\t\tpipeline.status = \"aborted\";\n\t\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\t\t// Delete feature artifacts\n\t\t\t\t\t\tawait this.store.clearFeatureDir(pipeline.featureId);\n\t\t\t\t\t\tyield createEvent(\"feature_aborted\", pipeline.featureId, step, {\n\t\t\t\t\t\t\taction: gateResult.action,\n\t\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.log.warn(\n\t\t\t\t\t\t`Gate rejected: ${step.gate.type}, retry ${pipeline.retryCount + 1}/${pipeline.maxRetries}`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tpipeline.status = \"blocked\";\n\t\t\t\t\tpipeline.retryCount++;\n\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\tyield createEvent(\"gate_rejected\", pipeline.featureId, step, {\n\t\t\t\t\t\taction: gateResult.action,\n\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (pipeline.retryCount >= pipeline.maxRetries) {\n\t\t\t\t\t\tyield createEvent(\"blocked\", pipeline.featureId, step, {\n\t\t\t\t\t\t\treason: \"max retries exceeded\",\n\t\t\t\t\t\t\tretryCount: pipeline.retryCount,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// On gate failure, do not increment currentStep so this step is re-executed\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Distinguish Skip vs Approve\n\t\t\t\tif (gateResult.action === \"skip\") {\n\t\t\t\t\tyield createEvent(\"gate_skipped\", pipeline.featureId, step);\n\t\t\t\t} else {\n\t\t\t\t\tyield createEvent(\"gate_approved\", pipeline.featureId, step);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// step_complete event\n\t\t\tyield createEvent(\"step_complete\", pipeline.featureId, step, {\n\t\t\t\toutputs: step.outputs,\n\t\t\t\telapsed,\n\t\t\t\tstepIndex: i,\n\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\tusage: context.lastStepUsage,\n\t\t\t\tresponseText: context.lastStepResponseText,\n\t\t\t});\n\t\t\tcontext.lastStepUsage = undefined;\n\t\t\tcontext.lastStepResponseText = undefined;\n\n\t\t\tpipeline.currentStep = i + 1;\n\n\t\t\t// Persist pipeline state on step completion\n\t\t\tawait this.persistPipeline(pipeline);\n\t\t}\n\n\t\t// All steps completed\n\t\tthis.log.info(`Pipeline completed: ${pipeline.featureId}`, { featureId: pipeline.featureId });\n\t\tpipeline.status = \"done\";\n\t\tawait this.persistPipeline(pipeline);\n\t\ttry {\n\t\t\tawait this.store.updateFeatureStatus(pipeline.featureId, \"done\");\n\t\t} catch {\n\t\t\t// Ignore status transition failure\n\t\t}\n\t\tyield createEvent(\"pipeline_complete\", pipeline.featureId);\n\t}\n\n\t/**\n\t * Resumes the pipeline. Continues execution from currentStep.\n\t */\n\tasync *resume(pipeline: FeaturePipeline): AsyncGenerator<VibeEvent> {\n\t\tyield* this.run(pipeline);\n\t}\n\n\t/** Pauses after the current step completes. */\n\tpause(): void {\n\t\tthis.paused = true;\n\t}\n\n\t/** Aborts immediately. */\n\tabort(): void {\n\t\tthis.aborted = true;\n\t}\n\n\t/** Persists the pipeline state to disk. */\n\tprivate async persistPipeline(pipeline: FeaturePipeline): Promise<void> {\n\t\ttry {\n\t\t\tawait this.store.savePipelineState(pipeline.featureId, toPersisted(pipeline));\n\t\t\tthis.log.debug(\"Pipeline state persisted\", {\n\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\tstatus: pipeline.status,\n\t\t\t\tcurrentStep: pipeline.currentStep,\n\t\t\t});\n\t\t} catch {\n\t\t\tthis.log.warn(\"Pipeline state persistence failed\", { featureId: pipeline.featureId });\n\t\t}\n\t}\n}\n"]}
|
package/dist/pipeline.js
CHANGED
|
@@ -31,6 +31,8 @@ export function agentRoleToFeatureStatus(role, action) {
|
|
|
31
31
|
return "planned";
|
|
32
32
|
case "systemArchitect":
|
|
33
33
|
return "designing";
|
|
34
|
+
case "recover":
|
|
35
|
+
return "planned";
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
// ─── Retry Helpers ───────────────────────────────────────────────────────────
|
|
@@ -90,8 +92,6 @@ export class PipelineRunner {
|
|
|
90
92
|
onAgentFinished;
|
|
91
93
|
log;
|
|
92
94
|
logger;
|
|
93
|
-
availableSkills;
|
|
94
|
-
projectContext;
|
|
95
95
|
retryDelayFn;
|
|
96
96
|
paused = false;
|
|
97
97
|
aborted = false;
|
|
@@ -106,8 +106,6 @@ export class PipelineRunner {
|
|
|
106
106
|
this.onAgentCreated = options.onAgentCreated;
|
|
107
107
|
this.onAgentFinished = options.onAgentFinished;
|
|
108
108
|
this.logger = options.logger;
|
|
109
|
-
this.availableSkills = options.availableSkills;
|
|
110
|
-
this.projectContext = options.projectContext;
|
|
111
109
|
this.retryDelayFn = options.retryDelayFn ?? defaultRetryDelay;
|
|
112
110
|
this.log = createModuleLogger(options.logger ?? noopLogger, "pipeline");
|
|
113
111
|
this.gateChecker = new GateChecker(this.store, this.config, this.model, options.logger);
|
|
@@ -134,8 +132,6 @@ export class PipelineRunner {
|
|
|
134
132
|
onAgentCreated: this.onAgentCreated,
|
|
135
133
|
onAgentFinished: this.onAgentFinished,
|
|
136
134
|
logger: this.logger,
|
|
137
|
-
availableSkills: this.availableSkills,
|
|
138
|
-
projectContext: this.projectContext,
|
|
139
135
|
};
|
|
140
136
|
for (let i = pipeline.currentStep; i < pipeline.steps.length; i++) {
|
|
141
137
|
if (this.aborted) {
|
|
@@ -281,8 +277,10 @@ export class PipelineRunner {
|
|
|
281
277
|
stepIndex: i,
|
|
282
278
|
totalSteps: pipeline.steps.length,
|
|
283
279
|
usage: context.lastStepUsage,
|
|
280
|
+
responseText: context.lastStepResponseText,
|
|
284
281
|
});
|
|
285
282
|
context.lastStepUsage = undefined;
|
|
283
|
+
context.lastStepResponseText = undefined;
|
|
286
284
|
pipeline.currentStep = i + 1;
|
|
287
285
|
// Persist pipeline state on step completion
|
|
288
286
|
await this.persistPipeline(pipeline);
|
package/dist/pipeline.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Agent } from \"@mariozechner/pi-agent-core\";\nimport type { Model } from \"@mariozechner/pi-ai\";\nimport type { GetApiKeyFn } from \"./agent-factory.js\";\nimport type { ApprovalRequestFn } from \"./gate.js\";\nimport { GateChecker } from \"./gate.js\";\nimport { createModuleLogger, type ModuleLogger, noopLogger, type VibeLogger } from \"./logger.js\";\nimport { defaultStepExecutor } from \"./step-executor.js\";\nimport type { VibeStore } from \"./store.js\";\nimport type {\n\tAgentRole,\n\tFeaturePipeline,\n\tFeatureStatusValue,\n\tPersistedPipeline,\n\tPipelineStep,\n\tVibeConfig,\n\tVibeEvent,\n} from \"./types.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Aggregated token usage for a single pipeline step. */\nexport interface StepUsage {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\ttotalTokens: number;\n\t/** Total cost in USD. */\n\tcost: number;\n}\n\n/** Context required for step execution */\nexport interface StepContext {\n\tstore: VibeStore;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Model to use. Uses the Agent's default model if not specified. */\n\tmodel?: Model<any>;\n\t/** Called immediately after agent creation. Allows external code to acquire an Agent reference. */\n\tonAgentCreated?: (agent: Agent) => void;\n\t/** Called after agent execution completes (success/error). Allows releasing the Agent reference. */\n\tonAgentFinished?: () => void;\n\t/** Logger. Uses noop if not specified. */\n\tlogger?: VibeLogger;\n\t/** Lightweight skill index. Included in the agent system prompt. */\n\tavailableSkills?: string;\n\t/** Project context (from project-context.md). Injected into system prompt for project awareness. */\n\tprojectContext?: string;\n\t/** Mutable. Set by StepExecutor after agent completion. Read by PipelineRunner for event data. */\n\tlastStepUsage?: StepUsage;\n}\n\n/** Step execution function. Called by the pipeline engine for each step. */\nexport type StepExecutor = (step: PipelineStep, featureId: string, context: StepContext) => Promise<void>;\n\n/** Pipeline execution options */\nexport interface PipelineRunnerOptions {\n\tstore: VibeStore;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\trequestApproval?: ApprovalRequestFn;\n\tstepExecutor?: StepExecutor;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Model to use. Uses the Agent's default model if not specified. */\n\tmodel?: Model<any>;\n\t/** Called immediately after agent creation. Allows acquiring an Agent reference during execution. */\n\tonAgentCreated?: (agent: Agent) => void;\n\t/** Called after agent execution completes. Allows releasing the Agent reference. */\n\tonAgentFinished?: () => void;\n\t/** Logger. Uses noop if not specified. */\n\tlogger?: VibeLogger;\n\t/** Lightweight skill index. Included in the agent system prompt. */\n\tavailableSkills?: string;\n\t/** Project context (from project-context.md). Injected into system prompt for project awareness. */\n\tprojectContext?: string;\n\t/** Custom retry delay function for step execution retries. Defaults to exponential backoff. */\n\tretryDelayFn?: RetryDelayFn;\n}\n\n// ─── Status Mapping ──────────────────────────────────────────────────────────\n\n/** Maps agent role (+ optional action) to FeatureStatusValue */\nexport function agentRoleToFeatureStatus(role: AgentRole, action?: string): FeatureStatusValue {\n\tswitch (role) {\n\t\tcase \"planner\":\n\t\t\treturn \"planned\";\n\t\tcase \"architect\":\n\t\t\treturn \"designing\";\n\t\tcase \"developer\":\n\t\t\treturn \"implementing\";\n\t\tcase \"tester\":\n\t\t\treturn \"testing\";\n\t\tcase \"reviewer\":\n\t\t\treturn \"reviewing\";\n\t\tcase \"cicd\":\n\t\t\treturn action === \"merge\" ? \"merging\" : \"branching\";\n\t\tcase \"analyzer\":\n\t\t\treturn \"designing\";\n\t\tcase \"diagnostician\":\n\t\t\treturn \"designing\";\n\t\tcase \"discovery\":\n\t\t\treturn \"planned\";\n\t\tcase \"projectAnalyzer\":\n\t\t\treturn \"planned\";\n\t\tcase \"documenter\":\n\t\t\treturn \"done\";\n\t\tcase \"standardsEnricher\":\n\t\t\treturn \"planned\";\n\t\tcase \"systemArchitect\":\n\t\t\treturn \"designing\";\n\t}\n}\n\n// ─── Retry Helpers ───────────────────────────────────────────────────────────\n\n/**\n * Pattern matching transient errors that should be retried.\n * Covers: undici fetch \"terminated\", HTTP 5xx, rate limits, connection errors.\n */\nconst RETRYABLE_ERROR_PATTERN =\n\t/terminated|overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|retry delay|ECONNRESET|ETIMEDOUT|EPIPE|EAI_AGAIN/i;\n\n/** Returns true if the error message indicates a transient failure worth retrying. */\nexport function isRetryableStepError(errorMessage: string): boolean {\n\treturn RETRYABLE_ERROR_PATTERN.test(errorMessage);\n}\n\n/** Default exponential backoff delay in ms: base * 2^attempt, capped at 60s. */\nexport function defaultRetryDelay(attempt: number): number {\n\tconst base = 5000;\n\tconst maxDelay = 60000;\n\treturn Math.min(base * 2 ** attempt, maxDelay);\n}\n\n/** Retry delay function signature. */\nexport type RetryDelayFn = (attempt: number) => number;\n\n// ─── Helper ──────────────────────────────────────────────────────────────────\n\nfunction createEvent(\n\ttype: VibeEvent[\"type\"],\n\tfeatureId: string,\n\tstep?: PipelineStep,\n\tdata?: Record<string, unknown>,\n): VibeEvent {\n\treturn {\n\t\ttype,\n\t\tfeatureId,\n\t\ttimestamp: new Date().toISOString(),\n\t\tstep,\n\t\tdata,\n\t};\n}\n\n// ─── Persistence Helpers ─────────────────────────────────────────────────────\n\n/** Creates a PersistedPipeline from a FeaturePipeline. */\nexport function toPersisted(pipeline: FeaturePipeline): PersistedPipeline {\n\treturn {\n\t\tfeatureId: pipeline.featureId,\n\t\tworkflowType: pipeline.workflowType,\n\t\tcurrentStep: pipeline.currentStep,\n\t\tstatus: pipeline.status,\n\t\tretryCount: pipeline.retryCount,\n\t\tmaxRetries: pipeline.maxRetries,\n\t\tparentFeatureId: pipeline.parentFeatureId,\n\t\tissueRef: pipeline.issueRef,\n\t};\n}\n\n// ─── PipelineRunner ──────────────────────────────────────────────────────────\n\n/**\n * Pipeline runner. Sequentially executes FeaturePipeline steps and emits events.\n */\nexport class PipelineRunner {\n\tprivate readonly store: VibeStore;\n\tprivate readonly config: VibeConfig;\n\tprivate readonly projectRoot: string;\n\tprivate readonly requestApproval?: ApprovalRequestFn;\n\tprivate readonly stepExecutor: StepExecutor;\n\tprivate readonly gateChecker: GateChecker;\n\tprivate readonly getApiKey?: GetApiKeyFn;\n\tprivate readonly model?: Model<any>;\n\tprivate readonly onAgentCreated?: (agent: Agent) => void;\n\tprivate readonly onAgentFinished?: () => void;\n\tprivate readonly log: ModuleLogger;\n\tprivate readonly logger?: VibeLogger;\n\tprivate readonly availableSkills?: string;\n\tprivate readonly projectContext?: string;\n\tprivate readonly retryDelayFn: RetryDelayFn;\n\n\tprivate paused = false;\n\tprivate aborted = false;\n\n\tconstructor(options: PipelineRunnerOptions) {\n\t\tthis.store = options.store;\n\t\tthis.config = options.config;\n\t\tthis.projectRoot = options.projectRoot;\n\t\tthis.requestApproval = options.requestApproval;\n\t\tthis.stepExecutor = options.stepExecutor ?? defaultStepExecutor;\n\t\tthis.getApiKey = options.getApiKey;\n\t\tthis.model = options.model;\n\t\tthis.onAgentCreated = options.onAgentCreated;\n\t\tthis.onAgentFinished = options.onAgentFinished;\n\t\tthis.logger = options.logger;\n\t\tthis.availableSkills = options.availableSkills;\n\t\tthis.projectContext = options.projectContext;\n\t\tthis.retryDelayFn = options.retryDelayFn ?? defaultRetryDelay;\n\t\tthis.log = createModuleLogger(options.logger ?? noopLogger, \"pipeline\");\n\t\tthis.gateChecker = new GateChecker(this.store, this.config, this.model, options.logger);\n\t}\n\n\t/**\n\t * Runs the pipeline and yields events.\n\t */\n\tasync *run(pipeline: FeaturePipeline): AsyncGenerator<VibeEvent> {\n\t\tthis.paused = false;\n\t\tthis.aborted = false;\n\t\tpipeline.status = \"running\";\n\t\tthis.log.info(`Pipeline started: ${pipeline.featureId}`, {\n\t\t\tfeatureId: pipeline.featureId,\n\t\t\tworkflowType: pipeline.workflowType,\n\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\tcurrentStep: pipeline.currentStep,\n\t\t});\n\n\t\tconst context: StepContext = {\n\t\t\tstore: this.store,\n\t\t\tconfig: this.config,\n\t\t\tprojectRoot: this.projectRoot,\n\t\t\tgetApiKey: this.getApiKey,\n\t\t\tmodel: this.model,\n\t\t\tonAgentCreated: this.onAgentCreated,\n\t\t\tonAgentFinished: this.onAgentFinished,\n\t\t\tlogger: this.logger,\n\t\t\tavailableSkills: this.availableSkills,\n\t\t\tprojectContext: this.projectContext,\n\t\t};\n\n\t\tfor (let i = pipeline.currentStep; i < pipeline.steps.length; i++) {\n\t\t\tif (this.aborted) {\n\t\t\t\tthis.log.warn(\"Pipeline aborted\", { featureId: pipeline.featureId, step: i });\n\t\t\t\tpipeline.status = \"failed\";\n\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\tyield createEvent(\"step_failed\", pipeline.featureId, pipeline.steps[i], {\n\t\t\t\t\treason: \"aborted\",\n\t\t\t\t\tstepIndex: i,\n\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.paused) {\n\t\t\t\tthis.log.info(\"Pipeline paused\", { featureId: pipeline.featureId, step: i });\n\t\t\t\tpipeline.status = \"blocked\";\n\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\tyield createEvent(\"blocked\", pipeline.featureId, pipeline.steps[i], { reason: \"paused\" });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst step = pipeline.steps[i];\n\n\t\t\t// Handle skip\n\t\t\tif (step.skip) {\n\t\t\t\tpipeline.currentStep = i + 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// step_start event\n\t\t\tyield createEvent(\"step_start\", pipeline.featureId, step, {\n\t\t\t\tagent: step.agent,\n\t\t\t\tinputs: step.inputs,\n\t\t\t\tstepIndex: i,\n\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t});\n\n\t\t\t// Update status\n\t\t\tconst featureStatus = agentRoleToFeatureStatus(step.agent, step.action);\n\t\t\ttry {\n\t\t\t\tawait this.store.updateFeatureStatus(pipeline.featureId, featureStatus);\n\t\t\t} catch {\n\t\t\t\t// Ignore status transition failure (may already be in this state)\n\t\t\t}\n\n\t\t\t// Execute step (with retry for transient errors)\n\t\t\tthis.log.info(`Step executing: ${step.agent}:${step.action}`, { featureId: pipeline.featureId, step: i });\n\t\t\tconst maxStepRetries = this.config.retry.maxStepRetries ?? 2;\n\t\t\tlet stepAttempt = 0;\n\t\t\tconst startTime = Date.now();\n\n\t\t\twhile (stepAttempt <= maxStepRetries) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.stepExecutor(step, pipeline.featureId, context);\n\t\t\t\t\tbreak;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\tconst errorStack = error instanceof Error ? error.stack : undefined;\n\t\t\t\t\tconst errorCause = error instanceof Error ? error.cause : undefined;\n\n\t\t\t\t\tif (stepAttempt < maxStepRetries && isRetryableStepError(errorMsg)) {\n\t\t\t\t\t\tstepAttempt++;\n\t\t\t\t\t\tconst delay = this.retryDelayFn(stepAttempt - 1);\n\t\t\t\t\t\tthis.log.warn(\n\t\t\t\t\t\t\t`Step error (retryable), retry ${stepAttempt}/${maxStepRetries} after ${delay}ms: ${step.agent}:${step.action}: ${errorMsg}`,\n\t\t\t\t\t\t\t{ featureId: pipeline.featureId, step: i, attempt: stepAttempt, cause: errorCause },\n\t\t\t\t\t\t);\n\t\t\t\t\t\tyield createEvent(\"step_retry\", pipeline.featureId, step, {\n\t\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t\t\tattempt: stepAttempt,\n\t\t\t\t\t\t\tmaxRetries: maxStepRetries,\n\t\t\t\t\t\t\tdelayMs: delay,\n\t\t\t\t\t\t\tstepIndex: i,\n\t\t\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.log.error(`Step failed: ${step.agent}:${step.action}: ${errorMsg}`, {\n\t\t\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\t\t\tstep: i,\n\t\t\t\t\t\tstack: errorStack,\n\t\t\t\t\t\tcause: errorCause,\n\t\t\t\t\t\tattempts: stepAttempt + 1,\n\t\t\t\t\t});\n\t\t\t\t\tpipeline.status = \"failed\";\n\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\tyield createEvent(\"step_failed\", pipeline.featureId, step, {\n\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t\tstepIndex: i,\n\t\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t\t\tattempts: stepAttempt + 1,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst elapsed = Date.now() - startTime;\n\t\t\tthis.log.info(`Step completed: ${step.agent}:${step.action} (${elapsed}ms)`, {\n\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\tstep: i,\n\t\t\t});\n\n\t\t\t// Gate validation\n\t\t\tif (step.gate) {\n\t\t\t\tconst gateResult = await this.gateChecker.evaluate(step, pipeline.featureId, this.requestApproval);\n\n\t\t\t\tif (!gateResult.passed) {\n\t\t\t\t\tif (gateResult.action === \"abort\") {\n\t\t\t\t\t\tthis.log.warn(`Gate abort: ${step.gate.type}`, { featureId: pipeline.featureId });\n\t\t\t\t\t\tpipeline.status = \"aborted\";\n\t\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\t\t// Delete feature artifacts\n\t\t\t\t\t\tawait this.store.clearFeatureDir(pipeline.featureId);\n\t\t\t\t\t\tyield createEvent(\"feature_aborted\", pipeline.featureId, step, {\n\t\t\t\t\t\t\taction: gateResult.action,\n\t\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.log.warn(\n\t\t\t\t\t\t`Gate rejected: ${step.gate.type}, retry ${pipeline.retryCount + 1}/${pipeline.maxRetries}`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tpipeline.status = \"blocked\";\n\t\t\t\t\tpipeline.retryCount++;\n\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\tyield createEvent(\"gate_rejected\", pipeline.featureId, step, {\n\t\t\t\t\t\taction: gateResult.action,\n\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (pipeline.retryCount >= pipeline.maxRetries) {\n\t\t\t\t\t\tyield createEvent(\"blocked\", pipeline.featureId, step, {\n\t\t\t\t\t\t\treason: \"max retries exceeded\",\n\t\t\t\t\t\t\tretryCount: pipeline.retryCount,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// On gate failure, do not increment currentStep so this step is re-executed\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Distinguish Skip vs Approve\n\t\t\t\tif (gateResult.action === \"skip\") {\n\t\t\t\t\tyield createEvent(\"gate_skipped\", pipeline.featureId, step);\n\t\t\t\t} else {\n\t\t\t\t\tyield createEvent(\"gate_approved\", pipeline.featureId, step);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// step_complete event\n\t\t\tyield createEvent(\"step_complete\", pipeline.featureId, step, {\n\t\t\t\toutputs: step.outputs,\n\t\t\t\telapsed,\n\t\t\t\tstepIndex: i,\n\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\tusage: context.lastStepUsage,\n\t\t\t});\n\t\t\tcontext.lastStepUsage = undefined;\n\n\t\t\tpipeline.currentStep = i + 1;\n\n\t\t\t// Persist pipeline state on step completion\n\t\t\tawait this.persistPipeline(pipeline);\n\t\t}\n\n\t\t// All steps completed\n\t\tthis.log.info(`Pipeline completed: ${pipeline.featureId}`, { featureId: pipeline.featureId });\n\t\tpipeline.status = \"done\";\n\t\tawait this.persistPipeline(pipeline);\n\t\ttry {\n\t\t\tawait this.store.updateFeatureStatus(pipeline.featureId, \"done\");\n\t\t} catch {\n\t\t\t// Ignore status transition failure\n\t\t}\n\t\tyield createEvent(\"pipeline_complete\", pipeline.featureId);\n\t}\n\n\t/**\n\t * Resumes the pipeline. Continues execution from currentStep.\n\t */\n\tasync *resume(pipeline: FeaturePipeline): AsyncGenerator<VibeEvent> {\n\t\tyield* this.run(pipeline);\n\t}\n\n\t/** Pauses after the current step completes. */\n\tpause(): void {\n\t\tthis.paused = true;\n\t}\n\n\t/** Aborts immediately. */\n\tabort(): void {\n\t\tthis.aborted = true;\n\t}\n\n\t/** Persists the pipeline state to disk. */\n\tprivate async persistPipeline(pipeline: FeaturePipeline): Promise<void> {\n\t\ttry {\n\t\t\tawait this.store.savePipelineState(pipeline.featureId, toPersisted(pipeline));\n\t\t\tthis.log.debug(\"Pipeline state persisted\", {\n\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\tstatus: pipeline.status,\n\t\t\t\tcurrentStep: pipeline.currentStep,\n\t\t\t});\n\t\t} catch {\n\t\t\tthis.log.warn(\"Pipeline state persistence failed\", { featureId: pipeline.featureId });\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../src/pipeline.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Agent } from \"@mariozechner/pi-agent-core\";\nimport type { Model } from \"@mariozechner/pi-ai\";\nimport type { GetApiKeyFn } from \"./agent-factory.js\";\nimport type { ApprovalRequestFn } from \"./gate.js\";\nimport { GateChecker } from \"./gate.js\";\nimport { createModuleLogger, type ModuleLogger, noopLogger, type VibeLogger } from \"./logger.js\";\nimport { defaultStepExecutor } from \"./step-executor.js\";\nimport type { VibeStore } from \"./store.js\";\nimport type {\n\tAgentRole,\n\tFeaturePipeline,\n\tFeatureStatusValue,\n\tPersistedPipeline,\n\tPipelineStep,\n\tVibeConfig,\n\tVibeEvent,\n} from \"./types.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Aggregated token usage for a single pipeline step. */\nexport interface StepUsage {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\ttotalTokens: number;\n\t/** Total cost in USD. */\n\tcost: number;\n}\n\n/** Context required for step execution */\nexport interface StepContext {\n\tstore: VibeStore;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Model to use. Uses the Agent's default model if not specified. */\n\tmodel?: Model<any>;\n\t/** Called immediately after agent creation. Allows external code to acquire an Agent reference. */\n\tonAgentCreated?: (agent: Agent) => void;\n\t/** Called after agent execution completes (success/error). Allows releasing the Agent reference. */\n\tonAgentFinished?: () => void;\n\t/** Logger. Uses noop if not specified. */\n\tlogger?: VibeLogger;\n\t/** Mutable. Set by StepExecutor after agent completion. Read by PipelineRunner for event data. */\n\tlastStepUsage?: StepUsage;\n\t/** Mutable. Set by StepExecutor after agent completion. Last assistant response text. */\n\tlastStepResponseText?: string;\n}\n\n/** Step execution function. Called by the pipeline engine for each step. */\nexport type StepExecutor = (step: PipelineStep, featureId: string, context: StepContext) => Promise<void>;\n\n/** Pipeline execution options */\nexport interface PipelineRunnerOptions {\n\tstore: VibeStore;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\trequestApproval?: ApprovalRequestFn;\n\tstepExecutor?: StepExecutor;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Model to use. Uses the Agent's default model if not specified. */\n\tmodel?: Model<any>;\n\t/** Called immediately after agent creation. Allows acquiring an Agent reference during execution. */\n\tonAgentCreated?: (agent: Agent) => void;\n\t/** Called after agent execution completes. Allows releasing the Agent reference. */\n\tonAgentFinished?: () => void;\n\t/** Logger. Uses noop if not specified. */\n\tlogger?: VibeLogger;\n\t/** Custom retry delay function for step execution retries. Defaults to exponential backoff. */\n\tretryDelayFn?: RetryDelayFn;\n}\n\n// ─── Status Mapping ──────────────────────────────────────────────────────────\n\n/** Maps agent role (+ optional action) to FeatureStatusValue */\nexport function agentRoleToFeatureStatus(role: AgentRole, action?: string): FeatureStatusValue {\n\tswitch (role) {\n\t\tcase \"planner\":\n\t\t\treturn \"planned\";\n\t\tcase \"architect\":\n\t\t\treturn \"designing\";\n\t\tcase \"developer\":\n\t\t\treturn \"implementing\";\n\t\tcase \"tester\":\n\t\t\treturn \"testing\";\n\t\tcase \"reviewer\":\n\t\t\treturn \"reviewing\";\n\t\tcase \"cicd\":\n\t\t\treturn action === \"merge\" ? \"merging\" : \"branching\";\n\t\tcase \"analyzer\":\n\t\t\treturn \"designing\";\n\t\tcase \"diagnostician\":\n\t\t\treturn \"designing\";\n\t\tcase \"discovery\":\n\t\t\treturn \"planned\";\n\t\tcase \"projectAnalyzer\":\n\t\t\treturn \"planned\";\n\t\tcase \"documenter\":\n\t\t\treturn \"done\";\n\t\tcase \"standardsEnricher\":\n\t\t\treturn \"planned\";\n\t\tcase \"systemArchitect\":\n\t\t\treturn \"designing\";\n\t\tcase \"recover\":\n\t\t\treturn \"planned\";\n\t}\n}\n\n// ─── Retry Helpers ───────────────────────────────────────────────────────────\n\n/**\n * Pattern matching transient errors that should be retried.\n * Covers: undici fetch \"terminated\", HTTP 5xx, rate limits, connection errors.\n */\nconst RETRYABLE_ERROR_PATTERN =\n\t/terminated|overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|retry delay|ECONNRESET|ETIMEDOUT|EPIPE|EAI_AGAIN/i;\n\n/** Returns true if the error message indicates a transient failure worth retrying. */\nexport function isRetryableStepError(errorMessage: string): boolean {\n\treturn RETRYABLE_ERROR_PATTERN.test(errorMessage);\n}\n\n/** Default exponential backoff delay in ms: base * 2^attempt, capped at 60s. */\nexport function defaultRetryDelay(attempt: number): number {\n\tconst base = 5000;\n\tconst maxDelay = 60000;\n\treturn Math.min(base * 2 ** attempt, maxDelay);\n}\n\n/** Retry delay function signature. */\nexport type RetryDelayFn = (attempt: number) => number;\n\n// ─── Helper ──────────────────────────────────────────────────────────────────\n\nfunction createEvent(\n\ttype: VibeEvent[\"type\"],\n\tfeatureId: string,\n\tstep?: PipelineStep,\n\tdata?: Record<string, unknown>,\n): VibeEvent {\n\treturn {\n\t\ttype,\n\t\tfeatureId,\n\t\ttimestamp: new Date().toISOString(),\n\t\tstep,\n\t\tdata,\n\t};\n}\n\n// ─── Persistence Helpers ─────────────────────────────────────────────────────\n\n/** Creates a PersistedPipeline from a FeaturePipeline. */\nexport function toPersisted(pipeline: FeaturePipeline): PersistedPipeline {\n\treturn {\n\t\tfeatureId: pipeline.featureId,\n\t\tworkflowType: pipeline.workflowType,\n\t\tcurrentStep: pipeline.currentStep,\n\t\tstatus: pipeline.status,\n\t\tretryCount: pipeline.retryCount,\n\t\tmaxRetries: pipeline.maxRetries,\n\t\tparentFeatureId: pipeline.parentFeatureId,\n\t\tissueRef: pipeline.issueRef,\n\t};\n}\n\n// ─── PipelineRunner ──────────────────────────────────────────────────────────\n\n/**\n * Pipeline runner. Sequentially executes FeaturePipeline steps and emits events.\n */\nexport class PipelineRunner {\n\tprivate readonly store: VibeStore;\n\tprivate readonly config: VibeConfig;\n\tprivate readonly projectRoot: string;\n\tprivate readonly requestApproval?: ApprovalRequestFn;\n\tprivate readonly stepExecutor: StepExecutor;\n\tprivate readonly gateChecker: GateChecker;\n\tprivate readonly getApiKey?: GetApiKeyFn;\n\tprivate readonly model?: Model<any>;\n\tprivate readonly onAgentCreated?: (agent: Agent) => void;\n\tprivate readonly onAgentFinished?: () => void;\n\tprivate readonly log: ModuleLogger;\n\tprivate readonly logger?: VibeLogger;\n\tprivate readonly retryDelayFn: RetryDelayFn;\n\n\tprivate paused = false;\n\tprivate aborted = false;\n\n\tconstructor(options: PipelineRunnerOptions) {\n\t\tthis.store = options.store;\n\t\tthis.config = options.config;\n\t\tthis.projectRoot = options.projectRoot;\n\t\tthis.requestApproval = options.requestApproval;\n\t\tthis.stepExecutor = options.stepExecutor ?? defaultStepExecutor;\n\t\tthis.getApiKey = options.getApiKey;\n\t\tthis.model = options.model;\n\t\tthis.onAgentCreated = options.onAgentCreated;\n\t\tthis.onAgentFinished = options.onAgentFinished;\n\t\tthis.logger = options.logger;\n\t\tthis.retryDelayFn = options.retryDelayFn ?? defaultRetryDelay;\n\t\tthis.log = createModuleLogger(options.logger ?? noopLogger, \"pipeline\");\n\t\tthis.gateChecker = new GateChecker(this.store, this.config, this.model, options.logger);\n\t}\n\n\t/**\n\t * Runs the pipeline and yields events.\n\t */\n\tasync *run(pipeline: FeaturePipeline): AsyncGenerator<VibeEvent> {\n\t\tthis.paused = false;\n\t\tthis.aborted = false;\n\t\tpipeline.status = \"running\";\n\t\tthis.log.info(`Pipeline started: ${pipeline.featureId}`, {\n\t\t\tfeatureId: pipeline.featureId,\n\t\t\tworkflowType: pipeline.workflowType,\n\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\tcurrentStep: pipeline.currentStep,\n\t\t});\n\n\t\tconst context: StepContext = {\n\t\t\tstore: this.store,\n\t\t\tconfig: this.config,\n\t\t\tprojectRoot: this.projectRoot,\n\t\t\tgetApiKey: this.getApiKey,\n\t\t\tmodel: this.model,\n\t\t\tonAgentCreated: this.onAgentCreated,\n\t\t\tonAgentFinished: this.onAgentFinished,\n\t\t\tlogger: this.logger,\n\t\t};\n\n\t\tfor (let i = pipeline.currentStep; i < pipeline.steps.length; i++) {\n\t\t\tif (this.aborted) {\n\t\t\t\tthis.log.warn(\"Pipeline aborted\", { featureId: pipeline.featureId, step: i });\n\t\t\t\tpipeline.status = \"failed\";\n\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\tyield createEvent(\"step_failed\", pipeline.featureId, pipeline.steps[i], {\n\t\t\t\t\treason: \"aborted\",\n\t\t\t\t\tstepIndex: i,\n\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (this.paused) {\n\t\t\t\tthis.log.info(\"Pipeline paused\", { featureId: pipeline.featureId, step: i });\n\t\t\t\tpipeline.status = \"blocked\";\n\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\tyield createEvent(\"blocked\", pipeline.featureId, pipeline.steps[i], { reason: \"paused\" });\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst step = pipeline.steps[i];\n\n\t\t\t// Handle skip\n\t\t\tif (step.skip) {\n\t\t\t\tpipeline.currentStep = i + 1;\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// step_start event\n\t\t\tyield createEvent(\"step_start\", pipeline.featureId, step, {\n\t\t\t\tagent: step.agent,\n\t\t\t\tinputs: step.inputs,\n\t\t\t\tstepIndex: i,\n\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t});\n\n\t\t\t// Update status\n\t\t\tconst featureStatus = agentRoleToFeatureStatus(step.agent, step.action);\n\t\t\ttry {\n\t\t\t\tawait this.store.updateFeatureStatus(pipeline.featureId, featureStatus);\n\t\t\t} catch {\n\t\t\t\t// Ignore status transition failure (may already be in this state)\n\t\t\t}\n\n\t\t\t// Execute step (with retry for transient errors)\n\t\t\tthis.log.info(`Step executing: ${step.agent}:${step.action}`, { featureId: pipeline.featureId, step: i });\n\t\t\tconst maxStepRetries = this.config.retry.maxStepRetries ?? 2;\n\t\t\tlet stepAttempt = 0;\n\t\t\tconst startTime = Date.now();\n\n\t\t\twhile (stepAttempt <= maxStepRetries) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.stepExecutor(step, pipeline.featureId, context);\n\t\t\t\t\tbreak;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst errorMsg = error instanceof Error ? error.message : String(error);\n\t\t\t\t\tconst errorStack = error instanceof Error ? error.stack : undefined;\n\t\t\t\t\tconst errorCause = error instanceof Error ? error.cause : undefined;\n\n\t\t\t\t\tif (stepAttempt < maxStepRetries && isRetryableStepError(errorMsg)) {\n\t\t\t\t\t\tstepAttempt++;\n\t\t\t\t\t\tconst delay = this.retryDelayFn(stepAttempt - 1);\n\t\t\t\t\t\tthis.log.warn(\n\t\t\t\t\t\t\t`Step error (retryable), retry ${stepAttempt}/${maxStepRetries} after ${delay}ms: ${step.agent}:${step.action}: ${errorMsg}`,\n\t\t\t\t\t\t\t{ featureId: pipeline.featureId, step: i, attempt: stepAttempt, cause: errorCause },\n\t\t\t\t\t\t);\n\t\t\t\t\t\tyield createEvent(\"step_retry\", pipeline.featureId, step, {\n\t\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t\t\tattempt: stepAttempt,\n\t\t\t\t\t\t\tmaxRetries: maxStepRetries,\n\t\t\t\t\t\t\tdelayMs: delay,\n\t\t\t\t\t\t\tstepIndex: i,\n\t\t\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, delay));\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.log.error(`Step failed: ${step.agent}:${step.action}: ${errorMsg}`, {\n\t\t\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\t\t\tstep: i,\n\t\t\t\t\t\tstack: errorStack,\n\t\t\t\t\t\tcause: errorCause,\n\t\t\t\t\t\tattempts: stepAttempt + 1,\n\t\t\t\t\t});\n\t\t\t\t\tpipeline.status = \"failed\";\n\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\tyield createEvent(\"step_failed\", pipeline.featureId, step, {\n\t\t\t\t\t\terror: errorMsg,\n\t\t\t\t\t\tstepIndex: i,\n\t\t\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\t\t\tattempts: stepAttempt + 1,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst elapsed = Date.now() - startTime;\n\t\t\tthis.log.info(`Step completed: ${step.agent}:${step.action} (${elapsed}ms)`, {\n\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\tstep: i,\n\t\t\t});\n\n\t\t\t// Gate validation\n\t\t\tif (step.gate) {\n\t\t\t\tconst gateResult = await this.gateChecker.evaluate(step, pipeline.featureId, this.requestApproval);\n\n\t\t\t\tif (!gateResult.passed) {\n\t\t\t\t\tif (gateResult.action === \"abort\") {\n\t\t\t\t\t\tthis.log.warn(`Gate abort: ${step.gate.type}`, { featureId: pipeline.featureId });\n\t\t\t\t\t\tpipeline.status = \"aborted\";\n\t\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\t\t// Delete feature artifacts\n\t\t\t\t\t\tawait this.store.clearFeatureDir(pipeline.featureId);\n\t\t\t\t\t\tyield createEvent(\"feature_aborted\", pipeline.featureId, step, {\n\t\t\t\t\t\t\taction: gateResult.action,\n\t\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.log.warn(\n\t\t\t\t\t\t`Gate rejected: ${step.gate.type}, retry ${pipeline.retryCount + 1}/${pipeline.maxRetries}`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\tpipeline.status = \"blocked\";\n\t\t\t\t\tpipeline.retryCount++;\n\t\t\t\t\tawait this.persistPipeline(pipeline);\n\t\t\t\t\tyield createEvent(\"gate_rejected\", pipeline.featureId, step, {\n\t\t\t\t\t\taction: gateResult.action,\n\t\t\t\t\t\tfeedback: gateResult.feedback,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (pipeline.retryCount >= pipeline.maxRetries) {\n\t\t\t\t\t\tyield createEvent(\"blocked\", pipeline.featureId, step, {\n\t\t\t\t\t\t\treason: \"max retries exceeded\",\n\t\t\t\t\t\t\tretryCount: pipeline.retryCount,\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// On gate failure, do not increment currentStep so this step is re-executed\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Distinguish Skip vs Approve\n\t\t\t\tif (gateResult.action === \"skip\") {\n\t\t\t\t\tyield createEvent(\"gate_skipped\", pipeline.featureId, step);\n\t\t\t\t} else {\n\t\t\t\t\tyield createEvent(\"gate_approved\", pipeline.featureId, step);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// step_complete event\n\t\t\tyield createEvent(\"step_complete\", pipeline.featureId, step, {\n\t\t\t\toutputs: step.outputs,\n\t\t\t\telapsed,\n\t\t\t\tstepIndex: i,\n\t\t\t\ttotalSteps: pipeline.steps.length,\n\t\t\t\tusage: context.lastStepUsage,\n\t\t\t\tresponseText: context.lastStepResponseText,\n\t\t\t});\n\t\t\tcontext.lastStepUsage = undefined;\n\t\t\tcontext.lastStepResponseText = undefined;\n\n\t\t\tpipeline.currentStep = i + 1;\n\n\t\t\t// Persist pipeline state on step completion\n\t\t\tawait this.persistPipeline(pipeline);\n\t\t}\n\n\t\t// All steps completed\n\t\tthis.log.info(`Pipeline completed: ${pipeline.featureId}`, { featureId: pipeline.featureId });\n\t\tpipeline.status = \"done\";\n\t\tawait this.persistPipeline(pipeline);\n\t\ttry {\n\t\t\tawait this.store.updateFeatureStatus(pipeline.featureId, \"done\");\n\t\t} catch {\n\t\t\t// Ignore status transition failure\n\t\t}\n\t\tyield createEvent(\"pipeline_complete\", pipeline.featureId);\n\t}\n\n\t/**\n\t * Resumes the pipeline. Continues execution from currentStep.\n\t */\n\tasync *resume(pipeline: FeaturePipeline): AsyncGenerator<VibeEvent> {\n\t\tyield* this.run(pipeline);\n\t}\n\n\t/** Pauses after the current step completes. */\n\tpause(): void {\n\t\tthis.paused = true;\n\t}\n\n\t/** Aborts immediately. */\n\tabort(): void {\n\t\tthis.aborted = true;\n\t}\n\n\t/** Persists the pipeline state to disk. */\n\tprivate async persistPipeline(pipeline: FeaturePipeline): Promise<void> {\n\t\ttry {\n\t\t\tawait this.store.savePipelineState(pipeline.featureId, toPersisted(pipeline));\n\t\t\tthis.log.debug(\"Pipeline state persisted\", {\n\t\t\t\tfeatureId: pipeline.featureId,\n\t\t\t\tstatus: pipeline.status,\n\t\t\t\tcurrentStep: pipeline.currentStep,\n\t\t\t});\n\t\t} catch {\n\t\t\tthis.log.warn(\"Pipeline state persistence failed\", { featureId: pipeline.featureId });\n\t\t}\n\t}\n}\n"]}
|
package/dist/planner.d.ts
CHANGED
|
@@ -17,8 +17,6 @@ export interface PlannerOptions {
|
|
|
17
17
|
onMessage?: (message: string) => void;
|
|
18
18
|
/** User feedback on rejection. Regenerates the existing plan with feedback applied. */
|
|
19
19
|
feedback?: string;
|
|
20
|
-
/** Lightweight skill index. Included in the agent system prompt. */
|
|
21
|
-
availableSkills?: string;
|
|
22
20
|
/** Callback invoked when the agent is created. Used for abort wiring, etc. */
|
|
23
21
|
onAgentCreated?: (agent: Agent) => void;
|
|
24
22
|
/** Callback invoked when the agent finishes execution. */
|
|
@@ -30,6 +28,15 @@ export interface PlannerResult {
|
|
|
30
28
|
completed: boolean;
|
|
31
29
|
/** Number of decomposed features */
|
|
32
30
|
featureCount: number;
|
|
31
|
+
/** Aggregated token usage. */
|
|
32
|
+
usage?: {
|
|
33
|
+
input: number;
|
|
34
|
+
output: number;
|
|
35
|
+
cacheRead: number;
|
|
36
|
+
cacheWrite: number;
|
|
37
|
+
totalTokens: number;
|
|
38
|
+
cost: number;
|
|
39
|
+
};
|
|
33
40
|
}
|
|
34
41
|
/**
|
|
35
42
|
* Runs the Planner Agent to generate plan.json and spec.md for each feature
|
package/dist/planner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAY,UAAU,EAAE,MAAM,YAAY,CAAC;AAIvD,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,qEAAqE;IACrE,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,kDAAkD;IAClD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,
|
|
1
|
+
{"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,KAAK,EAAY,UAAU,EAAE,MAAM,YAAY,CAAC;AAIvD,gCAAgC;AAChC,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,qEAAqE;IACrE,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C,kDAAkD;IAClD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,uFAAuF;IACvF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACxC,0DAA0D;IAC1D,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,+BAA+B;AAC/B,MAAM,WAAW,aAAa;IAC7B,sCAAsC;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,8BAA8B;IAC9B,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACpH;AAID;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA4FhF","sourcesContent":["import type { Agent, AgentEvent } from \"@mariozechner/pi-agent-core\";\nimport type { Model } from \"@mariozechner/pi-ai\";\nimport type { GetApiKeyFn } from \"./agent-factory.js\";\nimport { createRoleAgent, runAgent } from \"./agent-factory.js\";\nimport { getSystemPromptForRole } from \"./roles/index.js\";\nimport { aggregateUsage, extractArtifactContent } from \"./step-executor.js\";\nimport type { VibeStore } from \"./store.js\";\nimport type { PlanData, VibeConfig } from \"./types.js\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/** Planner execution options */\nexport interface PlannerOptions {\n\tstore: VibeStore;\n\tconfig: VibeConfig;\n\tprojectRoot: string;\n\tgetApiKey?: GetApiKeyFn;\n\t/** Model to use. Uses the Agent's default model if not specified. */\n\tmodel?: Model<any>;\n\t/** Agent event callback. Used for progress display, etc. */\n\tonAgentEvent?: (event: AgentEvent) => void;\n\t/** Callback to relay agent messages externally */\n\tonMessage?: (message: string) => void;\n\t/** User feedback on rejection. Regenerates the existing plan with feedback applied. */\n\tfeedback?: string;\n\t/** Callback invoked when the agent is created. Used for abort wiring, etc. */\n\tonAgentCreated?: (agent: Agent) => void;\n\t/** Callback invoked when the agent finishes execution. */\n\tonAgentFinished?: () => void;\n}\n\n/** Planner execution result */\nexport interface PlannerResult {\n\t/** Whether plan.json was generated */\n\tcompleted: boolean;\n\t/** Number of decomposed features */\n\tfeatureCount: number;\n\t/** Aggregated token usage. */\n\tusage?: { input: number; output: number; cacheRead: number; cacheWrite: number; totalTokens: number; cost: number };\n}\n\n// ─── Planner Runner ──────────────────────────────────────────────────────────\n\n/**\n * Runs the Planner Agent to generate plan.json and spec.md for each feature\n * based on requirements.md and project-context.md.\n *\n * 1. Load requirements.md and project-context.md from the store\n * 2. Create Planner Agent (readonly — extracts artifacts from response)\n * 3. Run the agent\n * 4. Extract plan.json from the response → save to store\n * 5. Extract each feature's spec.md → save to store\n */\nexport async function runPlanner(options: PlannerOptions): Promise<PlannerResult> {\n\tconst { store, config, projectRoot, getApiKey, model, onAgentEvent, onMessage, feedback } = options;\n\n\t// 1. Load inputs\n\tlet requirements: string | undefined;\n\tif (await store.hasRequirements()) {\n\t\trequirements = await store.readRequirements();\n\t}\n\n\tlet projectContext: string | undefined;\n\tif (await store.hasProjectContext()) {\n\t\tprojectContext = await store.readProjectContext();\n\t}\n\n\tlet impactReport: string | undefined;\n\tif (await store.hasGlobalArtifact(\"impact-report.md\")) {\n\t\timpactReport = await store.readGlobalArtifact(\"impact-report.md\");\n\t}\n\n\tlet systemDesign: string | undefined;\n\tif (await store.hasSystemDesign()) {\n\t\tsystemDesign = await store.readSystemDesign();\n\t}\n\n\t// 2. Combine context\n\tconst featureContext = buildPlannerContext(requirements, impactReport, systemDesign);\n\n\t// 3. Create Agent\n\tconst systemPrompt = getSystemPromptForRole(\"planner\");\n\tconst agent = await createRoleAgent({\n\t\trole: \"planner\",\n\t\tsystemPrompt,\n\t\tconfig,\n\t\tprojectRoot,\n\t\tmodel,\n\t\tfeatureContext: featureContext || undefined,\n\t\tgetApiKey,\n\t});\n\n\t// Notify external code that the agent has been created (for abort wiring)\n\toptions.onAgentCreated?.(agent);\n\n\t// 4. Build prompt and execute\n\ttry {\n\t\tlet prompt: string;\n\t\tif (feedback) {\n\t\t\tprompt =\n\t\t\t\t`The previous plan was rejected with the following feedback:\\n\\n${feedback}\\n\\n` +\n\t\t\t\t\"Please revise the plan based on this feedback.\\n\\n\" +\n\t\t\t\tbuildPlannerPrompt(requirements, projectContext, impactReport);\n\t\t} else {\n\t\t\tprompt = buildPlannerPrompt(requirements, projectContext, impactReport);\n\t\t}\n\n\t\tconst response = await runAgent(agent, prompt, onAgentEvent ? { onEvent: onAgentEvent } : undefined);\n\t\tconst usage = aggregateUsage(agent.state.messages);\n\t\tonMessage?.(response);\n\n\t\t// 5. Extract and save plan.json\n\t\tconst planContent = extractArtifactContent(response, \"plan.json\", false);\n\t\tif (!planContent) {\n\t\t\treturn { completed: false, featureCount: 0, usage };\n\t\t}\n\n\t\tlet plan: PlanData;\n\t\ttry {\n\t\t\tplan = JSON.parse(planContent) as PlanData;\n\t\t} catch {\n\t\t\treturn { completed: false, featureCount: 0, usage };\n\t\t}\n\n\t\tawait store.savePlan(plan);\n\n\t\t// 6. Extract and save each feature's spec.md\n\t\tfor (const feature of plan.features) {\n\t\t\tconst specContent = extractArtifactContent(response, `${feature.featureId}/spec.md`, false);\n\t\t\tif (specContent) {\n\t\t\t\tawait store.writeArtifact(feature.featureId, \"spec.md\", specContent);\n\t\t\t}\n\t\t}\n\n\t\treturn { completed: true, featureCount: plan.features.length, usage };\n\t} catch (error) {\n\t\t// Interruption by agent.abort(): \"Request was aborted\" error\n\t\tconst msg = error instanceof Error ? error.message : String(error);\n\t\tif (msg.includes(\"aborted\")) {\n\t\t\treturn { completed: false, featureCount: 0 };\n\t\t}\n\t\tthrow error;\n\t} finally {\n\t\toptions.onAgentFinished?.();\n\t}\n}\n\n// ─── Context & Prompt Builders ───────────────────────────────────────────────\n\nfunction buildPlannerContext(requirements?: string, impactReport?: string, systemDesign?: string): string {\n\tconst parts: string[] = [];\n\n\tif (requirements) {\n\t\tparts.push(\"## Requirements\\n\");\n\t\tparts.push(requirements);\n\t}\n\n\tif (impactReport) {\n\t\tparts.push(\"## Impact Report\\n\");\n\t\tparts.push(impactReport);\n\t}\n\n\tif (systemDesign) {\n\t\tparts.push(\"## System Architecture\\n\");\n\t\tparts.push(systemDesign);\n\t}\n\n\treturn parts.join(\"\\n\\n\");\n}\n\nfunction buildPlannerPrompt(requirements?: string, projectContext?: string, impactReport?: string): string {\n\tconst parts: string[] = [];\n\n\tparts.push(\"Analyze the following inputs and decompose the requirements into features.\");\n\tparts.push(\"\");\n\n\tif (requirements) {\n\t\tparts.push(\"## Requirements Document\");\n\t\tparts.push(\"\");\n\t\tparts.push(requirements);\n\t\tparts.push(\"\");\n\t} else {\n\t\tparts.push(\"Note: No requirements.md found. Use the project context to create a reasonable plan.\");\n\t\tparts.push(\"\");\n\t}\n\n\tif (projectContext) {\n\t\tparts.push(\"## Project Context\");\n\t\tparts.push(\"\");\n\t\tparts.push(projectContext);\n\t\tparts.push(\"\");\n\t}\n\n\tif (impactReport) {\n\t\tparts.push(\"## Impact Report\");\n\t\tparts.push(\"\");\n\t\tparts.push(\n\t\t\t\"The following impact analysis was performed on the existing codebase. Use it to inform feature decomposition, dependency ordering, and risk assessment.\",\n\t\t);\n\t\tparts.push(\"\");\n\t\tparts.push(impactReport);\n\t\tparts.push(\"\");\n\t}\n\n\tparts.push(\"## Instructions\");\n\tparts.push(\"\");\n\tparts.push(\"1. Decompose the requirements into independent, testable features\");\n\tparts.push(\"2. Map each feature to requirement IDs (FR-xxx) from requirements.md\");\n\tparts.push(\"3. Estimate complexity (low/medium/high) for each feature\");\n\tparts.push(\"4. Define dependency relationships and organize into phases\");\n\tparts.push(\"5. Output plan.json in a ```plan.json code block\");\n\tparts.push(\"6. Output each feature's spec.md in a ```{featureId}/spec.md code block\");\n\n\treturn parts.join(\"\\n\");\n}\n"]}
|