jeo-code 0.8.26 → 0.8.27
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/CHANGELOG.md +13 -0
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/package.json +1 -1
- package/src/agent/engine.ts +28 -7
- package/src/commands/launch.ts +6 -1
- package/src/types/playwriter.d.ts +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
The README mirrors the latest 5 entries — regenerate with `bun run changelog:sync`.
|
|
8
8
|
|
|
9
|
+
## [0.8.27] - 2026-07-16
|
|
10
|
+
_Repeat-read recovery now survives both context-overflow and refusal-result elision without reopening mutating-call loops._
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **Exact repeat-read recovery after context elision** (`src/agent/engine.ts`) — after either provider context-overflow or refusal-result elision, the engine may replay its exact prior all-read-only tool batch once; mutation batches remain covered by the anti-spin guard.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- **Targeted regression coverage** (`test/repeat-bounce-and-trim.test.ts`) — covers one-time exact all-read-only replay after both elision paths and mutation anti-spin preservation.
|
|
17
|
+
|
|
18
|
+
### Verified
|
|
19
|
+
- Full `bun test` — 3079 pass / 0 fail across 304 files.
|
|
20
|
+
- `bun run typecheck` — no errors.
|
|
21
|
+
|
|
9
22
|
## [0.8.26] - 2026-07-14
|
|
10
23
|
_Model catalog cleanup (drop sub-4.6 Anthropic `claude-haiku-4-5` from the exposed catalog/aliases per user direction) plus a focused gap analysis against `gajae-code`'s (gjc) 0.8.0→0.10.1 release history (~200 PRs) — most of gjc's surface (RPC/ACP/coordinator-mcp/IRC-sidebar/psmux/Windows-team) doesn't exist in jeo's smaller architecture and was ruled out with direct evidence; a few genuinely applicable gaps were found and closed._
|
|
11
24
|
|
package/README.ja.md
CHANGED
|
@@ -283,11 +283,11 @@ CI は `.github/workflows/npm-publish.yml` で公開します — GitHub リリ
|
|
|
283
283
|
## 変更履歴 (Changelog)
|
|
284
284
|
|
|
285
285
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
286
|
+
- **[0.8.27]** (2026-07-16) — Repeat-read recovery now survives both context-overflow and refusal-result elision without reopening mutating-call loops.
|
|
286
287
|
- **[0.8.26]** (2026-07-14) — Model catalog cleanup (drop sub-4.6 Anthropic `claude-haiku-4-5` from the exposed catalog/aliases per user direction) plus a focused gap analysis against `gajae-code`'s (gjc) 0.8.0→0.10.1 release history (~200 PRs) — most of gjc's surface (RPC/ACP/coordinator-mcp/IRC-sidebar/psmux/Windows-team) doesn't exist in jeo's smaller architecture and was ruled out with direct evidence; a few genuinely applicable gaps were found and closed.
|
|
287
288
|
- **[0.8.25]** (2026-07-13) — Post-audit follow-up: 0.8.24's fixture-repair subagent flagged (but, correctly, did not itself fix — out of its assigned scope) a case-sensitivity bug in the new PlanSchema maker→verifier ordering rule. Fixed.
|
|
288
289
|
- **[0.8.24]** (2026-07-13) — Follow-up gap analysis against the same external "self-improving agent system" framework (Fable-5-style loops), continuing 0.8.23's audit into 4 more primitives: independent-verifier ENFORCEMENT (0.8.23 had the gate logic but nothing forced a plan to actually contain one), model-tier safety-boundary fallback (a false-positive safety refusal previously backed off forever on the SAME model instead of trying a genuinely different one — the pattern already shipped for rate limits), memory confidence that was self-assigned once instead of earned via a real verification event, and Dynamic Workflows (jeo had parallel fan-out but no sequential composition or real control flow across subagent calls). Closed all 4, the last one non-trivially: an in-process `AsyncFunction` (the same pattern `browser {run}` already ships) cannot be given a real wall-clock timeout — a synchronous bug in agent-authored code blocks jeo's own event loop forever, and `Promise.race` can never preempt it (verified empirically). Fixed by running Dynamic Workflows scripts in an isolated `Worker` (a genuinely separate OS thread `worker.terminate()` can preempt unconditionally, mirroring `bashTool`'s own SIGTERM/SIGKILL escalation on a spawned process) with `task()` bridged back to the main thread over a `postMessage` RPC — config/credentials never leave the main thread, and every dispatch (however the script shapes it) stays bounded by a real concurrency semaphore, not just a per-call count cap.
|
|
289
290
|
- **[0.8.23]** (2026-07-12) — Gap analysis against an external "self-improving agent system" framework (Fable-5-style loops: independent verifiers, memory compounding, model-tier cost discipline, and scheduled routines) found jeo-code already had strong equivalents for most primitives — but 3 real gaps and 1 deliberately-scoped-safe gap. Closed all 4: skills that were "hand-authored, read-mostly, zero learning" now compound from real session failures; screenshots that were captured but never judged now close a real vision-verify loop; the `/goal` verifier and bulk fan-out dispatch that silently rode the same full-price model as the work they graded/executed now default to a cheap tier; and "runs without your laptop" is now achievable via a generated GitHub Actions template wrapping jeo's existing headless mode — with zero new attack surface inside jeo-code itself (no code-exec sandbox, no in-process scheduler/webhook receiver, both deliberately rejected as out of scope). Also absorbs 3 fixes shipped after 0.8.22 but never changelogged: a rate-limit fast-fallback audit that closed 4 real gaps, plus the cross-file `mock.module()` test-isolation class this release's own test additions collided with and fixed at its root cause.
|
|
290
|
-
- **[0.8.22]** (2026-07-11) — A rescan of the working tree turned up a resume-fidelity gap plus two unwired TUI safety-net helpers left by a concurrent session; each was traced, wired where needed, and verified before shipping.
|
|
291
291
|
|
|
292
292
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
293
293
|
<!-- CHANGELOG:END -->
|
package/README.ko.md
CHANGED
|
@@ -284,11 +284,11 @@ CI는 `.github/workflows/npm-publish.yml`로 배포합니다 — GitHub 릴리
|
|
|
284
284
|
## 변경 이력 (Changelog)
|
|
285
285
|
|
|
286
286
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
287
|
+
- **[0.8.27]** (2026-07-16) — Repeat-read recovery now survives both context-overflow and refusal-result elision without reopening mutating-call loops.
|
|
287
288
|
- **[0.8.26]** (2026-07-14) — Model catalog cleanup (drop sub-4.6 Anthropic `claude-haiku-4-5` from the exposed catalog/aliases per user direction) plus a focused gap analysis against `gajae-code`'s (gjc) 0.8.0→0.10.1 release history (~200 PRs) — most of gjc's surface (RPC/ACP/coordinator-mcp/IRC-sidebar/psmux/Windows-team) doesn't exist in jeo's smaller architecture and was ruled out with direct evidence; a few genuinely applicable gaps were found and closed.
|
|
288
289
|
- **[0.8.25]** (2026-07-13) — Post-audit follow-up: 0.8.24's fixture-repair subagent flagged (but, correctly, did not itself fix — out of its assigned scope) a case-sensitivity bug in the new PlanSchema maker→verifier ordering rule. Fixed.
|
|
289
290
|
- **[0.8.24]** (2026-07-13) — Follow-up gap analysis against the same external "self-improving agent system" framework (Fable-5-style loops), continuing 0.8.23's audit into 4 more primitives: independent-verifier ENFORCEMENT (0.8.23 had the gate logic but nothing forced a plan to actually contain one), model-tier safety-boundary fallback (a false-positive safety refusal previously backed off forever on the SAME model instead of trying a genuinely different one — the pattern already shipped for rate limits), memory confidence that was self-assigned once instead of earned via a real verification event, and Dynamic Workflows (jeo had parallel fan-out but no sequential composition or real control flow across subagent calls). Closed all 4, the last one non-trivially: an in-process `AsyncFunction` (the same pattern `browser {run}` already ships) cannot be given a real wall-clock timeout — a synchronous bug in agent-authored code blocks jeo's own event loop forever, and `Promise.race` can never preempt it (verified empirically). Fixed by running Dynamic Workflows scripts in an isolated `Worker` (a genuinely separate OS thread `worker.terminate()` can preempt unconditionally, mirroring `bashTool`'s own SIGTERM/SIGKILL escalation on a spawned process) with `task()` bridged back to the main thread over a `postMessage` RPC — config/credentials never leave the main thread, and every dispatch (however the script shapes it) stays bounded by a real concurrency semaphore, not just a per-call count cap.
|
|
290
291
|
- **[0.8.23]** (2026-07-12) — Gap analysis against an external "self-improving agent system" framework (Fable-5-style loops: independent verifiers, memory compounding, model-tier cost discipline, and scheduled routines) found jeo-code already had strong equivalents for most primitives — but 3 real gaps and 1 deliberately-scoped-safe gap. Closed all 4: skills that were "hand-authored, read-mostly, zero learning" now compound from real session failures; screenshots that were captured but never judged now close a real vision-verify loop; the `/goal` verifier and bulk fan-out dispatch that silently rode the same full-price model as the work they graded/executed now default to a cheap tier; and "runs without your laptop" is now achievable via a generated GitHub Actions template wrapping jeo's existing headless mode — with zero new attack surface inside jeo-code itself (no code-exec sandbox, no in-process scheduler/webhook receiver, both deliberately rejected as out of scope). Also absorbs 3 fixes shipped after 0.8.22 but never changelogged: a rate-limit fast-fallback audit that closed 4 real gaps, plus the cross-file `mock.module()` test-isolation class this release's own test additions collided with and fixed at its root cause.
|
|
291
|
-
- **[0.8.22]** (2026-07-11) — A rescan of the working tree turned up a resume-fidelity gap plus two unwired TUI safety-net helpers left by a concurrent session; each was traced, wired where needed, and verified before shipping.
|
|
292
292
|
|
|
293
293
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
294
294
|
<!-- CHANGELOG:END -->
|
package/README.md
CHANGED
|
@@ -291,11 +291,11 @@ Huge thanks to [gajae-code](https://github.com/Yeachan-Heo/gajae-code) for the i
|
|
|
291
291
|
## Changelog
|
|
292
292
|
|
|
293
293
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
294
|
+
- **[0.8.27]** (2026-07-16) — Repeat-read recovery now survives both context-overflow and refusal-result elision without reopening mutating-call loops.
|
|
294
295
|
- **[0.8.26]** (2026-07-14) — Model catalog cleanup (drop sub-4.6 Anthropic `claude-haiku-4-5` from the exposed catalog/aliases per user direction) plus a focused gap analysis against `gajae-code`'s (gjc) 0.8.0→0.10.1 release history (~200 PRs) — most of gjc's surface (RPC/ACP/coordinator-mcp/IRC-sidebar/psmux/Windows-team) doesn't exist in jeo's smaller architecture and was ruled out with direct evidence; a few genuinely applicable gaps were found and closed.
|
|
295
296
|
- **[0.8.25]** (2026-07-13) — Post-audit follow-up: 0.8.24's fixture-repair subagent flagged (but, correctly, did not itself fix — out of its assigned scope) a case-sensitivity bug in the new PlanSchema maker→verifier ordering rule. Fixed.
|
|
296
297
|
- **[0.8.24]** (2026-07-13) — Follow-up gap analysis against the same external "self-improving agent system" framework (Fable-5-style loops), continuing 0.8.23's audit into 4 more primitives: independent-verifier ENFORCEMENT (0.8.23 had the gate logic but nothing forced a plan to actually contain one), model-tier safety-boundary fallback (a false-positive safety refusal previously backed off forever on the SAME model instead of trying a genuinely different one — the pattern already shipped for rate limits), memory confidence that was self-assigned once instead of earned via a real verification event, and Dynamic Workflows (jeo had parallel fan-out but no sequential composition or real control flow across subagent calls). Closed all 4, the last one non-trivially: an in-process `AsyncFunction` (the same pattern `browser {run}` already ships) cannot be given a real wall-clock timeout — a synchronous bug in agent-authored code blocks jeo's own event loop forever, and `Promise.race` can never preempt it (verified empirically). Fixed by running Dynamic Workflows scripts in an isolated `Worker` (a genuinely separate OS thread `worker.terminate()` can preempt unconditionally, mirroring `bashTool`'s own SIGTERM/SIGKILL escalation on a spawned process) with `task()` bridged back to the main thread over a `postMessage` RPC — config/credentials never leave the main thread, and every dispatch (however the script shapes it) stays bounded by a real concurrency semaphore, not just a per-call count cap.
|
|
297
298
|
- **[0.8.23]** (2026-07-12) — Gap analysis against an external "self-improving agent system" framework (Fable-5-style loops: independent verifiers, memory compounding, model-tier cost discipline, and scheduled routines) found jeo-code already had strong equivalents for most primitives — but 3 real gaps and 1 deliberately-scoped-safe gap. Closed all 4: skills that were "hand-authored, read-mostly, zero learning" now compound from real session failures; screenshots that were captured but never judged now close a real vision-verify loop; the `/goal` verifier and bulk fan-out dispatch that silently rode the same full-price model as the work they graded/executed now default to a cheap tier; and "runs without your laptop" is now achievable via a generated GitHub Actions template wrapping jeo's existing headless mode — with zero new attack surface inside jeo-code itself (no code-exec sandbox, no in-process scheduler/webhook receiver, both deliberately rejected as out of scope). Also absorbs 3 fixes shipped after 0.8.22 but never changelogged: a rate-limit fast-fallback audit that closed 4 real gaps, plus the cross-file `mock.module()` test-isolation class this release's own test additions collided with and fixed at its root cause.
|
|
298
|
-
- **[0.8.22]** (2026-07-11) — A rescan of the working tree turned up a resume-fidelity gap plus two unwired TUI safety-net helpers left by a concurrent session; each was traced, wired where needed, and verified before shipping.
|
|
299
299
|
|
|
300
300
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
301
301
|
<!-- CHANGELOG:END -->
|
package/README.zh.md
CHANGED
|
@@ -283,11 +283,11 @@ CI 通过 `.github/workflows/npm-publish.yml` 发布 — GitHub 发布 release
|
|
|
283
283
|
## 更新日志 (Changelog)
|
|
284
284
|
|
|
285
285
|
<!-- CHANGELOG:START (auto-generated from CHANGELOG.md — run `bun run changelog:sync`) -->
|
|
286
|
+
- **[0.8.27]** (2026-07-16) — Repeat-read recovery now survives both context-overflow and refusal-result elision without reopening mutating-call loops.
|
|
286
287
|
- **[0.8.26]** (2026-07-14) — Model catalog cleanup (drop sub-4.6 Anthropic `claude-haiku-4-5` from the exposed catalog/aliases per user direction) plus a focused gap analysis against `gajae-code`'s (gjc) 0.8.0→0.10.1 release history (~200 PRs) — most of gjc's surface (RPC/ACP/coordinator-mcp/IRC-sidebar/psmux/Windows-team) doesn't exist in jeo's smaller architecture and was ruled out with direct evidence; a few genuinely applicable gaps were found and closed.
|
|
287
288
|
- **[0.8.25]** (2026-07-13) — Post-audit follow-up: 0.8.24's fixture-repair subagent flagged (but, correctly, did not itself fix — out of its assigned scope) a case-sensitivity bug in the new PlanSchema maker→verifier ordering rule. Fixed.
|
|
288
289
|
- **[0.8.24]** (2026-07-13) — Follow-up gap analysis against the same external "self-improving agent system" framework (Fable-5-style loops), continuing 0.8.23's audit into 4 more primitives: independent-verifier ENFORCEMENT (0.8.23 had the gate logic but nothing forced a plan to actually contain one), model-tier safety-boundary fallback (a false-positive safety refusal previously backed off forever on the SAME model instead of trying a genuinely different one — the pattern already shipped for rate limits), memory confidence that was self-assigned once instead of earned via a real verification event, and Dynamic Workflows (jeo had parallel fan-out but no sequential composition or real control flow across subagent calls). Closed all 4, the last one non-trivially: an in-process `AsyncFunction` (the same pattern `browser {run}` already ships) cannot be given a real wall-clock timeout — a synchronous bug in agent-authored code blocks jeo's own event loop forever, and `Promise.race` can never preempt it (verified empirically). Fixed by running Dynamic Workflows scripts in an isolated `Worker` (a genuinely separate OS thread `worker.terminate()` can preempt unconditionally, mirroring `bashTool`'s own SIGTERM/SIGKILL escalation on a spawned process) with `task()` bridged back to the main thread over a `postMessage` RPC — config/credentials never leave the main thread, and every dispatch (however the script shapes it) stays bounded by a real concurrency semaphore, not just a per-call count cap.
|
|
289
290
|
- **[0.8.23]** (2026-07-12) — Gap analysis against an external "self-improving agent system" framework (Fable-5-style loops: independent verifiers, memory compounding, model-tier cost discipline, and scheduled routines) found jeo-code already had strong equivalents for most primitives — but 3 real gaps and 1 deliberately-scoped-safe gap. Closed all 4: skills that were "hand-authored, read-mostly, zero learning" now compound from real session failures; screenshots that were captured but never judged now close a real vision-verify loop; the `/goal` verifier and bulk fan-out dispatch that silently rode the same full-price model as the work they graded/executed now default to a cheap tier; and "runs without your laptop" is now achievable via a generated GitHub Actions template wrapping jeo's existing headless mode — with zero new attack surface inside jeo-code itself (no code-exec sandbox, no in-process scheduler/webhook receiver, both deliberately rejected as out of scope). Also absorbs 3 fixes shipped after 0.8.22 but never changelogged: a rate-limit fast-fallback audit that closed 4 real gaps, plus the cross-file `mock.module()` test-isolation class this release's own test additions collided with and fixed at its root cause.
|
|
290
|
-
- **[0.8.22]** (2026-07-11) — A rescan of the working tree turned up a resume-fidelity gap plus two unwired TUI safety-net helpers left by a concurrent session; each was traced, wired where needed, and verified before shipping.
|
|
291
291
|
|
|
292
292
|
See [CHANGELOG.md](CHANGELOG.md) for the full history.
|
|
293
293
|
<!-- CHANGELOG:END -->
|
package/package.json
CHANGED
package/src/agent/engine.ts
CHANGED
|
@@ -108,6 +108,16 @@ export const DEFAULT_TOOLS: Record<string, ToolHandler> = {
|
|
|
108
108
|
browser: createBrowserTool(),
|
|
109
109
|
bisect: (a, cwd) => bisectTool(a.good, a.bad, a.run, !!a.invert, a.maxSteps, a.stepTimeoutMs, cwd),
|
|
110
110
|
};
|
|
111
|
+
|
|
112
|
+
/** Tool names whose calls have no workspace side effects. Shared by execution,
|
|
113
|
+
* failure accounting, and the refusal-recovery replay exemption. */
|
|
114
|
+
const READONLY_TOOL_NAMES: Record<string, true> = {
|
|
115
|
+
read: true,
|
|
116
|
+
find: true,
|
|
117
|
+
search: true,
|
|
118
|
+
ls: true,
|
|
119
|
+
web_search: true,
|
|
120
|
+
};
|
|
111
121
|
/** Tool-protocol description injected into the system prompt. */
|
|
112
122
|
export const TOOL_PROTOCOL = [
|
|
113
123
|
"You have these tools (call exactly ONE per step, or batch multiple independent calls):",
|
|
@@ -617,6 +627,10 @@ export async function runAgentLoop(history: Message[], opts: AgentLoopOptions):
|
|
|
617
627
|
// resend is exactly as safe as the refusal ladder's rung-1 free resend below.
|
|
618
628
|
let transientNetworkRetries = 0;
|
|
619
629
|
let lastSig = "";
|
|
630
|
+
// Context recovery can erase evidence the model was explicitly told it may
|
|
631
|
+
// re-run. Consume this exact prior signature at the next valid tool decision;
|
|
632
|
+
// only an identical all-read-only batch can bypass the normal repeat correction once.
|
|
633
|
+
let elidedReadReplaySig: string | null = null;
|
|
620
634
|
let repeatCount = 0;
|
|
621
635
|
// Cycle guard (the A↔B ping-pong the exact-repeat guard cannot see): the recent
|
|
622
636
|
// executed step signatures, as fixed-size digests. When a full window cycles
|
|
@@ -793,6 +807,7 @@ export async function runAgentLoop(history: Message[], opts: AgentLoopOptions):
|
|
|
793
807
|
// this prompt — freeing real space beats keeping evidence that can be re-run.
|
|
794
808
|
const res = trimToolResultsInPlace(history, { budgetTokens: Math.max(1, Math.floor(maxHistoryTokens / 2)), keepRecent: 2 });
|
|
795
809
|
if (res.trimmed > 0) {
|
|
810
|
+
if (lastSig) elidedReadReplaySig = lastSig;
|
|
796
811
|
ev.onNotice?.(`provider reported context overflow — elided ${res.trimmed} older tool result(s), retrying once`);
|
|
797
812
|
continue; // free retry: the step counter is unchanged
|
|
798
813
|
}
|
|
@@ -839,6 +854,7 @@ export async function runAgentLoop(history: Message[], opts: AgentLoopOptions):
|
|
|
839
854
|
const strippedTurns = stripReasoningArtifactsInPlace(history);
|
|
840
855
|
const parts: string[] = [];
|
|
841
856
|
if (res.trimmed > 0) parts.push(`reset ${res.trimmed} tool result(s)`);
|
|
857
|
+
if (res.trimmed > 0 && lastSig) elidedReadReplaySig = lastSig;
|
|
842
858
|
if (strippedTurns > 0) parts.push(`dropped thinking replay from ${strippedTurns} turn(s)`);
|
|
843
859
|
ev.onNotice?.(
|
|
844
860
|
parts.length
|
|
@@ -1161,7 +1177,16 @@ export async function runAgentLoop(history: Message[], opts: AgentLoopOptions):
|
|
|
1161
1177
|
|
|
1162
1178
|
|
|
1163
1179
|
const sig = callSigs.length === 1 ? callSigs[0] : hashSignature(callSigs.join(" | "));
|
|
1164
|
-
|
|
1180
|
+
const replayingElidedReadOnlyBatch =
|
|
1181
|
+
elidedReadReplaySig === sig &&
|
|
1182
|
+
toolCalls.every(call => READONLY_TOOL_NAMES[call.tool] === true);
|
|
1183
|
+
// The exemption is tied to the next valid tool-call decision, not to a later
|
|
1184
|
+
// matching call. A changed, mutating, or unknown-tool batch consumes it too.
|
|
1185
|
+
elidedReadReplaySig = null;
|
|
1186
|
+
if (replayingElidedReadOnlyBatch) {
|
|
1187
|
+
repeatCount = 1;
|
|
1188
|
+
lastSig = sig;
|
|
1189
|
+
} else if (sig === lastSig) repeatCount++;
|
|
1165
1190
|
else {
|
|
1166
1191
|
repeatCount = 1;
|
|
1167
1192
|
lastSig = sig;
|
|
@@ -1261,13 +1286,10 @@ export async function runAgentLoop(history: Message[], opts: AgentLoopOptions):
|
|
|
1261
1286
|
return { success, output };
|
|
1262
1287
|
};
|
|
1263
1288
|
|
|
1264
|
-
const READONLY_TOOLS = new Set(["read", "find", "search", "ls", "web_search"]);
|
|
1265
1289
|
const WRITE_TOOLS = new Set(["write", "edit"]);
|
|
1266
1290
|
// Batch grouping → concurrency plan (plan/gjc-inheritance.md cycle 12):
|
|
1267
1291
|
// read group — consecutive read-only calls run in parallel (safe).
|
|
1268
1292
|
// write group — consecutive write/edit calls to DISTINCT files run in
|
|
1269
|
-
// parallel; a same-file (or path-less) collision opens a
|
|
1270
|
-
// sequential boundary so ordered edits to one file stay ordered.
|
|
1271
1293
|
// exclusive group — bash (and anything else) always runs alone, in order.
|
|
1272
1294
|
// Reads and writes never share a group, so a read can never race a write.
|
|
1273
1295
|
type ToolGroup = {
|
|
@@ -1288,7 +1310,7 @@ export async function runAgentLoop(history: Message[], opts: AgentLoopOptions):
|
|
|
1288
1310
|
for (let i = 0; i < toolCalls.length; i++) {
|
|
1289
1311
|
const entry = { ...toolCalls[i], index: i };
|
|
1290
1312
|
const last = groups[groups.length - 1];
|
|
1291
|
-
if (
|
|
1313
|
+
if (READONLY_TOOL_NAMES[entry.tool] === true) {
|
|
1292
1314
|
if (last && last.kind === "read") last.calls.push(entry);
|
|
1293
1315
|
else groups.push({ kind: "read", calls: [entry] });
|
|
1294
1316
|
} else if (WRITE_TOOLS.has(entry.tool)) {
|
|
@@ -1442,11 +1464,10 @@ export async function runAgentLoop(history: Message[], opts: AgentLoopOptions):
|
|
|
1442
1464
|
// Read-only-only steps keep the old any-success rule.
|
|
1443
1465
|
const nonTrivial = toolCalls
|
|
1444
1466
|
.map((c, i) => ({ tool: c.tool, r: results[i] }))
|
|
1445
|
-
.filter(x =>
|
|
1467
|
+
.filter(x => READONLY_TOOL_NAMES[x.tool] !== true && x.r.executed);
|
|
1446
1468
|
const stepSuccess = nonTrivial.length > 0
|
|
1447
1469
|
? nonTrivial.some(x => x.r.success)
|
|
1448
1470
|
: results.some(r => r.success);
|
|
1449
|
-
|
|
1450
1471
|
if (stepSuccess) {
|
|
1451
1472
|
consecutiveFailures = 0;
|
|
1452
1473
|
} else if (++consecutiveFailures >= MAX_FAILURES) {
|
package/src/commands/launch.ts
CHANGED
|
@@ -1696,7 +1696,12 @@ export async function runLaunchCommand(args: string[]): Promise<void> {
|
|
|
1696
1696
|
? Math.floor(routeFallbackMaxRaw)
|
|
1697
1697
|
: 3;
|
|
1698
1698
|
for (let routeFallbackAttempt = 0; routeFallbackAttempt < routeFallbackMax; routeFallbackAttempt++) {
|
|
1699
|
-
|
|
1699
|
+
// A loop guard is a local safety boundary, not a provider failure. A
|
|
1700
|
+
// fresh loop on an equivalent model loses the guard state and could
|
|
1701
|
+
// re-execute a previously skipped mutation.
|
|
1702
|
+
const routedFailureReason = !result.done && !result.stopClass
|
|
1703
|
+
? routeFailureReason(result.doneReason)
|
|
1704
|
+
: null;
|
|
1700
1705
|
if (!routedFailureReason) break;
|
|
1701
1706
|
const fallback = await equivalentRouteFallback(fallbackBaseDecision, routedFailureReason, [...attemptedRouteModels]);
|
|
1702
1707
|
if (!fallback) break;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// src/types/playwriter.d.ts
|
|
2
|
+
// Declaration file to allow TypeScript to recognize the optional Playwriter CLI module.
|
|
3
|
+
// This is only needed for the example automation script in scripts/playwriter-apply.ts.
|
|
4
|
+
// The actual Playwriter package is expected to be installed globally or run via npx.
|
|
5
|
+
|
|
6
|
+
declare module "playwriter" {
|
|
7
|
+
export class Playwriter {
|
|
8
|
+
/** Connect to the running Chrome extension bridge */
|
|
9
|
+
connect(): Promise<void>;
|
|
10
|
+
/** Open a new page (tab) in the connected browser */
|
|
11
|
+
newPage(): Promise<any>;
|
|
12
|
+
/** Disconnect from the bridge */
|
|
13
|
+
disconnect(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
}
|