@moxxy/sdk 0.5.0 → 0.6.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/compactor-helpers.d.ts +22 -3
- package/dist/compactor-helpers.d.ts.map +1 -1
- package/dist/compactor-helpers.js +35 -11
- package/dist/compactor-helpers.js.map +1 -1
- package/dist/elision-helpers.d.ts.map +1 -1
- package/dist/elision-helpers.js +7 -4
- package/dist/elision-helpers.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/tool-dispatch.d.ts +50 -3
- package/dist/tool-dispatch.d.ts.map +1 -1
- package/dist/tool-dispatch.js +100 -1
- package/dist/tool-dispatch.js.map +1 -1
- package/package.json +3 -3
- package/src/compactor-helpers.test.ts +105 -9
- package/src/compactor-helpers.ts +37 -11
- package/src/elision-helpers.ts +7 -4
- package/src/index.ts +6 -1
- package/src/tool-dispatch.ts +136 -3
|
@@ -15,6 +15,26 @@ import type { ModeContext } from './mode.js';
|
|
|
15
15
|
* touch the network and is safe to run on every iteration.
|
|
16
16
|
*/
|
|
17
17
|
export declare function estimateContextTokens(log: EventLogReader): number;
|
|
18
|
+
/**
|
|
19
|
+
* Resolve the active model's context window for the proactive
|
|
20
|
+
* compaction / elision thresholds.
|
|
21
|
+
*
|
|
22
|
+
* `config.model` is a free-form, unvalidated string, and providers happily
|
|
23
|
+
* serve ids that aren't in their fixed descriptor list — a newer release
|
|
24
|
+
* (`claude-opus-4-8`), a dated id, or a model registered at runtime via
|
|
25
|
+
* provider-admin. So an exact `models.find(m => m.id === ctx.model)` often
|
|
26
|
+
* MISSES, and both auto-compaction and auto-elision used to silently turn into
|
|
27
|
+
* permanent no-ops for the whole session (the context then grows unbounded and
|
|
28
|
+
* the agent "loses its context"). Falling back to the provider's first
|
|
29
|
+
* descriptor — exactly what the TUI context meter already does
|
|
30
|
+
* (`resolveContextWindow` in @moxxy/plugin-cli) — keeps both features alive on
|
|
31
|
+
* an unrecognised id. Returns null only when the provider exposes no usable
|
|
32
|
+
* window at all (no models / a zero window).
|
|
33
|
+
*/
|
|
34
|
+
export declare function resolveModelContext(ctx: ModeContext): {
|
|
35
|
+
readonly contextWindow: number;
|
|
36
|
+
readonly reserveForOutput: number;
|
|
37
|
+
} | null;
|
|
18
38
|
/**
|
|
19
39
|
* Auto-compaction hook every mode calls once per iteration, right
|
|
20
40
|
* before building messages for the next provider call. Reads the
|
|
@@ -25,9 +45,8 @@ export declare function estimateContextTokens(log: EventLogReader): number;
|
|
|
25
45
|
* already honors compaction events, so the next provider call sees
|
|
26
46
|
* the summarized prefix automatically.
|
|
27
47
|
*
|
|
28
|
-
* Designed to be tolerant: no compactor
|
|
29
|
-
*
|
|
30
|
-
* compactor bug can't kill the turn. Failures emit a non-fatal
|
|
48
|
+
* Designed to be tolerant: no compactor or a compactor throw degrade to a
|
|
49
|
+
* no-op so a compactor bug can't kill the turn. Failures emit a non-fatal
|
|
31
50
|
* `error` event for observability.
|
|
32
51
|
*/
|
|
33
52
|
export declare function runCompactionIfNeeded(ctx: ModeContext, opts?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compactor-helpers.d.ts","sourceRoot":"","sources":["../src/compactor-helpers.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CA8BjE;AAqCD
|
|
1
|
+
{"version":3,"file":"compactor-helpers.d.ts","sourceRoot":"","sources":["../src/compactor-helpers.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CA8BjE;AAqCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,WAAW,GACf;IAAE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAK9E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,WAAW,EAChB,IAAI,GAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,OAAO,CAAC,CA0ElB;AAqBD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE/D"}
|
|
@@ -82,6 +82,29 @@ function safeJsonLen(v) {
|
|
|
82
82
|
return 0;
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Resolve the active model's context window for the proactive
|
|
87
|
+
* compaction / elision thresholds.
|
|
88
|
+
*
|
|
89
|
+
* `config.model` is a free-form, unvalidated string, and providers happily
|
|
90
|
+
* serve ids that aren't in their fixed descriptor list — a newer release
|
|
91
|
+
* (`claude-opus-4-8`), a dated id, or a model registered at runtime via
|
|
92
|
+
* provider-admin. So an exact `models.find(m => m.id === ctx.model)` often
|
|
93
|
+
* MISSES, and both auto-compaction and auto-elision used to silently turn into
|
|
94
|
+
* permanent no-ops for the whole session (the context then grows unbounded and
|
|
95
|
+
* the agent "loses its context"). Falling back to the provider's first
|
|
96
|
+
* descriptor — exactly what the TUI context meter already does
|
|
97
|
+
* (`resolveContextWindow` in @moxxy/plugin-cli) — keeps both features alive on
|
|
98
|
+
* an unrecognised id. Returns null only when the provider exposes no usable
|
|
99
|
+
* window at all (no models / a zero window).
|
|
100
|
+
*/
|
|
101
|
+
export function resolveModelContext(ctx) {
|
|
102
|
+
const descriptor = ctx.provider.models.find((m) => m.id === ctx.model) ?? ctx.provider.models[0];
|
|
103
|
+
const contextWindow = descriptor?.contextWindow;
|
|
104
|
+
if (!contextWindow || contextWindow <= 0)
|
|
105
|
+
return null;
|
|
106
|
+
return { contextWindow, reserveForOutput: descriptor?.maxOutputTokens ?? 0 };
|
|
107
|
+
}
|
|
85
108
|
/**
|
|
86
109
|
* Auto-compaction hook every mode calls once per iteration, right
|
|
87
110
|
* before building messages for the next provider call. Reads the
|
|
@@ -92,29 +115,30 @@ function safeJsonLen(v) {
|
|
|
92
115
|
* already honors compaction events, so the next provider call sees
|
|
93
116
|
* the summarized prefix automatically.
|
|
94
117
|
*
|
|
95
|
-
* Designed to be tolerant: no compactor
|
|
96
|
-
*
|
|
97
|
-
* compactor bug can't kill the turn. Failures emit a non-fatal
|
|
118
|
+
* Designed to be tolerant: no compactor or a compactor throw degrade to a
|
|
119
|
+
* no-op so a compactor bug can't kill the turn. Failures emit a non-fatal
|
|
98
120
|
* `error` event for observability.
|
|
99
121
|
*/
|
|
100
122
|
export async function runCompactionIfNeeded(ctx, opts = {}) {
|
|
101
123
|
const compactor = ctx.compactor;
|
|
102
124
|
if (!compactor)
|
|
103
125
|
return false;
|
|
104
|
-
// Resolve the active model's
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
126
|
+
// Resolve the active model's real context window (with a models[0] fallback
|
|
127
|
+
// for unlisted ids). A reactive `force` compaction must still run when the
|
|
128
|
+
// window can't be resolved — the provider has already told us the prompt
|
|
129
|
+
// overflowed — so only the proactive threshold path requires a window. The
|
|
130
|
+
// shipped compactor ignores `contextWindow` inside `compact()`, so the
|
|
131
|
+
// sentinel below only affects `shouldCompact`, which `force` bypasses.
|
|
132
|
+
const resolved = resolveModelContext(ctx);
|
|
133
|
+
if (!resolved && !opts.force)
|
|
110
134
|
return false;
|
|
111
135
|
const events = ctx.log.slice();
|
|
112
136
|
if (events.length === 0)
|
|
113
137
|
return false;
|
|
114
138
|
const budget = {
|
|
115
|
-
contextWindow,
|
|
139
|
+
contextWindow: resolved?.contextWindow ?? Number.MAX_SAFE_INTEGER,
|
|
116
140
|
estimatedTokens: estimateContextTokens(ctx.log),
|
|
117
|
-
reserveForOutput:
|
|
141
|
+
reserveForOutput: resolved?.reserveForOutput ?? 0,
|
|
118
142
|
};
|
|
119
143
|
// `force` skips the threshold gate — used reactively after the provider
|
|
120
144
|
// rejects a request for being over the context window (our estimate can
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compactor-helpers.js","sourceRoot":"","sources":["../src/compactor-helpers.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"compactor-helpers.js","sourceRoot":"","sources":["../src/compactor-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elision-helpers.d.ts","sourceRoot":"","sources":["../src/elision-helpers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE9D;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,6BAA6B,EAAE,MAAM,CAAC;IAC/C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACjD;AAgBD,wBAAgB,sBAAsB,CAAC,CAAC,CAAC,EAAE,eAAe,GAAG,uBAAuB,CAYnF;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"elision-helpers.d.ts","sourceRoot":"","sources":["../src/elision-helpers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE9D;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC;IACtC,QAAQ,CAAC,6BAA6B,EAAE,MAAM,CAAC;IAC/C,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACjD;AAgBD,wBAAgB,sBAAsB,CAAC,CAAC,CAAC,EAAE,eAAe,GAAG,uBAAuB,CAYnF;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAgExE"}
|
package/dist/elision-helpers.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { estimateContextTokens } from './compactor-helpers.js';
|
|
1
|
+
import { estimateContextTokens, resolveModelContext } from './compactor-helpers.js';
|
|
2
2
|
import { toolResultBytes } from './elision-state.js';
|
|
3
3
|
const DEFAULTS = {
|
|
4
4
|
enabled: true,
|
|
@@ -30,10 +30,13 @@ export async function runElisionIfNeeded(ctx) {
|
|
|
30
30
|
const s = resolveElisionSettings(ctx.elision);
|
|
31
31
|
if (!s.enabled)
|
|
32
32
|
return;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
// Resolve the model's real context window, with a models[0] fallback for
|
|
34
|
+
// ids not in the provider's fixed descriptor list — otherwise an
|
|
35
|
+
// unrecognised model id silently disabled elision for the whole session.
|
|
36
|
+
const resolved = resolveModelContext(ctx);
|
|
37
|
+
if (!resolved)
|
|
36
38
|
return;
|
|
39
|
+
const contextWindow = resolved.contextWindow;
|
|
37
40
|
// Gate: below this fill the whole history fits comfortably — eliding would
|
|
38
41
|
// only add missed-context risk for no token benefit.
|
|
39
42
|
if (estimateContextTokens(ctx.log) < s.minContextRatioToElide * contextWindow)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"elision-helpers.js","sourceRoot":"","sources":["../src/elision-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"elision-helpers.js","sourceRoot":"","sources":["../src/elision-helpers.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -21,7 +21,7 @@ export { readRequestBody, bearerTokenMatches } from './http-utils.js';
|
|
|
21
21
|
export { autoAllowResolver, denyByDefaultResolver, createCallbackResolver, createAllowListResolver, createDeferredPermissionResolver, evaluateToolRule, type CallbackResolverOptions, type PermissionPromptHandler, type DeferredPermissionResolver, type DeferredPermissionResolverOptions, } from './resolvers.js';
|
|
22
22
|
export { MoxxyError, classifyHttpStatus, classifyNetworkError, type MoxxyErrorCode, type MoxxyErrorInit, } from './errors.js';
|
|
23
23
|
export { collectProviderStream, runSingleShotTurn, projectMessagesFromLog, projectMessages, buildSystemPromptWithSkills, createStuckLoopDetector, stableHash, type CollectedToolUse, type StreamResult, type ProjectMessagesOptions, type ProjectedMessages, type StuckLoopDetector, type StuckSignal, } from './mode-helpers.js';
|
|
24
|
-
export { dispatchToolCall } from './tool-dispatch.js';
|
|
24
|
+
export { dispatchToolCall, executeToolUses, emitRequestsAndDetectStuck, type StuckLoopReport, } from './tool-dispatch.js';
|
|
25
25
|
export type { TokenBudget, CompactContext, CompactorDef } from './compactor.js';
|
|
26
26
|
export { estimateContextTokens, runCompactionIfNeeded, isContextOverflowError, } from './compactor-helpers.js';
|
|
27
27
|
export { runElisionIfNeeded, resolveElisionSettings, type ResolvedElisionSettings, } from './elision-helpers.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ export { readRequestBody, bearerTokenMatches } from './http-utils.js';
|
|
|
8
8
|
export { autoAllowResolver, denyByDefaultResolver, createCallbackResolver, createAllowListResolver, createDeferredPermissionResolver, evaluateToolRule, } from './resolvers.js';
|
|
9
9
|
export { MoxxyError, classifyHttpStatus, classifyNetworkError, } from './errors.js';
|
|
10
10
|
export { collectProviderStream, runSingleShotTurn, projectMessagesFromLog, projectMessages, buildSystemPromptWithSkills, createStuckLoopDetector, stableHash, } from './mode-helpers.js';
|
|
11
|
-
export { dispatchToolCall } from './tool-dispatch.js';
|
|
11
|
+
export { dispatchToolCall, executeToolUses, emitRequestsAndDetectStuck, } from './tool-dispatch.js';
|
|
12
12
|
export { estimateContextTokens, runCompactionIfNeeded, isContextOverflowError, } from './compactor-helpers.js';
|
|
13
13
|
export { runElisionIfNeeded, resolveElisionSettings, } from './elision-helpers.js';
|
|
14
14
|
export { computeElisionState, toolResultStub, conversationalStub, toolResultBytes, toolResultStubbed, conversationalStubbed, TINY_TURN_CHARS, } from './elision-state.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAmGjG,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAsChD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEzF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,kBAAkB,EAAmB,MAAM,qBAAqB,CAAC;AAC9H,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAA+B,MAAM,eAAe,CAAC;AACnG,OAAO,EAAE,WAAW,EAAc,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,gCAAgC,EAChC,gBAAgB,GAKjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,oBAAoB,GAGrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,EACf,2BAA2B,EAC3B,uBAAuB,EACvB,UAAU,GAOX,MAAM,mBAAmB,CAAC;AAC3B,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAmGjG,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAsChD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAEzF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,kBAAkB,EAAmB,MAAM,qBAAqB,CAAC;AAC9H,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,SAAS,EAA+B,MAAM,eAAe,CAAC;AACnG,OAAO,EAAE,WAAW,EAAc,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,gCAAgC,EAChC,gBAAgB,GAKjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,oBAAoB,GAGrB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,EACf,2BAA2B,EAC3B,uBAAuB,EACvB,UAAU,GAOX,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,0BAA0B,GAE3B,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GAEvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,GAEhB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,eAAe,GAEhB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,sBAAsB,EACtB,gCAAgC,EAChC,sBAAsB,EACtB,cAAc,EACd,gBAAgB,GAGjB,MAAM,uBAAuB,CAAC;AA4E/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AA8B/D,OAAO,EACL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,WAAW,EACX,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,GAIlB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,cAAc,GAGf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,qBAAqB,EACrB,6BAA6B,EAC7B,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"}
|
package/dist/tool-dispatch.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { MoxxyEvent } from './events.js';
|
|
1
|
+
import type { EmittedEvent, MoxxyEvent } from './events.js';
|
|
2
2
|
import type { ModeContext } from './mode.js';
|
|
3
|
-
import type { CollectedToolUse } from './mode-helpers.js';
|
|
3
|
+
import type { CollectedToolUse, StuckLoopDetector, StuckSignal } from './mode-helpers.js';
|
|
4
4
|
/**
|
|
5
5
|
* Execute a single tool-use end-to-end: dispatch `dispatchToolCall` hooks, run
|
|
6
6
|
* the permission check, invoke the tool, and emit the approved/denied/result
|
|
@@ -8,7 +8,7 @@ import type { CollectedToolUse } from './mode-helpers.js';
|
|
|
8
8
|
* don't need the events can drain it (`for await (const _ of …) {}`) — either
|
|
9
9
|
* way the events reach the log via `ctx.emit`.
|
|
10
10
|
*
|
|
11
|
-
* Shared by every loop strategy (
|
|
11
|
+
* Shared by every loop strategy (default, goal, and any contributed mode) so
|
|
12
12
|
* the defensive outer try/catch below lives in ONE place. Without it, a throw
|
|
13
13
|
* from a hook handler / permission resolver / the emit itself escapes the
|
|
14
14
|
* generator and leaves this (and any later) call as an orphan
|
|
@@ -16,4 +16,51 @@ import type { CollectedToolUse } from './mode-helpers.js';
|
|
|
16
16
|
* then rejects on the next turn.
|
|
17
17
|
*/
|
|
18
18
|
export declare function dispatchToolCall(ctx: ModeContext, t: CollectedToolUse, iteration: number): AsyncGenerator<MoxxyEvent, void, unknown>;
|
|
19
|
+
/**
|
|
20
|
+
* Run a batch of tool uses in order, handling mid-batch abort. On
|
|
21
|
+
* `ctx.signal.aborted` it synthesizes a failed `tool_result` for every
|
|
22
|
+
* not-yet-run call (so the log never ends on an orphan `tool_call_requested`),
|
|
23
|
+
* emits an `abort`, and returns `true` to tell the caller to stop. Returns
|
|
24
|
+
* `false` after a clean batch. Shared by every loop strategy so the
|
|
25
|
+
* orphan-on-abort guarantee lives in one place.
|
|
26
|
+
*/
|
|
27
|
+
export declare function executeToolUses(ctx: ModeContext, toolUses: ReadonlyArray<CollectedToolUse>, iteration: number): AsyncGenerator<MoxxyEvent, boolean, unknown>;
|
|
28
|
+
/**
|
|
29
|
+
* How a loop strategy phrases its stuck-loop abort. The skeleton — emit a
|
|
30
|
+
* `tool_call_requested` per call, feed the detector, and on a trip synthesize a
|
|
31
|
+
* failed `tool_result` for every already-emitted call before a fatal error — is
|
|
32
|
+
* identical across strategies and lives in {@link emitRequestsAndDetectStuck};
|
|
33
|
+
* only the wording, and goal mode's extra `goal_stuck` plugin_event, vary.
|
|
34
|
+
*/
|
|
35
|
+
export interface StuckLoopReport {
|
|
36
|
+
/** Message on the synthesized failed `tool_result` for the calls emitted
|
|
37
|
+
* before the trip (none of them ran). */
|
|
38
|
+
readonly abortedResultMessage: string;
|
|
39
|
+
/** Explanation for a `near` match (an `exact` match always reads
|
|
40
|
+
* "with identical input"). */
|
|
41
|
+
readonly nearHint: string;
|
|
42
|
+
/** Build the fatal error message shown to the user. */
|
|
43
|
+
readonly fatalMessage: (info: {
|
|
44
|
+
toolName: string;
|
|
45
|
+
count: number;
|
|
46
|
+
how: string;
|
|
47
|
+
}) => string;
|
|
48
|
+
/** Extra events to emit right before the fatal error — goal mode surfaces a
|
|
49
|
+
* `goal_stuck` plugin_event here. */
|
|
50
|
+
readonly extraOnStuck?: (info: {
|
|
51
|
+
toolName: string;
|
|
52
|
+
count: number;
|
|
53
|
+
kind: StuckSignal['kind'];
|
|
54
|
+
}) => ReadonlyArray<EmittedEvent>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Emit a `tool_call_requested` for each tool use and feed it to the stuck-loop
|
|
58
|
+
* detector. Returns `true` when the detector trips (caller should stop) — after
|
|
59
|
+
* synthesizing a failed `tool_result` for every request emitted this batch.
|
|
60
|
+
* That synthesis is load-bearing: a stuck trip bails WITHOUT running
|
|
61
|
+
* {@link executeToolUses}, so without it the emitted requests are left as orphan
|
|
62
|
+
* `tool_call_requested` events (which render as a tool stuck "running" forever
|
|
63
|
+
* and which the provider rejects next turn). Returns `false` when no trip fired.
|
|
64
|
+
*/
|
|
65
|
+
export declare function emitRequestsAndDetectStuck(ctx: ModeContext, toolUses: ReadonlyArray<CollectedToolUse>, detector: StuckLoopDetector, report: StuckLoopReport): AsyncGenerator<MoxxyEvent, boolean, unknown>;
|
|
19
66
|
//# sourceMappingURL=tool-dispatch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-dispatch.d.ts","sourceRoot":"","sources":["../src/tool-dispatch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-dispatch.d.ts","sourceRoot":"","sources":["../src/tool-dispatch.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE1F;;;;;;;;;;;;;GAaG;AACH,wBAAuB,gBAAgB,CACrC,GAAG,EAAE,WAAW,EAChB,CAAC,EAAE,gBAAgB,EACnB,SAAS,EAAE,MAAM,GAChB,cAAc,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,CAkF3C;AAgCD;;;;;;;GAOG;AACH,wBAAuB,eAAe,CACpC,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,aAAa,CAAC,gBAAgB,CAAC,EACzC,SAAS,EAAE,MAAM,GAChB,cAAc,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAmC9C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B;8CAC0C;IAC1C,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC;mCAC+B;IAC/B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,uDAAuD;IACvD,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;IAC1F;0CACsC;IACtC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE;QAC7B,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;KAC3B,KAAK,aAAa,CAAC,YAAY,CAAC,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAuB,0BAA0B,CAC/C,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,aAAa,CAAC,gBAAgB,CAAC,EACzC,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,eAAe,GACtB,cAAc,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CA2C9C"}
|
package/dist/tool-dispatch.js
CHANGED
|
@@ -6,7 +6,7 @@ import { asToolCallId } from './ids.js';
|
|
|
6
6
|
* don't need the events can drain it (`for await (const _ of …) {}`) — either
|
|
7
7
|
* way the events reach the log via `ctx.emit`.
|
|
8
8
|
*
|
|
9
|
-
* Shared by every loop strategy (
|
|
9
|
+
* Shared by every loop strategy (default, goal, and any contributed mode) so
|
|
10
10
|
* the defensive outer try/catch below lives in ONE place. Without it, a throw
|
|
11
11
|
* from a hook handler / permission resolver / the emit itself escapes the
|
|
12
12
|
* generator and leaves this (and any later) call as an orphan
|
|
@@ -115,4 +115,103 @@ async function* emitDenied(ctx, t, reason, by) {
|
|
|
115
115
|
error: { kind: 'denied', message: reason },
|
|
116
116
|
});
|
|
117
117
|
}
|
|
118
|
+
/**
|
|
119
|
+
* Run a batch of tool uses in order, handling mid-batch abort. On
|
|
120
|
+
* `ctx.signal.aborted` it synthesizes a failed `tool_result` for every
|
|
121
|
+
* not-yet-run call (so the log never ends on an orphan `tool_call_requested`),
|
|
122
|
+
* emits an `abort`, and returns `true` to tell the caller to stop. Returns
|
|
123
|
+
* `false` after a clean batch. Shared by every loop strategy so the
|
|
124
|
+
* orphan-on-abort guarantee lives in one place.
|
|
125
|
+
*/
|
|
126
|
+
export async function* executeToolUses(ctx, toolUses, iteration) {
|
|
127
|
+
// Tracks tool_call_requested events that haven't yet emitted a paired
|
|
128
|
+
// tool_result. On any early-exit (abort) we synthesize results for the
|
|
129
|
+
// leftovers so the event log can't end with orphan tool_call_requested events.
|
|
130
|
+
const unresolved = new Set(toolUses.map((t) => t.id));
|
|
131
|
+
for (const t of toolUses) {
|
|
132
|
+
if (ctx.signal.aborted) {
|
|
133
|
+
for (const orphanId of unresolved) {
|
|
134
|
+
yield await ctx.emit({
|
|
135
|
+
type: 'tool_result',
|
|
136
|
+
sessionId: ctx.sessionId,
|
|
137
|
+
turnId: ctx.turnId,
|
|
138
|
+
source: 'tool',
|
|
139
|
+
callId: asToolCallId(orphanId),
|
|
140
|
+
ok: false,
|
|
141
|
+
error: { kind: 'aborted', message: 'turn aborted before tool ran' },
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
unresolved.clear();
|
|
145
|
+
yield await ctx.emit({
|
|
146
|
+
type: 'abort',
|
|
147
|
+
sessionId: ctx.sessionId,
|
|
148
|
+
turnId: ctx.turnId,
|
|
149
|
+
source: 'system',
|
|
150
|
+
reason: 'signal aborted during tool execution',
|
|
151
|
+
});
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
yield* dispatchToolCall(ctx, t, iteration);
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
unresolved.delete(t.id);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Emit a `tool_call_requested` for each tool use and feed it to the stuck-loop
|
|
165
|
+
* detector. Returns `true` when the detector trips (caller should stop) — after
|
|
166
|
+
* synthesizing a failed `tool_result` for every request emitted this batch.
|
|
167
|
+
* That synthesis is load-bearing: a stuck trip bails WITHOUT running
|
|
168
|
+
* {@link executeToolUses}, so without it the emitted requests are left as orphan
|
|
169
|
+
* `tool_call_requested` events (which render as a tool stuck "running" forever
|
|
170
|
+
* and which the provider rejects next turn). Returns `false` when no trip fired.
|
|
171
|
+
*/
|
|
172
|
+
export async function* emitRequestsAndDetectStuck(ctx, toolUses, detector, report) {
|
|
173
|
+
const emitted = [];
|
|
174
|
+
for (const t of toolUses) {
|
|
175
|
+
yield await ctx.emit({
|
|
176
|
+
type: 'tool_call_requested',
|
|
177
|
+
sessionId: ctx.sessionId,
|
|
178
|
+
turnId: ctx.turnId,
|
|
179
|
+
source: 'model',
|
|
180
|
+
callId: asToolCallId(t.id),
|
|
181
|
+
name: t.name,
|
|
182
|
+
input: t.input,
|
|
183
|
+
});
|
|
184
|
+
emitted.push(t);
|
|
185
|
+
const sig = detector.record(t.name, t.input);
|
|
186
|
+
if (!sig.stuck)
|
|
187
|
+
continue;
|
|
188
|
+
for (const r of emitted) {
|
|
189
|
+
yield await ctx.emit({
|
|
190
|
+
type: 'tool_result',
|
|
191
|
+
sessionId: ctx.sessionId,
|
|
192
|
+
turnId: ctx.turnId,
|
|
193
|
+
source: 'tool',
|
|
194
|
+
callId: asToolCallId(r.id),
|
|
195
|
+
ok: false,
|
|
196
|
+
error: { kind: 'aborted', message: report.abortedResultMessage },
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
const how = sig.kind === 'near' ? report.nearHint : 'with identical input';
|
|
200
|
+
if (report.extraOnStuck) {
|
|
201
|
+
for (const e of report.extraOnStuck({ toolName: t.name, count: sig.count, kind: sig.kind })) {
|
|
202
|
+
yield await ctx.emit(e);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
yield await ctx.emit({
|
|
206
|
+
type: 'error',
|
|
207
|
+
sessionId: ctx.sessionId,
|
|
208
|
+
turnId: ctx.turnId,
|
|
209
|
+
source: 'system',
|
|
210
|
+
kind: 'fatal',
|
|
211
|
+
message: report.fatalMessage({ toolName: t.name, count: sig.count, how }),
|
|
212
|
+
});
|
|
213
|
+
return true;
|
|
214
|
+
}
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
118
217
|
//# sourceMappingURL=tool-dispatch.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-dispatch.js","sourceRoot":"","sources":["../src/tool-dispatch.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tool-dispatch.js","sourceRoot":"","sources":["../src/tool-dispatch.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moxxy/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Typed public surface for the moxxy framework: event types, define* factories, lifecycle hook signatures.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"moxxy",
|
|
@@ -61,8 +61,8 @@
|
|
|
61
61
|
"typescript": "^5.7.3",
|
|
62
62
|
"vitest": "^2.1.8",
|
|
63
63
|
"zod": "^3.24.0",
|
|
64
|
-
"@moxxy/
|
|
65
|
-
"@moxxy/
|
|
64
|
+
"@moxxy/tsconfig": "0.0.0",
|
|
65
|
+
"@moxxy/vitest-preset": "0.0.0"
|
|
66
66
|
},
|
|
67
67
|
"scripts": {
|
|
68
68
|
"build": "tsc -p tsconfig.json",
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
estimateContextTokens,
|
|
7
7
|
isContextOverflowError,
|
|
8
8
|
runCompactionIfNeeded,
|
|
9
|
+
runElisionIfNeeded,
|
|
9
10
|
type CompactorDef,
|
|
10
11
|
type EmittedEvent,
|
|
11
12
|
type EventLogReader,
|
|
@@ -131,6 +132,58 @@ describe('runCompactionIfNeeded', () => {
|
|
|
131
132
|
expect(ctx.emitted[0]).toMatchObject({ type: 'error', kind: 'retryable' });
|
|
132
133
|
});
|
|
133
134
|
|
|
135
|
+
it('still resolves a context window for a model id not in the descriptor list', async () => {
|
|
136
|
+
// Regression: an unlisted model id (e.g. a newer release the provider's
|
|
137
|
+
// fixed descriptor list doesn't enumerate) used to make shouldCompact never
|
|
138
|
+
// run, silently disabling auto-compaction for the whole session.
|
|
139
|
+
let observedWindow = -1;
|
|
140
|
+
const compactor: CompactorDef = {
|
|
141
|
+
name: 'inspect',
|
|
142
|
+
shouldCompact: (_log, budget) => {
|
|
143
|
+
observedWindow = budget.contextWindow;
|
|
144
|
+
return false;
|
|
145
|
+
},
|
|
146
|
+
compact: async () => {
|
|
147
|
+
throw new Error('should not run');
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
const ctx = makeCtx({
|
|
151
|
+
compactor,
|
|
152
|
+
model: 'claude-opus-4-7', // the listed descriptor
|
|
153
|
+
contextWindow: 800_000,
|
|
154
|
+
ctxModelId: 'claude-opus-4-8', // …but the session runs an unlisted id
|
|
155
|
+
});
|
|
156
|
+
await runCompactionIfNeeded(ctx);
|
|
157
|
+
// Falls back to models[0].contextWindow instead of bailing.
|
|
158
|
+
expect(observedWindow).toBe(800_000);
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
it('force-compacts even when the provider exposes no usable context window', async () => {
|
|
162
|
+
// Reactive overflow recovery: the provider already said the prompt is too
|
|
163
|
+
// big, so a missing/zero window must NOT block the forced compaction.
|
|
164
|
+
const compact = vi.fn(async () => ({
|
|
165
|
+
type: 'compaction' as const,
|
|
166
|
+
replacedRange: [0, 1] as [number, number],
|
|
167
|
+
summary: 'summary',
|
|
168
|
+
tokensSaved: 500,
|
|
169
|
+
}));
|
|
170
|
+
const compactor: CompactorDef = { name: 'gated', shouldCompact: () => false, compact };
|
|
171
|
+
const ctx = makeCtx({ compactor, emptyModels: true });
|
|
172
|
+
const did = await runCompactionIfNeeded(ctx, { force: true });
|
|
173
|
+
expect(did).toBe(true);
|
|
174
|
+
expect(compact).toHaveBeenCalledOnce();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('is a no-op (non-force) when the provider exposes no usable context window', async () => {
|
|
178
|
+
const compact = vi.fn();
|
|
179
|
+
const shouldCompact = vi.fn().mockReturnValue(true);
|
|
180
|
+
const ctx = makeCtx({ compactor: { name: 'x', shouldCompact, compact }, emptyModels: true });
|
|
181
|
+
const did = await runCompactionIfNeeded(ctx);
|
|
182
|
+
expect(did).toBe(false);
|
|
183
|
+
expect(shouldCompact).not.toHaveBeenCalled();
|
|
184
|
+
expect(compact).not.toHaveBeenCalled();
|
|
185
|
+
});
|
|
186
|
+
|
|
134
187
|
it('force compacts even when shouldCompact returns false', async () => {
|
|
135
188
|
const compact = vi.fn(async () => ({
|
|
136
189
|
type: 'compaction' as const,
|
|
@@ -172,11 +225,50 @@ describe('isContextOverflowError', () => {
|
|
|
172
225
|
});
|
|
173
226
|
});
|
|
174
227
|
|
|
228
|
+
describe('runElisionIfNeeded', () => {
|
|
229
|
+
// Six completed turns of bulky prompts, none matching ctx.turnId (so all are
|
|
230
|
+
// "completed"). With keepRecentTurns=4 the two oldest turns are elidable.
|
|
231
|
+
const bulkyTurns: MoxxyEvent[] = Array.from({ length: 6 }, (_, i) =>
|
|
232
|
+
event(i, {
|
|
233
|
+
type: 'user_prompt',
|
|
234
|
+
turnId: asTurnId(`turn-${i}`),
|
|
235
|
+
source: 'user',
|
|
236
|
+
text: 'x'.repeat(400),
|
|
237
|
+
}),
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
it('elides old turns for a model id not in the descriptor list', async () => {
|
|
241
|
+
// Regression: an unlisted model id used to disable elision entirely, so the
|
|
242
|
+
// context grew unbounded and the agent lost its earlier context. With the
|
|
243
|
+
// models[0] fallback the elision high-water mark advances as expected.
|
|
244
|
+
const ctx = makeCtx({
|
|
245
|
+
compactor: null,
|
|
246
|
+
events: bulkyTurns,
|
|
247
|
+
model: 'listed-model',
|
|
248
|
+
ctxModelId: 'unlisted-model-xyz',
|
|
249
|
+
contextWindow: 1_000, // estimate (~600 tok) is well over 0.3 * window (300)
|
|
250
|
+
});
|
|
251
|
+
await runElisionIfNeeded(ctx);
|
|
252
|
+
expect(ctx.emitted.some((e) => e.type === 'elision')).toBe(true);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('is a no-op when the provider exposes no usable context window', async () => {
|
|
256
|
+
const ctx = makeCtx({ compactor: null, events: bulkyTurns, emptyModels: true });
|
|
257
|
+
await runElisionIfNeeded(ctx);
|
|
258
|
+
expect(ctx.emitted).toHaveLength(0);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
175
262
|
interface MakeCtxOpts {
|
|
176
263
|
readonly compactor: CompactorDef | null;
|
|
177
264
|
readonly model?: string;
|
|
178
265
|
readonly contextWindow?: number;
|
|
179
266
|
readonly events?: ReadonlyArray<MoxxyEvent>;
|
|
267
|
+
/** Set ctx.model to an id the provider's descriptor list does NOT contain,
|
|
268
|
+
* so `models.find(...)` misses and the models[0] fallback must kick in. */
|
|
269
|
+
readonly ctxModelId?: string;
|
|
270
|
+
/** Give the provider an empty descriptor list (no usable context window). */
|
|
271
|
+
readonly emptyModels?: boolean;
|
|
180
272
|
}
|
|
181
273
|
|
|
182
274
|
function makeCtx(opts: MakeCtxOpts): ModeContext & { emitted: EmittedEvent[] } {
|
|
@@ -186,14 +278,16 @@ function makeCtx(opts: MakeCtxOpts): ModeContext & { emitted: EmittedEvent[] } {
|
|
|
186
278
|
const log = reader(events);
|
|
187
279
|
const provider = {
|
|
188
280
|
name: 'fake',
|
|
189
|
-
models:
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
281
|
+
models: opts.emptyModels
|
|
282
|
+
? []
|
|
283
|
+
: [
|
|
284
|
+
{
|
|
285
|
+
id: opts.model ?? 'fake-model',
|
|
286
|
+
contextWindow: opts.contextWindow ?? 100_000,
|
|
287
|
+
supportsTools: true,
|
|
288
|
+
supportsStreaming: true,
|
|
289
|
+
},
|
|
290
|
+
],
|
|
197
291
|
stream: async function* () { /* unused */ },
|
|
198
292
|
countTokens: async () => 0,
|
|
199
293
|
} as unknown as LLMProvider;
|
|
@@ -202,7 +296,9 @@ function makeCtx(opts: MakeCtxOpts): ModeContext & { emitted: EmittedEvent[] } {
|
|
|
202
296
|
const ctx = {
|
|
203
297
|
sessionId: sid,
|
|
204
298
|
turnId: tid,
|
|
205
|
-
|
|
299
|
+
// ctx.model may intentionally differ from the descriptor id to exercise the
|
|
300
|
+
// unlisted-model fallback.
|
|
301
|
+
model: opts.ctxModelId ?? opts.model ?? 'fake-model',
|
|
206
302
|
provider,
|
|
207
303
|
tools: { list: () => [], get: () => undefined, execute: async () => undefined },
|
|
208
304
|
skills: { list: () => [], get: () => undefined, byName: () => undefined, filterByTriggers: () => [] },
|
package/src/compactor-helpers.ts
CHANGED
|
@@ -91,6 +91,31 @@ function safeJsonLen(v: unknown): number {
|
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Resolve the active model's context window for the proactive
|
|
96
|
+
* compaction / elision thresholds.
|
|
97
|
+
*
|
|
98
|
+
* `config.model` is a free-form, unvalidated string, and providers happily
|
|
99
|
+
* serve ids that aren't in their fixed descriptor list — a newer release
|
|
100
|
+
* (`claude-opus-4-8`), a dated id, or a model registered at runtime via
|
|
101
|
+
* provider-admin. So an exact `models.find(m => m.id === ctx.model)` often
|
|
102
|
+
* MISSES, and both auto-compaction and auto-elision used to silently turn into
|
|
103
|
+
* permanent no-ops for the whole session (the context then grows unbounded and
|
|
104
|
+
* the agent "loses its context"). Falling back to the provider's first
|
|
105
|
+
* descriptor — exactly what the TUI context meter already does
|
|
106
|
+
* (`resolveContextWindow` in @moxxy/plugin-cli) — keeps both features alive on
|
|
107
|
+
* an unrecognised id. Returns null only when the provider exposes no usable
|
|
108
|
+
* window at all (no models / a zero window).
|
|
109
|
+
*/
|
|
110
|
+
export function resolveModelContext(
|
|
111
|
+
ctx: ModeContext,
|
|
112
|
+
): { readonly contextWindow: number; readonly reserveForOutput: number } | null {
|
|
113
|
+
const descriptor = ctx.provider.models.find((m) => m.id === ctx.model) ?? ctx.provider.models[0];
|
|
114
|
+
const contextWindow = descriptor?.contextWindow;
|
|
115
|
+
if (!contextWindow || contextWindow <= 0) return null;
|
|
116
|
+
return { contextWindow, reserveForOutput: descriptor?.maxOutputTokens ?? 0 };
|
|
117
|
+
}
|
|
118
|
+
|
|
94
119
|
/**
|
|
95
120
|
* Auto-compaction hook every mode calls once per iteration, right
|
|
96
121
|
* before building messages for the next provider call. Reads the
|
|
@@ -101,9 +126,8 @@ function safeJsonLen(v: unknown): number {
|
|
|
101
126
|
* already honors compaction events, so the next provider call sees
|
|
102
127
|
* the summarized prefix automatically.
|
|
103
128
|
*
|
|
104
|
-
* Designed to be tolerant: no compactor
|
|
105
|
-
*
|
|
106
|
-
* compactor bug can't kill the turn. Failures emit a non-fatal
|
|
129
|
+
* Designed to be tolerant: no compactor or a compactor throw degrade to a
|
|
130
|
+
* no-op so a compactor bug can't kill the turn. Failures emit a non-fatal
|
|
107
131
|
* `error` event for observability.
|
|
108
132
|
*/
|
|
109
133
|
export async function runCompactionIfNeeded(
|
|
@@ -113,20 +137,22 @@ export async function runCompactionIfNeeded(
|
|
|
113
137
|
const compactor = ctx.compactor;
|
|
114
138
|
if (!compactor) return false;
|
|
115
139
|
|
|
116
|
-
// Resolve the active model's
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
140
|
+
// Resolve the active model's real context window (with a models[0] fallback
|
|
141
|
+
// for unlisted ids). A reactive `force` compaction must still run when the
|
|
142
|
+
// window can't be resolved — the provider has already told us the prompt
|
|
143
|
+
// overflowed — so only the proactive threshold path requires a window. The
|
|
144
|
+
// shipped compactor ignores `contextWindow` inside `compact()`, so the
|
|
145
|
+
// sentinel below only affects `shouldCompact`, which `force` bypasses.
|
|
146
|
+
const resolved = resolveModelContext(ctx);
|
|
147
|
+
if (!resolved && !opts.force) return false;
|
|
122
148
|
|
|
123
149
|
const events = ctx.log.slice();
|
|
124
150
|
if (events.length === 0) return false;
|
|
125
151
|
|
|
126
152
|
const budget = {
|
|
127
|
-
contextWindow,
|
|
153
|
+
contextWindow: resolved?.contextWindow ?? Number.MAX_SAFE_INTEGER,
|
|
128
154
|
estimatedTokens: estimateContextTokens(ctx.log),
|
|
129
|
-
reserveForOutput:
|
|
155
|
+
reserveForOutput: resolved?.reserveForOutput ?? 0,
|
|
130
156
|
} as const;
|
|
131
157
|
|
|
132
158
|
// `force` skips the threshold gate — used reactively after the provider
|
package/src/elision-helpers.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { estimateContextTokens } from './compactor-helpers.js';
|
|
1
|
+
import { estimateContextTokens, resolveModelContext } from './compactor-helpers.js';
|
|
2
2
|
import { toolResultBytes } from './elision-state.js';
|
|
3
3
|
import type { EmittedEvent, MoxxyEvent } from './events.js';
|
|
4
4
|
import type { ElisionSettings, ModeContext } from './mode.js';
|
|
@@ -60,9 +60,12 @@ export async function runElisionIfNeeded(ctx: ModeContext): Promise<void> {
|
|
|
60
60
|
const s = resolveElisionSettings(ctx.elision);
|
|
61
61
|
if (!s.enabled) return;
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
// Resolve the model's real context window, with a models[0] fallback for
|
|
64
|
+
// ids not in the provider's fixed descriptor list — otherwise an
|
|
65
|
+
// unrecognised model id silently disabled elision for the whole session.
|
|
66
|
+
const resolved = resolveModelContext(ctx);
|
|
67
|
+
if (!resolved) return;
|
|
68
|
+
const contextWindow = resolved.contextWindow;
|
|
66
69
|
|
|
67
70
|
// Gate: below this fill the whole history fits comfortably — eliding would
|
|
68
71
|
// only add missed-context risk for no token benefit.
|
package/src/index.ts
CHANGED
|
@@ -183,7 +183,12 @@ export {
|
|
|
183
183
|
type StuckLoopDetector,
|
|
184
184
|
type StuckSignal,
|
|
185
185
|
} from './mode-helpers.js';
|
|
186
|
-
export {
|
|
186
|
+
export {
|
|
187
|
+
dispatchToolCall,
|
|
188
|
+
executeToolUses,
|
|
189
|
+
emitRequestsAndDetectStuck,
|
|
190
|
+
type StuckLoopReport,
|
|
191
|
+
} from './tool-dispatch.js';
|
|
187
192
|
|
|
188
193
|
export type { TokenBudget, CompactContext, CompactorDef } from './compactor.js';
|
|
189
194
|
export {
|
package/src/tool-dispatch.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { asToolCallId } from './ids.js';
|
|
2
|
-
import type { MoxxyEvent } from './events.js';
|
|
2
|
+
import type { EmittedEvent, MoxxyEvent } from './events.js';
|
|
3
3
|
import type { ModeContext } from './mode.js';
|
|
4
4
|
import type { ToolCallVerdict } from './hooks.js';
|
|
5
|
-
import type { CollectedToolUse } from './mode-helpers.js';
|
|
5
|
+
import type { CollectedToolUse, StuckLoopDetector, StuckSignal } from './mode-helpers.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Execute a single tool-use end-to-end: dispatch `dispatchToolCall` hooks, run
|
|
@@ -11,7 +11,7 @@ import type { CollectedToolUse } from './mode-helpers.js';
|
|
|
11
11
|
* don't need the events can drain it (`for await (const _ of …) {}`) — either
|
|
12
12
|
* way the events reach the log via `ctx.emit`.
|
|
13
13
|
*
|
|
14
|
-
* Shared by every loop strategy (
|
|
14
|
+
* Shared by every loop strategy (default, goal, and any contributed mode) so
|
|
15
15
|
* the defensive outer try/catch below lives in ONE place. Without it, a throw
|
|
16
16
|
* from a hook handler / permission resolver / the emit itself escapes the
|
|
17
17
|
* generator and leaves this (and any later) call as an orphan
|
|
@@ -135,3 +135,136 @@ async function* emitDenied(
|
|
|
135
135
|
error: { kind: 'denied', message: reason },
|
|
136
136
|
});
|
|
137
137
|
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Run a batch of tool uses in order, handling mid-batch abort. On
|
|
141
|
+
* `ctx.signal.aborted` it synthesizes a failed `tool_result` for every
|
|
142
|
+
* not-yet-run call (so the log never ends on an orphan `tool_call_requested`),
|
|
143
|
+
* emits an `abort`, and returns `true` to tell the caller to stop. Returns
|
|
144
|
+
* `false` after a clean batch. Shared by every loop strategy so the
|
|
145
|
+
* orphan-on-abort guarantee lives in one place.
|
|
146
|
+
*/
|
|
147
|
+
export async function* executeToolUses(
|
|
148
|
+
ctx: ModeContext,
|
|
149
|
+
toolUses: ReadonlyArray<CollectedToolUse>,
|
|
150
|
+
iteration: number,
|
|
151
|
+
): AsyncGenerator<MoxxyEvent, boolean, unknown> {
|
|
152
|
+
// Tracks tool_call_requested events that haven't yet emitted a paired
|
|
153
|
+
// tool_result. On any early-exit (abort) we synthesize results for the
|
|
154
|
+
// leftovers so the event log can't end with orphan tool_call_requested events.
|
|
155
|
+
const unresolved = new Set<string>(toolUses.map((t) => t.id));
|
|
156
|
+
for (const t of toolUses) {
|
|
157
|
+
if (ctx.signal.aborted) {
|
|
158
|
+
for (const orphanId of unresolved) {
|
|
159
|
+
yield await ctx.emit({
|
|
160
|
+
type: 'tool_result',
|
|
161
|
+
sessionId: ctx.sessionId,
|
|
162
|
+
turnId: ctx.turnId,
|
|
163
|
+
source: 'tool',
|
|
164
|
+
callId: asToolCallId(orphanId),
|
|
165
|
+
ok: false,
|
|
166
|
+
error: { kind: 'aborted', message: 'turn aborted before tool ran' },
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
unresolved.clear();
|
|
170
|
+
yield await ctx.emit({
|
|
171
|
+
type: 'abort',
|
|
172
|
+
sessionId: ctx.sessionId,
|
|
173
|
+
turnId: ctx.turnId,
|
|
174
|
+
source: 'system',
|
|
175
|
+
reason: 'signal aborted during tool execution',
|
|
176
|
+
});
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
yield* dispatchToolCall(ctx, t, iteration);
|
|
181
|
+
} finally {
|
|
182
|
+
unresolved.delete(t.id);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* How a loop strategy phrases its stuck-loop abort. The skeleton — emit a
|
|
190
|
+
* `tool_call_requested` per call, feed the detector, and on a trip synthesize a
|
|
191
|
+
* failed `tool_result` for every already-emitted call before a fatal error — is
|
|
192
|
+
* identical across strategies and lives in {@link emitRequestsAndDetectStuck};
|
|
193
|
+
* only the wording, and goal mode's extra `goal_stuck` plugin_event, vary.
|
|
194
|
+
*/
|
|
195
|
+
export interface StuckLoopReport {
|
|
196
|
+
/** Message on the synthesized failed `tool_result` for the calls emitted
|
|
197
|
+
* before the trip (none of them ran). */
|
|
198
|
+
readonly abortedResultMessage: string;
|
|
199
|
+
/** Explanation for a `near` match (an `exact` match always reads
|
|
200
|
+
* "with identical input"). */
|
|
201
|
+
readonly nearHint: string;
|
|
202
|
+
/** Build the fatal error message shown to the user. */
|
|
203
|
+
readonly fatalMessage: (info: { toolName: string; count: number; how: string }) => string;
|
|
204
|
+
/** Extra events to emit right before the fatal error — goal mode surfaces a
|
|
205
|
+
* `goal_stuck` plugin_event here. */
|
|
206
|
+
readonly extraOnStuck?: (info: {
|
|
207
|
+
toolName: string;
|
|
208
|
+
count: number;
|
|
209
|
+
kind: StuckSignal['kind'];
|
|
210
|
+
}) => ReadonlyArray<EmittedEvent>;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Emit a `tool_call_requested` for each tool use and feed it to the stuck-loop
|
|
215
|
+
* detector. Returns `true` when the detector trips (caller should stop) — after
|
|
216
|
+
* synthesizing a failed `tool_result` for every request emitted this batch.
|
|
217
|
+
* That synthesis is load-bearing: a stuck trip bails WITHOUT running
|
|
218
|
+
* {@link executeToolUses}, so without it the emitted requests are left as orphan
|
|
219
|
+
* `tool_call_requested` events (which render as a tool stuck "running" forever
|
|
220
|
+
* and which the provider rejects next turn). Returns `false` when no trip fired.
|
|
221
|
+
*/
|
|
222
|
+
export async function* emitRequestsAndDetectStuck(
|
|
223
|
+
ctx: ModeContext,
|
|
224
|
+
toolUses: ReadonlyArray<CollectedToolUse>,
|
|
225
|
+
detector: StuckLoopDetector,
|
|
226
|
+
report: StuckLoopReport,
|
|
227
|
+
): AsyncGenerator<MoxxyEvent, boolean, unknown> {
|
|
228
|
+
const emitted: CollectedToolUse[] = [];
|
|
229
|
+
for (const t of toolUses) {
|
|
230
|
+
yield await ctx.emit({
|
|
231
|
+
type: 'tool_call_requested',
|
|
232
|
+
sessionId: ctx.sessionId,
|
|
233
|
+
turnId: ctx.turnId,
|
|
234
|
+
source: 'model',
|
|
235
|
+
callId: asToolCallId(t.id),
|
|
236
|
+
name: t.name,
|
|
237
|
+
input: t.input,
|
|
238
|
+
});
|
|
239
|
+
emitted.push(t);
|
|
240
|
+
const sig = detector.record(t.name, t.input);
|
|
241
|
+
if (!sig.stuck) continue;
|
|
242
|
+
for (const r of emitted) {
|
|
243
|
+
yield await ctx.emit({
|
|
244
|
+
type: 'tool_result',
|
|
245
|
+
sessionId: ctx.sessionId,
|
|
246
|
+
turnId: ctx.turnId,
|
|
247
|
+
source: 'tool',
|
|
248
|
+
callId: asToolCallId(r.id),
|
|
249
|
+
ok: false,
|
|
250
|
+
error: { kind: 'aborted', message: report.abortedResultMessage },
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
const how = sig.kind === 'near' ? report.nearHint : 'with identical input';
|
|
254
|
+
if (report.extraOnStuck) {
|
|
255
|
+
for (const e of report.extraOnStuck({ toolName: t.name, count: sig.count, kind: sig.kind })) {
|
|
256
|
+
yield await ctx.emit(e);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
yield await ctx.emit({
|
|
260
|
+
type: 'error',
|
|
261
|
+
sessionId: ctx.sessionId,
|
|
262
|
+
turnId: ctx.turnId,
|
|
263
|
+
source: 'system',
|
|
264
|
+
kind: 'fatal',
|
|
265
|
+
message: report.fatalMessage({ toolName: t.name, count: sig.count, how }),
|
|
266
|
+
});
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
return false;
|
|
270
|
+
}
|