ralph-flow-pi 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +428 -0
- package/dist/cli.d.ts +9 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +56 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/prompts.d.ts +25 -0
- package/dist/commands/prompts.d.ts.map +1 -0
- package/dist/commands/prompts.js +249 -0
- package/dist/commands/prompts.js.map +1 -0
- package/dist/commands/tools.d.ts +47 -0
- package/dist/commands/tools.d.ts.map +1 -0
- package/dist/commands/tools.js +633 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/engine/check-bash.d.ts +121 -0
- package/dist/engine/check-bash.d.ts.map +1 -0
- package/dist/engine/check-bash.js +373 -0
- package/dist/engine/check-bash.js.map +1 -0
- package/dist/engine/check.d.ts +47 -0
- package/dist/engine/check.d.ts.map +1 -0
- package/dist/engine/check.js +298 -0
- package/dist/engine/check.js.map +1 -0
- package/dist/engine/core.d.ts +153 -0
- package/dist/engine/core.d.ts.map +1 -0
- package/dist/engine/core.js +1984 -0
- package/dist/engine/core.js.map +1 -0
- package/dist/engine/lock.d.ts +27 -0
- package/dist/engine/lock.d.ts.map +1 -0
- package/dist/engine/lock.js +121 -0
- package/dist/engine/lock.js.map +1 -0
- package/dist/engine/runner.d.ts +108 -0
- package/dist/engine/runner.d.ts.map +1 -0
- package/dist/engine/runner.js +510 -0
- package/dist/engine/runner.js.map +1 -0
- package/dist/engine/skills.d.ts +53 -0
- package/dist/engine/skills.d.ts.map +1 -0
- package/dist/engine/skills.js +109 -0
- package/dist/engine/skills.js.map +1 -0
- package/dist/engine/step-tools.d.ts +22 -0
- package/dist/engine/step-tools.d.ts.map +1 -0
- package/dist/engine/step-tools.js +45 -0
- package/dist/engine/step-tools.js.map +1 -0
- package/dist/engine/types.d.ts +136 -0
- package/dist/engine/types.d.ts.map +1 -0
- package/dist/engine/types.js +20 -0
- package/dist/engine/types.js.map +1 -0
- package/dist/headless.d.ts +57 -0
- package/dist/headless.d.ts.map +1 -0
- package/dist/headless.js +318 -0
- package/dist/headless.js.map +1 -0
- package/dist/pi/adapter.d.ts +135 -0
- package/dist/pi/adapter.d.ts.map +1 -0
- package/dist/pi/adapter.js +231 -0
- package/dist/pi/adapter.js.map +1 -0
- package/dist/pi/interactive.d.ts +28 -0
- package/dist/pi/interactive.d.ts.map +1 -0
- package/dist/pi/interactive.js +58 -0
- package/dist/pi/interactive.js.map +1 -0
- package/dist/pi/tui.d.ts +12 -0
- package/dist/pi/tui.d.ts.map +1 -0
- package/dist/pi/tui.js +12 -0
- package/dist/pi/tui.js.map +1 -0
- package/dist/tui/app.d.ts +25 -0
- package/dist/tui/app.d.ts.map +1 -0
- package/dist/tui/app.js +47 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/embed.d.ts +42 -0
- package/dist/tui/embed.d.ts.map +1 -0
- package/dist/tui/embed.js +38 -0
- package/dist/tui/embed.js.map +1 -0
- package/dist/tui/extension.d.ts +88 -0
- package/dist/tui/extension.d.ts.map +1 -0
- package/dist/tui/extension.js +114 -0
- package/dist/tui/extension.js.map +1 -0
- package/dist/tui/history-editor.d.ts +38 -0
- package/dist/tui/history-editor.d.ts.map +1 -0
- package/dist/tui/history-editor.js +55 -0
- package/dist/tui/history-editor.js.map +1 -0
- package/dist/tui/launcher.d.ts +24 -0
- package/dist/tui/launcher.d.ts.map +1 -0
- package/dist/tui/launcher.js +97 -0
- package/dist/tui/launcher.js.map +1 -0
- package/dist/tui/render.d.ts +87 -0
- package/dist/tui/render.d.ts.map +1 -0
- package/dist/tui/render.js +266 -0
- package/dist/tui/render.js.map +1 -0
- package/dist/tui/run-app.d.ts +49 -0
- package/dist/tui/run-app.d.ts.map +1 -0
- package/dist/tui/run-app.js +317 -0
- package/dist/tui/run-app.js.map +1 -0
- package/dist/tui/run-model.d.ts +162 -0
- package/dist/tui/run-model.d.ts.map +1 -0
- package/dist/tui/run-model.js +280 -0
- package/dist/tui/run-model.js.map +1 -0
- package/dist/tui/run-view.d.ts +71 -0
- package/dist/tui/run-view.d.ts.map +1 -0
- package/dist/tui/run-view.js +167 -0
- package/dist/tui/run-view.js.map +1 -0
- package/dist/tui/welcome-header.d.ts +40 -0
- package/dist/tui/welcome-header.d.ts.map +1 -0
- package/dist/tui/welcome-header.js +90 -0
- package/dist/tui/welcome-header.js.map +1 -0
- package/package.json +55 -0
- package/skills/c-to-rust-audit/SKILL.md +67 -0
- package/skills/c-to-rust-implement/SKILL.md +151 -0
- package/skills/c-to-rust-implement/references/c-to-rust-patterns.md +86 -0
- package/skills/c-to-rust-implement/references/conditional-compilation.md +47 -0
- package/skills/c-to-rust-implement/references/crate-reference.md +15 -0
- package/skills/c-to-rust-implement/references/error-strategies.md +80 -0
- package/skills/c-to-rust-implement/references/inline-asm.md +37 -0
- package/skills/c-to-rust-plan/SKILL.md +166 -0
- package/skills/c-to-rust-plan/references/detection-commands.md +66 -0
- package/skills/c-to-rust-test-gen/SKILL.md +130 -0
- package/skills/c-to-rust-test-gen/references/proptest-patterns.md +81 -0
- package/skills/c-to-rust-test-gen/references/test-porting.md +56 -0
- package/skills/c-to-rust-validate/SKILL.md +121 -0
- package/skills/everything2rust-audit/SKILL.md +69 -0
- package/skills/everything2rust-design/SKILL.md +121 -0
- package/skills/everything2rust-design/references/domain-playbooks.md +68 -0
- package/skills/everything2rust-design/references/paradigm-map.md +99 -0
- package/skills/everything2rust-implement/SKILL.md +101 -0
- package/skills/everything2rust-spec/SKILL.md +86 -0
- package/skills/everything2rust-spec/references/oracle-strategies.md +96 -0
- package/skills/everything2rust-survey/SKILL.md +99 -0
- package/skills/everything2rust-test-gen/SKILL.md +68 -0
- package/skills/everything2rust-test-gen/references/harness-patterns.md +186 -0
- package/skills/everything2rust-validate/SKILL.md +85 -0
- package/workflows/c-to-rust.yaml +202 -0
- package/workflows/everything2rust.yaml +259 -0
- package/workflows/loop.yaml +68 -0
- package/workflows/spec.yaml +183 -0
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The instance runner — one loop per active workflow instance.
|
|
3
|
+
*
|
|
4
|
+
* This file replaces driver.ts, and it is the place where ralph-flow-pi stops
|
|
5
|
+
* being a port and becomes a different thing. The opencode plugin could not own
|
|
6
|
+
* the DO session: it lived in the user's chat, so the plugin waited for a
|
|
7
|
+
* `session.idle` event, scraped the last assistant message, regex'd it for
|
|
8
|
+
* `<promise>done</promise>`, and poked the session with `promptAsync`. Every one
|
|
9
|
+
* of those steps was a guess about someone else's session.
|
|
10
|
+
*
|
|
11
|
+
* Here the engine creates the session, so the loop just awaits it:
|
|
12
|
+
*
|
|
13
|
+
* while (instance is live and unpaused):
|
|
14
|
+
* DO → fresh session per step, keep-alive until report_done
|
|
15
|
+
* gate → stop and let the user review (manual steps only)
|
|
16
|
+
* CHECK → fresh read-only session, verdict tool
|
|
17
|
+
* route → handleCheckPassed/Failed (verbatim engine logic)
|
|
18
|
+
*
|
|
19
|
+
* What the DO session gets is the point of the whole project: a brand-new
|
|
20
|
+
* context per step. Steps hand off through artifacts + the input/output fields,
|
|
21
|
+
* never through accumulated chat history — so step 7 cannot be poisoned by the
|
|
22
|
+
* debris of steps 1-6. The one exception is a check-failed retry of the SAME
|
|
23
|
+
* step, which resumes the same session because "here's what you just tried and
|
|
24
|
+
* why it failed" is exactly the context a fix needs, and max_fail_count bounds
|
|
25
|
+
* how far it can grow.
|
|
26
|
+
*
|
|
27
|
+
* Behaviors carried over verbatim from driver.ts (each was load-bearing):
|
|
28
|
+
* - keep-alive budget MAX_DO_REINJECT=5, keyed per step:phase, NOT burned while
|
|
29
|
+
* the model is making tool calls (it's working, not stuck); on exhaustion the
|
|
30
|
+
* loop stops driving and hands control to the user WITHOUT pausing the state.
|
|
31
|
+
* - the manual review gate sits BEFORE the check, not after.
|
|
32
|
+
* - a check verdict is DISCARDED if the state moved while the check ran.
|
|
33
|
+
* - infra failures pause with check_error and never burn a fail count.
|
|
34
|
+
*/
|
|
35
|
+
import fs from "fs";
|
|
36
|
+
import path from "path";
|
|
37
|
+
import { MANUAL_GATE_MARKER, MANUAL_STEP_MARKER } from "./core.js";
|
|
38
|
+
import { adversarialCheck } from "./check.js";
|
|
39
|
+
import { isSubWorkflowStep } from "./types.js";
|
|
40
|
+
import { createStepSession } from "../pi/adapter.js";
|
|
41
|
+
import { makeReportDoneTool } from "./step-tools.js";
|
|
42
|
+
/** Keep-alive nudges before the loop gives up and hands control to the user. */
|
|
43
|
+
export const MAX_DO_REINJECT = 5;
|
|
44
|
+
export function createRunner(engine, initialEvents = {}, deps = {}) {
|
|
45
|
+
const createSession = deps.createSession ?? createStepSession;
|
|
46
|
+
/**
|
|
47
|
+
* The runner has exactly one caller of these callbacks internally (`events.
|
|
48
|
+
* onXxx?.(...)`, unchanged below), but now potentially several consumers:
|
|
49
|
+
* the chat session's "post into the transcript" listener lives for the
|
|
50
|
+
* whole process, and a run-view's listener is added only while a human is
|
|
51
|
+
* actively attached (see attachRunView in tui/embed.ts) and removed on
|
|
52
|
+
* detach. `events` stays a single object with the same shape so every
|
|
53
|
+
* existing call site below is untouched — it just fans out to whichever
|
|
54
|
+
* listeners are currently registered instead of being one fixed sink.
|
|
55
|
+
*/
|
|
56
|
+
const listeners = new Set([initialEvents]);
|
|
57
|
+
const events = {
|
|
58
|
+
onStepStart: (instId, stepId, phase, attempt) => { for (const l of listeners)
|
|
59
|
+
l.onStepStart?.(instId, stepId, phase, attempt); },
|
|
60
|
+
onStepEvent: (instId, stepId, phase, event) => { for (const l of listeners)
|
|
61
|
+
l.onStepEvent?.(instId, stepId, phase, event); },
|
|
62
|
+
onVerdict: (instId, stepId, result) => { for (const l of listeners)
|
|
63
|
+
l.onVerdict?.(instId, stepId, result); },
|
|
64
|
+
onMessage: (instId, text) => { for (const l of listeners)
|
|
65
|
+
l.onMessage?.(instId, text); },
|
|
66
|
+
onGate: (instId, stepId) => { for (const l of listeners)
|
|
67
|
+
l.onGate?.(instId, stepId); },
|
|
68
|
+
onPaused: (instId, state) => { for (const l of listeners)
|
|
69
|
+
l.onPaused?.(instId, state); },
|
|
70
|
+
onStalled: (instId, stepId, attempts) => { for (const l of listeners)
|
|
71
|
+
l.onStalled?.(instId, stepId, attempts); },
|
|
72
|
+
onCompleted: (instId, reportPath) => { for (const l of listeners)
|
|
73
|
+
l.onCompleted?.(instId, reportPath); },
|
|
74
|
+
};
|
|
75
|
+
/** Attach an additional listener; call the returned function to detach it. */
|
|
76
|
+
function addEventListener(l) {
|
|
77
|
+
listeners.add(l);
|
|
78
|
+
return () => { listeners.delete(l); };
|
|
79
|
+
}
|
|
80
|
+
/** In-process guard: one loop per instance. Also the abort registry. */
|
|
81
|
+
const loops = new Map();
|
|
82
|
+
const activeStepSessions = new Map();
|
|
83
|
+
/** Pending "revise this gated step" instructions, consumed by the next DO turn. */
|
|
84
|
+
const pendingRevisions = new Map();
|
|
85
|
+
/**
|
|
86
|
+
* instIds that got a live human message since the loop last checked. A human
|
|
87
|
+
* talking to the session is not the model going silent, so that cycle must not
|
|
88
|
+
* burn the keep-alive budget — see sendUserMessage and its use in runDoPhase.
|
|
89
|
+
*/
|
|
90
|
+
const humanSteered = new Set();
|
|
91
|
+
/** Platform seam: destroyInstance aborts a DO session running in this process. */
|
|
92
|
+
function abortActiveStep(instId) {
|
|
93
|
+
const session = activeStepSessions.get(instId);
|
|
94
|
+
if (!session)
|
|
95
|
+
return;
|
|
96
|
+
activeStepSessions.delete(instId);
|
|
97
|
+
Promise.resolve().then(() => session.abort()).catch(() => { }).then(() => session.dispose()).catch(() => { });
|
|
98
|
+
}
|
|
99
|
+
function isRunning(instId) {
|
|
100
|
+
return loops.has(instId);
|
|
101
|
+
}
|
|
102
|
+
/** Start the loop for an instance unless one is already running for it. */
|
|
103
|
+
function ensureRunning(instId) {
|
|
104
|
+
if (loops.has(instId))
|
|
105
|
+
return;
|
|
106
|
+
const loop = runLoop(instId)
|
|
107
|
+
.catch((e) => {
|
|
108
|
+
engine.diag(`[runner] loop crashed for ${instId}:`, e?.stack || e?.message || String(e));
|
|
109
|
+
engine.logEvent(instId, "error", "runner_loop_crashed", { error: e?.message });
|
|
110
|
+
})
|
|
111
|
+
.finally(() => {
|
|
112
|
+
loops.delete(instId);
|
|
113
|
+
engine.clearRunnerPid(instId);
|
|
114
|
+
});
|
|
115
|
+
loops.set(instId, loop);
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The user reviewed a manual step and wants changes before verification.
|
|
119
|
+
* Re-open that step's DO session with their instruction and re-arm the gate —
|
|
120
|
+
* the opposite of approving it. The instruction is consumed by the next DO turn.
|
|
121
|
+
*/
|
|
122
|
+
function reviseGate(instId, instruction) {
|
|
123
|
+
if (!engine.instanceExists(instId))
|
|
124
|
+
return;
|
|
125
|
+
const text = String(instruction || "").trim();
|
|
126
|
+
if (!text)
|
|
127
|
+
return;
|
|
128
|
+
pendingRevisions.set(instId, text);
|
|
129
|
+
engine.clearManualGate(instId);
|
|
130
|
+
engine.clearDoneReported(instId); // must re-run DO, not go to CHECK
|
|
131
|
+
engine.logEvent(instId, "info", "manual_gate_revise", { instruction: text.slice(0, 200) });
|
|
132
|
+
ensureRunning(instId);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Steer the live DO session with a human-typed message. Only meaningful while
|
|
136
|
+
* a DO turn is actually running — CHECK is independent and read-only by
|
|
137
|
+
* design, and there's nothing to steer once the step has moved on. Returns
|
|
138
|
+
* whether the message actually had somewhere to go.
|
|
139
|
+
*/
|
|
140
|
+
function sendUserMessage(instId, text) {
|
|
141
|
+
const value = String(text || "").trim();
|
|
142
|
+
if (!value)
|
|
143
|
+
return false;
|
|
144
|
+
const session = activeStepSessions.get(instId);
|
|
145
|
+
if (!session)
|
|
146
|
+
return false;
|
|
147
|
+
const state = engine.readState(instId);
|
|
148
|
+
if (!state || !state.active || state.paused || state.current_phase !== "do")
|
|
149
|
+
return false;
|
|
150
|
+
humanSteered.add(instId);
|
|
151
|
+
void session.steer(value).catch((e) => engine.logEvent(instId, "warn", "steer_failed", { error: e?.message }));
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
/** Await every in-flight loop (tests; shutdown). */
|
|
155
|
+
async function idle() {
|
|
156
|
+
while (loops.size > 0)
|
|
157
|
+
await Promise.all([...loops.values()]);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Pause every instance this process is driving. Called on SIGINT/exit: the
|
|
161
|
+
* step transcripts are already on disk, so `ralphflow_continue` resumes the
|
|
162
|
+
* very session that was interrupted rather than restarting the step.
|
|
163
|
+
*/
|
|
164
|
+
function pauseAllForShutdown() {
|
|
165
|
+
for (const instId of loops.keys()) {
|
|
166
|
+
const state = engine.readState(instId);
|
|
167
|
+
if (state && state.active && !state.paused) {
|
|
168
|
+
engine.writeState({ ...state, paused: true, pause_reason: "session_aborted" }, instId);
|
|
169
|
+
engine.logEvent(instId, "warn", "session_aborted", { instance: instId, step: state.current_step, phase: state.current_phase });
|
|
170
|
+
}
|
|
171
|
+
abortActiveStep(instId);
|
|
172
|
+
engine.clearRunnerPid(instId);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
// ─── The loop ───────────────────────────────────────────────────────────────
|
|
176
|
+
async function runLoop(instId) {
|
|
177
|
+
engine.writeRunnerPid(instId);
|
|
178
|
+
for (;;) {
|
|
179
|
+
const state = engine.readState(instId);
|
|
180
|
+
// Gone: completed (destroyInstance) or cancelled by anyone.
|
|
181
|
+
if (!state || !state.active)
|
|
182
|
+
return;
|
|
183
|
+
if (state.paused) {
|
|
184
|
+
events.onPaused?.(instId, state);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const workflow = engine.loadWorkflow(state.workflow_name);
|
|
188
|
+
if (!workflow) {
|
|
189
|
+
// Workflow YAML deleted after the instance was created — pause instead
|
|
190
|
+
// of stalling silently (driver.ts did the same).
|
|
191
|
+
pause(instId, state, "config_error", `工作流 "${state.workflow_name}" 未找到。`);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const step = engine.getStep(workflow, state.current_step);
|
|
195
|
+
if (!step) {
|
|
196
|
+
pause(instId, state, "config_error", `步骤 "${state.current_step}" 在工作流 "${state.workflow_name}" 中未找到。`);
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
if (isSubWorkflowStep(step)) {
|
|
200
|
+
// Normal flow enters sub-workflows inline through the transition logic;
|
|
201
|
+
// landing here means a resume found the state parked on one. Resolve it.
|
|
202
|
+
const entry = engine.resolveSubWorkflowEntry(instId, step.workflow, state.user_task, step);
|
|
203
|
+
if (entry.error) {
|
|
204
|
+
pause(instId, state, "config_error", entry.text);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
events.onMessage?.(instId, entry.text);
|
|
208
|
+
}
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
// ── CHECK re-entry ──
|
|
212
|
+
// A state already in "check" means either a continue cleared a check_error
|
|
213
|
+
// pause, or a crash landed here. Either way: verify, don't re-run DO.
|
|
214
|
+
if (state.current_phase === "check") {
|
|
215
|
+
const finished = await runCheckAndAdvance(instId, workflow, step, state);
|
|
216
|
+
if (finished)
|
|
217
|
+
return;
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
// ── DO ──
|
|
221
|
+
const outcome = await runDoPhase(instId, workflow, step, state);
|
|
222
|
+
if (outcome === "gone")
|
|
223
|
+
return;
|
|
224
|
+
if (outcome === "stalled")
|
|
225
|
+
return; // user's turn; state deliberately NOT paused
|
|
226
|
+
// ── Manual review gate: BEFORE the check, never after ──
|
|
227
|
+
// The user's ralphflow_continue is the approval that starts verification.
|
|
228
|
+
if (engine.markerExists(MANUAL_STEP_MARKER, instId)) {
|
|
229
|
+
if (outcome === "done") {
|
|
230
|
+
// Just finished a manual step → stop for review.
|
|
231
|
+
engine.writeManualGate(instId);
|
|
232
|
+
engine.logEvent(instId, "info", "manual_gate_armed", { step: step.id });
|
|
233
|
+
events.onGate?.(instId, step.id);
|
|
234
|
+
events.onMessage?.(instId, `📋 手动步骤 \`${step.id}\` 已完成,等待你的审查。\n\n- 满意后运行 /ralphflow-continue 进入独立验证\n- 需要修改直接在对话里说明,修改完成后会再次提示审查\n- 放弃可运行 /ralphflow-cancel`);
|
|
235
|
+
return; // ralphflow_continue re-enters the loop
|
|
236
|
+
}
|
|
237
|
+
// Re-entered on a step that had already reported done. If the gate is
|
|
238
|
+
// still armed the user hasn't approved yet — stay out of their way.
|
|
239
|
+
// If it's gone, ralphflow_continue cleared it: that IS the approval.
|
|
240
|
+
if (engine.markerExists(MANUAL_GATE_MARKER, instId))
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const fresh = engine.readState(instId);
|
|
244
|
+
if (!fresh || !fresh.active)
|
|
245
|
+
return;
|
|
246
|
+
const finished = await runCheckAndAdvance(instId, workflow, step, fresh);
|
|
247
|
+
if (finished)
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function pause(instId, state, reason, failure) {
|
|
252
|
+
engine.writeState({ ...state, paused: true, pause_reason: reason, last_failure_reason: failure }, instId);
|
|
253
|
+
engine.logEvent(instId, "warn", "workflow_paused", { workflow: state.workflow_name, step: state.current_step, reason });
|
|
254
|
+
}
|
|
255
|
+
// ─── DO phase ───────────────────────────────────────────────────────────────
|
|
256
|
+
/**
|
|
257
|
+
* Drive one step's DO phase to `report_done`.
|
|
258
|
+
*
|
|
259
|
+
* Session identity is the interesting part. `resumeSession` is true only when
|
|
260
|
+
* this step is being retried after its own check failed (state carries a
|
|
261
|
+
* last_failure_reason and the attempt dir already exists) — then the model
|
|
262
|
+
* keeps the context of what it just tried. Any other entry (a new step, a
|
|
263
|
+
* route from elsewhere) opens a fresh attempt dir, and therefore a fresh
|
|
264
|
+
* context window.
|
|
265
|
+
*/
|
|
266
|
+
async function runDoPhase(instId, workflow, step, state) {
|
|
267
|
+
// A DO that already reported done (a gate the user just approved, or a crash
|
|
268
|
+
// between report_done and the check) must not be re-run — the work exists.
|
|
269
|
+
if (engine.doneReported(instId))
|
|
270
|
+
return "already-done";
|
|
271
|
+
// A gate revision resumes the SAME session (so the model keeps what it built)
|
|
272
|
+
// and leads with the user's requested change.
|
|
273
|
+
const revision = pendingRevisions.get(instId);
|
|
274
|
+
const attemptDir = revision !== undefined
|
|
275
|
+
? (engine.listStepSessionDirs(instId, step.id, "do").slice(-1)[0] ?? pickAttemptDir(instId, step.id, state))
|
|
276
|
+
: pickAttemptDir(instId, step.id, state);
|
|
277
|
+
const model = deps.currentModel?.() ?? {};
|
|
278
|
+
let session;
|
|
279
|
+
try {
|
|
280
|
+
session = await createSession({
|
|
281
|
+
cwd: engine.projectDir,
|
|
282
|
+
model: model.model,
|
|
283
|
+
thinkingLevel: model.thinkingLevel,
|
|
284
|
+
sessionDir: attemptDir,
|
|
285
|
+
customTools: [makeReportDoneTool(engine, instId), ...(deps.stepTools?.(instId) ?? [])],
|
|
286
|
+
appendSystemPrompt: deps.stepSystemPromptSuffix?.(),
|
|
287
|
+
skillPaths: deps.skillPaths?.(),
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
catch (e) {
|
|
291
|
+
pause(instId, state, "config_error", `无法创建步骤会话:${e.message}`);
|
|
292
|
+
events.onMessage?.(instId, `## ⚠️ 无法创建步骤会话\n\n${e.message}\n\n工作流已暂停。解决后运行 \`/ralphflow-continue\` 恢复。`);
|
|
293
|
+
return "gone";
|
|
294
|
+
}
|
|
295
|
+
activeStepSessions.set(instId, session);
|
|
296
|
+
const attempt = (state.fail_count || 0) + 1;
|
|
297
|
+
events.onStepStart?.(instId, step.id, "do", attempt);
|
|
298
|
+
// Track tool activity per turn: a model that is calling tools is working,
|
|
299
|
+
// not stuck, so its keep-alive budget must not be burned.
|
|
300
|
+
let turnHadToolCalls = false;
|
|
301
|
+
let compacted = false;
|
|
302
|
+
const unsubscribe = session.subscribe((event) => {
|
|
303
|
+
if (event.type === "tool_start")
|
|
304
|
+
turnHadToolCalls = true;
|
|
305
|
+
if (event.type === "compaction_end")
|
|
306
|
+
compacted = true;
|
|
307
|
+
events.onStepEvent?.(instId, step.id, "do", event);
|
|
308
|
+
});
|
|
309
|
+
try {
|
|
310
|
+
const reinjectKey = `${step.id}:do`;
|
|
311
|
+
// First turn: a gate revision leads with the user's change (resuming the
|
|
312
|
+
// same session); otherwise the DO prompt itself (already cached).
|
|
313
|
+
let message;
|
|
314
|
+
if (revision !== undefined) {
|
|
315
|
+
pendingRevisions.delete(instId);
|
|
316
|
+
message = `用户审查了这一步的成果,要求如下修改:\n\n${revision}\n\n请据此调整,完成后再次调用 report_done 工具。`;
|
|
317
|
+
}
|
|
318
|
+
else {
|
|
319
|
+
message = engine.readDoPromptCache(instId)
|
|
320
|
+
?? engine.buildDoPrompt(instId, step, state.user_task, state.last_failure_reason, state.fail_count || undefined);
|
|
321
|
+
}
|
|
322
|
+
await session.prompt(message);
|
|
323
|
+
for (;;) {
|
|
324
|
+
if (engine.doneReported(instId)) {
|
|
325
|
+
engine.clearReinjectCounter(instId);
|
|
326
|
+
return "done";
|
|
327
|
+
}
|
|
328
|
+
const cur = engine.readState(instId);
|
|
329
|
+
if (!cur || !cur.active || cur.paused)
|
|
330
|
+
return "gone"; // cancelled / paused underneath us
|
|
331
|
+
// A human just steered this session — that is engagement, not the model
|
|
332
|
+
// going silent, so this cycle must not burn the keep-alive budget.
|
|
333
|
+
const steered = humanSteered.delete(instId);
|
|
334
|
+
const attempts = turnHadToolCalls || steered
|
|
335
|
+
? engine.readReinjectCount(instId, reinjectKey)
|
|
336
|
+
: engine.incrementReinjectCount(instId, reinjectKey);
|
|
337
|
+
if (attempts > MAX_DO_REINJECT && !turnHadToolCalls && !steered) {
|
|
338
|
+
// Stop driving, but do NOT pause: the workflow is fine, the model is
|
|
339
|
+
// just stuck. Driving resumes the moment the user says something.
|
|
340
|
+
engine.logEvent(instId, "warn", "do_reinject_exhausted", { step: step.id, attempts });
|
|
341
|
+
events.onStalled?.(instId, step.id, attempts);
|
|
342
|
+
events.onMessage?.(instId, `## ⚠️ Ralph Flow 已停止自动驱动\n\n步骤 \`${step.id}\` 的 DO 阶段已连续 ${attempts} 次收到继续提示但未调用 report_done,请人工介入:\n1. 查看任务卡在哪里,补充信息后让模型继续\n2. 若任务实际已完成,运行 /ralphflow-continue 进入验证\n3. 运行 /ralphflow-cancel 取消工作流`);
|
|
343
|
+
return "stalled";
|
|
344
|
+
}
|
|
345
|
+
// A compaction just dropped the task out of context — re-inject the full
|
|
346
|
+
// DO prompt rather than a bare "continue" (driver.ts did this on the
|
|
347
|
+
// session.compacted event). A human message was already steered into the
|
|
348
|
+
// turn directly, so the generic nudge would just be noise stacked right
|
|
349
|
+
// after real feedback — use a short acknowledgement instead.
|
|
350
|
+
const nudge = steered
|
|
351
|
+
? "(已收到你的补充说明,请据此继续;完成后调用 report_done 工具。)"
|
|
352
|
+
: compacted
|
|
353
|
+
? `继续执行步骤 \`${step.id}\` 的任务。\n\n${engine.readDoPromptCache(instId) ?? ""}\n\n所有要求满足后调用 \`report_done\` 工具。`
|
|
354
|
+
: `继续执行步骤 \`${step.id}\` 的任务。当所有要求满足后,调用 \`report_done\` 工具。`;
|
|
355
|
+
compacted = false;
|
|
356
|
+
turnHadToolCalls = false;
|
|
357
|
+
await session.followUp(nudge);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
catch (e) {
|
|
361
|
+
if (!engine.instanceExists(instId))
|
|
362
|
+
return "gone"; // cancelled mid-turn
|
|
363
|
+
engine.logEvent(instId, "error", "do_session_error", { step: step.id, error: e.message });
|
|
364
|
+
const cur = engine.readState(instId);
|
|
365
|
+
if (cur && cur.active && !cur.paused) {
|
|
366
|
+
pause(instId, cur, "check_error", `步骤会话执行失败:${e.message}`);
|
|
367
|
+
events.onMessage?.(instId, `## ⚠️ 步骤会话执行失败\n\n${e.message}\n\n工作流已暂停(不计入失败次数)。解决后运行 \`/ralphflow-continue\` 恢复。`);
|
|
368
|
+
}
|
|
369
|
+
return "gone";
|
|
370
|
+
}
|
|
371
|
+
finally {
|
|
372
|
+
unsubscribe();
|
|
373
|
+
if (activeStepSessions.get(instId) === session)
|
|
374
|
+
activeStepSessions.delete(instId);
|
|
375
|
+
session.dispose();
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Where this step attempt's transcript lives.
|
|
380
|
+
*
|
|
381
|
+
* Retrying the same step after ITS check failed resumes the newest attempt dir
|
|
382
|
+
* (fail_count > 0 and a dir exists). Everything else gets a new one — which is
|
|
383
|
+
* what makes "fresh context per step" true rather than aspirational.
|
|
384
|
+
*/
|
|
385
|
+
/**
|
|
386
|
+
* Where this step attempt's transcript lives.
|
|
387
|
+
*
|
|
388
|
+
* Two conditions must BOTH hold to resume an existing session:
|
|
389
|
+
* 1. The state carries failure context (a check just rejected something, and
|
|
390
|
+
* we are here to fix it — fail_count > 0, last_failure_reason present).
|
|
391
|
+
* 2. THIS specific step has been attempted before (its session dir exists).
|
|
392
|
+
*
|
|
393
|
+
* Together they mean "we came back to a step that already ran, with a reason
|
|
394
|
+
* to fix it." The second condition is the important guard: if on_fail routes
|
|
395
|
+
* to a DIFFERENT step that has never been tried, existing is empty → a new
|
|
396
|
+
* session is created (fresh context per step, even during failure routing).
|
|
397
|
+
*
|
|
398
|
+
* The common cases:
|
|
399
|
+
* - Self-retry (on_fail == this step): resumes, model sees what it just tried.
|
|
400
|
+
* - Loop-back (test fails → on_fail: implement): resumes implement's own
|
|
401
|
+
* session so the model has its prior implementation context + the failure.
|
|
402
|
+
* - Route to a recovery step never run before: fresh session.
|
|
403
|
+
*/
|
|
404
|
+
function pickAttemptDir(instId, stepId, state) {
|
|
405
|
+
const hasFailureContext = (state.fail_count || 0) > 0 && !!state.last_failure_reason;
|
|
406
|
+
const existing = engine.listStepSessionDirs(instId, stepId, "do");
|
|
407
|
+
if (hasFailureContext && existing.length > 0)
|
|
408
|
+
return existing[existing.length - 1];
|
|
409
|
+
return engine.getStepSessionDir(instId, stepId, "do", existing.length + 1);
|
|
410
|
+
}
|
|
411
|
+
// ─── CHECK phase ────────────────────────────────────────────────────────────
|
|
412
|
+
/** @returns true when the loop should stop (completed, paused, or gone). */
|
|
413
|
+
async function runCheckAndAdvance(instId, workflow, step, state) {
|
|
414
|
+
// The DO-completion record belongs to the real do→check edge only. This
|
|
415
|
+
// function is re-entered with the state already in "check" (an infra retry
|
|
416
|
+
// after continue, or the crashed-check path), where re-recording would
|
|
417
|
+
// double the report rows.
|
|
418
|
+
if (state.current_phase === "do") {
|
|
419
|
+
engine.logEvent(instId, "info", "done_detected", { step: state.current_step });
|
|
420
|
+
engine.addStepRecord(instId, state.current_step, "do", "passed", state.fail_count || 0);
|
|
421
|
+
}
|
|
422
|
+
engine.clearManualStepMarker(instId);
|
|
423
|
+
engine.clearManualGate(instId);
|
|
424
|
+
engine.clearReinjectCounter(instId);
|
|
425
|
+
engine.clearDoPromptCache(instId);
|
|
426
|
+
engine.clearDoneReported(instId);
|
|
427
|
+
engine.writeState({ ...state, current_phase: "check" }, instId);
|
|
428
|
+
engine.recordStepStart(instId, state.current_step, "check");
|
|
429
|
+
engine.logEvent(instId, "info", "step_start", { step: state.current_step, phase: "check" });
|
|
430
|
+
events.onStepStart?.(instId, step.id, "check", (state.fail_count || 0) + 1);
|
|
431
|
+
const checkPrompt = engine.buildCheckPrompt(instId, step, state.user_task);
|
|
432
|
+
let checkResult;
|
|
433
|
+
try {
|
|
434
|
+
checkResult = await adversarialCheck(engine, instId, step, checkPrompt, state.user_task, workflow.adversarial_check, undefined, // onBashEvent: superseded by the live event stream below
|
|
435
|
+
deps.checkDeps, (event) => events.onStepEvent?.(instId, step.id, "check", event));
|
|
436
|
+
}
|
|
437
|
+
catch (err) {
|
|
438
|
+
engine.logEvent(instId, "error", "adversarial_check_uncaught", { stepId: step.id, error: err.message });
|
|
439
|
+
const st = engine.readState(instId);
|
|
440
|
+
if (st && st.active && st.current_phase === "check" && st.current_step === state.current_step && st.workflow_name === state.workflow_name) {
|
|
441
|
+
engine.writeState({ ...st, paused: true, pause_reason: "check_error", last_failure_reason: `对抗性检查崩溃:${err.message}` }, instId);
|
|
442
|
+
}
|
|
443
|
+
events.onMessage?.(instId, `## ⚠️ 验证未能运行\n\n对抗性检查崩溃:${err.message}\n\n工作流已暂停(不计入失败次数,已完成的工作保持原样)。问题解决后运行 \`/ralphflow-continue\` 重新验证。`);
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
446
|
+
// The state may have moved while the check ran (a cancel, a continue from
|
|
447
|
+
// another process, a shutdown pause). Applying a stale verdict would clear
|
|
448
|
+
// someone else's pause and drive a workflow that has moved on — discard it.
|
|
449
|
+
const cur = engine.readState(instId);
|
|
450
|
+
if (!cur || !cur.active || cur.paused || cur.current_phase !== "check"
|
|
451
|
+
|| cur.workflow_name !== state.workflow_name || cur.current_step !== state.current_step) {
|
|
452
|
+
engine.logEvent(instId, "warn", "check_result_discarded", { reason: cur?.paused ? "instance paused during check" : "state changed during check" });
|
|
453
|
+
return true;
|
|
454
|
+
}
|
|
455
|
+
events.onVerdict?.(instId, step.id, { passed: checkResult.passed, infra: checkResult.infra, reason: checkResult.reason });
|
|
456
|
+
// Infra failure: no verdict was produced. Pause in check WITHOUT burning a
|
|
457
|
+
// fail count — the work is fine, the verifier isn't.
|
|
458
|
+
if (checkResult.infra) {
|
|
459
|
+
engine.writeState({ ...cur, paused: true, pause_reason: "check_error", last_failure_reason: checkResult.reason }, instId);
|
|
460
|
+
engine.logEvent(instId, "warn", "workflow_paused", { workflow: cur.workflow_name, step: cur.current_step, reason: "check_infra_error" });
|
|
461
|
+
events.onMessage?.(instId, `## ⚠️ 验证未能运行\n\n${checkResult.reason}\n\n这是验证进程自身的问题(额度/API/超时),**不是**工作成果的问题:本次不计入失败次数,已完成的工作无需重做。问题解决后运行 \`/ralphflow-continue\` 直接重新验证。`);
|
|
462
|
+
const p = engine.readState(instId);
|
|
463
|
+
if (p)
|
|
464
|
+
events.onPaused?.(instId, p);
|
|
465
|
+
return true;
|
|
466
|
+
}
|
|
467
|
+
engine.addStepRecord(instId, cur.current_step, "check", checkResult.passed ? "passed" : "failed", cur.fail_count || 0, checkResult.reason);
|
|
468
|
+
const result = checkResult.passed
|
|
469
|
+
? engine.handleCheckPassed(instId, cur, workflow, step, checkResult)
|
|
470
|
+
: engine.handleCheckFailed(instId, cur, workflow, step, checkResult);
|
|
471
|
+
// Arm the next DO phase's markers before emitting the transition text
|
|
472
|
+
// (handleCheckPassed/Failed already wrote the state and cached the prompt).
|
|
473
|
+
if (!result.completed && !result.paused) {
|
|
474
|
+
const next = engine.readState(instId);
|
|
475
|
+
if (next && next.active && next.current_phase === "do") {
|
|
476
|
+
engine.clearDoneReported(instId);
|
|
477
|
+
engine.clearManualGate(instId);
|
|
478
|
+
const nextWf = next.workflow_name === workflow.name ? workflow : engine.loadWorkflow(next.workflow_name);
|
|
479
|
+
if (nextWf?.manual_step?.includes(next.current_step))
|
|
480
|
+
engine.writeManualStepMarker(instId);
|
|
481
|
+
else
|
|
482
|
+
engine.clearManualStepMarker(instId);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
// Only a transition that needs the user (paused/completed) reaches the
|
|
486
|
+
// permanent chat listener — an ordinary silent pass-and-advance or
|
|
487
|
+
// fail-and-retry is exactly what "runs in the background, tells you when
|
|
488
|
+
// it needs you" promises NOT to surface unprompted. The run view (if
|
|
489
|
+
// attached) already shows every attempt live via onStepStart/onStepEvent/
|
|
490
|
+
// onVerdict, independent of onMessage, so nothing here is lost by staying
|
|
491
|
+
// quiet — only who gets told, and when.
|
|
492
|
+
if (result.completed || result.paused)
|
|
493
|
+
events.onMessage?.(instId, result.text);
|
|
494
|
+
if (result.completed) {
|
|
495
|
+
// The instance dir is gone now, but the archived report survives here.
|
|
496
|
+
const reportPath = path.join(engine.getReportsDir(), `${instId}-final-report.md`);
|
|
497
|
+
events.onCompleted?.(instId, fs.existsSync(reportPath) ? reportPath : undefined);
|
|
498
|
+
return true;
|
|
499
|
+
}
|
|
500
|
+
if (result.paused) {
|
|
501
|
+
const paused = engine.readState(instId);
|
|
502
|
+
if (paused)
|
|
503
|
+
events.onPaused?.(instId, paused);
|
|
504
|
+
return true;
|
|
505
|
+
}
|
|
506
|
+
return false; // keep looping into the next step's DO
|
|
507
|
+
}
|
|
508
|
+
return { ensureRunning, reviseGate, sendUserMessage, addEventListener, abortActiveStep, isRunning, idle, pauseAllForShutdown };
|
|
509
|
+
}
|
|
510
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/engine/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill discovery, in the same three tiers as workflows: project → global → built-in.
|
|
3
|
+
*
|
|
4
|
+
* The engine deliberately knows almost nothing about skills. A workflow step's
|
|
5
|
+
* `do:` text just says "use the c-to-rust-plan skill"; the model reads that,
|
|
6
|
+
* finds the skill in its system prompt catalog, and loads it. That decoupling is
|
|
7
|
+
* inherited from both plugin versions and is why the 12 domain skills could move
|
|
8
|
+
* here as plain text.
|
|
9
|
+
*
|
|
10
|
+
* What changed from the plan: pi already ships this. `loadSkillsFromDir` parses
|
|
11
|
+
* SKILL.md frontmatter, and the default system prompt appends a catalog (name,
|
|
12
|
+
* description, ABSOLUTE location) plus the instruction to resolve a skill's
|
|
13
|
+
* relative references against its own directory — as long as the session has the
|
|
14
|
+
* `read` tool. So there is no `use_skill` tool here: writing one would have
|
|
15
|
+
* duplicated pi's mechanism and fought its prompt.
|
|
16
|
+
*
|
|
17
|
+
* All this file adds is the tier resolution pi doesn't do: same-named skills
|
|
18
|
+
* shadow, nearest tier wins, and only the winners are handed to the session.
|
|
19
|
+
*/
|
|
20
|
+
export type SkillSource = "project" | "global" | "builtin";
|
|
21
|
+
export interface ResolvedSkill {
|
|
22
|
+
name: string;
|
|
23
|
+
description: string;
|
|
24
|
+
/** Absolute path to SKILL.md — what goes in the model's catalog. */
|
|
25
|
+
filePath: string;
|
|
26
|
+
source: SkillSource;
|
|
27
|
+
/** Same-named skills this one shadows, nearest-tier-first. */
|
|
28
|
+
shadowed: Array<{
|
|
29
|
+
source: SkillSource;
|
|
30
|
+
filePath: string;
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
export interface SkillIndex {
|
|
34
|
+
skills: ResolvedSkill[];
|
|
35
|
+
/** Absolute SKILL.md paths for the winners — pass to a session's skillPaths. */
|
|
36
|
+
paths: string[];
|
|
37
|
+
/** Human-readable problems (unparseable SKILL.md, etc). */
|
|
38
|
+
diagnostics: string[];
|
|
39
|
+
}
|
|
40
|
+
/** Skills shipped inside the package. */
|
|
41
|
+
export declare function getBuiltinSkillsDir(): string;
|
|
42
|
+
export declare function getProjectSkillsDir(ralphFlowDir: string): string;
|
|
43
|
+
export declare function getGlobalSkillsDir(globalConfigHome: string | null): string | null;
|
|
44
|
+
/**
|
|
45
|
+
* Resolve the skills available to a DO session.
|
|
46
|
+
*
|
|
47
|
+
* @param ralphFlowDir the project's .ralph-flow dir
|
|
48
|
+
* @param globalConfigHome ~/.config/ralph-flow-pi, or null when there's no home
|
|
49
|
+
*/
|
|
50
|
+
export declare function loadSkillIndex(ralphFlowDir: string, globalConfigHome: string | null): SkillIndex;
|
|
51
|
+
/** Doctor section: which skills are available, and what shadows what. */
|
|
52
|
+
export declare function formatSkillReport(index: SkillIndex): string;
|
|
53
|
+
//# sourceMappingURL=skills.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/engine/skills.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE3D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,8DAA8D;IAC9D,QAAQ,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC5D;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,gFAAgF;IAChF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,2DAA2D;IAC3D,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,yCAAyC;AACzC,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,wBAAgB,kBAAkB,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAEjF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,UAAU,CA2ChG;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAoB3D"}
|