@skillstate/opencode 2.2.2 → 3.0.1
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 +194 -142
- package/dist/feedback.d.ts +178 -0
- package/dist/feedback.d.ts.map +1 -0
- package/dist/feedback.js +235 -0
- package/dist/feedback.js.map +1 -0
- package/dist/index.d.ts +58 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +48 -3
- package/dist/index.js.map +1 -1
- package/dist/mode.d.ts +97 -0
- package/dist/mode.d.ts.map +1 -0
- package/dist/mode.js +111 -0
- package/dist/mode.js.map +1 -0
- package/dist/opencode-adapter.d.ts +10 -46
- package/dist/opencode-adapter.d.ts.map +1 -1
- package/dist/opencode-adapter.js +1 -64
- package/dist/opencode-adapter.js.map +1 -1
- package/dist/paper-mode.d.ts +421 -0
- package/dist/paper-mode.d.ts.map +1 -0
- package/dist/paper-mode.js +445 -0
- package/dist/paper-mode.js.map +1 -0
- package/dist/plugin.d.ts +218 -76
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +867 -232
- package/dist/plugin.js.map +1 -1
- package/dist/response-sink.d.ts +208 -0
- package/dist/response-sink.d.ts.map +1 -0
- package/dist/response-sink.js +243 -0
- package/dist/response-sink.js.map +1 -0
- package/dist/runtime.d.ts +203 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +332 -0
- package/dist/runtime.js.map +1 -0
- package/dist/session-registry.d.ts +148 -0
- package/dist/session-registry.d.ts.map +1 -0
- package/dist/session-registry.js +236 -0
- package/dist/session-registry.js.map +1 -0
- package/dist/spec-loader.d.ts +81 -0
- package/dist/spec-loader.d.ts.map +1 -0
- package/dist/spec-loader.js +163 -0
- package/dist/spec-loader.js.map +1 -0
- package/dist/state-store.d.ts +126 -0
- package/dist/state-store.d.ts.map +1 -0
- package/dist/state-store.js +186 -0
- package/dist/state-store.js.map +1 -0
- package/dist/step-boundary.d.ts +91 -0
- package/dist/step-boundary.d.ts.map +1 -0
- package/dist/step-boundary.js +109 -0
- package/dist/step-boundary.js.map +1 -0
- package/dist/system-hint.d.ts +129 -0
- package/dist/system-hint.d.ts.map +1 -0
- package/dist/system-hint.js +166 -0
- package/dist/system-hint.js.map +1 -0
- package/dist/tools.d.ts +148 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +350 -0
- package/dist/tools.js.map +1 -0
- package/package.json +3 -2
- package/dist/plugin-types.d.ts +0 -71
- package/dist/plugin-types.d.ts.map +0 -1
- package/dist/plugin-types.js +0 -8
- package/dist/plugin-types.js.map +0 -1
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runtime that owns the loop — the half of Algorithm 1 a plugin otherwise
|
|
3
|
+
* has to ask the model to do for it.
|
|
4
|
+
*
|
|
5
|
+
* ── What was missing, and why it was not a model problem ──────────────────
|
|
6
|
+
*
|
|
7
|
+
* A.4 tells the model to answer with `{state_patch, action}` and says nothing
|
|
8
|
+
* about who runs `action`, because in the paper a runtime does: Algorithm 1
|
|
9
|
+
* runs aₜ and feeds Oₜ₊₁ back. Everything here existed to compensate for that
|
|
10
|
+
* gap with prompts — a note in the system slot, a rule in the spec, a notice
|
|
11
|
+
* about drift. Measured on two models, in three placements: the run still
|
|
12
|
+
* ended after the first or second file.
|
|
13
|
+
*
|
|
14
|
+
* And the model was right to stop. It was asked for a patch, it produced a
|
|
15
|
+
* correct patch, and the instruction had been satisfied completely. Every
|
|
16
|
+
* prompt added to compensate made the ask larger without ever supplying the
|
|
17
|
+
* missing executor. The defect was that the step loop belonged to the model at
|
|
18
|
+
* all; it belongs here.
|
|
19
|
+
*
|
|
20
|
+
* ── The mechanism ────────────────────────────────────────────────────────
|
|
21
|
+
*
|
|
22
|
+
* When a patch is applied and its `action` is not terminal, this calls
|
|
23
|
+
* `session.prompt` to request the next step. The context hook then rebuilds
|
|
24
|
+
* (P, Σₜ, Oₜ) from the new state, the model reads the observation, and the
|
|
25
|
+
* cycle continues without the model having volunteered anything.
|
|
26
|
+
*
|
|
27
|
+
* The plugin still cannot invoke a tool on the model's behalf — the host owns
|
|
28
|
+
* that, and that is a real limit. What it can own is step advancement, and
|
|
29
|
+
* that is exactly the part the loop was missing. Aₜ is a request, and the
|
|
30
|
+
* model performs it; who decides that step t+1 happens at all is the
|
|
31
|
+
* runtime's job, and it is this.
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* Default ceiling on runtime-driven steps before it stops asking.
|
|
35
|
+
*
|
|
36
|
+
* 100, not a number chosen here. §10.1's reference `Run` signature reads
|
|
37
|
+
* `Run(P, Σ0, O0, llm, execute, isDone, maxSteps = 100)`, and this value was 64
|
|
38
|
+
* until the paper was re-read for that line — with a comment claiming the paper
|
|
39
|
+
* did not give a number. It does.
|
|
40
|
+
*
|
|
41
|
+
* The cost of getting this wrong was measured rather than argued: at 64 a
|
|
42
|
+
* thirty-file task stopped at 25/30 having answered correctly, and the ceiling
|
|
43
|
+
* looked like the binding constraint when the real cause was that narration
|
|
44
|
+
* turns were each spending a step. Fixing the retry loop changed the pace;
|
|
45
|
+
* matching the paper's ceiling is what makes the two agree.
|
|
46
|
+
*/
|
|
47
|
+
export declare const DEFAULT_MAX_STEPS = 100;
|
|
48
|
+
/**
|
|
49
|
+
* Why {@link RuntimeDriver.advance} declined to spend a step.
|
|
50
|
+
*
|
|
51
|
+
* `'terminal'` — the model emitted a terminal action: a real ending.
|
|
52
|
+
* `'max_steps'` — §10.1's ceiling arrived. NOT completion.
|
|
53
|
+
* `'no_action'` — the turn carried no action to advance on.
|
|
54
|
+
* `'host_refused'` — the host would not start a turn.
|
|
55
|
+
*/
|
|
56
|
+
export type StopReason = 'terminal' | 'max_steps' | 'no_action' | 'host_refused';
|
|
57
|
+
/** What the loop driver needs from its host, injected so it is testable. */
|
|
58
|
+
export interface RuntimeDriverOptions {
|
|
59
|
+
/**
|
|
60
|
+
* Ask the host for another step in `sessionID`. Returns true when the
|
|
61
|
+
* request was accepted, false when the host refused — a refusal is a fact
|
|
62
|
+
* to count, not an error to throw, because it usually means the session has
|
|
63
|
+
* already ended.
|
|
64
|
+
*/
|
|
65
|
+
readonly prompt: (sessionID: string, text: string) => Promise<boolean>;
|
|
66
|
+
/** Hard ceiling on runtime-driven steps per session. */
|
|
67
|
+
readonly maxSteps?: number;
|
|
68
|
+
/** §5.1's `k`. Attempts per step are `k + 1`. */
|
|
69
|
+
readonly retries?: number;
|
|
70
|
+
}
|
|
71
|
+
/** One advancement the driver decided to make. */
|
|
72
|
+
export interface RuntimeStep {
|
|
73
|
+
readonly sessionID: string;
|
|
74
|
+
/** The action the model asked for, carried forward verbatim. */
|
|
75
|
+
readonly action: string;
|
|
76
|
+
/** The step number, 1-based, for this session. */
|
|
77
|
+
readonly step: number;
|
|
78
|
+
/** True when this prompt was a §5.1 retry inside the current step. */
|
|
79
|
+
readonly retry: boolean;
|
|
80
|
+
}
|
|
81
|
+
/** §5.1 line 2: `k` retries, so `k + 1` attempts per step. */
|
|
82
|
+
export declare const DEFAULT_VALIDATION_RETRIES = 2;
|
|
83
|
+
/** §5.1 line 10: the sentinel a step returns when every attempt failed. */
|
|
84
|
+
export declare const INVALID_PATCH = "__invalid_patch__";
|
|
85
|
+
export declare class RuntimeDriver {
|
|
86
|
+
#private;
|
|
87
|
+
/** Every advancement made, for diagnostics and tests. */
|
|
88
|
+
readonly advanced: RuntimeStep[];
|
|
89
|
+
/** Every step that exhausted its attempts, for diagnostics and tests. */
|
|
90
|
+
readonly invalidated: string[];
|
|
91
|
+
constructor(options: RuntimeDriverOptions);
|
|
92
|
+
/**
|
|
93
|
+
* How many attempts the current step has spent, and what it should do next.
|
|
94
|
+
*
|
|
95
|
+
* `retry` means the step continues: the loop is asked again, the corrective
|
|
96
|
+
* feedback rides in Oₜ, and the step number does not move. `advance` means
|
|
97
|
+
* the attempts are spent and the next prompt opens step t+1. `done` means
|
|
98
|
+
* the step succeeded and needs no further prompting at all.
|
|
99
|
+
*/
|
|
100
|
+
record(sessionID: string, applied: boolean): {
|
|
101
|
+
readonly action: 'retry' | 'advance';
|
|
102
|
+
readonly attempt: number;
|
|
103
|
+
readonly step: number;
|
|
104
|
+
readonly result: typeof INVALID_PATCH | null;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Whether an action ends the procedure.
|
|
108
|
+
*
|
|
109
|
+
* Exported as a function because the test for it is worth more than the
|
|
110
|
+
* call site: getting this wrong in the permissive direction costs tokens
|
|
111
|
+
* forever, and getting it wrong in the strict direction ends a run early,
|
|
112
|
+
* so both directions are pinned.
|
|
113
|
+
*/
|
|
114
|
+
static isTerminal(action: string): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Why {@link RuntimeDriver.advance} last declined to spend a step.
|
|
117
|
+
*
|
|
118
|
+
* Four ways `advance` returns `null` and the caller cannot tell them from the
|
|
119
|
+
* return value: the model emitted a terminal action (a real ending), the host
|
|
120
|
+
* would not start a turn, the turn had no action at all, or the ceiling
|
|
121
|
+
* arrived. The last is the one that lies — a loop stopped at `maxSteps` is
|
|
122
|
+
* indistinguishable from a loop that ran its course.
|
|
123
|
+
*
|
|
124
|
+
* A 90-file run was read as "the model lost track of its running sum at file
|
|
125
|
+
* 78" when the ceiling had arrived at step 100, mid-file-79, with the work
|
|
126
|
+
* still going. Nothing in this driver said so, and the caller discards
|
|
127
|
+
* `advance`'s return value entirely. The honest fix is to make the reason
|
|
128
|
+
* readable, not to guess it back out of a transcript.
|
|
129
|
+
*/
|
|
130
|
+
get lastStop(): {
|
|
131
|
+
reason: StopReason;
|
|
132
|
+
sessionID: string;
|
|
133
|
+
steps: number;
|
|
134
|
+
} | undefined;
|
|
135
|
+
/**
|
|
136
|
+
* Advance the loop for one applied patch.
|
|
137
|
+
*
|
|
138
|
+
* Returns the step it took, or `null` when it deliberately did not — a
|
|
139
|
+
* terminal action, an already-ended turn, or the ceiling. The ceiling is the
|
|
140
|
+
* important one: a runtime that asks forever against a model that keeps
|
|
141
|
+
* answering "continue" is a runaway, and the cost of that is paid at the
|
|
142
|
+
* provider.
|
|
143
|
+
*/
|
|
144
|
+
advance(sessionID: string, action: string | undefined): Promise<RuntimeStep | null>;
|
|
145
|
+
/**
|
|
146
|
+
* What the runtime did at the end of the last step, for Oₜ.
|
|
147
|
+
*
|
|
148
|
+
* A REPORT, not an order, and the distinction is the whole of this method.
|
|
149
|
+
*
|
|
150
|
+
* The model's own action used to ride here. §2 forbids it — "the agent
|
|
151
|
+
* receives only Oₜ — never prior observations or actions" — and with it in
|
|
152
|
+
* place the model obeyed a stored order rather than choosing: 54 `read` calls
|
|
153
|
+
* for thirty files, and one grep used three times as a side errand, where a
|
|
154
|
+
* control with no step driver read one file, ran ONE grep and finished in six
|
|
155
|
+
* calls. The order was its own past action, so it never looked for a better
|
|
156
|
+
* way than the one already written down.
|
|
157
|
+
*
|
|
158
|
+
* Simply removing it was also wrong, and measurably so. The runtime re-prompts
|
|
159
|
+
* when a turn produced a patch but no tool call, and with nothing in Oₜ
|
|
160
|
+
* saying why, the model looped instead of converging: 98 text blocks against
|
|
161
|
+
* a baseline of 43, and 7.9M prompt tokens against 1.6M. It read 41 files
|
|
162
|
+
* rather than 53, so the re-reads did halve — and the run never finished.
|
|
163
|
+
*
|
|
164
|
+
* So the environment says what it did. Factual, not imperative, and the model
|
|
165
|
+
* still chooses its own next action, which is the division the paper draws:
|
|
166
|
+
* `execute(aₜ, Σ_{t+1})` is the runtime's, and choosing aₜ is the model's.
|
|
167
|
+
*/
|
|
168
|
+
stepReport(sessionID: string): string | undefined;
|
|
169
|
+
/**
|
|
170
|
+
* Note what the environment executed on this session's behalf, and return how
|
|
171
|
+
* much of it is new.
|
|
172
|
+
*
|
|
173
|
+
* The context hook is the only place the host's own tool results are visible,
|
|
174
|
+
* and it runs on EVERY model request. A tool message that is still the newest
|
|
175
|
+
* one across two requests — which happens whenever the model is re-asked
|
|
176
|
+
* before it has produced a message of its own — would therefore be counted
|
|
177
|
+
* twice, and a report of "2 actions ran" for one `read` is a lie of exactly
|
|
178
|
+
* the kind this whole method exists to stop.
|
|
179
|
+
*
|
|
180
|
+
* So the driver keeps a watermark per session: the id of the last message it
|
|
181
|
+
* counted, and only results after it are new. Idempotent by construction —
|
|
182
|
+
* calling it with the same messages twice is a no-op, which is also what makes
|
|
183
|
+
* it testable without a host.
|
|
184
|
+
*/
|
|
185
|
+
noteExecutions(sessionID: string, messages: ReadonlyArray<{
|
|
186
|
+
id: string;
|
|
187
|
+
role: string;
|
|
188
|
+
content: unknown;
|
|
189
|
+
}>): number;
|
|
190
|
+
/**
|
|
191
|
+
* Take the action this session was last asked to perform, if any.
|
|
192
|
+
*
|
|
193
|
+
* Taken exactly once per step, so a prompt built twice for one turn cannot
|
|
194
|
+
* show the model the same continuation twice — the same discipline the
|
|
195
|
+
* feedback queue uses, and for the same reason.
|
|
196
|
+
*/
|
|
197
|
+
takeContinuation(sessionID: string): string | undefined;
|
|
198
|
+
/** Forget a session's pending action, on reset or teardown. */
|
|
199
|
+
forget(sessionID: string): void;
|
|
200
|
+
/** Steps taken for a session, for diagnostics. */
|
|
201
|
+
stepsFor(sessionID: string): number;
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAKH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,WAAW,GAAG,cAAc,CAAC;AAEjF,4EAA4E;AAC5E,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvE,wDAAwD;IACxD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,iDAAiD;IACjD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,kDAAkD;AAClD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,gEAAgE;IAChE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,kDAAkD;IAClD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB;AAED,8DAA8D;AAC9D,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C,2EAA2E;AAC3E,eAAO,MAAM,aAAa,sBAAsB,CAAC;AAEjD,qBAAa,aAAa;;IA2CxB,yDAAyD;IACzD,QAAQ,CAAC,QAAQ,EAAE,WAAW,EAAE,CAAM;IAGtC,yEAAyE;IACzE,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAM;IAEpC,YAAY,OAAO,EAAE,oBAAoB,EAIxC;IAED;;;;;;;OAOG;IACH,MAAM,CACJ,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,GACf;QACD,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;QACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,aAAa,GAAG,IAAI,CAAC;KAC9C,CA8BA;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEzC;IAED;;;;;;;;;;;;;;OAcG;IACH,IAAI,QAAQ,IAAI;QAAE,MAAM,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAEnF;IAaD;;;;;;;;OAQG;IACG,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAgCxF;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAmBhD;IAED;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC,GAAG,MAAM,CAwBjH;IAED;;;;;;OAMG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKtD;IAED,+DAA+D;IAC/D,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE9B;IAED,kDAAkD;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAElC;CACF"}
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The runtime that owns the loop — the half of Algorithm 1 a plugin otherwise
|
|
3
|
+
* has to ask the model to do for it.
|
|
4
|
+
*
|
|
5
|
+
* ── What was missing, and why it was not a model problem ──────────────────
|
|
6
|
+
*
|
|
7
|
+
* A.4 tells the model to answer with `{state_patch, action}` and says nothing
|
|
8
|
+
* about who runs `action`, because in the paper a runtime does: Algorithm 1
|
|
9
|
+
* runs aₜ and feeds Oₜ₊₁ back. Everything here existed to compensate for that
|
|
10
|
+
* gap with prompts — a note in the system slot, a rule in the spec, a notice
|
|
11
|
+
* about drift. Measured on two models, in three placements: the run still
|
|
12
|
+
* ended after the first or second file.
|
|
13
|
+
*
|
|
14
|
+
* And the model was right to stop. It was asked for a patch, it produced a
|
|
15
|
+
* correct patch, and the instruction had been satisfied completely. Every
|
|
16
|
+
* prompt added to compensate made the ask larger without ever supplying the
|
|
17
|
+
* missing executor. The defect was that the step loop belonged to the model at
|
|
18
|
+
* all; it belongs here.
|
|
19
|
+
*
|
|
20
|
+
* ── The mechanism ────────────────────────────────────────────────────────
|
|
21
|
+
*
|
|
22
|
+
* When a patch is applied and its `action` is not terminal, this calls
|
|
23
|
+
* `session.prompt` to request the next step. The context hook then rebuilds
|
|
24
|
+
* (P, Σₜ, Oₜ) from the new state, the model reads the observation, and the
|
|
25
|
+
* cycle continues without the model having volunteered anything.
|
|
26
|
+
*
|
|
27
|
+
* The plugin still cannot invoke a tool on the model's behalf — the host owns
|
|
28
|
+
* that, and that is a real limit. What it can own is step advancement, and
|
|
29
|
+
* that is exactly the part the loop was missing. Aₜ is a request, and the
|
|
30
|
+
* model performs it; who decides that step t+1 happens at all is the
|
|
31
|
+
* runtime's job, and it is this.
|
|
32
|
+
*/
|
|
33
|
+
/** Actions that mean the model considers the procedure finished. */
|
|
34
|
+
const TERMINAL_ACTIONS = new Set(['done', 'complete', 'completed', 'finished', 'stop', 'end', '']);
|
|
35
|
+
/**
|
|
36
|
+
* Default ceiling on runtime-driven steps before it stops asking.
|
|
37
|
+
*
|
|
38
|
+
* 100, not a number chosen here. §10.1's reference `Run` signature reads
|
|
39
|
+
* `Run(P, Σ0, O0, llm, execute, isDone, maxSteps = 100)`, and this value was 64
|
|
40
|
+
* until the paper was re-read for that line — with a comment claiming the paper
|
|
41
|
+
* did not give a number. It does.
|
|
42
|
+
*
|
|
43
|
+
* The cost of getting this wrong was measured rather than argued: at 64 a
|
|
44
|
+
* thirty-file task stopped at 25/30 having answered correctly, and the ceiling
|
|
45
|
+
* looked like the binding constraint when the real cause was that narration
|
|
46
|
+
* turns were each spending a step. Fixing the retry loop changed the pace;
|
|
47
|
+
* matching the paper's ceiling is what makes the two agree.
|
|
48
|
+
*/
|
|
49
|
+
export const DEFAULT_MAX_STEPS = 100;
|
|
50
|
+
/** §5.1 line 2: `k` retries, so `k + 1` attempts per step. */
|
|
51
|
+
export const DEFAULT_VALIDATION_RETRIES = 2;
|
|
52
|
+
/** §5.1 line 10: the sentinel a step returns when every attempt failed. */
|
|
53
|
+
export const INVALID_PATCH = '__invalid_patch__';
|
|
54
|
+
export class RuntimeDriver {
|
|
55
|
+
#prompt;
|
|
56
|
+
#maxSteps;
|
|
57
|
+
#retries;
|
|
58
|
+
#steps = new Map();
|
|
59
|
+
/** The action each session is mid-way through, read by the context hook. */
|
|
60
|
+
#pending = new Map();
|
|
61
|
+
/**
|
|
62
|
+
* Attempts spent on the CURRENT step, per session.
|
|
63
|
+
*
|
|
64
|
+
* §5.1 lines 2–8: a step is up to `k + 1` attempts at the *same* Aₜ, each
|
|
65
|
+
* after the first carrying the reason the last one failed. Only when all of
|
|
66
|
+
* them fail does the step return `__invalid_patch__` and the loop move on.
|
|
67
|
+
*
|
|
68
|
+
* This was missing, and it was not a small omission. Without it every failed
|
|
69
|
+
* attempt became its own step, so the corrective feedback arrived on a
|
|
70
|
+
* *different* Aₜ than the one it was correcting — which is precisely what
|
|
71
|
+
* §7's rollback-retry forbids. Measured consequence: the model narrated
|
|
72
|
+
* instead of patching on about 63% of turns, and because the state advances
|
|
73
|
+
* only on patching turns, the state grew at 37% of the step rate. Thirty
|
|
74
|
+
* files cost about 88 steps against a ceiling of 64, and the run stopped at
|
|
75
|
+
* 25/30 having answered correctly anyway.
|
|
76
|
+
*
|
|
77
|
+
* A narration turn is now an attempt, not a step.
|
|
78
|
+
*/
|
|
79
|
+
#attempts = new Map();
|
|
80
|
+
/**
|
|
81
|
+
* Tool results seen since the last report, per session. The environment's own
|
|
82
|
+
* account of what it did — the only account that is not the model's claim.
|
|
83
|
+
*/
|
|
84
|
+
#executed = new Map();
|
|
85
|
+
/**
|
|
86
|
+
* The id of the last message counted, per session.
|
|
87
|
+
*
|
|
88
|
+
* The context hook runs on every model request, so without this a tool
|
|
89
|
+
* message that stays newest across two requests is counted twice. See
|
|
90
|
+
* {@link noteExecutions}.
|
|
91
|
+
*/
|
|
92
|
+
#counted = new Map();
|
|
93
|
+
/** What {@link record} decided, so `advance` does not re-decide it. */
|
|
94
|
+
#decisions = new Map();
|
|
95
|
+
/** Every advancement made, for diagnostics and tests. */
|
|
96
|
+
advanced = [];
|
|
97
|
+
#stops = new Map();
|
|
98
|
+
#lastStoppedSession = '';
|
|
99
|
+
/** Every step that exhausted its attempts, for diagnostics and tests. */
|
|
100
|
+
invalidated = [];
|
|
101
|
+
constructor(options) {
|
|
102
|
+
this.#prompt = options.prompt;
|
|
103
|
+
this.#maxSteps = options.maxSteps ?? DEFAULT_MAX_STEPS;
|
|
104
|
+
this.#retries = options.retries ?? DEFAULT_VALIDATION_RETRIES;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* How many attempts the current step has spent, and what it should do next.
|
|
108
|
+
*
|
|
109
|
+
* `retry` means the step continues: the loop is asked again, the corrective
|
|
110
|
+
* feedback rides in Oₜ, and the step number does not move. `advance` means
|
|
111
|
+
* the attempts are spent and the next prompt opens step t+1. `done` means
|
|
112
|
+
* the step succeeded and needs no further prompting at all.
|
|
113
|
+
*/
|
|
114
|
+
record(sessionID, applied) {
|
|
115
|
+
if (applied) {
|
|
116
|
+
// Lines 11-13: the patch is applied and the step still opens the next
|
|
117
|
+
// one, chaining Oₜ into Oₜ₊₁. A success is not the end of the loop —
|
|
118
|
+
// only a terminal action or the ceiling is, and both live in `advance`.
|
|
119
|
+
this.#attempts.delete(sessionID);
|
|
120
|
+
this.#decisions.set(sessionID, 'advance');
|
|
121
|
+
return {
|
|
122
|
+
action: 'advance',
|
|
123
|
+
attempt: 0,
|
|
124
|
+
step: (this.#steps.get(sessionID) ?? 0) + 1,
|
|
125
|
+
result: null,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const attempt = (this.#attempts.get(sessionID) ?? 0) + 1;
|
|
129
|
+
this.#attempts.set(sessionID, attempt);
|
|
130
|
+
if (attempt > this.#retries) {
|
|
131
|
+
// Line 10: Σ_t is UNCHANGED and never written. The step is spent.
|
|
132
|
+
this.#attempts.delete(sessionID);
|
|
133
|
+
this.invalidated.push(sessionID);
|
|
134
|
+
this.#decisions.set(sessionID, 'advance');
|
|
135
|
+
return {
|
|
136
|
+
action: 'advance',
|
|
137
|
+
attempt,
|
|
138
|
+
step: (this.#steps.get(sessionID) ?? 0) + 1,
|
|
139
|
+
result: INVALID_PATCH,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
this.#decisions.set(sessionID, 'retry');
|
|
143
|
+
return { action: 'retry', attempt, step: this.#steps.get(sessionID) ?? 0, result: null };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Whether an action ends the procedure.
|
|
147
|
+
*
|
|
148
|
+
* Exported as a function because the test for it is worth more than the
|
|
149
|
+
* call site: getting this wrong in the permissive direction costs tokens
|
|
150
|
+
* forever, and getting it wrong in the strict direction ends a run early,
|
|
151
|
+
* so both directions are pinned.
|
|
152
|
+
*/
|
|
153
|
+
static isTerminal(action) {
|
|
154
|
+
return TERMINAL_ACTIONS.has(action.trim().toLowerCase());
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Why {@link RuntimeDriver.advance} last declined to spend a step.
|
|
158
|
+
*
|
|
159
|
+
* Four ways `advance` returns `null` and the caller cannot tell them from the
|
|
160
|
+
* return value: the model emitted a terminal action (a real ending), the host
|
|
161
|
+
* would not start a turn, the turn had no action at all, or the ceiling
|
|
162
|
+
* arrived. The last is the one that lies — a loop stopped at `maxSteps` is
|
|
163
|
+
* indistinguishable from a loop that ran its course.
|
|
164
|
+
*
|
|
165
|
+
* A 90-file run was read as "the model lost track of its running sum at file
|
|
166
|
+
* 78" when the ceiling had arrived at step 100, mid-file-79, with the work
|
|
167
|
+
* still going. Nothing in this driver said so, and the caller discards
|
|
168
|
+
* `advance`'s return value entirely. The honest fix is to make the reason
|
|
169
|
+
* readable, not to guess it back out of a transcript.
|
|
170
|
+
*/
|
|
171
|
+
get lastStop() {
|
|
172
|
+
return this.#stops.get(this.#lastStoppedSession);
|
|
173
|
+
}
|
|
174
|
+
#stop(reason, sessionID, steps) {
|
|
175
|
+
const entry = {
|
|
176
|
+
reason,
|
|
177
|
+
sessionID,
|
|
178
|
+
steps: steps ?? this.#steps.get(sessionID) ?? 0,
|
|
179
|
+
};
|
|
180
|
+
this.#stops.set(sessionID, entry);
|
|
181
|
+
this.#lastStoppedSession = sessionID;
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Advance the loop for one applied patch.
|
|
186
|
+
*
|
|
187
|
+
* Returns the step it took, or `null` when it deliberately did not — a
|
|
188
|
+
* terminal action, an already-ended turn, or the ceiling. The ceiling is the
|
|
189
|
+
* important one: a runtime that asks forever against a model that keeps
|
|
190
|
+
* answering "continue" is a runaway, and the cost of that is paid at the
|
|
191
|
+
* provider.
|
|
192
|
+
*/
|
|
193
|
+
async advance(sessionID, action) {
|
|
194
|
+
if (action === undefined)
|
|
195
|
+
return this.#stop('no_action', sessionID);
|
|
196
|
+
if (RuntimeDriver.isTerminal(action))
|
|
197
|
+
return this.#stop('terminal', sessionID);
|
|
198
|
+
// A retry re-asks within the CURRENT step and must not spend another one.
|
|
199
|
+
// §5.1 counts attempts inside a step, not steps: the whole point of the
|
|
200
|
+
// bounded retry is that the model gets its corrections without the loop
|
|
201
|
+
// moving on, and a retry that consumed a step would be indistinguishable
|
|
202
|
+
// from the behaviour this replaced.
|
|
203
|
+
const decision = this.#decisions.get(sessionID);
|
|
204
|
+
this.#decisions.delete(sessionID);
|
|
205
|
+
const isRetry = decision === 'retry';
|
|
206
|
+
const step = isRetry ? (this.#steps.get(sessionID) ?? 0) : (this.#steps.get(sessionID) ?? 0) + 1;
|
|
207
|
+
if (step > this.#maxSteps)
|
|
208
|
+
return this.#stop('max_steps', sessionID, step - 1);
|
|
209
|
+
// The action is remembered BEFORE the host is asked, because the context
|
|
210
|
+
// hook that follows reads it, and a host that starts the turn quickly must
|
|
211
|
+
// not find an empty slot. The text handed to `session.prompt` is only a
|
|
212
|
+
// wake-up: `applyPaperContext` clears the messages, so the model reads the
|
|
213
|
+
// action from Oₜ instead. See the `continuation` option.
|
|
214
|
+
this.#pending.set(sessionID, action);
|
|
215
|
+
const asked = await this.#prompt(sessionID, action);
|
|
216
|
+
if (!asked) {
|
|
217
|
+
this.#pending.delete(sessionID);
|
|
218
|
+
return this.#stop('host_refused', sessionID);
|
|
219
|
+
}
|
|
220
|
+
this.#steps.set(sessionID, step);
|
|
221
|
+
const record = { sessionID, action, step, retry: isRetry };
|
|
222
|
+
this.advanced.push(record);
|
|
223
|
+
return record;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* What the runtime did at the end of the last step, for Oₜ.
|
|
227
|
+
*
|
|
228
|
+
* A REPORT, not an order, and the distinction is the whole of this method.
|
|
229
|
+
*
|
|
230
|
+
* The model's own action used to ride here. §2 forbids it — "the agent
|
|
231
|
+
* receives only Oₜ — never prior observations or actions" — and with it in
|
|
232
|
+
* place the model obeyed a stored order rather than choosing: 54 `read` calls
|
|
233
|
+
* for thirty files, and one grep used three times as a side errand, where a
|
|
234
|
+
* control with no step driver read one file, ran ONE grep and finished in six
|
|
235
|
+
* calls. The order was its own past action, so it never looked for a better
|
|
236
|
+
* way than the one already written down.
|
|
237
|
+
*
|
|
238
|
+
* Simply removing it was also wrong, and measurably so. The runtime re-prompts
|
|
239
|
+
* when a turn produced a patch but no tool call, and with nothing in Oₜ
|
|
240
|
+
* saying why, the model looped instead of converging: 98 text blocks against
|
|
241
|
+
* a baseline of 43, and 7.9M prompt tokens against 1.6M. It read 41 files
|
|
242
|
+
* rather than 53, so the re-reads did halve — and the run never finished.
|
|
243
|
+
*
|
|
244
|
+
* So the environment says what it did. Factual, not imperative, and the model
|
|
245
|
+
* still chooses its own next action, which is the division the paper draws:
|
|
246
|
+
* `execute(aₜ, Σ_{t+1})` is the runtime's, and choosing aₜ is the model's.
|
|
247
|
+
*/
|
|
248
|
+
stepReport(sessionID) {
|
|
249
|
+
const step = this.#steps.get(sessionID);
|
|
250
|
+
if (step === undefined)
|
|
251
|
+
return undefined;
|
|
252
|
+
const executed = this.#executed.get(sessionID) ?? 0;
|
|
253
|
+
this.#executed.delete(sessionID);
|
|
254
|
+
// The count is the environment's, and it is read from tool RESULTS the host
|
|
255
|
+
// handed back — not from the action the model proposed. Those are different
|
|
256
|
+
// facts: a model can name an action and never cause it, which is precisely
|
|
257
|
+
// what happened for a week in this project.
|
|
258
|
+
//
|
|
259
|
+
// The sentence used to be unconditional, and it was wrong whenever a model
|
|
260
|
+
// both patched and acted in one turn. On the n=3 run it happened to be
|
|
261
|
+
// right — 45 patches, 58 tool calls, and not one turn containing both — but
|
|
262
|
+
// nothing enforced that, it was a property of the model that day, and a
|
|
263
|
+
// false report in O_t is worse than no report: O_t is the environment's
|
|
264
|
+
// channel and the whole contract is that what arrives there happened.
|
|
265
|
+
return executed === 0
|
|
266
|
+
? `step ${step} ended; your state patch was applied; nothing was executed.`
|
|
267
|
+
: `step ${step} ended; your state patch was applied; ${executed} action${executed === 1 ? '' : 's'} ran.`;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Note what the environment executed on this session's behalf, and return how
|
|
271
|
+
* much of it is new.
|
|
272
|
+
*
|
|
273
|
+
* The context hook is the only place the host's own tool results are visible,
|
|
274
|
+
* and it runs on EVERY model request. A tool message that is still the newest
|
|
275
|
+
* one across two requests — which happens whenever the model is re-asked
|
|
276
|
+
* before it has produced a message of its own — would therefore be counted
|
|
277
|
+
* twice, and a report of "2 actions ran" for one `read` is a lie of exactly
|
|
278
|
+
* the kind this whole method exists to stop.
|
|
279
|
+
*
|
|
280
|
+
* So the driver keeps a watermark per session: the id of the last message it
|
|
281
|
+
* counted, and only results after it are new. Idempotent by construction —
|
|
282
|
+
* calling it with the same messages twice is a no-op, which is also what makes
|
|
283
|
+
* it testable without a host.
|
|
284
|
+
*/
|
|
285
|
+
noteExecutions(sessionID, messages) {
|
|
286
|
+
const seen = this.#counted.get(sessionID);
|
|
287
|
+
// Everything up to and INCLUDING the watermark was already counted. Skipping
|
|
288
|
+
// only the matching id is not enough: a request that carries three new
|
|
289
|
+
// messages would advance the watermark three times, and the next request
|
|
290
|
+
// would re-count the first two.
|
|
291
|
+
const start = seen === undefined ? 0 : messages.findIndex((m) => m.id === seen) + 1;
|
|
292
|
+
let fresh = 0;
|
|
293
|
+
for (const message of messages.slice(start)) {
|
|
294
|
+
if (message.role === 'tool' && Array.isArray(message.content)) {
|
|
295
|
+
fresh += message.content.filter((part) => typeof part === 'object' &&
|
|
296
|
+
part !== null &&
|
|
297
|
+
String(part.type).startsWith('tool-result')).length;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
const last = messages[messages.length - 1];
|
|
301
|
+
// A watermark that is not in this list means the host trimmed the history.
|
|
302
|
+
// Everything present is then new, and `start` is 0, so nothing is lost.
|
|
303
|
+
if (last !== undefined)
|
|
304
|
+
this.#counted.set(sessionID, last.id);
|
|
305
|
+
if (fresh > 0)
|
|
306
|
+
this.#executed.set(sessionID, (this.#executed.get(sessionID) ?? 0) + fresh);
|
|
307
|
+
return fresh;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Take the action this session was last asked to perform, if any.
|
|
311
|
+
*
|
|
312
|
+
* Taken exactly once per step, so a prompt built twice for one turn cannot
|
|
313
|
+
* show the model the same continuation twice — the same discipline the
|
|
314
|
+
* feedback queue uses, and for the same reason.
|
|
315
|
+
*/
|
|
316
|
+
takeContinuation(sessionID) {
|
|
317
|
+
const action = this.#pending.get(sessionID);
|
|
318
|
+
if (action === undefined)
|
|
319
|
+
return undefined;
|
|
320
|
+
this.#pending.delete(sessionID);
|
|
321
|
+
return action;
|
|
322
|
+
}
|
|
323
|
+
/** Forget a session's pending action, on reset or teardown. */
|
|
324
|
+
forget(sessionID) {
|
|
325
|
+
this.#pending.delete(sessionID);
|
|
326
|
+
}
|
|
327
|
+
/** Steps taken for a session, for diagnostics. */
|
|
328
|
+
stepsFor(sessionID) {
|
|
329
|
+
return this.#steps.get(sessionID) ?? 0;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|