zam-core 0.6.3 → 0.7.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.
- package/.agent/skills/zam/SKILL.md +7 -3
- package/.agents/skills/zam/SKILL.md +7 -3
- package/.claude/skills/zam/SKILL.md +7 -3
- package/dist/cli/index.js +752 -31
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +122 -2
- package/dist/index.js +268 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1010,6 +1010,97 @@ interface SourceProposalInput {
|
|
|
1010
1010
|
*/
|
|
1011
1011
|
declare function confirmSourceImport(db: Database, userId: string, sourceId: string, proposals: SourceProposalInput[]): Promise<ConfirmFoundationsResult>;
|
|
1012
1012
|
|
|
1013
|
+
/**
|
|
1014
|
+
* Token embedding repository — stores per-token vectors for semantic search
|
|
1015
|
+
* (ADR 2026-07-03) and derives staleness from a content hash.
|
|
1016
|
+
*
|
|
1017
|
+
* This module is pure storage + classification: no HTTP, no LLM calls. The
|
|
1018
|
+
* CLI layer (`src/cli/llm/embedder.ts`) generates vectors and calls in here.
|
|
1019
|
+
*/
|
|
1020
|
+
|
|
1021
|
+
interface TokenEmbedding {
|
|
1022
|
+
token_id: string;
|
|
1023
|
+
model: string;
|
|
1024
|
+
dims: number;
|
|
1025
|
+
content_hash: string;
|
|
1026
|
+
embedded_at: string;
|
|
1027
|
+
embedding: Float32Array;
|
|
1028
|
+
}
|
|
1029
|
+
type EmbeddingStaleness = "missing" | "content-changed" | "model-changed" | "dimension-changed";
|
|
1030
|
+
interface TokenNeedingEmbedding {
|
|
1031
|
+
token: Token;
|
|
1032
|
+
/** Canonical text to embed — already hashed the same way. */
|
|
1033
|
+
text: string;
|
|
1034
|
+
reason: EmbeddingStaleness;
|
|
1035
|
+
}
|
|
1036
|
+
interface EmbeddingCoverage {
|
|
1037
|
+
tokens: number;
|
|
1038
|
+
embedded: number;
|
|
1039
|
+
missing: number;
|
|
1040
|
+
stale: number;
|
|
1041
|
+
}
|
|
1042
|
+
interface EmbeddedTokenRow {
|
|
1043
|
+
token: Token;
|
|
1044
|
+
embedding: Float32Array;
|
|
1045
|
+
}
|
|
1046
|
+
/**
|
|
1047
|
+
* The canonical text embedded for a token. Every stored hash and every stored
|
|
1048
|
+
* vector derives from exactly this string — never the slug, which is an
|
|
1049
|
+
* identifier, not meaning.
|
|
1050
|
+
*/
|
|
1051
|
+
declare function embeddingContentForToken(t: Pick<Token, "concept" | "question" | "domain">): string;
|
|
1052
|
+
declare function computeContentHash(text: string): string;
|
|
1053
|
+
/**
|
|
1054
|
+
* Encode a vector as a little-endian float32 BLOB. Builds a fresh buffer (no
|
|
1055
|
+
* aliasing into the caller's array) so the row can be stored independently of
|
|
1056
|
+
* whatever produced the vector.
|
|
1057
|
+
*/
|
|
1058
|
+
declare function encodeEmbedding(vec: ArrayLike<number>): Uint8Array;
|
|
1059
|
+
/**
|
|
1060
|
+
* Decode a stored BLOB back into a Float32Array.
|
|
1061
|
+
*
|
|
1062
|
+
* BLOB values come back as `Buffer` (better-sqlite3) or `Uint8Array` (remote
|
|
1063
|
+
* provider). better-sqlite3 Buffers are views into a shared pool and may have
|
|
1064
|
+
* a non-zero, non-4-aligned `byteOffset` — constructing a Float32Array
|
|
1065
|
+
* directly over such a buffer throws (RangeError) or silently reads garbage.
|
|
1066
|
+
* Copying guarantees a fresh, 0-offset backing buffer — but `blob.slice()`
|
|
1067
|
+
* cannot be used for this: `Buffer.prototype.slice` overrides
|
|
1068
|
+
* `Uint8Array.prototype.slice` to return a *view* into the same backing
|
|
1069
|
+
* buffer (a legacy Node.js Buffer API quirk), not a copy, so it would still
|
|
1070
|
+
* carry the misaligned offset. Uint8Array's own `slice` must be borrowed
|
|
1071
|
+
* explicitly to force an actual copy.
|
|
1072
|
+
*/
|
|
1073
|
+
declare function decodeEmbedding(blob: Uint8Array): Float32Array;
|
|
1074
|
+
declare function upsertTokenEmbedding(db: Database, input: {
|
|
1075
|
+
tokenId: string;
|
|
1076
|
+
embedding: ArrayLike<number>;
|
|
1077
|
+
model: string;
|
|
1078
|
+
contentHash: string;
|
|
1079
|
+
}): Promise<void>;
|
|
1080
|
+
declare function getTokenEmbedding(db: Database, tokenId: string): Promise<TokenEmbedding | undefined>;
|
|
1081
|
+
/**
|
|
1082
|
+
* Classify every non-deprecated token against a target embedding model:
|
|
1083
|
+
* missing (no stored row), model-changed (stored under a different model
|
|
1084
|
+
* id), or content-changed (stored hash no longer matches the canonical
|
|
1085
|
+
* text). `force: true` returns every token regardless of freshness, tagged
|
|
1086
|
+
* `content-changed` since that is the closest-fitting reason to re-embed.
|
|
1087
|
+
*/
|
|
1088
|
+
declare function listTokensNeedingEmbedding(db: Database, model: string, opts?: {
|
|
1089
|
+
limit?: number;
|
|
1090
|
+
force?: boolean;
|
|
1091
|
+
dims?: number;
|
|
1092
|
+
}): Promise<TokenNeedingEmbedding[]>;
|
|
1093
|
+
/** Same classification scan as {@link listTokensNeedingEmbedding}, counts only. */
|
|
1094
|
+
declare function getEmbeddingCoverage(db: Database, model: string, opts?: {
|
|
1095
|
+
dims?: number;
|
|
1096
|
+
}): Promise<EmbeddingCoverage>;
|
|
1097
|
+
/**
|
|
1098
|
+
* All tokens with a fresh vector under `model` to enter the vector search leg.
|
|
1099
|
+
* Re-hashes rows here because lazy top-up is intentionally bounded: a stale
|
|
1100
|
+
* row beyond the current batch must never participate with its old meaning.
|
|
1101
|
+
*/
|
|
1102
|
+
declare function listEmbeddedTokens(db: Database, model: string): Promise<EmbeddedTokenRow[]>;
|
|
1103
|
+
|
|
1013
1104
|
/**
|
|
1014
1105
|
* Monitor log analyzer — maps observed shell commands to token ratings.
|
|
1015
1106
|
*
|
|
@@ -1790,6 +1881,35 @@ interface ReviewQueue {
|
|
|
1790
1881
|
*/
|
|
1791
1882
|
declare function buildReviewQueue(db: Database, options: ReviewQueueOptions): Promise<ReviewQueue>;
|
|
1792
1883
|
|
|
1884
|
+
/**
|
|
1885
|
+
* Hybrid lexical/vector token search using reciprocal-rank fusion (RRF).
|
|
1886
|
+
* (ADR 2026-07-03)
|
|
1887
|
+
*
|
|
1888
|
+
* This module is pure math + database queries — zero LLM dependencies, no HTTP.
|
|
1889
|
+
*/
|
|
1890
|
+
|
|
1891
|
+
interface HybridSearchOptions {
|
|
1892
|
+
queryEmbedding?: ArrayLike<number>;
|
|
1893
|
+
/** Model the stored vectors must match; required when queryEmbedding is set. */
|
|
1894
|
+
model?: string;
|
|
1895
|
+
limit?: number;
|
|
1896
|
+
rrfK?: number;
|
|
1897
|
+
vectorTopK?: number;
|
|
1898
|
+
}
|
|
1899
|
+
interface HybridScoredToken extends Token {
|
|
1900
|
+
score: number;
|
|
1901
|
+
lexicalRank: number | null;
|
|
1902
|
+
vectorRank: number | null;
|
|
1903
|
+
similarity: number | null;
|
|
1904
|
+
}
|
|
1905
|
+
/** Calculates the cosine similarity between two float vectors. Returns 0 if either norm is 0. */
|
|
1906
|
+
declare function cosineSimilarity(a: Float32Array, b: Float32Array): number;
|
|
1907
|
+
/**
|
|
1908
|
+
* Performs a hybrid search over active tokens.
|
|
1909
|
+
* Combines lexical relevance rankings with vector cosine similarities.
|
|
1910
|
+
*/
|
|
1911
|
+
declare function searchTokensHybrid(db: Database, query: string, opts?: HybridSearchOptions): Promise<HybridScoredToken[]>;
|
|
1912
|
+
|
|
1793
1913
|
/**
|
|
1794
1914
|
* Get the path to ZAM's internal package SKILL.md.
|
|
1795
1915
|
*/
|
|
@@ -1914,7 +2034,7 @@ interface InstallConfig {
|
|
|
1914
2034
|
/** Machine-local id of the workspace currently active in this install. */
|
|
1915
2035
|
activeWorkspaceId?: string;
|
|
1916
2036
|
}
|
|
1917
|
-
type MachineAiRole = "vision" | "recall" | "text";
|
|
2037
|
+
type MachineAiRole = "vision" | "recall" | "text" | "embedding";
|
|
1918
2038
|
type MachineApiFlavor = "chat-completions" | "anthropic-messages";
|
|
1919
2039
|
interface MachineProviderRecord {
|
|
1920
2040
|
label?: string;
|
|
@@ -2074,4 +2194,4 @@ declare function resolveAllBeliefPaths(db: Database): Promise<string[]>;
|
|
|
2074
2194
|
*/
|
|
2075
2195
|
declare function resolveAllGoalPaths(db: Database): Promise<string[]>;
|
|
2076
2196
|
|
|
2077
|
-
export { type ADOConfig, type ADOCredentials, type AgentSkill, type AnalysisResult, type ApplySessionSynthesisInput, type ApplySessionSynthesisResult, BUILT_IN_SENSITIVE_MATCHERS, type BloomLevel$1 as BloomLevel, type CaptureDecision, type CaptureDenialReason, type CaptureRequest, type Card, type CardDeletionImpact, type CardState$1 as CardState, type CascadeBlockResult, type CommandRecord, type CommandSequence, type ConfirmFoundationsResult, type ConnectionOptions, type CreateAgentSkillInput, type CreateGoalInput, type CreateReviewInput, type CreateSessionInput, type CreateTokenInput, type Credentials, type CurriculumCardInput, DEFAULT_OBSERVER_POLICY, DEFAULT_REVIEW_CONTEXT_MAX_CHARS, type Database, type DatabaseProvider, type DatabaseTargetInfo, type DatabaseValue, type DeleteCardResult, type DeleteTokenResult, type DiscoveryOptions, type DomainCompetence, type EvaluateInput, type EvaluateResult, type ExecuteReviewActionInput, type ExecutionContext, type FSRSParameters, type FoundationProposalInput, type Goal, type GoalFrontmatter, type GoalStatus, type GoalSummary, HOMEBREW_CASK, type ImportCurriculumResult, type ImportResult, type InstallChannel, type InstallConfig, type InstallMode, type InstallPlan, type InstallResult, type LocalLLMRunner, type LogStepInput, type MachineAiConfig, type MachineProviderRecord, type MachineRoleBinding, type MonitorEvent, type Neighborhood, type NeighborhoodToken, OBSERVER_POLICY_UNSET_HINT, OBSERVER_POLICY_VERSION, type ObservationRating, type ObserverConsent, type ObserverPolicy, type ObserverRetention, type ObserverScope, type ObserverSettingKey, type OllamaDetectionOptions, type PersonalCard, type PrepareSessionSynthesisInput, type Prerequisite, type PrerequisiteWithToken, type PromptInput, REVIEW_CONTEXT_CACHE_TTL_MS, type Rating, type RecallPrompt, type RemoteDatabaseOptions, type RepoPaths, type ResolvedCaptureTarget, type ResolvedReference, type ReviewActionResult, type ReviewActionType, type ReviewContext, type ReviewLog, type ReviewQueue, type ReviewQueueItem, type ReviewQueueOptions, type RunResult, SIDECAR_POLICY_FILE, SNAPSHOT_VERSION, type SchedulingCard, type Session, type SessionStep, type SessionSummary, type SessionSynthesisCandidate, type SessionSynthesisEvidence, type SessionSynthesisPreview, type SessionSynthesisRecord, type SidecarPrivacyPolicy, type SkillProposal, type SkillSource, type SnapshotManifest, type SourceProposalInput, type SplitProposalInput, type Statement, type SupportedLocale, type SymbiosisMode, type SynthesisConfidence, type SystemProfile, type Token, type TokenDeleteImpact, type TokenPattern, type TranslationKey, type TursoCredentials, UI_OBSERVATION_PROTOCOL_VERSION, type UiActionType, type UiApplicationContext, type UiCandidateToken, type UiEvidenceRef, type UiEvidenceType, type UiObservationKind, type UiObservationReport, type UiObservedAction, type UnblockResult, type UpdateActionKind, type UpdateCardInput, type UpdateDecision, type UpdateStep, type UpdateStepKind, type UpdateTokenInput, type UserSetting, type UserStats, WINGET_PACKAGE_ID, type WorkItem, type WorkspaceConfig, type WorkspaceKind, type WorkspaceSourceControl, addPrerequisite, analyzeObservation, appendUiObservationReport, applySessionSynthesis, buildReviewQueue, buildUiSynthesisCandidates, cascadeBlock, clearADOCredentials, clearProviderApiKey, clearReviewContextCache, clearTursoCredentials, compareVersions, confirmCardSplit, confirmFoundations, confirmSourceImport, createAgentSkill, createFSRS, createGoal, createToken, decidePostCapture, decidePreCapture, decideUpdate, deleteCardForUser, deleteSetting, deleteToken, deprecateToken, detectSyncProvider, detectSystemLocale, discoverSkills, distributeGlobalSkills, endSession, ensureCard, ensureMonitorDir, ensureUiObserverDir, evaluateRating, executeReviewAction, exportSnapshot, extractTasks, extractTokenRefs, fetchActiveWorkItems, findTokens, generateBashHooks, generateBashUnhooks, generateConceptFreeCue, generatePowerShellHooks, generatePowerShellUnhooks, generatePrompt, generateTokenSlug, generateZshHooks, generateZshUnhooks, getADOCredentials, getActiveWorkspace, getActiveWorkspaceId, getAgentSkill, getAllSettings, getAllSettingsDetailed, getBlockedCards, getCard, getCardById, getCardDeletionImpact, getConfiguredWorkspaces, getDatabaseTargetInfo, getDefaultDbPath, getDependents, getDomainCompetence, getDueCards, getGoal, getGoalTree, getInstallChannel, getInstallMode, getMachineAiConfig, getMonitorDir, getMonitorLogStats, getMonitorPath, getPackageSkillPath, getPrerequisites, getProviderApiKey, getRepoPaths, getReviewsForCard, getReviewsForUser, getSessionSummary, getSessionSynthesisRecords, getSetting, getSystemProfile, getTokenById, getTokenBySlug, getTokenDeleteImpact, getTokenNeighborhood, getTursoCredentials, getUiObservationPath, getUiObserverDir, getUserStats, hasCommand, importCurriculumCards, importSnapshot, injectShellHooks, installFastFlowLM, installOllama, installOpenCode, interleave, isObserverPolicyConfigured, isOllamaInstalled, isUiObservationReport, listAgentSkills, listGoals, listPersonalCards, listProviderApiKeyRefs, listTokens, loadADOConfig, loadCredentials, loadInstallConfig, logReview, logStep, matchBuiltInSensitive, matchDenylist, matchesFilePath, monitorLogExists, normalizeLocale, normalizePath, openDatabase, openDatabaseWithSync, openRemoteDatabase, pairCommands, parseGoalFile, parseMonitorLog, parseObserverList, parseObserverPolicy, parseSnapshot, parseUiObservationLog, planOpenCodeInstall, planUpdate, prepareLocalModel, prepareSessionSynthesis, readMonitorLog, readUiObservationLog, removeConfiguredWorkspace, resolveAllBeliefPaths, resolveAllGoalPaths, resolveObserverPolicy, resolveOllamaCommand, resolveReference, resolveRepoPath, resolveReviewContext, saveConfiguredWorkspaces, saveCredentials, saveInstallConfig, saveMachineAiConfig, serializeGoal, setADOCredentials, setActiveWorkspaceId, setInstallChannel, setInstallMode, setProviderApiKey, setSetting, setTursoCredentials, slugify, startSession, syncObserverSidecarPolicy, t, toSidecarPrivacyPolicy, uiObservationLogExists, uiObservationTimeSpan, unblockReady, updateCard, updateGoalStatus, updateToken, upsertConfiguredWorkspace, verifySnapshot, wouldCreateCycle, writeMonitorEvent };
|
|
2197
|
+
export { type ADOConfig, type ADOCredentials, type AgentSkill, type AnalysisResult, type ApplySessionSynthesisInput, type ApplySessionSynthesisResult, BUILT_IN_SENSITIVE_MATCHERS, type BloomLevel$1 as BloomLevel, type CaptureDecision, type CaptureDenialReason, type CaptureRequest, type Card, type CardDeletionImpact, type CardState$1 as CardState, type CascadeBlockResult, type CommandRecord, type CommandSequence, type ConfirmFoundationsResult, type ConnectionOptions, type CreateAgentSkillInput, type CreateGoalInput, type CreateReviewInput, type CreateSessionInput, type CreateTokenInput, type Credentials, type CurriculumCardInput, DEFAULT_OBSERVER_POLICY, DEFAULT_REVIEW_CONTEXT_MAX_CHARS, type Database, type DatabaseProvider, type DatabaseTargetInfo, type DatabaseValue, type DeleteCardResult, type DeleteTokenResult, type DiscoveryOptions, type DomainCompetence, type EmbeddedTokenRow, type EmbeddingCoverage, type EmbeddingStaleness, type EvaluateInput, type EvaluateResult, type ExecuteReviewActionInput, type ExecutionContext, type FSRSParameters, type FoundationProposalInput, type Goal, type GoalFrontmatter, type GoalStatus, type GoalSummary, HOMEBREW_CASK, type HybridScoredToken, type HybridSearchOptions, type ImportCurriculumResult, type ImportResult, type InstallChannel, type InstallConfig, type InstallMode, type InstallPlan, type InstallResult, type LocalLLMRunner, type LogStepInput, type MachineAiConfig, type MachineProviderRecord, type MachineRoleBinding, type MonitorEvent, type Neighborhood, type NeighborhoodToken, OBSERVER_POLICY_UNSET_HINT, OBSERVER_POLICY_VERSION, type ObservationRating, type ObserverConsent, type ObserverPolicy, type ObserverRetention, type ObserverScope, type ObserverSettingKey, type OllamaDetectionOptions, type PersonalCard, type PrepareSessionSynthesisInput, type Prerequisite, type PrerequisiteWithToken, type PromptInput, REVIEW_CONTEXT_CACHE_TTL_MS, type Rating, type RecallPrompt, type RemoteDatabaseOptions, type RepoPaths, type ResolvedCaptureTarget, type ResolvedReference, type ReviewActionResult, type ReviewActionType, type ReviewContext, type ReviewLog, type ReviewQueue, type ReviewQueueItem, type ReviewQueueOptions, type RunResult, SIDECAR_POLICY_FILE, SNAPSHOT_VERSION, type SchedulingCard, type Session, type SessionStep, type SessionSummary, type SessionSynthesisCandidate, type SessionSynthesisEvidence, type SessionSynthesisPreview, type SessionSynthesisRecord, type SidecarPrivacyPolicy, type SkillProposal, type SkillSource, type SnapshotManifest, type SourceProposalInput, type SplitProposalInput, type Statement, type SupportedLocale, type SymbiosisMode, type SynthesisConfidence, type SystemProfile, type Token, type TokenDeleteImpact, type TokenEmbedding, type TokenNeedingEmbedding, type TokenPattern, type TranslationKey, type TursoCredentials, UI_OBSERVATION_PROTOCOL_VERSION, type UiActionType, type UiApplicationContext, type UiCandidateToken, type UiEvidenceRef, type UiEvidenceType, type UiObservationKind, type UiObservationReport, type UiObservedAction, type UnblockResult, type UpdateActionKind, type UpdateCardInput, type UpdateDecision, type UpdateStep, type UpdateStepKind, type UpdateTokenInput, type UserSetting, type UserStats, WINGET_PACKAGE_ID, type WorkItem, type WorkspaceConfig, type WorkspaceKind, type WorkspaceSourceControl, addPrerequisite, analyzeObservation, appendUiObservationReport, applySessionSynthesis, buildReviewQueue, buildUiSynthesisCandidates, cascadeBlock, clearADOCredentials, clearProviderApiKey, clearReviewContextCache, clearTursoCredentials, compareVersions, computeContentHash, confirmCardSplit, confirmFoundations, confirmSourceImport, cosineSimilarity, createAgentSkill, createFSRS, createGoal, createToken, decidePostCapture, decidePreCapture, decideUpdate, decodeEmbedding, deleteCardForUser, deleteSetting, deleteToken, deprecateToken, detectSyncProvider, detectSystemLocale, discoverSkills, distributeGlobalSkills, embeddingContentForToken, encodeEmbedding, endSession, ensureCard, ensureMonitorDir, ensureUiObserverDir, evaluateRating, executeReviewAction, exportSnapshot, extractTasks, extractTokenRefs, fetchActiveWorkItems, findTokens, generateBashHooks, generateBashUnhooks, generateConceptFreeCue, generatePowerShellHooks, generatePowerShellUnhooks, generatePrompt, generateTokenSlug, generateZshHooks, generateZshUnhooks, getADOCredentials, getActiveWorkspace, getActiveWorkspaceId, getAgentSkill, getAllSettings, getAllSettingsDetailed, getBlockedCards, getCard, getCardById, getCardDeletionImpact, getConfiguredWorkspaces, getDatabaseTargetInfo, getDefaultDbPath, getDependents, getDomainCompetence, getDueCards, getEmbeddingCoverage, getGoal, getGoalTree, getInstallChannel, getInstallMode, getMachineAiConfig, getMonitorDir, getMonitorLogStats, getMonitorPath, getPackageSkillPath, getPrerequisites, getProviderApiKey, getRepoPaths, getReviewsForCard, getReviewsForUser, getSessionSummary, getSessionSynthesisRecords, getSetting, getSystemProfile, getTokenById, getTokenBySlug, getTokenDeleteImpact, getTokenEmbedding, getTokenNeighborhood, getTursoCredentials, getUiObservationPath, getUiObserverDir, getUserStats, hasCommand, importCurriculumCards, importSnapshot, injectShellHooks, installFastFlowLM, installOllama, installOpenCode, interleave, isObserverPolicyConfigured, isOllamaInstalled, isUiObservationReport, listAgentSkills, listEmbeddedTokens, listGoals, listPersonalCards, listProviderApiKeyRefs, listTokens, listTokensNeedingEmbedding, loadADOConfig, loadCredentials, loadInstallConfig, logReview, logStep, matchBuiltInSensitive, matchDenylist, matchesFilePath, monitorLogExists, normalizeLocale, normalizePath, openDatabase, openDatabaseWithSync, openRemoteDatabase, pairCommands, parseGoalFile, parseMonitorLog, parseObserverList, parseObserverPolicy, parseSnapshot, parseUiObservationLog, planOpenCodeInstall, planUpdate, prepareLocalModel, prepareSessionSynthesis, readMonitorLog, readUiObservationLog, removeConfiguredWorkspace, resolveAllBeliefPaths, resolveAllGoalPaths, resolveObserverPolicy, resolveOllamaCommand, resolveReference, resolveRepoPath, resolveReviewContext, saveConfiguredWorkspaces, saveCredentials, saveInstallConfig, saveMachineAiConfig, searchTokensHybrid, serializeGoal, setADOCredentials, setActiveWorkspaceId, setInstallChannel, setInstallMode, setProviderApiKey, setSetting, setTursoCredentials, slugify, startSession, syncObserverSidecarPolicy, t, toSidecarPrivacyPolicy, uiObservationLogExists, uiObservationTimeSpan, unblockReady, updateCard, updateGoalStatus, updateToken, upsertConfiguredWorkspace, upsertTokenEmbedding, verifySnapshot, wouldCreateCycle, writeMonitorEvent };
|
package/dist/index.js
CHANGED
|
@@ -643,6 +643,18 @@ CREATE TABLE IF NOT EXISTS user_config (
|
|
|
643
643
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
644
644
|
);
|
|
645
645
|
|
|
646
|
+
-- Token embeddings: one vector per token for semantic search (ADR 2026-07-03).
|
|
647
|
+
-- Not a column on tokens: hot paths do SELECT * FROM tokens and a ~3KB blob
|
|
648
|
+
-- per row would ride along on all of them.
|
|
649
|
+
CREATE TABLE IF NOT EXISTS token_embeddings (
|
|
650
|
+
token_id TEXT PRIMARY KEY REFERENCES tokens(id) ON DELETE CASCADE,
|
|
651
|
+
embedding BLOB NOT NULL,
|
|
652
|
+
model TEXT NOT NULL,
|
|
653
|
+
dims INTEGER NOT NULL,
|
|
654
|
+
content_hash TEXT NOT NULL,
|
|
655
|
+
embedded_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
656
|
+
);
|
|
657
|
+
|
|
646
658
|
-- Agent skills: task recipes the agent learns from user guidance
|
|
647
659
|
CREATE TABLE IF NOT EXISTS agent_skills (
|
|
648
660
|
id TEXT PRIMARY KEY,
|
|
@@ -989,6 +1001,16 @@ async function runMigrations(db) {
|
|
|
989
1001
|
await db.exec(`ALTER TABLE tokens ADD COLUMN topic_id TEXT`);
|
|
990
1002
|
}
|
|
991
1003
|
}
|
|
1004
|
+
await db.exec(`
|
|
1005
|
+
CREATE TABLE IF NOT EXISTS token_embeddings (
|
|
1006
|
+
token_id TEXT PRIMARY KEY REFERENCES tokens(id) ON DELETE CASCADE,
|
|
1007
|
+
embedding BLOB NOT NULL,
|
|
1008
|
+
model TEXT NOT NULL,
|
|
1009
|
+
dims INTEGER NOT NULL,
|
|
1010
|
+
content_hash TEXT NOT NULL,
|
|
1011
|
+
embedded_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
1012
|
+
)
|
|
1013
|
+
`);
|
|
992
1014
|
}
|
|
993
1015
|
|
|
994
1016
|
// src/kernel/db/snapshot.ts
|
|
@@ -2451,6 +2473,165 @@ async function deleteSetting(db, key) {
|
|
|
2451
2473
|
return result.changes > 0;
|
|
2452
2474
|
}
|
|
2453
2475
|
|
|
2476
|
+
// src/kernel/models/token-embedding.ts
|
|
2477
|
+
import { createHash as createHash2 } from "crypto";
|
|
2478
|
+
function embeddingContentForToken(t2) {
|
|
2479
|
+
return `${t2.concept}
|
|
2480
|
+
${t2.question ?? ""}
|
|
2481
|
+
${t2.domain}`;
|
|
2482
|
+
}
|
|
2483
|
+
function computeContentHash(text) {
|
|
2484
|
+
return createHash2("sha256").update(text, "utf8").digest("hex");
|
|
2485
|
+
}
|
|
2486
|
+
function encodeEmbedding(vec) {
|
|
2487
|
+
const f = Float32Array.from(vec);
|
|
2488
|
+
return new Uint8Array(f.buffer);
|
|
2489
|
+
}
|
|
2490
|
+
function decodeEmbedding(blob) {
|
|
2491
|
+
if (blob.byteLength % 4 !== 0) {
|
|
2492
|
+
throw new Error(
|
|
2493
|
+
"Invalid embedding blob size: must be a multiple of 4 bytes"
|
|
2494
|
+
);
|
|
2495
|
+
}
|
|
2496
|
+
if (blob.byteOffset % 4 === 0) {
|
|
2497
|
+
return new Float32Array(blob.buffer, blob.byteOffset, blob.byteLength / 4);
|
|
2498
|
+
}
|
|
2499
|
+
const copy = Uint8Array.prototype.slice.call(blob);
|
|
2500
|
+
return new Float32Array(copy.buffer, 0, copy.byteLength / 4);
|
|
2501
|
+
}
|
|
2502
|
+
function decodeRow(row) {
|
|
2503
|
+
return {
|
|
2504
|
+
token_id: row.token_id,
|
|
2505
|
+
model: row.model,
|
|
2506
|
+
dims: row.dims,
|
|
2507
|
+
content_hash: row.content_hash,
|
|
2508
|
+
embedded_at: row.embedded_at,
|
|
2509
|
+
embedding: decodeEmbedding(row.embedding)
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
async function upsertTokenEmbedding(db, input) {
|
|
2513
|
+
const encoded = encodeEmbedding(input.embedding);
|
|
2514
|
+
const dims = input.embedding.length;
|
|
2515
|
+
const embeddedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
2516
|
+
await db.prepare(`
|
|
2517
|
+
INSERT INTO token_embeddings (token_id, embedding, model, dims, content_hash, embedded_at)
|
|
2518
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
2519
|
+
ON CONFLICT(token_id) DO UPDATE SET
|
|
2520
|
+
embedding = excluded.embedding,
|
|
2521
|
+
model = excluded.model,
|
|
2522
|
+
dims = excluded.dims,
|
|
2523
|
+
content_hash = excluded.content_hash,
|
|
2524
|
+
embedded_at = excluded.embedded_at
|
|
2525
|
+
`).run(
|
|
2526
|
+
input.tokenId,
|
|
2527
|
+
encoded,
|
|
2528
|
+
input.model,
|
|
2529
|
+
dims,
|
|
2530
|
+
input.contentHash,
|
|
2531
|
+
embeddedAt
|
|
2532
|
+
);
|
|
2533
|
+
}
|
|
2534
|
+
async function getTokenEmbedding(db, tokenId) {
|
|
2535
|
+
const row = await db.prepare("SELECT * FROM token_embeddings WHERE token_id = ?").get(tokenId);
|
|
2536
|
+
return row ? decodeRow(row) : void 0;
|
|
2537
|
+
}
|
|
2538
|
+
async function listTokensNeedingEmbedding(db, model, opts) {
|
|
2539
|
+
const rows = await db.prepare(`
|
|
2540
|
+
SELECT t.*, e.model AS emb_model, e.dims AS emb_dims, e.content_hash AS emb_hash
|
|
2541
|
+
FROM tokens t
|
|
2542
|
+
LEFT JOIN token_embeddings e ON e.token_id = t.id
|
|
2543
|
+
WHERE t.deprecated_at IS NULL
|
|
2544
|
+
`).all();
|
|
2545
|
+
const needing = [];
|
|
2546
|
+
for (const row of rows) {
|
|
2547
|
+
let reason = null;
|
|
2548
|
+
let text = "";
|
|
2549
|
+
if (opts?.force) {
|
|
2550
|
+
reason = "content-changed";
|
|
2551
|
+
} else if (row.emb_model === null) {
|
|
2552
|
+
reason = "missing";
|
|
2553
|
+
} else if (row.emb_model !== model) {
|
|
2554
|
+
reason = "model-changed";
|
|
2555
|
+
} else if (opts?.dims !== void 0 && row.emb_dims !== opts.dims) {
|
|
2556
|
+
reason = "dimension-changed";
|
|
2557
|
+
} else {
|
|
2558
|
+
const computedText = embeddingContentForToken(row);
|
|
2559
|
+
const hash = computeContentHash(computedText);
|
|
2560
|
+
if (row.emb_hash !== hash) {
|
|
2561
|
+
reason = "content-changed";
|
|
2562
|
+
text = computedText;
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
if (reason) {
|
|
2566
|
+
if (!text) {
|
|
2567
|
+
text = embeddingContentForToken(row);
|
|
2568
|
+
}
|
|
2569
|
+
needing.push({ token: row, text, reason });
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
if (opts?.limit !== void 0) {
|
|
2573
|
+
return needing.slice(0, opts.limit);
|
|
2574
|
+
}
|
|
2575
|
+
return needing;
|
|
2576
|
+
}
|
|
2577
|
+
async function getEmbeddingCoverage(db, model, opts) {
|
|
2578
|
+
const rows = await db.prepare(`
|
|
2579
|
+
SELECT t.*, e.model AS emb_model, e.dims AS emb_dims, e.content_hash AS emb_hash
|
|
2580
|
+
FROM tokens t
|
|
2581
|
+
LEFT JOIN token_embeddings e ON e.token_id = t.id
|
|
2582
|
+
WHERE t.deprecated_at IS NULL
|
|
2583
|
+
`).all();
|
|
2584
|
+
let missing = 0;
|
|
2585
|
+
let stale = 0;
|
|
2586
|
+
for (const row of rows) {
|
|
2587
|
+
if (row.emb_model === null) {
|
|
2588
|
+
missing++;
|
|
2589
|
+
continue;
|
|
2590
|
+
}
|
|
2591
|
+
if (row.emb_model !== model) {
|
|
2592
|
+
stale++;
|
|
2593
|
+
continue;
|
|
2594
|
+
}
|
|
2595
|
+
if (opts?.dims !== void 0 && row.emb_dims !== opts.dims) {
|
|
2596
|
+
stale++;
|
|
2597
|
+
continue;
|
|
2598
|
+
}
|
|
2599
|
+
const hash = computeContentHash(embeddingContentForToken(row));
|
|
2600
|
+
if (row.emb_hash !== hash) {
|
|
2601
|
+
stale++;
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
const tokens = rows.length;
|
|
2605
|
+
return {
|
|
2606
|
+
tokens,
|
|
2607
|
+
embedded: tokens - missing - stale,
|
|
2608
|
+
missing,
|
|
2609
|
+
stale
|
|
2610
|
+
};
|
|
2611
|
+
}
|
|
2612
|
+
async function listEmbeddedTokens(db, model) {
|
|
2613
|
+
const rows = await db.prepare(`
|
|
2614
|
+
SELECT t.*, e.embedding AS embedding, e.content_hash AS emb_hash
|
|
2615
|
+
FROM token_embeddings e
|
|
2616
|
+
JOIN tokens t ON t.id = e.token_id
|
|
2617
|
+
WHERE e.model = ? AND t.deprecated_at IS NULL
|
|
2618
|
+
`).all(model);
|
|
2619
|
+
return rows.flatMap((row) => {
|
|
2620
|
+
const { embedding, emb_hash, ...token } = row;
|
|
2621
|
+
if (emb_hash !== computeContentHash(embeddingContentForToken(token))) {
|
|
2622
|
+
return [];
|
|
2623
|
+
}
|
|
2624
|
+
try {
|
|
2625
|
+
return [{ token, embedding: decodeEmbedding(embedding) }];
|
|
2626
|
+
} catch (err) {
|
|
2627
|
+
console.warn(
|
|
2628
|
+
`Warning: Corrupted embedding for token ${token.slug} (${token.id}) ignored: ${err.message}`
|
|
2629
|
+
);
|
|
2630
|
+
return [];
|
|
2631
|
+
}
|
|
2632
|
+
});
|
|
2633
|
+
}
|
|
2634
|
+
|
|
2454
2635
|
// src/kernel/observation/analyzer.ts
|
|
2455
2636
|
function parseMonitorLog(jsonl) {
|
|
2456
2637
|
const events = [];
|
|
@@ -4593,6 +4774,82 @@ function intersperseNew(reviews, newCards, interval) {
|
|
|
4593
4774
|
return result;
|
|
4594
4775
|
}
|
|
4595
4776
|
|
|
4777
|
+
// src/kernel/search/hybrid.ts
|
|
4778
|
+
function cosineSimilarity(a, b) {
|
|
4779
|
+
if (a.length !== b.length) return 0;
|
|
4780
|
+
let dot = 0;
|
|
4781
|
+
let normA = 0;
|
|
4782
|
+
let normB = 0;
|
|
4783
|
+
const len = a.length;
|
|
4784
|
+
for (let i = 0; i < len; i++) {
|
|
4785
|
+
dot += a[i] * b[i];
|
|
4786
|
+
normA += a[i] * a[i];
|
|
4787
|
+
normB += b[i] * b[i];
|
|
4788
|
+
}
|
|
4789
|
+
if (normA === 0 || normB === 0) return 0;
|
|
4790
|
+
return dot / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
4791
|
+
}
|
|
4792
|
+
async function searchTokensHybrid(db, query, opts) {
|
|
4793
|
+
const limit = opts?.limit ?? 20;
|
|
4794
|
+
const rrfK = opts?.rrfK ?? 60;
|
|
4795
|
+
const vectorTopK = opts?.vectorTopK ?? 10;
|
|
4796
|
+
const lexicalHits = await findTokens(db, query);
|
|
4797
|
+
let vectorHits = [];
|
|
4798
|
+
if (opts?.queryEmbedding && opts?.model) {
|
|
4799
|
+
const queryVec = Float32Array.from(opts.queryEmbedding);
|
|
4800
|
+
const embedded = await listEmbeddedTokens(db, opts.model);
|
|
4801
|
+
const candidates = [];
|
|
4802
|
+
for (const row of embedded) {
|
|
4803
|
+
if (row.embedding.length !== queryVec.length) {
|
|
4804
|
+
continue;
|
|
4805
|
+
}
|
|
4806
|
+
const similarity = cosineSimilarity(queryVec, row.embedding);
|
|
4807
|
+
if (similarity <= 0) {
|
|
4808
|
+
continue;
|
|
4809
|
+
}
|
|
4810
|
+
candidates.push({ token: row.token, similarity });
|
|
4811
|
+
}
|
|
4812
|
+
candidates.sort((a, b) => b.similarity - a.similarity);
|
|
4813
|
+
vectorHits = candidates.slice(0, vectorTopK);
|
|
4814
|
+
}
|
|
4815
|
+
const tokenMap = /* @__PURE__ */ new Map();
|
|
4816
|
+
const getOrCreateEntry = (token) => {
|
|
4817
|
+
let entry = tokenMap.get(token.id);
|
|
4818
|
+
if (!entry) {
|
|
4819
|
+
entry = {
|
|
4820
|
+
...token,
|
|
4821
|
+
score: 0,
|
|
4822
|
+
lexicalRank: null,
|
|
4823
|
+
vectorRank: null,
|
|
4824
|
+
similarity: null
|
|
4825
|
+
};
|
|
4826
|
+
tokenMap.set(token.id, entry);
|
|
4827
|
+
}
|
|
4828
|
+
return entry;
|
|
4829
|
+
};
|
|
4830
|
+
for (let i = 0; i < lexicalHits.length; i++) {
|
|
4831
|
+
const hit = lexicalHits[i];
|
|
4832
|
+
const entry = getOrCreateEntry(hit);
|
|
4833
|
+
entry.lexicalRank = i + 1;
|
|
4834
|
+
entry.score += 1 / (rrfK + entry.lexicalRank);
|
|
4835
|
+
}
|
|
4836
|
+
for (let j = 0; j < vectorHits.length; j++) {
|
|
4837
|
+
const hit = vectorHits[j];
|
|
4838
|
+
const entry = getOrCreateEntry(hit.token);
|
|
4839
|
+
entry.vectorRank = j + 1;
|
|
4840
|
+
entry.similarity = hit.similarity;
|
|
4841
|
+
entry.score += 1 / (rrfK + entry.vectorRank);
|
|
4842
|
+
}
|
|
4843
|
+
const results = Array.from(tokenMap.values());
|
|
4844
|
+
results.sort((a, b) => {
|
|
4845
|
+
if (Math.abs(a.score - b.score) > 1e-9) {
|
|
4846
|
+
return b.score - a.score;
|
|
4847
|
+
}
|
|
4848
|
+
return a.slug.localeCompare(b.slug);
|
|
4849
|
+
});
|
|
4850
|
+
return results.slice(0, limit);
|
|
4851
|
+
}
|
|
4852
|
+
|
|
4596
4853
|
// src/kernel/system/hooks.ts
|
|
4597
4854
|
import {
|
|
4598
4855
|
appendFileSync as appendFileSync3,
|
|
@@ -5625,9 +5882,11 @@ export {
|
|
|
5625
5882
|
clearReviewContextCache,
|
|
5626
5883
|
clearTursoCredentials,
|
|
5627
5884
|
compareVersions,
|
|
5885
|
+
computeContentHash,
|
|
5628
5886
|
confirmCardSplit,
|
|
5629
5887
|
confirmFoundations,
|
|
5630
5888
|
confirmSourceImport,
|
|
5889
|
+
cosineSimilarity,
|
|
5631
5890
|
createAgentSkill,
|
|
5632
5891
|
createFSRS,
|
|
5633
5892
|
createGoal,
|
|
@@ -5635,6 +5894,7 @@ export {
|
|
|
5635
5894
|
decidePostCapture,
|
|
5636
5895
|
decidePreCapture,
|
|
5637
5896
|
decideUpdate,
|
|
5897
|
+
decodeEmbedding,
|
|
5638
5898
|
deleteCardForUser,
|
|
5639
5899
|
deleteSetting,
|
|
5640
5900
|
deleteToken,
|
|
@@ -5643,6 +5903,8 @@ export {
|
|
|
5643
5903
|
detectSystemLocale,
|
|
5644
5904
|
discoverSkills,
|
|
5645
5905
|
distributeGlobalSkills,
|
|
5906
|
+
embeddingContentForToken,
|
|
5907
|
+
encodeEmbedding,
|
|
5646
5908
|
endSession,
|
|
5647
5909
|
ensureCard,
|
|
5648
5910
|
ensureMonitorDir,
|
|
@@ -5679,6 +5941,7 @@ export {
|
|
|
5679
5941
|
getDependents,
|
|
5680
5942
|
getDomainCompetence,
|
|
5681
5943
|
getDueCards,
|
|
5944
|
+
getEmbeddingCoverage,
|
|
5682
5945
|
getGoal,
|
|
5683
5946
|
getGoalTree,
|
|
5684
5947
|
getInstallChannel,
|
|
@@ -5700,6 +5963,7 @@ export {
|
|
|
5700
5963
|
getTokenById,
|
|
5701
5964
|
getTokenBySlug,
|
|
5702
5965
|
getTokenDeleteImpact,
|
|
5966
|
+
getTokenEmbedding,
|
|
5703
5967
|
getTokenNeighborhood,
|
|
5704
5968
|
getTursoCredentials,
|
|
5705
5969
|
getUiObservationPath,
|
|
@@ -5717,10 +5981,12 @@ export {
|
|
|
5717
5981
|
isOllamaInstalled,
|
|
5718
5982
|
isUiObservationReport,
|
|
5719
5983
|
listAgentSkills,
|
|
5984
|
+
listEmbeddedTokens,
|
|
5720
5985
|
listGoals,
|
|
5721
5986
|
listPersonalCards,
|
|
5722
5987
|
listProviderApiKeyRefs,
|
|
5723
5988
|
listTokens,
|
|
5989
|
+
listTokensNeedingEmbedding,
|
|
5724
5990
|
loadADOConfig,
|
|
5725
5991
|
loadCredentials,
|
|
5726
5992
|
loadInstallConfig,
|
|
@@ -5760,6 +6026,7 @@ export {
|
|
|
5760
6026
|
saveCredentials,
|
|
5761
6027
|
saveInstallConfig,
|
|
5762
6028
|
saveMachineAiConfig,
|
|
6029
|
+
searchTokensHybrid,
|
|
5763
6030
|
serializeGoal,
|
|
5764
6031
|
setADOCredentials,
|
|
5765
6032
|
setActiveWorkspaceId,
|
|
@@ -5780,6 +6047,7 @@ export {
|
|
|
5780
6047
|
updateGoalStatus,
|
|
5781
6048
|
updateToken,
|
|
5782
6049
|
upsertConfiguredWorkspace,
|
|
6050
|
+
upsertTokenEmbedding,
|
|
5783
6051
|
verifySnapshot,
|
|
5784
6052
|
wouldCreateCycle,
|
|
5785
6053
|
writeMonitorEvent
|