fix(compaction): pass model through runtime for safeguard summaries#17864
fix(compaction): pass model through runtime for safeguard summaries#17864vincentkoc merged 7 commits intoopenclaw:mainfrom
Conversation
mudrii
left a comment
There was a problem hiding this comment.
Code Review
Verdict: APPROVE ✅
What it fixes
Compaction always fails with "Summary unavailable due to context limits" because ctx.model is undefined in the compact.ts workflow — extensionRunner.initialize() is never called there, so the model is never set on the context.
Analysis
Model passthrough via runtime registry — Well done. Adds model field to CompactionSafeguardRuntimeValue, stores params.model in buildEmbeddedExtensionPaths, and uses ctx.model ?? runtime?.model fallback in the safeguard. This follows the exact same pattern already used for maxHistoryShare and contextWindowTokens — consistent and low-risk.
BASE_CHUNK_RATIO: 0.4 → 0.25 — Reasonable and conservative. On 200K context, chunks go from 80K → 50K tokens. MIN_CHUNK_RATIO is 0.15, so there is room to shrink further if needed. The rationale is sound: when compaction triggers reactively at 90%+ usage, oversized chunks can exceed what the summarization model can handle after adding prompt overhead. Trade-off is more summarization calls (slightly higher cost/latency) but significantly more reliable compaction.
Code quality — The runtime variable was already fetched later in the function; the diff just moves its usage earlier for cleaner flow. Type is Model<Api> which is correct. The redundant if (!ctx.model && !runtime?.model) inside the existing if (!model) block is always true at that point (since model = ctx.model ?? runtime?.model), so the inner check is unnecessary but harmless as documentation.
Minor suggestion
No unit tests were added for the ctx.model undefined → runtime fallback path. Would be nice to have but the change surface is small and the pattern is proven.
Overall clean, well-scoped fix. Ship it. 🚀
ced5b48 to
20ebf07
Compare
|
Updated the PR based on review feedback: Removed:
Added:
The PR now focuses solely on fixing the root cause: ctx.model being undefined in compact.ts workflow. |
Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864
Test Coverage AddedAdded comprehensive integration tests for the model fallback behavior: New Tests (4 total)
Test ResultsAll tests pass, covering:
Commit: 9ebb455 |
Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864
9ebb455 to
cf69df1
Compare
Test Improvements (addressing medium-priority feedback)Concrete Evidence of Fallback PathAdded explicit assertions to prove the fallback expression Test 1: Model fallback path // Proves handler used runtime.model by verifying getApiKey was called with it
expect(getApiKeyMock).toHaveBeenCalledWith(model);Test 2: Early return path // Proves handler returned early without trying to use a model
expect(getApiKeyMock).not.toHaveBeenCalled();What This Proves
The previous version only verified the output and registry state, which could be true even if the fallback path was never used. Now we have direct evidence the handler consumed Test Classification NoteAcknowledged: test file is named Commit: cf69df1 |
Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864
cf69df1 to
15ced77
Compare
Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864
15ced77 to
c3ca172
Compare
Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864
f63ea1d to
0488b97
Compare
Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864
Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864
0488b97 to
cd8f8af
Compare
Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864
cd8f8af to
f9b1fb5
Compare
Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864
804dbfe to
9122ef6
Compare
Fixes openclaw#3479 Root cause: extensionRunner.initialize() is never called in compact.ts workflow, leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns fallback summary immediately without attempting LLM summarization. Changes: 1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare) 2. Fall back to runtime.model when ctx.model is undefined 3. Add once-per-session warning when both models are missing (prevents log spam) 4. Add regression test for runtime.model fallback This follows the established runtime registry pattern rather than attempting to call extensionRunner.initialize() (which is SDK-internal and not meant for direct access). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864
- Add baseUrl to Model mock objects (now required by Model<Api>) - Add explicit Model<Api> annotation to prevent provider string widening - Cast modelRegistry mock through unknown (ModelRegistry expanded) - Use non-null assertion for compactionHandler (TypeScript strict) - Type compaction result explicitly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6520fcb to
5945769
Compare
|
Rebase + readiness update:
Given overlap, #4223 has been closed as duplicate with attribution preserved. This should stay canonical for the |
|
@greptile review |
…penclaw#17864) * fix(compaction): pass model through runtime to fix ctx.model undefined Fixes openclaw#3479 Root cause: extensionRunner.initialize() is never called in compact.ts workflow, leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns fallback summary immediately without attempting LLM summarization. Changes: 1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare) 2. Fall back to runtime.model when ctx.model is undefined 3. Add once-per-session warning when both models are missing (prevents log spam) 4. Add regression test for runtime.model fallback This follows the established runtime registry pattern rather than attempting to call extensionRunner.initialize() (which is SDK-internal and not meant for direct access). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * test: add comprehensive tests for compaction-safeguard model fallback Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864 * fix(test): adapt compaction-safeguard tests to upstream type changes - Add baseUrl to Model mock objects (now required by Model<Api>) - Add explicit Model<Api> annotation to prevent provider string widening - Cast modelRegistry mock through unknown (ModelRegistry expanded) - Use non-null assertion for compactionHandler (TypeScript strict) - Type compaction result explicitly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Compaction: add changelog credit for model fallback fix * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#17864) * fix(compaction): pass model through runtime to fix ctx.model undefined Fixes openclaw#3479 Root cause: extensionRunner.initialize() is never called in compact.ts workflow, leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns fallback summary immediately without attempting LLM summarization. Changes: 1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare) 2. Fall back to runtime.model when ctx.model is undefined 3. Add once-per-session warning when both models are missing (prevents log spam) 4. Add regression test for runtime.model fallback This follows the established runtime registry pattern rather than attempting to call extensionRunner.initialize() (which is SDK-internal and not meant for direct access). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * test: add comprehensive tests for compaction-safeguard model fallback Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864 * fix(test): adapt compaction-safeguard tests to upstream type changes - Add baseUrl to Model mock objects (now required by Model<Api>) - Add explicit Model<Api> annotation to prevent provider string widening - Cast modelRegistry mock through unknown (ModelRegistry expanded) - Use non-null assertion for compactionHandler (TypeScript strict) - Type compaction result explicitly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Compaction: add changelog credit for model fallback fix * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#17864) * fix(compaction): pass model through runtime to fix ctx.model undefined Fixes openclaw#3479 Root cause: extensionRunner.initialize() is never called in compact.ts workflow, leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns fallback summary immediately without attempting LLM summarization. Changes: 1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare) 2. Fall back to runtime.model when ctx.model is undefined 3. Add once-per-session warning when both models are missing (prevents log spam) 4. Add regression test for runtime.model fallback This follows the established runtime registry pattern rather than attempting to call extensionRunner.initialize() (which is SDK-internal and not meant for direct access). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * test: add comprehensive tests for compaction-safeguard model fallback Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864 * fix(test): adapt compaction-safeguard tests to upstream type changes - Add baseUrl to Model mock objects (now required by Model<Api>) - Add explicit Model<Api> annotation to prevent provider string widening - Cast modelRegistry mock through unknown (ModelRegistry expanded) - Use non-null assertion for compactionHandler (TypeScript strict) - Type compaction result explicitly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Compaction: add changelog credit for model fallback fix * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#17864) * fix(compaction): pass model through runtime to fix ctx.model undefined Fixes openclaw#3479 Root cause: extensionRunner.initialize() is never called in compact.ts workflow, leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns fallback summary immediately without attempting LLM summarization. Changes: 1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare) 2. Fall back to runtime.model when ctx.model is undefined 3. Add once-per-session warning when both models are missing (prevents log spam) 4. Add regression test for runtime.model fallback This follows the established runtime registry pattern rather than attempting to call extensionRunner.initialize() (which is SDK-internal and not meant for direct access). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * test: add comprehensive tests for compaction-safeguard model fallback Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864 * fix(test): adapt compaction-safeguard tests to upstream type changes - Add baseUrl to Model mock objects (now required by Model<Api>) - Add explicit Model<Api> annotation to prevent provider string widening - Cast modelRegistry mock through unknown (ModelRegistry expanded) - Use non-null assertion for compactionHandler (TypeScript strict) - Type compaction result explicitly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Compaction: add changelog credit for model fallback fix * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#17864) * fix(compaction): pass model through runtime to fix ctx.model undefined Fixes openclaw#3479 Root cause: extensionRunner.initialize() is never called in compact.ts workflow, leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns fallback summary immediately without attempting LLM summarization. Changes: 1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare) 2. Fall back to runtime.model when ctx.model is undefined 3. Add once-per-session warning when both models are missing (prevents log spam) 4. Add regression test for runtime.model fallback This follows the established runtime registry pattern rather than attempting to call extensionRunner.initialize() (which is SDK-internal and not meant for direct access). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * test: add comprehensive tests for compaction-safeguard model fallback Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864 * fix(test): adapt compaction-safeguard tests to upstream type changes - Add baseUrl to Model mock objects (now required by Model<Api>) - Add explicit Model<Api> annotation to prevent provider string widening - Cast modelRegistry mock through unknown (ModelRegistry expanded) - Use non-null assertion for compactionHandler (TypeScript strict) - Type compaction result explicitly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Compaction: add changelog credit for model fallback fix * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#17864) * fix(compaction): pass model through runtime to fix ctx.model undefined Fixes openclaw#3479 Root cause: extensionRunner.initialize() is never called in compact.ts workflow, leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns fallback summary immediately without attempting LLM summarization. Changes: 1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare) 2. Fall back to runtime.model when ctx.model is undefined 3. Add once-per-session warning when both models are missing (prevents log spam) 4. Add regression test for runtime.model fallback This follows the established runtime registry pattern rather than attempting to call extensionRunner.initialize() (which is SDK-internal and not meant for direct access). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * test: add comprehensive tests for compaction-safeguard model fallback Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864 * fix(test): adapt compaction-safeguard tests to upstream type changes - Add baseUrl to Model mock objects (now required by Model<Api>) - Add explicit Model<Api> annotation to prevent provider string widening - Cast modelRegistry mock through unknown (ModelRegistry expanded) - Use non-null assertion for compactionHandler (TypeScript strict) - Type compaction result explicitly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Compaction: add changelog credit for model fallback fix * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#17864) * fix(compaction): pass model through runtime to fix ctx.model undefined Fixes openclaw#3479 Root cause: extensionRunner.initialize() is never called in compact.ts workflow, leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns fallback summary immediately without attempting LLM summarization. Changes: 1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare) 2. Fall back to runtime.model when ctx.model is undefined 3. Add once-per-session warning when both models are missing (prevents log spam) 4. Add regression test for runtime.model fallback This follows the established runtime registry pattern rather than attempting to call extensionRunner.initialize() (which is SDK-internal and not meant for direct access). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * test: add comprehensive tests for compaction-safeguard model fallback Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864 * fix(test): adapt compaction-safeguard tests to upstream type changes - Add baseUrl to Model mock objects (now required by Model<Api>) - Add explicit Model<Api> annotation to prevent provider string widening - Cast modelRegistry mock through unknown (ModelRegistry expanded) - Use non-null assertion for compactionHandler (TypeScript strict) - Type compaction result explicitly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Compaction: add changelog credit for model fallback fix * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#17864) * fix(compaction): pass model through runtime to fix ctx.model undefined Fixes openclaw#3479 Root cause: extensionRunner.initialize() is never called in compact.ts workflow, leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns fallback summary immediately without attempting LLM summarization. Changes: 1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare) 2. Fall back to runtime.model when ctx.model is undefined 3. Add once-per-session warning when both models are missing (prevents log spam) 4. Add regression test for runtime.model fallback This follows the established runtime registry pattern rather than attempting to call extensionRunner.initialize() (which is SDK-internal and not meant for direct access). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * test: add comprehensive tests for compaction-safeguard model fallback Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864 * fix(test): adapt compaction-safeguard tests to upstream type changes - Add baseUrl to Model mock objects (now required by Model<Api>) - Add explicit Model<Api> annotation to prevent provider string widening - Cast modelRegistry mock through unknown (ModelRegistry expanded) - Use non-null assertion for compactionHandler (TypeScript strict) - Type compaction result explicitly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Compaction: add changelog credit for model fallback fix * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#17864) * fix(compaction): pass model through runtime to fix ctx.model undefined Fixes openclaw#3479 Root cause: extensionRunner.initialize() is never called in compact.ts workflow, leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns fallback summary immediately without attempting LLM summarization. Changes: 1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare) 2. Fall back to runtime.model when ctx.model is undefined 3. Add once-per-session warning when both models are missing (prevents log spam) 4. Add regression test for runtime.model fallback This follows the established runtime registry pattern rather than attempting to call extensionRunner.initialize() (which is SDK-internal and not meant for direct access). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * test: add comprehensive tests for compaction-safeguard model fallback Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864 * fix(test): adapt compaction-safeguard tests to upstream type changes - Add baseUrl to Model mock objects (now required by Model<Api>) - Add explicit Model<Api> annotation to prevent provider string widening - Cast modelRegistry mock through unknown (ModelRegistry expanded) - Use non-null assertion for compactionHandler (TypeScript strict) - Type compaction result explicitly Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Compaction: add changelog credit for model fallback fix * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
…penclaw#17864) * fix(compaction): pass model through runtime to fix ctx.model undefined Fixes openclaw#3479 Root cause: extensionRunner.initialize() is never called in compact.ts workflow, leaving ctx.model undefined. Compaction safeguard checks ctx.model and returns fallback summary immediately without attempting LLM summarization. Changes: 1. Pass model through compaction safeguard runtime registry (same pattern as maxHistoryShare) 2. Fall back to runtime.model when ctx.model is undefined 3. Add once-per-session warning when both models are missing (prevents log spam) 4. Add regression test for runtime.model fallback This follows the established runtime registry pattern rather than attempting to call extensionRunner.initialize() (which is SDK-internal and not meant for direct access). * test: add comprehensive tests for compaction-safeguard model fallback Add integration tests to verify the model fallback behavior: - Test runtime.model fallback when ctx.model is undefined (compact.ts workflow) - Test fallback summary when both ctx.model and runtime.model are undefined - Test contextWindowTokens runtime storage/retrieval - Test combined runtime values (maxHistoryShare + contextWindowTokens + model) These tests verify the fix for issue openclaw#3479 where compaction fails due to ctx.model being undefined in the compact.ts workflow. The runtime registry pattern allows model to be passed when extensionRunner.initialize() is not called, ensuring summarization works in all code paths. Related: PR openclaw#17864 * fix(test): adapt compaction-safeguard tests to upstream type changes - Add baseUrl to Model mock objects (now required by Model<Api>) - Add explicit Model<Api> annotation to prevent provider string widening - Cast modelRegistry mock through unknown (ModelRegistry expanded) - Use non-null assertion for compactionHandler (TypeScript strict) - Type compaction result explicitly * Compaction: add changelog credit for model fallback fix * Update CHANGELOG.md * Update CHANGELOG.md --------- Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
Summary
Fixes #3479 — compaction always failing with "Summary unavailable due to context limits"
This PR addresses the root cause:
ctx.modelis undefined during compaction becauseextensionRunner.initialize()is never called in thecompact.tsworkflow. The compaction safeguard immediately returns a fallback summary without attempting LLM summarization.Changes
modelfield toCompactionSafeguardRuntimeValuetypeparams.modelwhen building embedded extension pathsruntime.modelwhenctx.modelis undefinedWhy This Approach
Following the established runtime registry pattern (same as
maxHistoryShareandcontextWindowTokens) rather than attempting to callextensionRunner.initialize()directly, which is SDK-internal and not meant for external access.Testing
Related
Greptile Summary
This PR addresses a critical bug where compaction always failed with "Summary unavailable due to context limits" because
ctx.modelwas undefined during thecompact.tsworkflow.The fix passes the model through the runtime registry (following the established pattern used for
maxHistoryShareandcontextWindowTokens), allowing the compaction safeguard to fall back toruntime.modelwhenctx.modelis unavailable. The implementation is clean and well-tested:modelfield toCompactionSafeguardRuntimeValuetype with clear documentationbuildEmbeddedExtensionFactoriesto storeparams.modelin runtime registrycompaction-safeguard.tsto usectx.model ?? runtime?.modelfallback patternConfidence Score: 5/5
Last reviewed commit: d9b1f0e