@moxxy/sdk 0.5.0 → 0.5.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moxxy/sdk",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
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.