@miller-tech/uap 1.130.2 → 1.132.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/deliver.js +45 -29
- package/dist/cli/deliver.js.map +1 -1
- package/dist/cli/handsfree.d.ts.map +1 -1
- package/dist/cli/handsfree.js +12 -1
- package/dist/cli/handsfree.js.map +1 -1
- package/dist/delivery/context-budget.d.ts +25 -3
- package/dist/delivery/context-budget.d.ts.map +1 -1
- package/dist/delivery/context-budget.js +74 -3
- package/dist/delivery/context-budget.js.map +1 -1
- package/dist/delivery/decompose.d.ts.map +1 -1
- package/dist/delivery/decompose.js +4 -1
- package/dist/delivery/decompose.js.map +1 -1
- package/dist/delivery/epic-controller.d.ts +20 -1
- package/dist/delivery/epic-controller.d.ts.map +1 -1
- package/dist/delivery/epic-controller.js +21 -10
- package/dist/delivery/epic-controller.js.map +1 -1
- package/dist/delivery/persistence-profile.d.ts.map +1 -1
- package/dist/delivery/persistence-profile.js +19 -2
- 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 +148 -6
- package/tools/agents/tests/test_prune_preserve_force_write.py +209 -0
|
@@ -23,16 +23,31 @@ export const DEFAULT_SESSION_TOKEN_BUDGET = 131072;
|
|
|
23
23
|
* anthropic-proxy's prune threshold (PROXY_CONTEXT_PRUNE_THRESHOLD=0.70): a
|
|
24
24
|
* session that finishes below 70% of the rail is never pruned mid-mission, so
|
|
25
25
|
* an epic sized to the working budget completes with its full context intact.
|
|
26
|
+
* Operator-tunable via UAP_DELIVER_WORKING_FRACTION (0<f≤1) to push toward
|
|
27
|
+
* maximum ctx use — but keep it ALIGNED with the proxy prune threshold, or
|
|
28
|
+
* sessions sized past the threshold get pruned mid-mission (defeating it).
|
|
26
29
|
*/
|
|
27
|
-
export const SESSION_WORKING_FRACTION =
|
|
30
|
+
export const SESSION_WORKING_FRACTION = (() => {
|
|
31
|
+
const raw = Number(process.env.UAP_DELIVER_WORKING_FRACTION);
|
|
32
|
+
return Number.isFinite(raw) && raw > 0 && raw <= 1 ? raw : 0.7;
|
|
33
|
+
})();
|
|
28
34
|
/** Floor below which a budget value is treated as a misconfiguration. */
|
|
29
35
|
const MIN_SANE_BUDGET = 8192;
|
|
30
36
|
function saneBudget(raw) {
|
|
31
37
|
const n = Number(raw);
|
|
32
38
|
return Number.isFinite(n) && n >= MIN_SANE_BUDGET ? Math.floor(n) : undefined;
|
|
33
39
|
}
|
|
34
|
-
/**
|
|
35
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Resolve the full per-session (per-rail) token budget.
|
|
42
|
+
*
|
|
43
|
+
* Precedence: explicit operator override (env) → project config → the
|
|
44
|
+
* DISCOVERED live window of the model actually being called (see
|
|
45
|
+
* discoverModelContextWindow) → the model preset → a conservative default. The
|
|
46
|
+
* discovered value sits above the preset so sizing auto-adapts to whatever
|
|
47
|
+
* model/ctx is live (a rail resize, a different model) instead of a hardcoded
|
|
48
|
+
* preset, while an explicit env/config value still wins for a deliberate cap.
|
|
49
|
+
*/
|
|
50
|
+
export function resolveSessionTokenBudget(model, cfgRaw, discovered) {
|
|
36
51
|
const fromEnv = saneBudget(process.env.UAP_DELIVER_SESSION_TOKEN_BUDGET);
|
|
37
52
|
if (fromEnv)
|
|
38
53
|
return fromEnv;
|
|
@@ -40,11 +55,67 @@ export function resolveSessionTokenBudget(model, cfgRaw) {
|
|
|
40
55
|
const fromCfg = saneBudget(deliverCfg?.sessionTokenBudget);
|
|
41
56
|
if (fromCfg)
|
|
42
57
|
return fromCfg;
|
|
58
|
+
const fromDiscovered = saneBudget(discovered);
|
|
59
|
+
if (fromDiscovered)
|
|
60
|
+
return fromDiscovered;
|
|
43
61
|
const fromModel = saneBudget(model?.modelContextBudget ?? model?.maxContextTokens);
|
|
44
62
|
if (fromModel)
|
|
45
63
|
return fromModel;
|
|
46
64
|
return DEFAULT_SESSION_TOKEN_BUDGET;
|
|
47
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Auto-discover the SERVING model's actual per-rail context window so sizing
|
|
68
|
+
* adapts to whatever model/ctx is live, rather than a hardcoded preset. Queries
|
|
69
|
+
* the anthropic-proxy's `/v1/context` first (authoritative per-rail window,
|
|
70
|
+
* auto-updated from llama's `/slots`), then falls back to llama.cpp's native
|
|
71
|
+
* `/props` (`n_ctx`). Returns undefined on any failure — the caller falls back
|
|
72
|
+
* to the preset. Fail-soft and time-boxed so discovery can never block or wedge
|
|
73
|
+
* a deliver run.
|
|
74
|
+
*/
|
|
75
|
+
export async function discoverModelContextWindow(endpoint, timeoutMs = 1500) {
|
|
76
|
+
if (!endpoint)
|
|
77
|
+
return undefined;
|
|
78
|
+
let origin;
|
|
79
|
+
try {
|
|
80
|
+
origin = new URL(endpoint).origin;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
const attempts = [
|
|
86
|
+
{ url: `${origin}/v1/context`, pick: (j) => j.context_window },
|
|
87
|
+
{
|
|
88
|
+
url: `${origin}/props`,
|
|
89
|
+
pick: (j) => {
|
|
90
|
+
const gen = j.default_generation_settings;
|
|
91
|
+
return gen?.n_ctx ?? j.n_ctx;
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
for (const a of attempts) {
|
|
96
|
+
try {
|
|
97
|
+
const ctl = new AbortController();
|
|
98
|
+
const t = setTimeout(() => ctl.abort(), timeoutMs);
|
|
99
|
+
let res;
|
|
100
|
+
try {
|
|
101
|
+
res = await fetch(a.url, { signal: ctl.signal });
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
clearTimeout(t);
|
|
105
|
+
}
|
|
106
|
+
if (!res.ok)
|
|
107
|
+
continue;
|
|
108
|
+
const j = (await res.json());
|
|
109
|
+
const n = saneBudget(a.pick(j));
|
|
110
|
+
if (n)
|
|
111
|
+
return n;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
/* unreachable/timeout/parse — try next attempt, then fall back to preset */
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
48
119
|
/** The budget a session may actually consume (rail × working fraction). */
|
|
49
120
|
export function sessionWorkingBudget(fullBudget) {
|
|
50
121
|
return Math.floor(fullBudget * SESSION_WORKING_FRACTION);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-budget.js","sourceRoot":"","sources":["../../src/delivery/context-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,iFAAiF;AACjF,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAAC;AAEnD
|
|
1
|
+
{"version":3,"file":"context-budget.js","sourceRoot":"","sources":["../../src/delivery/context-budget.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decompose.d.ts","sourceRoot":"","sources":["../../src/delivery/decompose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;AAE3E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb;kFAC8E;IAC9E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;
|
|
1
|
+
{"version":3,"file":"decompose.d.ts","sourceRoot":"","sources":["../../src/delivery/decompose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1D;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;AAE3E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb;kFAC8E;IAC9E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB;AAqBD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAEjF;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAqC7D;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,aAAa,EAAE,CAiBlE;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AA6CD;;;;GAIG;AACH,wBAAsB,kBAAkB,CACtC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,YAAY,EACtB,YAAY,CAAC,EAAE,qBAAqB,EACpC,IAAI,CAAC,EAAE,iBAAiB,GACvB,OAAO,CAAC,aAAa,EAAE,CAAC,CAQ1B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,aAAa,EAAE,EACvB,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,MAAM,EAAE,GACvB,MAAM,CAcR"}
|
|
@@ -20,7 +20,10 @@ function maxPhases() {
|
|
|
20
20
|
const raw = Number(process.env.UAP_DELIVER_MAX_PHASES);
|
|
21
21
|
if (Number.isFinite(raw) && raw >= MIN_PHASES)
|
|
22
22
|
return Math.min(Math.floor(raw), MAX_PHASES_HARD_CEILING);
|
|
23
|
-
|
|
23
|
+
// (#4a) Default 8→10: a huge mission was being squeezed into ≤8 phases, each
|
|
24
|
+
// then too big for a rail. Still bounded by the hard ceiling; env overrides up
|
|
25
|
+
// to 20 for the largest missions.
|
|
26
|
+
return 10;
|
|
24
27
|
}
|
|
25
28
|
/** Only instructions this long are epic-shaped enough to auto-decompose. */
|
|
26
29
|
const AUTO_DECOMPOSE_MIN_CHARS = 200;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decompose.js","sourceRoot":"","sources":["../../src/delivery/decompose.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAqBH,MAAM,UAAU,GAAG,CAAC,CAAC;AACrB;;;;;GAKG;AACH,MAAM,uBAAuB,GAAG,EAAE,CAAC;AACnC,SAAS,SAAS;IAChB,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACvD,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,UAAU;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,uBAAuB,CAAC,CAAC;IACzG,OAAO,
|
|
1
|
+
{"version":3,"file":"decompose.js","sourceRoot":"","sources":["../../src/delivery/decompose.ts"],"names":[],"mappings":"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"}
|
|
@@ -62,8 +62,27 @@ export interface EpicControllerConfig {
|
|
|
62
62
|
* treated as "not accepted" so the controller retries rather than wedging.
|
|
63
63
|
*/
|
|
64
64
|
checkAcceptance?: (epic: Epic, result: EpicRunResult) => boolean | Promise<boolean>;
|
|
65
|
-
/** Max fresh-session attempts per epic before it is declared failed. Default
|
|
65
|
+
/** Max fresh-session attempts per epic before it is declared failed. Default 3. */
|
|
66
66
|
maxAttemptsPerEpic?: number;
|
|
67
|
+
/**
|
|
68
|
+
* (#4c) Max recursive split levels when an epic can't be delivered whole.
|
|
69
|
+
* Default 1 (one level: an over-budget epic splits into sub-epics, which
|
|
70
|
+
* never re-split). deliver raises this for LARGE missions so a genuinely huge
|
|
71
|
+
* epic recursively shrinks — a sub-epic that still can't land is split again,
|
|
72
|
+
* one level shallower — until each piece fits a rail, instead of failing the
|
|
73
|
+
* whole mission at the first split. Bounded: the depth counter decrements to
|
|
74
|
+
* 0, and each `splitEpic` planner can decline (return null) to stop early.
|
|
75
|
+
*/
|
|
76
|
+
splitDepth?: number;
|
|
77
|
+
/**
|
|
78
|
+
* (#5) When true, split a failed epic on ANY exhausted-attempts failure, not
|
|
79
|
+
* only on context-budget exhaustion — turning "epic failed, mission
|
|
80
|
+
* incomplete" into "re-plan it into smaller pieces and try those." Default
|
|
81
|
+
* false (budget exhaustion only, preserving the conservative path). deliver
|
|
82
|
+
* enables it for large missions so give-up becomes auto-escalation. Still
|
|
83
|
+
* bounded by `splitDepth` and by the planner's option to decline the split.
|
|
84
|
+
*/
|
|
85
|
+
splitOnAnyFailure?: boolean;
|
|
67
86
|
/** Progress hook. */
|
|
68
87
|
onEpic?: (epic: Epic, outcome: EpicOutcome) => void;
|
|
69
88
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"epic-controller.d.ts","sourceRoot":"","sources":["../../src/delivery/epic-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIpD,4EAA4E;AAC5E,MAAM,WAAW,IAAK,SAAQ,aAAa;IACzC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd;;;;;OAKG;IACH,OAAO,EAAE,CACP,IAAI,EAAE,IAAI,EACV,GAAG,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,KACrE,OAAO,CAAC,aAAa,CAAC,CAAC;IAC5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpF,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,qBAAqB;IACrB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACpD;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;IACzE;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAID;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,
|
|
1
|
+
{"version":3,"file":"epic-controller.d.ts","sourceRoot":"","sources":["../../src/delivery/epic-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIpD,4EAA4E;AAC5E,MAAM,WAAW,IAAK,SAAQ,aAAa;IACzC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,iFAAiF;IACjF,OAAO,EAAE,MAAM,CAAC;IAChB,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,sFAAsF;IACtF,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd;;;;;OAKG;IACH,OAAO,EAAE,CACP,IAAI,EAAE,IAAI,EACV,GAAG,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,KACrE,OAAO,CAAC,aAAa,CAAC,CAAC;IAC5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpF,mFAAmF;IACnF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;;;OAQG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,qBAAqB;IACrB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;IACpD;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;IACzE;;;OAGG;IACH,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,WAAW,EAAE,CAAC;CACzB;AAID;;;;;GAKG;AACH,wBAAsB,QAAQ,CAAC,MAAM,EAAE,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAgJ1F"}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import { topoOrder } from './decompose.js';
|
|
24
24
|
import { CONTEXT_BUDGET_MARKER } from './context-budget.js';
|
|
25
|
-
const DEFAULT_MAX_ATTEMPTS =
|
|
25
|
+
const DEFAULT_MAX_ATTEMPTS = 3;
|
|
26
26
|
/**
|
|
27
27
|
* Run the epic sequence. Epics execute in dependency order; an epic whose
|
|
28
28
|
* dependency failed is skipped (never build an epic on an unfinished one). Each
|
|
@@ -85,14 +85,24 @@ export async function runEpics(config) {
|
|
|
85
85
|
: `attempt ${attempts} failed to deliver: ${result.summary}`;
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
|
-
// Rail sizing: an epic that
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
//
|
|
92
|
-
|
|
88
|
+
// Rail sizing + auto-escalation: an epic that exhausted its attempts is
|
|
89
|
+
// re-planned as smaller sub-epics and run in place, rather than failing the
|
|
90
|
+
// whole mission. Fires on context-budget exhaustion always, and on ANY
|
|
91
|
+
// failure when splitOnAnyFailure is set (#5). Recurses up to `splitDepth`
|
|
92
|
+
// levels (#4c): sub-epics inherit the prior summaries and may split again
|
|
93
|
+
// one level shallower until each piece fits a rail. Default depth 1 keeps
|
|
94
|
+
// the conservative one-level behavior.
|
|
95
|
+
const depthRemaining = config.splitDepth ?? 1;
|
|
96
|
+
const budgetExhausted = (lastFailure ?? '').includes(CONTEXT_BUDGET_MARKER);
|
|
97
|
+
const splitFn = config.splitEpic;
|
|
98
|
+
const shouldSplit = !accepted &&
|
|
99
|
+
!!splitFn &&
|
|
100
|
+
depthRemaining > 0 &&
|
|
101
|
+
(budgetExhausted || config.splitOnAnyFailure === true);
|
|
102
|
+
if (shouldSplit && splitFn) {
|
|
93
103
|
let subs = null;
|
|
94
104
|
try {
|
|
95
|
-
subs = await
|
|
105
|
+
subs = await splitFn(epic, lastFailure);
|
|
96
106
|
}
|
|
97
107
|
catch {
|
|
98
108
|
subs = null; // fail-soft: an unplannable split just keeps the failure
|
|
@@ -113,7 +123,7 @@ export async function runEpics(config) {
|
|
|
113
123
|
const subResult = await runEpics({
|
|
114
124
|
...config,
|
|
115
125
|
epics: chained,
|
|
116
|
-
|
|
126
|
+
splitDepth: depthRemaining - 1, // recurse one level shallower (#4c); 0 ⇒ no re-split
|
|
117
127
|
initialPriorSummaries: [...priorSummaries],
|
|
118
128
|
});
|
|
119
129
|
epicTurns += subResult.turns; // flows into totalTurns below
|
|
@@ -124,9 +134,10 @@ export async function runEpics(config) {
|
|
|
124
134
|
// project gates, i.e. the epic's goal is delivered.
|
|
125
135
|
const finalPieceGreen = subResult.outcomes.length > 0 && subResult.outcomes[subResult.outcomes.length - 1].accepted;
|
|
126
136
|
accepted = subResult.success || finalPieceGreen;
|
|
137
|
+
const splitReason = budgetExhausted ? 'context auto-size' : 'auto-escalation';
|
|
127
138
|
lastSummary = accepted
|
|
128
|
-
? `split into ${chained.length} sub-epics (
|
|
129
|
-
: `split into ${chained.length} sub-epics
|
|
139
|
+
? `split into ${chained.length} sub-epics (${splitReason}): ${subResult.outcomes.map((o) => o.summary).join('; ')}`
|
|
140
|
+
: `split into ${chained.length} sub-epics (${splitReason}); failed: ${subResult.failed.join(', ')}`;
|
|
130
141
|
}
|
|
131
142
|
}
|
|
132
143
|
totalTurns += epicTurns;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"epic-controller.js","sourceRoot":"","sources":["../../src/delivery/epic-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"epic-controller.js","sourceRoot":"","sources":["../../src/delivery/epic-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -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;
|
|
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;AAsBD,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,CAoCpB"}
|
|
@@ -18,8 +18,11 @@ const PROFILES = {
|
|
|
18
18
|
light: { intensity: 'light', stopHookBlocks: true, maxBlocks: 3, stagnationLimit: 2, injectAutonomy: false },
|
|
19
19
|
// Opus/Sonnet/GPT — nudge past premature-done; moderate blocking.
|
|
20
20
|
moderate: { intensity: 'moderate', stopHookBlocks: true, maxBlocks: 6, stagnationLimit: 3, injectAutonomy: true },
|
|
21
|
-
// qwen / small local — firmly drive; more blocks tolerated
|
|
22
|
-
|
|
21
|
+
// qwen / small local — firmly drive; more blocks tolerated. (#4d) maxBlocks
|
|
22
|
+
// 9→12 and stagnationLimit 3→4 give a huge multi-epic build more runway
|
|
23
|
+
// before give-up, now that #2 (state carryover) and #3 (force-write) keep the
|
|
24
|
+
// model making real progress across resets. Still finite — anti-spin holds.
|
|
25
|
+
aggressive: { intensity: 'aggressive', stopHookBlocks: true, maxBlocks: 12, stagnationLimit: 4, injectAutonomy: true },
|
|
23
26
|
};
|
|
24
27
|
const OFF_PROFILE = {
|
|
25
28
|
intensity: 'off',
|
|
@@ -73,6 +76,20 @@ export function resolvePersistenceProfile(modelId, cfg = {}) {
|
|
|
73
76
|
}
|
|
74
77
|
}
|
|
75
78
|
}
|
|
79
|
+
// (#4d) Env caps: raise the hands-free runway for a huge mission without
|
|
80
|
+
// weakening per-family defaults. Applied last so an explicit operator value
|
|
81
|
+
// wins. Only meaningful when the profile blocks; both stay finite (clamped
|
|
82
|
+
// to 50) so the "never spin forever" guarantee holds.
|
|
83
|
+
if (profile.stopHookBlocks) {
|
|
84
|
+
const envBlocks = Number(process.env.UAP_HANDSFREE_MAX_BLOCKS);
|
|
85
|
+
const envStag = Number(process.env.UAP_HANDSFREE_STAGNATION_LIMIT);
|
|
86
|
+
if (Number.isFinite(envBlocks) && envBlocks >= 1) {
|
|
87
|
+
profile = { ...profile, maxBlocks: Math.min(Math.floor(envBlocks), 50) };
|
|
88
|
+
}
|
|
89
|
+
if (Number.isFinite(envStag) && envStag >= 1) {
|
|
90
|
+
profile = { ...profile, stagnationLimit: Math.min(Math.floor(envStag), 50) };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
76
93
|
return profile;
|
|
77
94
|
}
|
|
78
95
|
//# sourceMappingURL=persistence-profile.js.map
|
|
@@ -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,
|
|
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
|
|
@@ -2320,10 +2320,24 @@ def prune_conversation(
|
|
|
2320
2320
|
kept_msgs = middle[drop_count:]
|
|
2321
2321
|
|
|
2322
2322
|
if dropped:
|
|
2323
|
-
# Replace the dropped block with a findings-breadcrumb summary (B2)
|
|
2323
|
+
# Replace the dropped block with a findings-breadcrumb summary (B2),
|
|
2324
|
+
# PLUS a state-carryover (plan + files ALREADY WRITTEN) reconstructed
|
|
2325
|
+
# from the full pre-prune conversation. The breadcrumb only captures
|
|
2326
|
+
# tool_result *reads*; it never captures the assistant's own write
|
|
2327
|
+
# actions, so on a long build the pruner drops the write-history and the
|
|
2328
|
+
# model forgets what it created — then re-reads/re-creates its own files
|
|
2329
|
+
# (observed live: `cat lib.rs` ×16 at ctx 140% on a 3-day session). The
|
|
2330
|
+
# carryover keeps "you already wrote X — don't redo it" across the drop.
|
|
2331
|
+
# (#2 companion: the contamination breaker already carries this; the
|
|
2332
|
+
# pruner is the HIGHER-frequency state-dropper on huge sessions, so the
|
|
2333
|
+
# carryover matters most here.)
|
|
2334
|
+
carry = _extract_state_carryover(messages)
|
|
2335
|
+
marker_content = _summarize_pruned_block(dropped)
|
|
2336
|
+
if carry:
|
|
2337
|
+
marker_content = f"{carry}\n\n{marker_content}"
|
|
2324
2338
|
prune_marker = {
|
|
2325
2339
|
"role": "user",
|
|
2326
|
-
"content":
|
|
2340
|
+
"content": marker_content,
|
|
2327
2341
|
}
|
|
2328
2342
|
anthropic_body["messages"] = (
|
|
2329
2343
|
protected_head + [prune_marker] + kept_msgs + protected_tail
|
|
@@ -4645,6 +4659,7 @@ def _maybe_inject_recon_convergence(
|
|
|
4645
4659
|
openai_body["messages"] = msgs
|
|
4646
4660
|
|
|
4647
4661
|
restored: list[str] = []
|
|
4662
|
+
stripped: list[str] = []
|
|
4648
4663
|
if escalate:
|
|
4649
4664
|
# Strip tools entirely so the only possible response is terminal prose.
|
|
4650
4665
|
openai_body.pop("tools", None)
|
|
@@ -4691,11 +4706,44 @@ def _maybe_inject_recon_convergence(
|
|
|
4691
4706
|
present.add(name.lower())
|
|
4692
4707
|
restored.append(name)
|
|
4693
4708
|
|
|
4709
|
+
# FORCE-WRITE (hard tier): a nudge that leaves BOTH read and write tools
|
|
4710
|
+
# available lets the model keep picking a read — the live failure mode
|
|
4711
|
+
# (no_write_streak climbing to 45+ while write tools were re-injected but
|
|
4712
|
+
# tool_choice stayed 'auto', so the model just read again). At the hard
|
|
4713
|
+
# tier, remove the exploration path (read-only class + escape hatches) so
|
|
4714
|
+
# the only actions left are write/deliver, and force tool_choice=required
|
|
4715
|
+
# so a write MUST happen this turn. Floor-guarded: if stripping would
|
|
4716
|
+
# leave no write path, leave the toolset untouched (never strand — the
|
|
4717
|
+
# firm tier keeps reads, the escalate tier strips everything). Bounded:
|
|
4718
|
+
# if the model still produces no write, the streak keeps climbing and the
|
|
4719
|
+
# next fire escalates to the terminal-summary tier above.
|
|
4720
|
+
if hard:
|
|
4721
|
+
tools_now = openai_body.get("tools") or []
|
|
4722
|
+
deny = {c.lower() for c in _READ_ONLY_TOOL_CLASS} | {
|
|
4723
|
+
e.lower() for e in _EXPLORATION_ESCAPE_TOOLS
|
|
4724
|
+
}
|
|
4725
|
+
write_lower = {w.lower() for w in _WRITE_TOOL_CLASS}
|
|
4726
|
+
|
|
4727
|
+
def _rc_name(t: dict) -> str:
|
|
4728
|
+
return ((t.get("function", {}) or {}).get("name", "") or "").lower()
|
|
4729
|
+
|
|
4730
|
+
kept = [t for t in tools_now if _rc_name(t) not in deny]
|
|
4731
|
+
if kept and any(_rc_name(t) in write_lower for t in kept):
|
|
4732
|
+
stripped = [
|
|
4733
|
+
((t.get("function", {}) or {}).get("name", "") or "")
|
|
4734
|
+
for t in tools_now
|
|
4735
|
+
if _rc_name(t) in deny
|
|
4736
|
+
]
|
|
4737
|
+
if stripped:
|
|
4738
|
+
openai_body["tools"] = kept
|
|
4739
|
+
openai_body["tool_choice"] = "required"
|
|
4740
|
+
openai_body.pop("grammar", None)
|
|
4741
|
+
|
|
4694
4742
|
logger.warning(
|
|
4695
4743
|
"RECON CONVERGENCE: injected %s directive (no_write_streak=%d, hard_fires=%d, "
|
|
4696
|
-
"ctx=%.0f%%, tool_choice=%s, restored_write_tools=%s)",
|
|
4744
|
+
"ctx=%.0f%%, tool_choice=%s, restored_write_tools=%s, stripped_read_tools=%s)",
|
|
4697
4745
|
tier, streak, monitor.recon_hard_fires, util * 100,
|
|
4698
|
-
openai_body.get("tool_choice", "stripped"), restored or "none",
|
|
4746
|
+
openai_body.get("tool_choice", "stripped"), restored or "none", stripped or "none",
|
|
4699
4747
|
)
|
|
4700
4748
|
|
|
4701
4749
|
|
|
@@ -8151,6 +8199,94 @@ async def _apply_malformed_tool_guardrail(
|
|
|
8151
8199
|
)
|
|
8152
8200
|
|
|
8153
8201
|
|
|
8202
|
+
def _extract_state_carryover(messages: list[dict], max_files: int = 20) -> str | None:
|
|
8203
|
+
"""Reconstruct mission state (plan + files written) from a conversation that
|
|
8204
|
+
is about to be pruned by the contamination breaker, so the reset does not
|
|
8205
|
+
throw away what the build has planned and done.
|
|
8206
|
+
|
|
8207
|
+
The contamination/attractor reset keeps only the first user turn (+ a short
|
|
8208
|
+
tail), dropping the middle of the conversation — which is where the TodoWrite
|
|
8209
|
+
plan and the file-write actions live. On a huge build that drop destroys
|
|
8210
|
+
mission state: the model then re-explores from scratch, regrows the history,
|
|
8211
|
+
overflows again, and thrashes. The client's on-disk ledger is not visible to
|
|
8212
|
+
the proxy, but the plan and the writes ARE in the message stream, so
|
|
8213
|
+
reconstruct a compact carryover from them and re-inject it after the reset.
|
|
8214
|
+
|
|
8215
|
+
Returns a carryover block, or None when no state is found (fresh session).
|
|
8216
|
+
"""
|
|
8217
|
+
write_lower = {w.lower() for w in _WRITE_TOOL_CLASS}
|
|
8218
|
+
plan_tools = {
|
|
8219
|
+
"todowrite", "taskcreate", "taskupdate", "task_create", "task_update",
|
|
8220
|
+
"todo_write", "update_todo_list",
|
|
8221
|
+
}
|
|
8222
|
+
latest_plan: list[str] = []
|
|
8223
|
+
files: list[str] = []
|
|
8224
|
+
seen: set[str] = set()
|
|
8225
|
+
for m in messages:
|
|
8226
|
+
if not isinstance(m, dict) or m.get("role") != "assistant":
|
|
8227
|
+
continue
|
|
8228
|
+
content = m.get("content")
|
|
8229
|
+
if not isinstance(content, list):
|
|
8230
|
+
continue
|
|
8231
|
+
for block in content:
|
|
8232
|
+
if not isinstance(block, dict) or block.get("type") != "tool_use":
|
|
8233
|
+
continue
|
|
8234
|
+
name = (block.get("name") or "").lower()
|
|
8235
|
+
inp = block.get("input") if isinstance(block.get("input"), dict) else {}
|
|
8236
|
+
if name in plan_tools:
|
|
8237
|
+
todos = inp.get("todos") or inp.get("tasks") or inp.get("items")
|
|
8238
|
+
if isinstance(todos, list):
|
|
8239
|
+
rendered = []
|
|
8240
|
+
for t in todos:
|
|
8241
|
+
if not isinstance(t, dict):
|
|
8242
|
+
continue
|
|
8243
|
+
text = (
|
|
8244
|
+
t.get("content") or t.get("title")
|
|
8245
|
+
or t.get("task") or t.get("description") or ""
|
|
8246
|
+
).strip()
|
|
8247
|
+
if not text:
|
|
8248
|
+
continue
|
|
8249
|
+
status = (t.get("status") or t.get("state") or "").strip().lower()
|
|
8250
|
+
mark = {
|
|
8251
|
+
"completed": "x", "done": "x", "complete": "x",
|
|
8252
|
+
"in_progress": "~", "in-progress": "~", "active": "~",
|
|
8253
|
+
}.get(status, " ")
|
|
8254
|
+
rendered.append(f" [{mark}] {text}")
|
|
8255
|
+
if rendered:
|
|
8256
|
+
latest_plan = rendered # keep the MOST RECENT plan only
|
|
8257
|
+
elif name in write_lower:
|
|
8258
|
+
path = (
|
|
8259
|
+
inp.get("file_path") or inp.get("path")
|
|
8260
|
+
or inp.get("target") or inp.get("filename") or inp.get("task")
|
|
8261
|
+
)
|
|
8262
|
+
if isinstance(path, str) and path.strip() and path not in seen:
|
|
8263
|
+
seen.add(path)
|
|
8264
|
+
files.append(path.strip())
|
|
8265
|
+
if not latest_plan and not files:
|
|
8266
|
+
return None
|
|
8267
|
+
parts = [
|
|
8268
|
+
"[STATE CARRYOVER — preserved across the reset; do NOT restart from "
|
|
8269
|
+
"scratch or re-explore what is already done]"
|
|
8270
|
+
]
|
|
8271
|
+
if latest_plan:
|
|
8272
|
+
parts.append(
|
|
8273
|
+
"Your current plan (most recent TodoWrite) — resume the first "
|
|
8274
|
+
"unfinished item ([ ] = todo, [~] = in progress, [x] = done):"
|
|
8275
|
+
)
|
|
8276
|
+
parts.extend(latest_plan[:40])
|
|
8277
|
+
if files:
|
|
8278
|
+
shown = files[-max_files:]
|
|
8279
|
+
omitted = len(files) - len(shown)
|
|
8280
|
+
head_note = f" (showing last {len(shown)} of {len(files)})" if omitted > 0 else ""
|
|
8281
|
+
parts.append(f"Files you have already written/edited this session{head_note}:")
|
|
8282
|
+
parts.extend(f" - {p}" for p in shown)
|
|
8283
|
+
parts.append(
|
|
8284
|
+
"Continue the plan from where it stands. Take the next concrete action "
|
|
8285
|
+
"toward the first unfinished item now."
|
|
8286
|
+
)
|
|
8287
|
+
return "\n".join(parts)
|
|
8288
|
+
|
|
8289
|
+
|
|
8154
8290
|
def _maybe_apply_session_contamination_breaker(
|
|
8155
8291
|
anthropic_body: dict, monitor: SessionMonitor, session_id: str
|
|
8156
8292
|
) -> dict:
|
|
@@ -8283,7 +8419,11 @@ def _maybe_apply_session_contamination_breaker(
|
|
|
8283
8419
|
"Just call the tool."
|
|
8284
8420
|
),
|
|
8285
8421
|
}
|
|
8286
|
-
|
|
8422
|
+
carry = _extract_state_carryover(messages)
|
|
8423
|
+
new_messages = (
|
|
8424
|
+
head + [reset_marker, {"role": "user", "content": carry}]
|
|
8425
|
+
if carry else head + [reset_marker]
|
|
8426
|
+
)
|
|
8287
8427
|
monitor.attractor_correction_active = True
|
|
8288
8428
|
log_reason = "attractor"
|
|
8289
8429
|
else:
|
|
@@ -8296,7 +8436,9 @@ def _maybe_apply_session_contamination_breaker(
|
|
|
8296
8436
|
"Continue from the recent context and emit valid tool calls with strict JSON arguments only.]"
|
|
8297
8437
|
),
|
|
8298
8438
|
}
|
|
8299
|
-
|
|
8439
|
+
carry = _extract_state_carryover(messages)
|
|
8440
|
+
carry_msgs = [{"role": "user", "content": carry}] if carry else []
|
|
8441
|
+
new_messages = head + [reset_marker] + carry_msgs + tail
|
|
8300
8442
|
log_reason = "standard"
|
|
8301
8443
|
|
|
8302
8444
|
updated_body = dict(anthropic_body)
|