Releases: MyPrototypeWhat/context-chef
@context-chef/[email protected]
Patch Changes
- Updated dependencies [
351d172]:- @context-chef/[email protected]
@context-chef/[email protected]
Patch Changes
-
351d172Thanks @MyPrototypeWhat! - AddAbortSignalsupport tocompile()and event handlers (T2.4).CompileOptions.signal?: AbortSignalpropagates cooperative cancellation in two ways:- Forwarded to event handlers as the second argument.
chef.on(event, async (payload, signal) => { await db.write(payload, { signal }); })lets observers honor cancellation in slow async work (DB writes, metric exports, fetch calls). - Checked at compile() phase boundaries — after
compile:start, after Janitor compress, afteronBeforeCompile, after memory sweep, aftertransformContext. Aborting throws viasignal.throwIfAborted()(DOMExceptionwithname: 'AbortError').
EventHandler<T>signature widened to(payload: T, signal?: AbortSignal) => void | Promise<void>. Backward compatible — handlers that don't declare the second parameter continue to work unchanged.Memory events fired from external
memory().set()/memory().delete()calls (outsidecompile()) receivesignal: undefined.Caveats (documented in
CompileOptions.signalJSDoc):compile:startis emitted before any abort check — observers may receive acompile:startfor a compile that ultimately throws without firingcompile:done.- Memory turn counter advances at step 4; aborting after step 4 leaves
Memory.turnCountadvanced even though no payload was produced. - Cancellation is coarse-grained — long-running phases run to completion; abort honored at the next phase boundary.
Known limitation:
compile()is not concurrency-safe on the same chef instance — concurrent calls clobber_currentSignal, double-advance the memory turn counter, and interleave skill/history reads. Serialize per chef instance, or create separate instances for parallel work. Snapshot+serialize support is planned (seeTODO.mdT2.4.1). - Forwarded to event handlers as the second argument.
@context-chef/[email protected]
Patch Changes
- Updated dependencies [
351d172]:- @context-chef/[email protected]
@context-chef/[email protected]
Patch Changes
-
0b09ce5Thanks @MyPrototypeWhat! - Error message UX patch — clearer text, consistent empty-registry rendering, and one real config-field-name fix.Real bug fix
ContextChef.getMemory(): previously claimedrequires a memoryStore in ChefConfig, but the actual config field ismemory: { store: ... }— notmemoryStore. Users hitting this error and grep'ing the docs found nothing. Now points at the correct field name plus a hint about the three built-in store implementations (InMemoryStore,VFSMemoryStore, customMemoryStore).
Clearer error text
tanstack-ai'scompactConfigrejection: previouslyUnrecognized toolCalls compact mode: "X"left users to grep the source for valid values. Now lists all four ('none','all','before-last-message','before-last-N-messages') with the N-substitution example.loadSkillparse errors: missingname/descriptionerrors now embed a minimal SKILL.md frontmatter snippet so the fix is obvious from the error alone. The "indented values are not supported" error now points to inline-array / quoted-string workarounds. The missing-descriptionsnippet reuses the user's parsedname(sanitized: long names or---literals fall back tomy-skillto avoid generating a malformed example).
Consistent empty-registry rendering
Five throw sites across the library now render an empty options list as
(none)rather than producingAvailable:(trailing empty space) orRegistered: [].— matches the pattern already used byContextChef.activateSkill:Pruner.extractToolkit— empty toolkit registryPruner.resolveNamespace(unknown namespace) — empty namespace registryPruner.resolveNamespace(unknown action) — namespace with no toolsAdapterRegistry.get— empty adapter registry
Consumer-visible side effect for
loadSkillerrors onlyThe missing-
nameand missing-descriptionloadSkillerrors now contain literal\nnewlines (the example snippet). Code that doeserror.message.split('\n')[0]to summarize, or relies on these messages being single-line for log formatting, will see the extra lines. Multi-line messages flow throughloadSkillsDir'sresult.errors[].messagefield; if you JSON-serialize that for transport or UI, the newlines become\\nand the snippet renders less readably than in a terminal log. The other rewritten messages (getMemory,compactConfig,Pruner/AdapterRegistryempty fallbacks, "indented values") all remain single-line. -
Updated dependencies [
0b09ce5]:- @context-chef/[email protected]
@context-chef/[email protected]
Patch Changes
-
135337dThanks @MyPrototypeWhat! - Tightentokenizeroption signature from(messages: unknown[]) => numberto(messages: Message[]) => number.The middleware always invokes the user-supplied tokenizer with
Message[](the core IR type) — the previousunknown[]was a leak in the public type, forcing callers to cast or narrow inside their tokenizer. The new signature matches the actual runtime contract and matches@context-chef/core'sJanitorconfig.Type-only change; no runtime behavior change. Existing tokenizers typed as
(messages: unknown[]) => numberwill continue to compile, but callers can now drop the cast and readMessagefields directly.
@context-chef/[email protected]
Patch Changes
-
0b09ce5Thanks @MyPrototypeWhat! - Error message UX patch — clearer text, consistent empty-registry rendering, and one real config-field-name fix.Real bug fix
ContextChef.getMemory(): previously claimedrequires a memoryStore in ChefConfig, but the actual config field ismemory: { store: ... }— notmemoryStore. Users hitting this error and grep'ing the docs found nothing. Now points at the correct field name plus a hint about the three built-in store implementations (InMemoryStore,VFSMemoryStore, customMemoryStore).
Clearer error text
tanstack-ai'scompactConfigrejection: previouslyUnrecognized toolCalls compact mode: "X"left users to grep the source for valid values. Now lists all four ('none','all','before-last-message','before-last-N-messages') with the N-substitution example.loadSkillparse errors: missingname/descriptionerrors now embed a minimal SKILL.md frontmatter snippet so the fix is obvious from the error alone. The "indented values are not supported" error now points to inline-array / quoted-string workarounds. The missing-descriptionsnippet reuses the user's parsedname(sanitized: long names or---literals fall back tomy-skillto avoid generating a malformed example).
Consistent empty-registry rendering
Five throw sites across the library now render an empty options list as
(none)rather than producingAvailable:(trailing empty space) orRegistered: [].— matches the pattern already used byContextChef.activateSkill:Pruner.extractToolkit— empty toolkit registryPruner.resolveNamespace(unknown namespace) — empty namespace registryPruner.resolveNamespace(unknown action) — namespace with no toolsAdapterRegistry.get— empty adapter registry
Consumer-visible side effect for
loadSkillerrors onlyThe missing-
nameand missing-descriptionloadSkillerrors now contain literal\nnewlines (the example snippet). Code that doeserror.message.split('\n')[0]to summarize, or relies on these messages being single-line for log formatting, will see the extra lines. Multi-line messages flow throughloadSkillsDir'sresult.errors[].messagefield; if you JSON-serialize that for transport or UI, the newlines become\\nand the snippet renders less readably than in a terminal log. The other rewritten messages (getMemory,compactConfig,Pruner/AdapterRegistryempty fallbacks, "indented values") all remain single-line.
@context-chef/[email protected]
Patch Changes
- Updated dependencies [
0b09ce5]:- @context-chef/[email protected]
@context-chef/[email protected]
Patch Changes
-
135337dThanks @MyPrototypeWhat! - Tightentokenizeroption signature from(messages: unknown[]) => numberto(messages: Message[]) => number.The middleware always invokes the user-supplied tokenizer with
Message[](the core IR type) — the previousunknown[]was a leak in the public type, forcing callers to cast or narrow inside their tokenizer. The new signature matches the actual runtime contract and matches@context-chef/core'sJanitorconfig.Type-only change; no runtime behavior change. Existing tokenizers typed as
(messages: unknown[]) => numberwill continue to compile, but callers can now drop the cast and readMessagefields directly.
@context-chef/[email protected]
Patch Changes
- Updated dependencies [
31d1812]:- @context-chef/[email protected]
@context-chef/[email protected]
Minor Changes
-
b9cec8bThanks @MyPrototypeWhat! - feat: addusagePreferenceto control which token source drives compression triggersWhen both a
tokenizerand areportTokenUsage()value are available, you can now choose
how the Janitor decides whether to compress:'max'(default, backward-compatible) —Math.max(tokenizer, fed). Most conservative;
any over-budget signal triggers compression.'feedFirst'— prefer the API-reported usage when present, fall back to the tokenizer.
Use when reported usage is authoritative and the tokenizer over-estimates (e.g. one
config shared across providers, some of which report usage and some of which rely on
the tokenizer fallback).'tokenizerFirst'— ignore the fed value entirely; trust the tokenizer.
The split-index calculation is unchanged — it always uses precise per-turn tokenization
in the tokenizer path.usagePreferenceonly affects the trigger decision.Both middleware packages expose this as
compress.usagePreference. When'tokenizerFirst'
is set without atokenizer, the middleware sanitizes it to'max'at construction time
with a console warning.Type-level note.
JanitorConfigis now a discriminated union ontokenizerpresence.
TypeScript rejects'tokenizerFirst'at compile time when no tokenizer is configured.
Callers that previously passedtokenizer: SomeFn | undefinedin a single literal will
need to split construction into two branches (tokenizer ? new Janitor({...}) : new Janitor({...}));
runtime behavior is unchanged.
Patch Changes
- Updated dependencies [
b9cec8b]:- @context-chef/[email protected]