@miller-tech/uap 1.118.1 → 1.119.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/dist/.tsbuildinfo +1 -1
- package/dist/cli/handsfree.d.ts.map +1 -1
- package/dist/cli/handsfree.js +39 -3
- package/dist/cli/handsfree.js.map +1 -1
- package/dist/delivery/handsfree-config.d.ts.map +1 -1
- package/dist/delivery/handsfree-config.js +2 -0
- package/dist/delivery/handsfree-config.js.map +1 -1
- package/dist/delivery/persistence-profile.d.ts +9 -0
- package/dist/delivery/persistence-profile.d.ts.map +1 -1
- package/dist/delivery/persistence-profile.js.map +1 -1
- package/package.json +1 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
- package/tools/agents/scripts/anthropic_proxy.py +257 -11
- package/tools/agents/tests/test_anthropic_proxy_streaming.py +20 -11
- package/tools/agents/tests/test_cycle_break_exploration.py +149 -0
- package/tools/agents/tests/test_deferral_break.py +177 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handsfree.d.ts","sourceRoot":"","sources":["../../src/cli/handsfree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;
|
|
1
|
+
{"version":3,"file":"handsfree.d.ts","sourceRoot":"","sources":["../../src/cli/handsfree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAiEH;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,cAAc,EAAE,OAAO,GACtB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAgFvD;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,CA8Jf"}
|
package/dist/cli/handsfree.js
CHANGED
|
@@ -22,6 +22,8 @@ import { findUapConfigPath, modifyUapConfig } from '../utils/config-loader.js';
|
|
|
22
22
|
import { loadLedger, initLedger, markItem, remainingItems, isComplete, formatRemaining, progress, syncLedgerFromTodos, } from '../delivery/completion-ledger.js';
|
|
23
23
|
import { loadPersistenceConfig, resolveActiveModel } from '../delivery/handsfree-config.js';
|
|
24
24
|
import { resolvePersistenceProfile } from '../delivery/persistence-profile.js';
|
|
25
|
+
/** Fix C: hard cap on pre-ledger nudges so a planning stall can never wedge. */
|
|
26
|
+
const PRE_LEDGER_MAX = Math.max(0, Number(process.env.UAP_HANDSFREE_PRELEDGER_MAX ?? 1));
|
|
25
27
|
function statePath(cwd) {
|
|
26
28
|
return join(cwd, '.uap', 'handsfree-state.json');
|
|
27
29
|
}
|
|
@@ -44,7 +46,7 @@ function saveState(cwd, st) {
|
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
function resetState(cwd) {
|
|
47
|
-
saveState(cwd, { blocks: 0, lastRemaining: Number.MAX_SAFE_INTEGER });
|
|
49
|
+
saveState(cwd, { blocks: 0, lastRemaining: Number.MAX_SAFE_INTEGER, preLedgerBlocks: 0 });
|
|
48
50
|
}
|
|
49
51
|
async function readStdin() {
|
|
50
52
|
if (process.stdin.isTTY)
|
|
@@ -70,8 +72,42 @@ export function decideStopCheck(cwd, stopHookActive) {
|
|
|
70
72
|
if (stopHookActive)
|
|
71
73
|
return { block: false, message: 'stop_hook_active — never re-block' };
|
|
72
74
|
const ledger = loadLedger(cwd);
|
|
73
|
-
if (!ledger)
|
|
74
|
-
|
|
75
|
+
if (!ledger) {
|
|
76
|
+
// Fix C: pre-ledger safety net. A LOCAL model (qwen) can defer at the
|
|
77
|
+
// PLANNING stage — "I need more exploration cycles to complete the plan" —
|
|
78
|
+
// and end the turn before ever writing a TodoWrite plan, so no ledger exists
|
|
79
|
+
// and the build silently stops. Nudge it (bounded to PRE_LEDGER_MAX,
|
|
80
|
+
// anti-wedge) to lay out the plan and start. Scoped to the LOCAL family only:
|
|
81
|
+
// it is the one that emits these deferrals and drives hands-free builds here.
|
|
82
|
+
// Frontier models keep their post-ledger blocker + intrinsic persistence, and
|
|
83
|
+
// Fable is trusted — so a casual (non-build) frontier/Fable session is never
|
|
84
|
+
// pre-ledger blocked. Disable via config / UAP_HANDSFREE_PRELEDGER=0.
|
|
85
|
+
const preProfile = resolvePersistenceProfile(resolveActiveModel(cwd), cfg);
|
|
86
|
+
const nudgeOn = cfg.preLedgerNudge !== false && PRE_LEDGER_MAX > 0;
|
|
87
|
+
const driven = preProfile.stopHookBlocks && preProfile.injectAutonomy && preProfile.family === 'local';
|
|
88
|
+
if (!nudgeOn || !driven) {
|
|
89
|
+
return { block: false, message: 'no active build ledger' };
|
|
90
|
+
}
|
|
91
|
+
const st0 = loadState(cwd);
|
|
92
|
+
const pre = st0.preLedgerBlocks ?? 0;
|
|
93
|
+
if (pre >= PRE_LEDGER_MAX) {
|
|
94
|
+
resetState(cwd);
|
|
95
|
+
return {
|
|
96
|
+
block: false,
|
|
97
|
+
giveUp: true,
|
|
98
|
+
message: `hands-free pre-ledger nudge exhausted after ${pre} attempt(s) — no ` +
|
|
99
|
+
'build plan was started; allowing stop. Consider escalating the model.',
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
saveState(cwd, { ...st0, preLedgerBlocks: pre + 1 });
|
|
103
|
+
return {
|
|
104
|
+
block: true,
|
|
105
|
+
message: 'NOT DONE — hands-free is on but no build plan exists yet. Do NOT stop to ' +
|
|
106
|
+
'ask for more cycles or permission. Lay out the full build as a TodoWrite ' +
|
|
107
|
+
'plan now (it auto-creates the completion ledger) and start building the ' +
|
|
108
|
+
'first item this turn.',
|
|
109
|
+
};
|
|
110
|
+
}
|
|
75
111
|
if (isComplete(ledger)) {
|
|
76
112
|
resetState(cwd);
|
|
77
113
|
return { block: false, message: 'build complete — all ledger items done' };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handsfree.js","sourceRoot":"","sources":["../../src/cli/handsfree.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"handsfree.js","sourceRoot":"","sources":["../../src/cli/handsfree.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handsfree-config.d.ts","sourceRoot":"","sources":["../../src/delivery/handsfree-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,mFAAmF;AACnF,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAsB,GAAG,iBAAiB,
|
|
1
|
+
{"version":3,"file":"handsfree-config.d.ts","sourceRoot":"","sources":["../../src/delivery/handsfree-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAElE,mFAAmF;AACnF,wBAAgB,qBAAqB,CAAC,GAAG,GAAE,MAAsB,GAAG,iBAAiB,CAiBpF;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAWtE"}
|
|
@@ -22,6 +22,8 @@ export function loadPersistenceConfig(cwd = process.cwd()) {
|
|
|
22
22
|
enabled: hf.enabled !== false && process.env.UAP_HANDSFREE !== '0',
|
|
23
23
|
...(envIntensity ? { intensity: envIntensity } : hf.intensity ? { intensity: hf.intensity } : {}),
|
|
24
24
|
...(hf.overrides ? { overrides: hf.overrides } : {}),
|
|
25
|
+
// Fix C: pre-ledger nudge, default ON; disable via config or UAP_HANDSFREE_PRELEDGER=0.
|
|
26
|
+
preLedgerNudge: hf.preLedgerNudge !== false && process.env.UAP_HANDSFREE_PRELEDGER !== '0',
|
|
25
27
|
};
|
|
26
28
|
}
|
|
27
29
|
/** The model doing the work — env override, else the executor role, else unknown. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handsfree-config.js","sourceRoot":"","sources":["../../src/delivery/handsfree-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAG7D,mFAAmF;AACnF,MAAM,UAAU,qBAAqB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC/D,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,GAAG;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACjE,IAAI,GAAG,GAA4B,EAAE,CAAC;IACtC,IAAI,CAAC;QACH,GAAG,GAAI,gBAAgB,CAAC,GAAG,CAA6B,IAAI,EAAE,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,GAAG,EAAE,CAAC;IACX,CAAC;IACD,MAAM,EAAE,GAAI,GAAG,CAAC,SAA2C,IAAI,EAAE,CAAC;IAClE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAqE,CAAC;IACvG,OAAO;QACL,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,GAAG;QAClE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjG,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"handsfree-config.js","sourceRoot":"","sources":["../../src/delivery/handsfree-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAG7D,mFAAmF;AACnF,MAAM,UAAU,qBAAqB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC/D,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,GAAG;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACjE,IAAI,GAAG,GAA4B,EAAE,CAAC;IACtC,IAAI,CAAC;QACH,GAAG,GAAI,gBAAgB,CAAC,GAAG,CAA6B,IAAI,EAAE,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,GAAG,EAAE,CAAC;IACX,CAAC;IACD,MAAM,EAAE,GAAI,GAAG,CAAC,SAA2C,IAAI,EAAE,CAAC;IAClE,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAqE,CAAC;IACvG,OAAO;QACL,OAAO,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,GAAG;QAClE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjG,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,wFAAwF;QACxF,cAAc,EAAE,EAAE,CAAC,cAAc,KAAK,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,KAAK,GAAG;KAC3F,CAAC;AACJ,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,kBAAkB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC5D,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IACtE,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACpE,IAAI,CAAC;QACH,MAAM,GAAG,GAAI,gBAAgB,CAAC,GAAG,CAA6B,IAAI,EAAE,CAAC;QACrE,MAAM,EAAE,GAAG,GAAG,CAAC,UAA2D,CAAC;QAC3E,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ;YAAE,OAAO,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -37,6 +37,15 @@ export interface PersistenceConfig {
|
|
|
37
37
|
intensity?: PersistenceIntensity;
|
|
38
38
|
/** per-model overrides keyed by model id substring. */
|
|
39
39
|
overrides?: Record<string, Partial<PersistenceProfile>>;
|
|
40
|
+
/**
|
|
41
|
+
* Fix C: pre-ledger safety net. When hands-free is ON but NO completion
|
|
42
|
+
* ledger exists yet, a driven model (local/frontier) can defer at the
|
|
43
|
+
* planning stage — "I need more exploration cycles to complete the plan" —
|
|
44
|
+
* and end the turn before ever writing a plan, so nothing blocks the stop.
|
|
45
|
+
* When enabled, the Stop hook nudges once (bounded, anti-wedge) to lay out
|
|
46
|
+
* the plan and start building. Default ON; only ever nudges driven models.
|
|
47
|
+
*/
|
|
48
|
+
preLedgerNudge?: boolean;
|
|
40
49
|
}
|
|
41
50
|
/**
|
|
42
51
|
* Resolve the effective persistence profile for a model. `off` when hands-free
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence-profile.d.ts","sourceRoot":"","sources":["../../src/delivery/persistence-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,OAAO,GAAG,UAAU,GAAG,YAAY,CAAC;AAC/E,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAErE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,oBAAoB,CAAC;IAChC,iFAAiF;IACjF,cAAc,EAAE,OAAO,CAAC;IACxB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,eAAe,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,cAAc,EAAE,OAAO,CAAC;CACzB;AAmBD,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAMhE;AAeD,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"persistence-profile.d.ts","sourceRoot":"","sources":["../../src/delivery/persistence-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,oBAAoB,GAAG,KAAK,GAAG,OAAO,GAAG,UAAU,GAAG,YAAY,CAAC;AAC/E,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAC;AAErE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;IACpB,SAAS,EAAE,oBAAoB,CAAC;IAChC,iFAAiF;IACjF,cAAc,EAAE,OAAO,CAAC;IACxB,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,eAAe,EAAE,MAAM,CAAC;IACxB,gFAAgF;IAChF,cAAc,EAAE,OAAO,CAAC;CACzB;AAmBD,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,CAMhE;AAeD,MAAM,WAAW,iBAAiB;IAChC,2DAA2D;IAC3D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sDAAsD;IACtD,SAAS,CAAC,EAAE,oBAAoB,CAAC;IACjC,uDAAuD;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACxD;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,GAAG,GAAE,iBAAsB,GAC1B,kBAAkB,CAqBpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"persistence-profile.js","sourceRoot":"","sources":["../../src/delivery/persistence-profile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAmBH,MAAM,QAAQ,GAA+F;IAC3G,qEAAqE;IACrE,KAAK,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,cAAc,EAAE,KAAK,EAAE;IAC5G,kEAAkE;IAClE,QAAQ,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE;IACjH,gFAAgF;IAChF,UAAU,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE;CACtH,CAAC;AAEF,MAAM,WAAW,GAAiD;IAChE,SAAS,EAAE,KAAK;IAChB,cAAc,EAAE,KAAK;IACrB,SAAS,EAAE,CAAC;IACZ,eAAe,EAAE,CAAC;IAClB,cAAc,EAAE,KAAK;CACtB,CAAC;AAEF,wEAAwE;AACxE,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,MAAM,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACxC,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,IAAI,wEAAwE,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,OAAO,CAAC;IACrG,IAAI,gDAAgD,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,UAAU,CAAC;IAChF,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,eAAe,CAAC,MAAmB;IAC1C,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,YAAY,CAAC;QACtB,KAAK,UAAU;YACb,OAAO,UAAU,CAAC;QACpB;YACE,OAAO,UAAU,CAAC;IACtB,CAAC;AACH,CAAC;
|
|
1
|
+
{"version":3,"file":"persistence-profile.js","sourceRoot":"","sources":["../../src/delivery/persistence-profile.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -231,6 +231,48 @@ _RATE_LIMITED_API_RE = re.compile(r"api\.github\.com", re.IGNORECASE)
|
|
|
231
231
|
PROXY_STUCK_TEXT_THRESHOLD = int(os.environ.get("PROXY_STUCK_TEXT_THRESHOLD", "2"))
|
|
232
232
|
PROXY_STUCK_API_THRESHOLD = int(os.environ.get("PROXY_STUCK_API_THRESHOLD", "3"))
|
|
233
233
|
|
|
234
|
+
# ---------------------------------------------------------------------------
|
|
235
|
+
# DEFERRAL-BREAK guardrail (Fix A): a model can end a turn with plain prose that
|
|
236
|
+
# DEFERS the work instead of doing it -- "I need more exploration cycles to
|
|
237
|
+
# complete the plan", "let me continue exploring", "I'll need a few more passes"
|
|
238
|
+
# -- with NO tool call. This is a turn-ending *capitulation*, not a loop
|
|
239
|
+
# admission, so STUCK-BREAK's phrase list never matches it; and because it is a
|
|
240
|
+
# no-tool turn, recon-convergence never advanced its streak either (that counter
|
|
241
|
+
# only moves on turns that emit tool calls). The stall therefore slips through
|
|
242
|
+
# every guardrail and silently halts a hands-free build (observed live: a run of
|
|
243
|
+
# back-to-back session-ends with "Code changed: false"). When a no-tool turn
|
|
244
|
+
# matches the deferral phrasing PROXY_DEFERRAL_THRESHOLD times in a row, the
|
|
245
|
+
# proxy forces the NEXT turn to take a concrete action: tool_choice=required plus
|
|
246
|
+
# a firm "continue autonomously, you will not be re-prompted" directive. This is
|
|
247
|
+
# the INVERSE of STUCK-BREAK (which releases to a prose exit) -- a deferral means
|
|
248
|
+
# work REMAINS, so we drive an action rather than allow a stop. Default on;
|
|
249
|
+
# PROXY_DEFERRAL_BREAK=off to disable.
|
|
250
|
+
PROXY_DEFERRAL_BREAK = os.environ.get("PROXY_DEFERRAL_BREAK", "on").lower() not in {
|
|
251
|
+
"0", "false", "off", "no",
|
|
252
|
+
}
|
|
253
|
+
# Turn-ending deferral/capitulation phrases (lowercased match). Deliberately
|
|
254
|
+
# narrow -- it must catch "I need more exploration cycles to complete the plan"
|
|
255
|
+
# and close kin, WITHOUT firing on ordinary forward-looking narration that is
|
|
256
|
+
# actually followed by a tool call (the no-tool-turn gate handles that too).
|
|
257
|
+
_DEFERRAL_PHRASE_RE = re.compile(
|
|
258
|
+
r"need (?:more|additional|further|extra) (?:exploration |investigation |research )?"
|
|
259
|
+
r"(?:cycles|passes|turns|iterations|rounds)"
|
|
260
|
+
r"|more (?:exploration |investigation )?(?:cycles|passes|iterations) "
|
|
261
|
+
r"(?:to|are needed|is needed|required|before)"
|
|
262
|
+
r"|to (?:complete|finish|continue) (?:the|my) (?:plan|exploration|investigation)"
|
|
263
|
+
r"|(?:let me|allow me to|i'?ll|i will|i need to|i'?d need to|"
|
|
264
|
+
r"we(?:'?ll| will| need to)) (?:keep|continue) "
|
|
265
|
+
r"(?:exploring|investigating|researching|working through|going)"
|
|
266
|
+
r"|(?:once|after) i(?:'ve| have)? (?:explored|investigated|gathered|reviewed) "
|
|
267
|
+
r"(?:more|additional|further|enough)"
|
|
268
|
+
r"|need to (?:gather|do|run|perform) (?:more|additional|further) "
|
|
269
|
+
r"(?:exploration|research|investigation|analysis)",
|
|
270
|
+
re.IGNORECASE,
|
|
271
|
+
)
|
|
272
|
+
# Fire on the FIRST deferral by default: a single "I need more cycles" no-tool
|
|
273
|
+
# turn IS the halt, unlike STUCK-BREAK which waits for a sustained loop.
|
|
274
|
+
PROXY_DEFERRAL_THRESHOLD = int(os.environ.get("PROXY_DEFERRAL_THRESHOLD", "1"))
|
|
275
|
+
|
|
234
276
|
PROXY_TOOL_STATE_MACHINE = os.environ.get(
|
|
235
277
|
"PROXY_TOOL_STATE_MACHINE", "on"
|
|
236
278
|
).lower() not in {
|
|
@@ -340,6 +382,83 @@ _WRITE_TOOL_CLASS = frozenset({
|
|
|
340
382
|
"write_file", "edit_file", "save_file",
|
|
341
383
|
})
|
|
342
384
|
|
|
385
|
+
# Open-ended exploration tools the agent uses to make a DIFFERENT move once a
|
|
386
|
+
# read/grep/glob loop is broken. The code cannot enumerate every exploration
|
|
387
|
+
# tool, but these are the universal escape hatches. Cycle-break narrowing must
|
|
388
|
+
# NEVER strip these: a cycling *Bash* means "vary the command" (handled by the
|
|
389
|
+
# injected cycle hint), NOT "lose the ability to run bash at all". Excluding
|
|
390
|
+
# Bash here stranded autonomous ("auto mode") agents with no way to explore the
|
|
391
|
+
# filesystem — the whole toolset minus its exploration escape hatch.
|
|
392
|
+
_EXPLORATION_ESCAPE_TOOLS = frozenset({
|
|
393
|
+
"bash", "shell", "sh", "run_bash", "runbash", "run_command",
|
|
394
|
+
"run_terminal_cmd", "execute_command", "executecommand", "terminal",
|
|
395
|
+
"webfetch", "web_fetch", "fetch", "websearch", "web_search",
|
|
396
|
+
"agent", "task", "dispatch_agent",
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def _narrow_tools_for_cycle_break(tools, cycling_tool_names, session_banned_tools):
|
|
401
|
+
"""Drop cycling + session-banned tools from the toolset, expanding to the
|
|
402
|
+
whole read-only class when any excluded tool is read-only.
|
|
403
|
+
|
|
404
|
+
The open-ended exploration escape hatch (Bash/WebFetch/Agent) is kept out of
|
|
405
|
+
the CYCLING-derived exclusion: a cycling Bash means "vary the command"
|
|
406
|
+
(handled by the injected cycle hint), not "lose the ability to run bash".
|
|
407
|
+
An explicit session ban is a stronger, deliberate signal (a tool that keeps
|
|
408
|
+
malforming) and IS still honored, even for those tools.
|
|
409
|
+
|
|
410
|
+
Returns ``(narrowed_tools, expanded_read_only_class)``. Tool-name matching is
|
|
411
|
+
case-insensitive so "Bash"/"bash" and "Read"/"read" behave identically.
|
|
412
|
+
"""
|
|
413
|
+
read_only_lower = {c.lower() for c in _READ_ONLY_TOOL_CLASS}
|
|
414
|
+
cycling_lower = {n.lower() for n in cycling_tool_names}
|
|
415
|
+
banned_lower = {n.lower() for n in session_banned_tools}
|
|
416
|
+
# Expand to the full read-only class if any excluded tool is read-only
|
|
417
|
+
# (preserves the original trigger over cycling ∪ banned).
|
|
418
|
+
expanded = any(n in read_only_lower for n in (cycling_lower | banned_lower))
|
|
419
|
+
cycling_exclude = set(cycling_lower)
|
|
420
|
+
if expanded:
|
|
421
|
+
cycling_exclude |= read_only_lower
|
|
422
|
+
# Never let the cycling path narrow away the exploration escape hatch — that
|
|
423
|
+
# is exactly the filesystem-exploration capability the cycle-break is trying
|
|
424
|
+
# to redirect the agent toward.
|
|
425
|
+
cycling_exclude -= _EXPLORATION_ESCAPE_TOOLS
|
|
426
|
+
exclude_set = cycling_exclude | banned_lower
|
|
427
|
+
|
|
428
|
+
def _name(t):
|
|
429
|
+
return ((t.get("function", {}) or {}).get("name", "") or "").lower()
|
|
430
|
+
|
|
431
|
+
narrowed = [t for t in tools if _name(t) not in exclude_set]
|
|
432
|
+
|
|
433
|
+
# Floor invariant: a loop-breaker must never strand the agent. If narrowing
|
|
434
|
+
# would remove the last way to make a DIFFERENT move — i.e. no exploration
|
|
435
|
+
# escape hatch AND no write tool survives, but the original set had one —
|
|
436
|
+
# keep the original toolset. This closes the door where an explicit ban of
|
|
437
|
+
# the sole exploration tool re-creates the very "can't explore" bug.
|
|
438
|
+
write_lower = {w.lower() for w in _WRITE_TOOL_CLASS}
|
|
439
|
+
|
|
440
|
+
def _has_action_path(tool_list):
|
|
441
|
+
names = {_name(t) for t in tool_list}
|
|
442
|
+
return bool(names & _EXPLORATION_ESCAPE_TOOLS) or bool(names & write_lower)
|
|
443
|
+
|
|
444
|
+
if _has_action_path(tools) and not _has_action_path(narrowed):
|
|
445
|
+
return list(tools), expanded
|
|
446
|
+
return narrowed, expanded
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
def _should_auto_ban(name, cycle_count, ban_at):
|
|
450
|
+
"""Whether a cycling tool should be added to session_banned_tools this round.
|
|
451
|
+
|
|
452
|
+
The auto-ban accumulator is itself cycling-derived (ban after N detections),
|
|
453
|
+
so exploration escape-hatch tools (Bash/WebFetch/Agent) are NEVER auto-banned
|
|
454
|
+
— banning Bash would re-strip the agent's only way to explore the filesystem
|
|
455
|
+
on the Nth cycle, re-creating the bug the narrowing exemption fixes for
|
|
456
|
+
earlier cycles. Repeated Bash is redirected via the injected cycle hint.
|
|
457
|
+
"""
|
|
458
|
+
if name.lower() in _EXPLORATION_ESCAPE_TOOLS:
|
|
459
|
+
return False
|
|
460
|
+
return cycle_count >= ban_at
|
|
461
|
+
|
|
343
462
|
PROXY_GUARDRAIL_RETRY = os.environ.get("PROXY_GUARDRAIL_RETRY", "on").lower() not in {
|
|
344
463
|
"0",
|
|
345
464
|
"false",
|
|
@@ -1175,6 +1294,8 @@ class SessionMonitor:
|
|
|
1175
1294
|
self_stuck_streak: int = 0 # consecutive assistant texts self-reporting a loop
|
|
1176
1295
|
rate_limited_api_streak: int = 0 # consecutive tool calls hitting a rate-limited API host
|
|
1177
1296
|
stuck_break_fires: int = 0 # monotonic count of forced stuck-breaks
|
|
1297
|
+
deferral_streak: int = 0 # consecutive no-tool turns deferring the work (Fix A)
|
|
1298
|
+
deferral_break_fires: int = 0 # monotonic count of forced deferral-breaks (Fix A)
|
|
1178
1299
|
tool_starvation_streak: int = 0 # Consecutive forced turns with no tool_calls produced
|
|
1179
1300
|
malformed_tool_streak: int = 0 # consecutive malformed pseudo tool payloads
|
|
1180
1301
|
invalid_tool_call_streak: int = 0 # consecutive invalid tool arg payloads
|
|
@@ -1444,6 +1565,50 @@ class SessionMonitor:
|
|
|
1444
1565
|
return True, f"rate-limited-API retries x{self.rate_limited_api_streak}"
|
|
1445
1566
|
return False, ""
|
|
1446
1567
|
|
|
1568
|
+
def note_deferral_signal(self, text: str, had_tool_call: bool) -> None:
|
|
1569
|
+
"""Track a turn-ending deferral/capitulation stall (Fix A): a plain-text
|
|
1570
|
+
assistant turn with NO tool call that asks for more cycles / more
|
|
1571
|
+
exploration / permission to keep going instead of taking the next build
|
|
1572
|
+
action. Only a no-tool turn whose text matches the deferral phrasing
|
|
1573
|
+
increments the streak; ANY tool call or non-matching text resets it, so a
|
|
1574
|
+
model that actually acts (or writes a normal summary) is never flagged."""
|
|
1575
|
+
if not PROXY_DEFERRAL_BREAK:
|
|
1576
|
+
self.deferral_streak = 0
|
|
1577
|
+
return
|
|
1578
|
+
if (not had_tool_call) and text and _DEFERRAL_PHRASE_RE.search(text):
|
|
1579
|
+
self.deferral_streak += 1
|
|
1580
|
+
else:
|
|
1581
|
+
self.deferral_streak = 0
|
|
1582
|
+
|
|
1583
|
+
def should_force_deferral_break(self) -> tuple[bool, str]:
|
|
1584
|
+
"""True + reason when a deferral-break should be forced this turn."""
|
|
1585
|
+
if not PROXY_DEFERRAL_BREAK:
|
|
1586
|
+
return False, ""
|
|
1587
|
+
if self.deferral_streak >= PROXY_DEFERRAL_THRESHOLD:
|
|
1588
|
+
return True, f"deferral/plan-capitulation x{self.deferral_streak}"
|
|
1589
|
+
return False, ""
|
|
1590
|
+
|
|
1591
|
+
def recon_convergence_pending(self) -> bool:
|
|
1592
|
+
"""True when recon-convergence will own this turn. DEFERRAL-BREAK yields
|
|
1593
|
+
to it (as it does to STUCK-BREAK) so the two guards never emit
|
|
1594
|
+
contradictory tool_choice/directives in the same request. Fix B makes
|
|
1595
|
+
their triggers climb in lockstep on prose-only stalls, so without this
|
|
1596
|
+
yield a deep prose stall could trip both and undo recon's terminal tier
|
|
1597
|
+
(which may strip tools and force a plain-text summary that ends the task)."""
|
|
1598
|
+
return (
|
|
1599
|
+
PROXY_RECON_CONVERGENCE_THRESHOLD > 0
|
|
1600
|
+
and self.consecutive_no_write_turns >= PROXY_RECON_CONVERGENCE_THRESHOLD
|
|
1601
|
+
)
|
|
1602
|
+
|
|
1603
|
+
def note_no_tool_turn(self) -> None:
|
|
1604
|
+
"""Fix B: a plain-text assistant turn with no tool call is still a
|
|
1605
|
+
non-write turn, so advance the recon-convergence streak. The old code
|
|
1606
|
+
only moved `consecutive_no_write_turns` on turns that emitted tool calls,
|
|
1607
|
+
so a model that stalls in prose (no tools at all) froze the counter and
|
|
1608
|
+
never escalated to the recon-convergence directive. Resets, like the
|
|
1609
|
+
tool-turn path, whenever a write tool is later emitted."""
|
|
1610
|
+
self.consecutive_no_write_turns += 1
|
|
1611
|
+
|
|
1447
1612
|
def has_duplicate_read_target(self, threshold: int = 2) -> tuple[bool, str]:
|
|
1448
1613
|
"""Check if any read-only tool has re-read the same target >= threshold times.
|
|
1449
1614
|
|
|
@@ -4028,7 +4193,13 @@ def _resolve_state_machine_tool_choice(
|
|
|
4028
4193
|
and PROXY_COORDINATION_BAN_THRESHOLD > 0
|
|
4029
4194
|
)
|
|
4030
4195
|
ban_at = PROXY_COORDINATION_BAN_THRESHOLD if is_coord else 3
|
|
4031
|
-
|
|
4196
|
+
# Exploration escape-hatch tools are never auto-banned — see
|
|
4197
|
+
# _should_auto_ban (banning Bash re-creates the "can't explore"
|
|
4198
|
+
# bug since the ban is itself cycling-derived).
|
|
4199
|
+
if (
|
|
4200
|
+
_should_auto_ban(name, monitor.tool_cycle_counts[name], ban_at)
|
|
4201
|
+
and name not in monitor.session_banned_tools
|
|
4202
|
+
):
|
|
4032
4203
|
monitor.session_banned_tools.add(name)
|
|
4033
4204
|
logger.warning(
|
|
4034
4205
|
"TOOL BAN: '%s' banned for session after %d cycle detections "
|
|
@@ -4178,6 +4349,60 @@ def _maybe_inject_stuck_break(openai_body: dict, monitor: "SessionMonitor") -> N
|
|
|
4178
4349
|
logger.warning("STUCK-BREAK: forced terminal turn (%s, fires=%d)", reason, monitor.stuck_break_fires)
|
|
4179
4350
|
|
|
4180
4351
|
|
|
4352
|
+
def _maybe_inject_deferral_break(openai_body: dict, monitor: "SessionMonitor") -> None:
|
|
4353
|
+
"""Convert a turn-ending deferral into forward motion (Fix A).
|
|
4354
|
+
|
|
4355
|
+
The model ended a turn with prose that DEFERS the work -- "I need more
|
|
4356
|
+
exploration cycles to complete the plan", "let me continue exploring" -- with
|
|
4357
|
+
no tool call, instead of taking the next build step. That stall is invisible
|
|
4358
|
+
to STUCK-BREAK (not a loop-admission phrase) and to recon-convergence (a
|
|
4359
|
+
no-tool turn never advanced its streak), so it silently ends a hands-free
|
|
4360
|
+
build. This forces the NEXT turn to ACT: it forces tool_choice and tells the
|
|
4361
|
+
model it will not be re-prompted. The INVERSE of STUCK-BREAK, which releases
|
|
4362
|
+
to a prose exit -- a deferral means work REMAINS.
|
|
4363
|
+
"""
|
|
4364
|
+
should, reason = monitor.should_force_deferral_break()
|
|
4365
|
+
if not should:
|
|
4366
|
+
return
|
|
4367
|
+
# STUCK-BREAK (a self-aware loop wanting a prose exit) is the more urgent
|
|
4368
|
+
# signal; if it will fire this turn, yield to it rather than force a tool.
|
|
4369
|
+
stuck, _ = monitor.should_force_stuck_break()
|
|
4370
|
+
if stuck:
|
|
4371
|
+
return
|
|
4372
|
+
# Also yield to recon-convergence: once the no-write streak is deep enough
|
|
4373
|
+
# for recon to own the turn (it may strip tools / force a terminal summary),
|
|
4374
|
+
# a "keep building" deferral directive would directly contradict it.
|
|
4375
|
+
if monitor.recon_convergence_pending():
|
|
4376
|
+
return
|
|
4377
|
+
# Only force an action if there are tools to call and the choice is not
|
|
4378
|
+
# already pinned to a specific tool by an earlier guard.
|
|
4379
|
+
has_tools = bool(openai_body.get("tools"))
|
|
4380
|
+
if has_tools and openai_body.get("tool_choice") in (None, "auto"):
|
|
4381
|
+
openai_body["tool_choice"] = "required"
|
|
4382
|
+
monitor.deferral_break_fires += 1
|
|
4383
|
+
directive = (
|
|
4384
|
+
"\n\nCONTINUE AUTONOMOUSLY (" + reason + "). You do NOT need more "
|
|
4385
|
+
"exploration cycles, another pass, or permission, and you will NOT be "
|
|
4386
|
+
"re-prompted to keep going. Do the next concrete step of the plan NOW: "
|
|
4387
|
+
"pick the next un-built file/component and create it with the write tool "
|
|
4388
|
+
"(or run the next required command). Never end a turn with only a plan, a "
|
|
4389
|
+
"status note, or a request for more cycles -- take the action this turn."
|
|
4390
|
+
)
|
|
4391
|
+
msgs = openai_body.get("messages")
|
|
4392
|
+
if not isinstance(msgs, list):
|
|
4393
|
+
msgs = []
|
|
4394
|
+
if msgs and msgs[0].get("role") == "system":
|
|
4395
|
+
msgs[0]["content"] = (msgs[0].get("content") or "") + directive
|
|
4396
|
+
else:
|
|
4397
|
+
msgs.insert(0, {"role": "system", "content": directive.strip()})
|
|
4398
|
+
openai_body["messages"] = msgs # reattach in case messages was empty/absent
|
|
4399
|
+
logger.warning(
|
|
4400
|
+
"DEFERRAL-BREAK: forced action turn (%s, fires=%d)",
|
|
4401
|
+
reason,
|
|
4402
|
+
monitor.deferral_break_fires,
|
|
4403
|
+
)
|
|
4404
|
+
|
|
4405
|
+
|
|
4181
4406
|
def _maybe_inject_recon_convergence(
|
|
4182
4407
|
openai_body: dict,
|
|
4183
4408
|
monitor: "SessionMonitor",
|
|
@@ -4853,16 +5078,15 @@ def build_openai_request(
|
|
|
4853
5078
|
(monitor.cycling_tool_names or monitor.session_banned_tools)
|
|
4854
5079
|
and "tools" in openai_body
|
|
4855
5080
|
):
|
|
4856
|
-
exclude_set = set(monitor.cycling_tool_names) | monitor.session_banned_tools
|
|
4857
|
-
# Expand to full read-only class if any cycling tool is read-only
|
|
4858
|
-
if any(n.lower() in {c.lower() for c in _READ_ONLY_TOOL_CLASS} for n in exclude_set):
|
|
4859
|
-
exclude_set |= _READ_ONLY_TOOL_CLASS
|
|
4860
5081
|
original_count = len(openai_body["tools"])
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
5082
|
+
# Drop cycling/banned tools (and the read-only class if any
|
|
5083
|
+
# cycling tool is read-only) but always keep the exploration
|
|
5084
|
+
# escape hatch — see _narrow_tools_for_cycle_break.
|
|
5085
|
+
narrowed, expanded_read_only = _narrow_tools_for_cycle_break(
|
|
5086
|
+
openai_body["tools"],
|
|
5087
|
+
monitor.cycling_tool_names,
|
|
5088
|
+
monitor.session_banned_tools,
|
|
5089
|
+
)
|
|
4866
5090
|
if narrowed:
|
|
4867
5091
|
openai_body["tools"] = narrowed
|
|
4868
5092
|
# Only log on first activation or phase transitions to reduce noise
|
|
@@ -4872,7 +5096,7 @@ def build_openai_request(
|
|
|
4872
5096
|
original_count,
|
|
4873
5097
|
len(narrowed),
|
|
4874
5098
|
monitor.cycling_tool_names,
|
|
4875
|
-
|
|
5099
|
+
expanded_read_only,
|
|
4876
5100
|
)
|
|
4877
5101
|
else:
|
|
4878
5102
|
logger.warning(
|
|
@@ -4959,6 +5183,10 @@ def build_openai_request(
|
|
|
4959
5183
|
|
|
4960
5184
|
_maybe_inject_stuck_break(openai_body, monitor)
|
|
4961
5185
|
|
|
5186
|
+
# DEFERRAL-BREAK (Fix A): after stuck-break, drive a no-tool deferral turn
|
|
5187
|
+
# into a concrete action. Runs last so it can yield to stuck-break.
|
|
5188
|
+
_maybe_inject_deferral_break(openai_body, monitor)
|
|
5189
|
+
|
|
4962
5190
|
_apply_thinking_grammar(openai_body)
|
|
4963
5191
|
|
|
4964
5192
|
_apply_json_response_grammar(openai_body, anthropic_body)
|
|
@@ -5090,12 +5318,21 @@ def _record_last_assistant_tool_calls(
|
|
|
5090
5318
|
messages = anthropic_body.get("messages", [])
|
|
5091
5319
|
tool_fingerprints = []
|
|
5092
5320
|
tool_targets: dict[str, str] = {}
|
|
5321
|
+
assistant_had_text = False # Fix B: did the last assistant turn emit prose?
|
|
5093
5322
|
for msg in reversed(messages):
|
|
5094
5323
|
if msg.get("role") != "assistant":
|
|
5095
5324
|
continue
|
|
5096
5325
|
content = msg.get("content")
|
|
5326
|
+
if isinstance(content, str) and content.strip():
|
|
5327
|
+
assistant_had_text = True
|
|
5097
5328
|
if isinstance(content, list):
|
|
5098
5329
|
for block in content:
|
|
5330
|
+
if (
|
|
5331
|
+
isinstance(block, dict)
|
|
5332
|
+
and block.get("type") == "text"
|
|
5333
|
+
and str(block.get("text", "")).strip()
|
|
5334
|
+
):
|
|
5335
|
+
assistant_had_text = True
|
|
5099
5336
|
if isinstance(block, dict) and block.get("type") == "tool_use":
|
|
5100
5337
|
tool_fingerprints.append(_tool_call_fingerprint(block))
|
|
5101
5338
|
# Extract target key for read-only dedup (Option 3)
|
|
@@ -5119,6 +5356,12 @@ def _record_last_assistant_tool_calls(
|
|
|
5119
5356
|
fingerprint=fingerprint,
|
|
5120
5357
|
)
|
|
5121
5358
|
return fingerprint
|
|
5359
|
+
# Fix B: no tool call in the last assistant turn. A plain-text turn is still
|
|
5360
|
+
# a non-write turn, so advance the recon-convergence streak (previously it
|
|
5361
|
+
# only moved on tool turns, freezing the counter through prose-only stalls).
|
|
5362
|
+
# Guard on real prose so an empty/absent assistant turn never inflates it.
|
|
5363
|
+
if assistant_had_text:
|
|
5364
|
+
monitor.note_no_tool_turn()
|
|
5122
5365
|
return ""
|
|
5123
5366
|
|
|
5124
5367
|
|
|
@@ -8729,6 +8972,9 @@ async def stream_anthropic_response(
|
|
|
8729
8972
|
try:
|
|
8730
8973
|
monitor.note_assistant_text(accumulated_text)
|
|
8731
8974
|
monitor.note_tool_arg_hosts(list(tc_args))
|
|
8975
|
+
# DEFERRAL-BREAK signal (Fix A): a no-tool prose turn that defers the
|
|
8976
|
+
# work. `tc_names` empty means this turn emitted no tool call.
|
|
8977
|
+
monitor.note_deferral_signal(accumulated_text, bool(tc_names))
|
|
8732
8978
|
except Exception:
|
|
8733
8979
|
pass
|
|
8734
8980
|
|
|
@@ -3465,8 +3465,10 @@ class TestCycleBreakOptions(unittest.TestCase):
|
|
|
3465
3465
|
setattr(proxy, "PROXY_TOOL_STATE_STAGNATION_THRESHOLD", old_stagnation)
|
|
3466
3466
|
setattr(proxy, "PROXY_TOOL_STATE_CYCLE_WINDOW", old_cycle_window)
|
|
3467
3467
|
|
|
3468
|
-
def
|
|
3469
|
-
"""
|
|
3468
|
+
def test_cycle_break_keeps_bash_exploration(self):
|
|
3469
|
+
"""Cycling on Bash must NOT strip the Bash tool — it is the agent's
|
|
3470
|
+
exploration escape hatch. (Regression: the cycle-break used to exclude
|
|
3471
|
+
Bash by name, blocking all filesystem exploration.)"""
|
|
3470
3472
|
old_state = getattr(proxy, "PROXY_TOOL_STATE_MACHINE")
|
|
3471
3473
|
old_min_msgs = getattr(proxy, "PROXY_TOOL_STATE_MIN_MESSAGES")
|
|
3472
3474
|
old_forced = getattr(proxy, "PROXY_TOOL_STATE_FORCED_BUDGET")
|
|
@@ -3516,9 +3518,10 @@ class TestCycleBreakOptions(unittest.TestCase):
|
|
|
3516
3518
|
|
|
3517
3519
|
openai = proxy.build_openai_request(body, monitor)
|
|
3518
3520
|
self.assertEqual(monitor.tool_turn_phase, "review")
|
|
3519
|
-
# Bash
|
|
3521
|
+
# Bash is the exploration escape hatch — it must remain available
|
|
3522
|
+
# even while cycling. Read and Write remain too.
|
|
3520
3523
|
tool_names = [t["function"]["name"] for t in openai.get("tools", [])]
|
|
3521
|
-
self.
|
|
3524
|
+
self.assertIn("Bash", tool_names)
|
|
3522
3525
|
self.assertIn("Read", tool_names)
|
|
3523
3526
|
self.assertIn("Write", tool_names)
|
|
3524
3527
|
finally:
|
|
@@ -4548,7 +4551,8 @@ class TestReadOnlyCycleClassExclusion(unittest.TestCase):
|
|
|
4548
4551
|
setattr(proxy, k, v)
|
|
4549
4552
|
|
|
4550
4553
|
def test_non_read_tool_cycling_no_class_expansion(self):
|
|
4551
|
-
"""When 'bash' is cycling, only
|
|
4554
|
+
"""When 'bash' is cycling, the read-only class is NOT expanded, and bash
|
|
4555
|
+
itself is preserved as the exploration escape hatch."""
|
|
4552
4556
|
old_vals = {
|
|
4553
4557
|
"PROXY_TOOL_STATE_MACHINE": getattr(proxy, "PROXY_TOOL_STATE_MACHINE"),
|
|
4554
4558
|
"PROXY_TOOL_STATE_MIN_MESSAGES": getattr(proxy, "PROXY_TOOL_STATE_MIN_MESSAGES"),
|
|
@@ -4581,8 +4585,9 @@ class TestReadOnlyCycleClassExclusion(unittest.TestCase):
|
|
|
4581
4585
|
remaining_names = [
|
|
4582
4586
|
t.get("function", {}).get("name") for t in openai_body.get("tools", [])
|
|
4583
4587
|
]
|
|
4584
|
-
|
|
4585
|
-
|
|
4588
|
+
# bash is an exploration escape hatch — cycling does not strip it.
|
|
4589
|
+
self.assertIn("bash", remaining_names)
|
|
4590
|
+
# Read-only tools should still be available (no class expansion)
|
|
4586
4591
|
self.assertIn("read", remaining_names)
|
|
4587
4592
|
self.assertIn("glob", remaining_names)
|
|
4588
4593
|
self.assertIn("grep", remaining_names)
|
|
@@ -4685,16 +4690,20 @@ class TestPersistentCycleExclusion(unittest.TestCase):
|
|
|
4685
4690
|
body = self._make_body_with_tools(all_tools)
|
|
4686
4691
|
monitor = proxy.SessionMonitor(context_window=262144)
|
|
4687
4692
|
|
|
4688
|
-
# Simulate
|
|
4689
|
-
|
|
4693
|
+
# Simulate a non-exploration tool cycling that triggers review. (Bash
|
|
4694
|
+
# is exempt from cycling exclusion, so use 'edit' to exercise the
|
|
4695
|
+
# persistence path.)
|
|
4696
|
+
monitor.cycling_tool_names = ["edit"]
|
|
4690
4697
|
monitor.tool_turn_phase = "act"
|
|
4691
4698
|
monitor.tool_state_forced_budget_remaining = 5
|
|
4692
4699
|
|
|
4693
4700
|
openai = proxy.build_openai_request(body, monitor)
|
|
4694
4701
|
|
|
4695
|
-
# In act phase with cycling_tool_names set,
|
|
4702
|
+
# In act phase with cycling_tool_names set, the cycling tool stays
|
|
4703
|
+
# excluded — but the exploration escape hatch (bash) is preserved.
|
|
4696
4704
|
remaining = [t["function"]["name"] for t in openai.get("tools", [])]
|
|
4697
|
-
self.assertNotIn("
|
|
4705
|
+
self.assertNotIn("edit", remaining)
|
|
4706
|
+
self.assertIn("bash", remaining)
|
|
4698
4707
|
self.assertIn("read", remaining)
|
|
4699
4708
|
self.assertIn("write", remaining)
|
|
4700
4709
|
finally:
|