@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.
@@ -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, no model descriptor, no
29
- * contextWindow, or a compactor throw all degrade to a no-op so a
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;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,WAAW,EAChB,IAAI,GAAE;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GACtC,OAAO,CAAC,OAAO,CAAC,CAwElB;AAqBD,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAE/D"}
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, no model descriptor, no
96
- * contextWindow, or a compactor throw all degrade to a no-op so a
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 descriptor so we use the *real* context
105
- // window. `Number.MAX_SAFE_INTEGER` (the old /compact behavior) made
106
- // threshold-based compactors always look comfortable, even at 99%.
107
- const descriptor = ctx.provider.models.find((m) => m.id === ctx.model);
108
- const contextWindow = descriptor?.contextWindow;
109
- if (!contextWindow || contextWindow <= 0)
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: descriptor?.maxOutputTokens ?? 0,
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,CA6DxE"}
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"}
@@ -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
- const descriptor = ctx.provider.models.find((m) => m.id === ctx.model);
34
- const contextWindow = descriptor?.contextWindow;
35
- if (!contextWindow || contextWindow <= 0)
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":"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"}
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';
@@ -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,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAGtD,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"}
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"}
@@ -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 (tool-use, plan-execute, developer, bmad) so
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;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;;;;;;;;;;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"}
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"}
@@ -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 (tool-use, plan-execute, developer, bmad) so
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":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAMxC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,gBAAgB,CACrC,GAAgB,EAChB,CAAmB,EACnB,SAAiB;IAEjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC;YAC/C,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,GAAG,EAAE,EAAE;YACP,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,GAAG,EAAE,EAAE;YACP,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,SAAS;YACT,IAAI,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE;SACnE,CAAC,CAAC;QACH,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAE3E,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,KAAK,CAC1C,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,EAChE,EAAE,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,eAAe,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,CAC1F,CAAC;QACF,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC7B,KAAK,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,QAAQ,CAAC,MAAM,IAAI,oBAAoB,EAAE,UAAU,CAAC,CAAC;YAC/E,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC;YACnB,IAAI,EAAE,oBAAoB;YAC1B,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1B,SAAS,EAAE,UAAU;YACrB,IAAI,EAAE,QAAQ,CAAC,IAAI;SACpB,CAAC,CAAC;QAEH,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE;gBACtE,MAAM,EAAE,CAAC,CAAC,EAAE;gBACZ,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC;gBAChC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;gBAC1B,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACvD,CAAC,CAAC;YACH,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC;gBACnB,IAAI,EAAE,aAAa;gBACnB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,EAAE,EAAE,IAAI;gBACR,MAAM;aACP,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,IAAI,GAAwB,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;YAC3E,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC;gBACnB,IAAI,EAAE,aAAa;gBACnB,SAAS,EAAE,GAAG,CAAC,SAAS;gBACxB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,MAAM,EAAE,MAAM;gBACd,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC1B,EAAE,EAAE,KAAK;gBACT,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;aACzB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,2EAA2E;QAC3E,2EAA2E;QAC3E,+DAA+D;QAC/D,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC;YACnB,IAAI,EAAE,aAAa;YACnB,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1B,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,wBAAwB,OAAO,EAAE,EAAE;SACrE,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,OAAwB;IACxC,OAAO,OAAO,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3D,CAAC;AAED,KAAK,SAAS,CAAC,CAAC,UAAU,CACxB,GAAgB,EAChB,CAAmB,EACnB,MAAc,EACd,EAAkC;IAElC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC;QACnB,IAAI,EAAE,kBAAkB;QACxB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,MAAM,EAAE,QAAQ;QAChB,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1B,SAAS,EAAE,EAAE;QACb,MAAM;KACP,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC;QACnB,IAAI,EAAE,aAAa;QACnB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,MAAM,EAAE,MAAM;QACd,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1B,EAAE,EAAE,KAAK;QACT,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE;KAC3C,CAAC,CAAC;AACL,CAAC"}
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.5.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/vitest-preset": "0.0.0",
65
- "@moxxy/tsconfig": "0.0.0"
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
- id: opts.model ?? 'fake-model',
192
- contextWindow: opts.contextWindow ?? 100_000,
193
- supportsTools: true,
194
- supportsStreaming: true,
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
- model: opts.model ?? 'fake-model',
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: () => [] },
@@ -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, no model descriptor, no
105
- * contextWindow, or a compactor throw all degrade to a no-op so a
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 descriptor so we use the *real* context
117
- // window. `Number.MAX_SAFE_INTEGER` (the old /compact behavior) made
118
- // threshold-based compactors always look comfortable, even at 99%.
119
- const descriptor = ctx.provider.models.find((m) => m.id === ctx.model);
120
- const contextWindow = descriptor?.contextWindow;
121
- if (!contextWindow || contextWindow <= 0) return false;
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: descriptor?.maxOutputTokens ?? 0,
155
+ reserveForOutput: resolved?.reserveForOutput ?? 0,
130
156
  } as const;
131
157
 
132
158
  // `force` skips the threshold gate — used reactively after the provider
@@ -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
- const descriptor = ctx.provider.models.find((m) => m.id === ctx.model);
64
- const contextWindow = descriptor?.contextWindow;
65
- if (!contextWindow || contextWindow <= 0) return;
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 { dispatchToolCall } from './tool-dispatch.js';
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 {
@@ -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 (tool-use, plan-execute, developer, bmad) so
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
+ }