feat(cognition,#1411): tool_embedding PR-2 — process cache + async embed/search + IPC handlers#1416
Merged
Merged
Conversation
…bed/search + IPC handlers Stacks on PR-1 #1413 (MERGED). Wires the async path: process-wide LazyLock<Mutex<ToolEmbeddingCache>> + async embed_tools (replaces TS ToolRegistry.generateToolEmbeddings) + async semantic_search_tools (replaces TS ToolRegistry.semanticSearchTools) + cognition/embed-tools + cognition/semantic-search-tools IPC handlers. ## What this ships - ToolEmbeddingCache (process-singleton) — Vec<ToolEmbedding> + parallel Vec<ToolDescription> + model. Replaces TS ToolRegistry.toolEmbeddings: Map<string, Float32Array>. - ToolEmbeddingError — typed: NoAdapter, EmbeddingFailed, CacheEmpty, EmbeddingCountMismatch. - embed_tools(EmbedToolsRequest) -> Result<EmbedToolsResponse, _> — async. Routes via global_registry → adapter.create_embedding, validates count parity, replaces (not merges) cache atomically under one lock acquire. - semantic_search_tools(SemanticSearchToolsRequest) -> Result<Vec<SemanticSearchResult>, _> — async. Reads cached embeddings (CacheEmpty if absent), embeds the query through the cache's model (no silent space-mixing), computes cosine via PR-1 pure fn, filters by threshold, sorts descending, truncates to limit. - IPC command arms: cognition/embed-tools + cognition/semantic-search-tools. - Test scaffolding (_clear_cache_for_tests + _install_cache_for_tests) for cache-state tests without requiring a real adapter. ## NOT in this PR - PR-3: TS shim — ToolRegistry.generateToolEmbeddings + semanticSearchTools delegate to client.cognitionEmbedTools + client.cognitionSemanticSearchTools. - PR-4: Delete dead TS — inline cosineSimilarity, toolEmbeddings Map, AIProviderDaemon.createEmbedding call sites. ## Discipline - No silent default-on-error. Provider failure / count mismatch / empty cache surface as typed Result. - semantic_search_tools uses the cache's model unless explicitly overridden — never silently mixes embedding spaces (different models = meaningless cosine). - Cache replacement atomic under one Mutex acquire — no read-modify-write window for partial state. - expect("mutex poisoned") panics rather than swallowing — by design. - generated_at_ms intentionally NOT retained on cache struct (no internal reader yet; EmbedToolsResponse already carries it for caller observability; a future cache-state IPC can re-add). ## Tests (5 new — full module now 27 passing) - Error Display: NoAdapter carries provider+model, CacheEmpty gives actionable hint, EmbeddingCountMismatch includes both numbers. - semantic_search_empty_cache_errors pins CacheEmpty before any adapter lookup. - cache_install_and_clear_for_tests pins scaffolding contract. Full cognition regression: 373/373 pass. Clippy held at 157 baseline. Ref: #1411 PR-1 (MERGED #1413), #1248 umbrella. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
joelteply
added a commit
that referenced
this pull request
May 18, 2026
… (PR-4 folded) (#1418) * feat(cognition,#1411): tool_embedding PR-2 — process cache + async embed/search + IPC handlers Stacks on PR-1 #1413 (MERGED). Wires the async path: process-wide LazyLock<Mutex<ToolEmbeddingCache>> + async embed_tools (replaces TS ToolRegistry.generateToolEmbeddings) + async semantic_search_tools (replaces TS ToolRegistry.semanticSearchTools) + cognition/embed-tools + cognition/semantic-search-tools IPC handlers. ## What this ships - ToolEmbeddingCache (process-singleton) — Vec<ToolEmbedding> + parallel Vec<ToolDescription> + model. Replaces TS ToolRegistry.toolEmbeddings: Map<string, Float32Array>. - ToolEmbeddingError — typed: NoAdapter, EmbeddingFailed, CacheEmpty, EmbeddingCountMismatch. - embed_tools(EmbedToolsRequest) -> Result<EmbedToolsResponse, _> — async. Routes via global_registry → adapter.create_embedding, validates count parity, replaces (not merges) cache atomically under one lock acquire. - semantic_search_tools(SemanticSearchToolsRequest) -> Result<Vec<SemanticSearchResult>, _> — async. Reads cached embeddings (CacheEmpty if absent), embeds the query through the cache's model (no silent space-mixing), computes cosine via PR-1 pure fn, filters by threshold, sorts descending, truncates to limit. - IPC command arms: cognition/embed-tools + cognition/semantic-search-tools. - Test scaffolding (_clear_cache_for_tests + _install_cache_for_tests) for cache-state tests without requiring a real adapter. ## NOT in this PR - PR-3: TS shim — ToolRegistry.generateToolEmbeddings + semanticSearchTools delegate to client.cognitionEmbedTools + client.cognitionSemanticSearchTools. - PR-4: Delete dead TS — inline cosineSimilarity, toolEmbeddings Map, AIProviderDaemon.createEmbedding call sites. ## Discipline - No silent default-on-error. Provider failure / count mismatch / empty cache surface as typed Result. - semantic_search_tools uses the cache's model unless explicitly overridden — never silently mixes embedding spaces (different models = meaningless cosine). - Cache replacement atomic under one Mutex acquire — no read-modify-write window for partial state. - expect("mutex poisoned") panics rather than swallowing — by design. - generated_at_ms intentionally NOT retained on cache struct (no internal reader yet; EmbedToolsResponse already carries it for caller observability; a future cache-state IPC can re-add). ## Tests (5 new — full module now 27 passing) - Error Display: NoAdapter carries provider+model, CacheEmpty gives actionable hint, EmbeddingCountMismatch includes both numbers. - semantic_search_empty_cache_errors pins CacheEmpty before any adapter lookup. - cache_install_and_clear_for_tests pins scaffolding contract. Full cognition regression: 373/373 pass. Clippy held at 157 baseline. Ref: #1411 PR-1 (MERGED #1413), #1248 umbrella. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(cognition,#1411): tool_embedding PR-3 — TS shim + delete dead TS (PR-4 folded) Stacks on PR-2 #1416. ToolRegistry.generateToolEmbeddings (inline AIProviderDaemon.createEmbedding) + semanticSearchTools (inline cosineSimilarity + manual sort) now delegate to RustCoreIPCClient.cognitionEmbedTools + RustCoreIPCClient.cognitionSemanticSearchTools. Mirrors codex's check_redundancy PR-3 #1383 shape (PR-4 dead-code delete folded in). ## What this ships - `ToolRegistry.populateRustEmbeddingCache` — calls client.cognitionEmbedTools with all registered tools. Rust populates the process-wide cache. - `ToolRegistry.ensureToolEmbeddings` simplified — one-shot guard + concurrent-call dedup. TTL gone (Rust cache persists for the process lifetime; a future "tools changed" event will re-trigger). - `ToolRegistry.semanticSearchTools` thin shim — call client.cognitionSemanticSearchTools(query, limit), map descriptions through cleanDescription for chat UX presentation. - TS cognition mixin adds `cognitionEmbedTools` + `cognitionSemanticSearchTools` binding methods. - New ts-rs barrel re-exports: EmbedToolsRequest, EmbedToolsResponse, SemanticSearchToolsRequest, SemanticSearchResult. ## Dead TS deleted (PR-4 folded in) - `private toolEmbeddings: Map<string, number[]>` cache state — Rust owns the cache now. - `private embeddingsGeneratedAt: number` + `EMBEDDINGS_TTL_MS` — TTL belongs to Rust if reintroduced. - `private cosineSimilarity(a, b)` — Rust's pure cosine_similarity (PR-1) is the source of truth. - `import { AIProviderDaemon }` from '../../../daemons/ai-provider-daemon/shared/AIProviderDaemon' — unused after both call sites moved to IPC. - Inline embedding request construction + Math.round + threshold-comparison loop — all in Rust now. Net diff: -136 LOC TS, +51 LOC mixin (which lives in the bindings layer next to other cognition delegates). Net cognition-TS deletion in the ratchet-watched dirs. ## Discipline - ensureToolEmbeddings cache flag scoped to TS singleton — no global state outside the registry instance. - Concurrent-call dedup retained (multiple callers hitting semanticSearchTools at boot won't trigger N parallel embed_tools IPC calls — TS pipes them through one promise). - cleanDescription stays TS — that's pure UI/presentation; Rust returns the raw description. - Error handling: IPC failures throw (no fail-open default), matches the pattern in cognitionGenerateResponse + cognitionCheckRedundancy. ## Stack progress - #1411 PR-1 (pure types + cosine + threshold): #1413 MERGED - #1411 PR-2 (cache + async + IPC handlers): #1416 OPEN - #1411 PR-3 (TS shim + dead-TS delete): **this PR** - #1411 PR-4 (dead-TS delete): **folded into this PR** After merge: `ToolRegistry.ts` semantic-search surface is a 40-LOC shim. AIProviderDaemon dependency gone from this file. ## Refs - #1411 sub-card - #1413 PR-1 (MERGED) - #1416 PR-2 (in flight) - #1383 codex's check_redundancy PR-3 — same shape, folded-PR-4 pattern - #1248 umbrella Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Test <test@test.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacks on PR-1 #1413 (MERGED). PR-2 wires the async path: process-wide
LazyLock<Mutex<ToolEmbeddingCache>>+ asyncembed_tools(replaces TSToolRegistry.generateToolEmbeddings) + asyncsemantic_search_tools(replaces TSToolRegistry.semanticSearchTools) +cognition/embed-tools+cognition/semantic-search-toolsIPC handlers.What this ships
ToolEmbeddingCache(process-singleton) —Vec<ToolEmbedding>+ parallelVec<ToolDescription>+ model. Replaces TSToolRegistry.toolEmbeddings: Map<string, Float32Array>so cache lifecycle stays Rust-side.ToolEmbeddingError— typed:NoAdapter,EmbeddingFailed,CacheEmpty,EmbeddingCountMismatch.embed_tools(EmbedToolsRequest) -> Result<EmbedToolsResponse, _>— async. Routes viaglobal_registry→adapter.create_embedding, validates count parity, replaces (not merges) cache atomically under one Mutex acquire.semantic_search_tools(SemanticSearchToolsRequest) -> Result<Vec<SemanticSearchResult>, _>— async. Reads cached embeddings (CacheEmptyif absent), embeds the query through the cache's model (no silent embedding-space mixing), computes cosine via PR-1 pure fn, filters by threshold, sorts descending, truncates to limit.cognition/embed-toolscognition/semantic-search-tools_clear_cache_for_tests+_install_cache_for_tests) for cache-state tests without a real adapter.NOT in this PR
ToolRegistry.generateToolEmbeddings+ToolRegistry.semanticSearchToolsdelegate toclient.cognitionEmbedTools+client.cognitionSemanticSearchTools.cosineSimilarity,toolEmbeddingsMap,AIProviderDaemon.createEmbeddingcall sites.Discipline
Resultvariants.semantic_search_toolsuses the cache's model unless explicitly overridden — never silently mixes embedding spaces (different models = meaningless cosine).Mutexacquire — no read-modify-write window for partial state.expect("mutex poisoned")panics rather than swallowing — by design (cache poisoning is a logic bug, not runtime).generated_at_msintentionally NOT retained on cache struct (no internal reader;EmbedToolsResponsecarries it for caller observability; future cache-state IPC can re-add).Tests (5 new — full module now 27 passing)
Full cognition regression: 373/373 pass. Clippy held at 157 baseline.
Refs
Test plan
cargo test cognition::tool_embedding::— 27/27 passcargo test cognition::— 373/373 pass (no regressions)cargo clippy— held at 157 baseline🤖 Generated with Claude Code