memorix 1.2.10 → 1.3.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +28 -2
  3. package/README.zh-CN.md +28 -2
  4. package/assets/star-history-dark.svg +30 -0
  5. package/assets/star-history-light.svg +30 -0
  6. package/assets/star-history.json +599 -0
  7. package/dist/cli/index.js +1783 -557
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/index.js +1292 -267
  10. package/dist/index.js.map +1 -1
  11. package/dist/maintenance-runner.js +97 -21
  12. package/dist/maintenance-runner.js.map +1 -1
  13. package/dist/memcode-runtime/CHANGELOG.md +15 -0
  14. package/dist/sdk.d.ts +1 -1
  15. package/dist/sdk.js +1294 -269
  16. package/dist/sdk.js.map +1 -1
  17. package/dist/types.d.ts +99 -1
  18. package/dist/types.js.map +1 -1
  19. package/dist/vector-backfill-runner.js +97 -21
  20. package/dist/vector-backfill-runner.js.map +1 -1
  21. package/docs/1.3-MEMORY-ARCHITECTURE.md +236 -0
  22. package/docs/AGENT_OPERATOR_PLAYBOOK.md +3 -1
  23. package/docs/API_REFERENCE.md +20 -1
  24. package/docs/ARCHITECTURE.md +34 -1
  25. package/docs/DEVELOPMENT.md +3 -2
  26. package/docs/MODULES.md +27 -1
  27. package/docs/README.md +3 -3
  28. package/docs/dev-log/progress.txt +22 -0
  29. package/llms-full.txt +5 -1
  30. package/llms.txt +2 -0
  31. package/package.json +2 -1
  32. package/plugins/antigravity/memorix/rules/memorix.md +2 -0
  33. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  34. package/plugins/claude/memorix/skills/memorix-memory/SKILL.md +3 -0
  35. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  36. package/plugins/codex/memorix/skills/memorix-memory/SKILL.md +3 -0
  37. package/plugins/copilot/memorix/plugin.json +1 -1
  38. package/plugins/copilot/memorix/skills/memorix-memory/SKILL.md +3 -0
  39. package/plugins/cursor/memorix/skills/memorix-memory/SKILL.md +3 -0
  40. package/plugins/gemini/memorix/GEMINI.md +2 -0
  41. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  42. package/plugins/omp/memorix/package.json +1 -1
  43. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  44. package/plugins/pi/memorix/package.json +1 -1
  45. package/plugins/pi/memorix/skills/memorix-memory/SKILL.md +3 -0
  46. package/server.json +2 -2
  47. package/src/cli/command-guide.ts +9 -1
  48. package/src/cli/commands/codegraph.ts +1 -0
  49. package/src/cli/commands/memory.ts +217 -1
  50. package/src/codegraph/auto-context.ts +11 -0
  51. package/src/codegraph/context-pack.ts +3 -0
  52. package/src/embedding/api-provider.ts +23 -9
  53. package/src/embedding/provider.ts +21 -10
  54. package/src/hooks/installers/index.ts +2 -0
  55. package/src/knowledge/context-assembly.ts +2 -1
  56. package/src/knowledge/workset.ts +77 -4
  57. package/src/memory/long-term-store.ts +242 -0
  58. package/src/memory/long-term-types.ts +136 -0
  59. package/src/memory/long-term.ts +626 -0
  60. package/src/memory/owner.ts +75 -0
  61. package/src/server.ts +112 -30
  62. package/src/store/sqlite-db.ts +74 -0
  63. package/src/types.ts +20 -0
package/dist/types.d.ts CHANGED
@@ -1,3 +1,101 @@
1
+ /**
2
+ * Durable cognitive-memory contracts. These types are intentionally separate
3
+ * from Observation provenance and Knowledge Claim truth contracts.
4
+ */
5
+ declare const LONG_TERM_MEMORY_KINDS: readonly ["episodic", "semantic", "procedural"];
6
+ type LongTermMemoryKind = typeof LONG_TERM_MEMORY_KINDS[number];
7
+ declare const LONG_TERM_MEMORY_SCOPES: readonly ["project", "user", "team"];
8
+ type LongTermMemoryScope = typeof LONG_TERM_MEMORY_SCOPES[number];
9
+ declare const LONG_TERM_MEMORY_STATES: readonly ["candidate", "qualified", "approved", "archived", "superseded"];
10
+ type LongTermMemoryState = typeof LONG_TERM_MEMORY_STATES[number];
11
+ declare const LONG_TERM_MEMORY_PORTABILITIES: readonly ["project-bound", "portable"];
12
+ type LongTermMemoryPortability = typeof LONG_TERM_MEMORY_PORTABILITIES[number];
13
+ declare const LONG_TERM_MEMORY_EVIDENCE_KINDS: readonly ["observation", "claim", "workflow", "session", "checkpoint", "git", "code", "test", "run", "document", "manual", "user"];
14
+ type LongTermMemoryEvidenceKind = typeof LONG_TERM_MEMORY_EVIDENCE_KINDS[number];
15
+ declare const LONG_TERM_MEMORY_EVIDENCE_RELATIONS: readonly ["supports", "verifies", "derives", "user-confirmed"];
16
+ type LongTermMemoryEvidenceRelation = typeof LONG_TERM_MEMORY_EVIDENCE_RELATIONS[number];
17
+ type LongTermMemoryOrigin = 'manual' | 'agent' | 'hook' | 'git' | 'migration';
18
+ interface LongTermMemoryEvidence {
19
+ id: string;
20
+ memoryId: string;
21
+ kind: LongTermMemoryEvidenceKind;
22
+ referenceId: string;
23
+ relation: LongTermMemoryEvidenceRelation;
24
+ locator?: string;
25
+ capturedHash?: string;
26
+ createdAt: string;
27
+ }
28
+ interface LongTermMemory {
29
+ id: string;
30
+ /** Project from which this item and its evidence originated. */
31
+ originProjectId: string;
32
+ /** Local stable owner identity. Team and project records retain attribution. */
33
+ ownerId: string;
34
+ scope: LongTermMemoryScope;
35
+ kind: LongTermMemoryKind;
36
+ state: LongTermMemoryState;
37
+ portability: LongTermMemoryPortability;
38
+ title: string;
39
+ content: string;
40
+ facts: string[];
41
+ tags: string[];
42
+ /** Short condition explaining when the procedure/fact applies. */
43
+ applicability?: string;
44
+ origin: LongTermMemoryOrigin;
45
+ createdAt: string;
46
+ updatedAt: string;
47
+ qualifiedAt?: string;
48
+ approvedAt?: string;
49
+ archivedAt?: string;
50
+ supersededBy?: string;
51
+ lastValidatedAt?: string;
52
+ accessCount: number;
53
+ lastAccessedAt?: string;
54
+ }
55
+ type LongTermMemoryEventKind = 'created' | 'qualified' | 'approved' | 'archived' | 'superseded';
56
+ interface LongTermMemoryEvent {
57
+ id: string;
58
+ memoryId: string;
59
+ kind: LongTermMemoryEventKind;
60
+ fromState?: LongTermMemoryState;
61
+ toState?: LongTermMemoryState;
62
+ detail?: string;
63
+ createdAt: string;
64
+ }
65
+ interface LongTermMemoryReader {
66
+ projectId: string;
67
+ ownerId?: string;
68
+ agentId?: string;
69
+ isTeamMember?: boolean;
70
+ }
71
+ interface LongTermMemoryEvidenceInput {
72
+ kind: LongTermMemoryEvidenceKind;
73
+ referenceId: string;
74
+ relation: LongTermMemoryEvidenceRelation;
75
+ locator?: string;
76
+ capturedHash?: string;
77
+ }
78
+ interface CreateLongTermMemoryInput {
79
+ originProjectId: string;
80
+ ownerId: string;
81
+ scope: LongTermMemoryScope;
82
+ kind: LongTermMemoryKind;
83
+ portability?: LongTermMemoryPortability;
84
+ title: string;
85
+ content: string;
86
+ facts?: string[];
87
+ tags?: string[];
88
+ applicability?: string;
89
+ origin?: LongTermMemoryOrigin;
90
+ evidence: LongTermMemoryEvidenceInput[];
91
+ }
92
+ interface LongTermMemorySelection {
93
+ memory: LongTermMemory;
94
+ evidence: LongTermMemoryEvidence[];
95
+ score: number;
96
+ reason: string;
97
+ }
98
+
1
99
  /**
2
100
  * Memorix Core Types
3
101
  *
@@ -490,4 +588,4 @@ interface MCPConfigAdapter {
490
588
  getConfigPath(projectRoot?: string): string;
491
589
  }
492
590
 
493
- export { type AgentTarget, type CompactionCaptureKind, type CompactionCheckpoint, type CompactionCheckpointPhase, type CompactionCheckpointStatus, type CompactionReason, DEFAULT_CONFIG, type DetectionFailure, type DetectionFailureReason, type DetectionResult, type DocumentType, type Entity, type IndexEntry, type KnowledgeGraph, type KnowledgeLayer, type MCPConfigAdapter, type MCPServerEntry, type MemorixConfig, type MemorixDocument, type MemoryRef, type MiniSkill, OBSERVATION_ICONS, type Observation, type ObservationAdmissionState, type ObservationReader, type ObservationRef, type ObservationStatus, type ObservationType, type ObservationVisibility, type ProgressInfo, type ProjectInfo, type Relation, type RetrievalQuality, type RuleFormatAdapter, type RuleSource, type SearchOptions, type Session, type SkillConflict, type SkillEntry, type SnapshotObservation, type SourceSnapshot, TOPIC_KEY_FAMILIES, type TimelineContext, type UnifiedRule, type WorkflowEntry, type WorkspaceSyncResult };
591
+ export { type AgentTarget, type CompactionCaptureKind, type CompactionCheckpoint, type CompactionCheckpointPhase, type CompactionCheckpointStatus, type CompactionReason, type CreateLongTermMemoryInput, DEFAULT_CONFIG, type DetectionFailure, type DetectionFailureReason, type DetectionResult, type DocumentType, type Entity, type IndexEntry, type KnowledgeGraph, type KnowledgeLayer, type LongTermMemory, type LongTermMemoryEvent, type LongTermMemoryEventKind, type LongTermMemoryEvidence, type LongTermMemoryEvidenceInput, type LongTermMemoryEvidenceKind, type LongTermMemoryEvidenceRelation, type LongTermMemoryKind, type LongTermMemoryOrigin, type LongTermMemoryPortability, type LongTermMemoryReader, type LongTermMemoryScope, type LongTermMemorySelection, type LongTermMemoryState, type MCPConfigAdapter, type MCPServerEntry, type MemorixConfig, type MemorixDocument, type MemoryRef, type MiniSkill, OBSERVATION_ICONS, type Observation, type ObservationAdmissionState, type ObservationReader, type ObservationRef, type ObservationStatus, type ObservationType, type ObservationVisibility, type ProgressInfo, type ProjectInfo, type Relation, type RetrievalQuality, type RuleFormatAdapter, type RuleSource, type SearchOptions, type Session, type SkillConflict, type SkillEntry, type SnapshotObservation, type SourceSnapshot, TOPIC_KEY_FAMILIES, type TimelineContext, type UnifiedRule, type WorkflowEntry, type WorkspaceSyncResult };
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * Memorix Core Types\n *\n * Data model sources:\n * - Entity/Relation/KnowledgeGraph: MCP Official Memory Server (v0.6.3)\n * - Observation/ObservationType: claude-mem Progressive Disclosure\n * - UnifiedRule/RuleSource: Memorix original (rules sync)\n *\n * Designed for extensibility: new agent formats (Kiro, Copilot, Antigravity)\n * can be added by extending RuleSource and adding format adapters.\n */\n\n// ============================================================\n// Knowledge Graph (adopted from MCP Official Memory Server)\n// ============================================================\n\n/** A node in the knowledge graph representing a concept, component, or config */\nexport interface Entity {\n name: string;\n entityType: string;\n observations: string[];\n}\n\n/** A directed edge between two entities */\nexport interface Relation {\n from: string;\n to: string;\n relationType: string;\n}\n\n/** The complete knowledge graph */\nexport interface KnowledgeGraph {\n entities: Entity[];\n relations: Relation[];\n}\n\n// ============================================================\n// Observation (adopted from claude-mem Progressive Disclosure)\n// ============================================================\n\n/**\n * Observation type classification using claude-mem's icon-based legend system.\n *\n * Icon mapping:\n * [SESSION] session-request — User's original goal\n * [GOTCHA] gotcha — Critical pitfall / trap\n * [FIX] problem-solution — Bug fix or workaround\n * [INFO] how-it-works — Technical explanation\n * [CHANGE] what-changed — Code/architecture change\n * [DISCOVERY] discovery — New learning or insight\n * [WHY] why-it-exists — Design rationale\n * [DECISION] decision — Architecture decision\n * [TRADEOFF] trade-off — Deliberate compromise\n * [REASONING] reasoning — Why this approach was chosen (System 2 reasoning trace)\n * [PROBE] probe — Operational heartbeat / connectivity check (short-lived, excluded from default search)\n */\nexport type ObservationType =\n | 'session-request'\n | 'gotcha'\n | 'problem-solution'\n | 'how-it-works'\n | 'what-changed'\n | 'discovery'\n | 'why-it-exists'\n | 'decision'\n | 'trade-off'\n | 'reasoning'\n | 'probe';\n\n/** Map from ObservationType to display icon */\nexport const OBSERVATION_ICONS: Record<ObservationType, string> = {\n 'session-request': '[SESSION]',\n 'gotcha': '[GOTCHA]',\n 'problem-solution': '[FIX]',\n 'how-it-works': '[INFO]',\n 'what-changed': '[CHANGE]',\n 'discovery': '[DISCOVERY]',\n 'why-it-exists': '[WHY]',\n 'decision': '[DECISION]',\n 'trade-off': '[TRADEOFF]',\n 'reasoning': '[REASONING]',\n 'probe': '[PROBE]',\n};\n\n/** Observation lifecycle status */\nexport type ObservationStatus = 'active' | 'resolved' | 'archived';\n\n/**\n * Control-plane admission state for automatically captured observations.\n * Candidate and ephemeral records remain inspectable, but only qualified\n * records are eligible for automatic context delivery. Missing state preserves\n * legacy behavior for observations written before this policy existed.\n */\nexport type ObservationAdmissionState = 'ephemeral' | 'candidate' | 'qualified';\n\n/**\n * Who may retrieve an observation through agent-facing memory surfaces.\n * Missing visibility is a legacy record and resolves to `project`.\n */\nexport type ObservationVisibility = 'personal' | 'project' | 'team';\n\n/**\n * Identity available to an agent-facing retrieval call. Internal maintenance\n * deliberately omits this and may inspect all project records for lifecycle work.\n */\nexport interface ObservationReader {\n /** Bound project for a normal project-scoped call. Omit only for explicit global search. */\n projectId?: string;\n /** Stable coordination identity, available after an explicit team join. */\n agentId?: string;\n /** True only when agentId is an active member of the bound project team. */\n isTeamMember?: boolean;\n}\n\n/** Progress tracking for task/feature observations */\nexport interface ProgressInfo {\n feature: string;\n status: 'in-progress' | 'completed' | 'blocked';\n completion?: number;\n}\n\n/** A rich observation record attached to an entity */\nexport interface Observation {\n id: number;\n entityName: string;\n type: ObservationType;\n title: string;\n narrative: string;\n facts: string[];\n filesModified: string[];\n concepts: string[];\n tokens: number;\n createdAt: string;\n updatedAt?: string;\n projectId: string;\n /** Whether the observation contains causal language (because, due to, etc.) */\n hasCausalLanguage?: boolean;\n /** Optional topic key for upsert — same project+topicKey updates existing observation */\n topicKey?: string;\n /** How many times this observation was revised via topic key upsert (starts at 1) */\n revisionCount?: number;\n /** Session ID this observation belongs to */\n sessionId?: string;\n /** Lifecycle status: active (default) → resolved → archived */\n status?: ObservationStatus;\n /** ID of the observation that superseded this one (set when auto-resolved by topicKey upsert) */\n supersededBy?: number;\n /** Progress tracking for task/feature observations */\n progress?: ProgressInfo;\n /** Origin of this observation: agent (IDE hooks/MCP), git (commit ingest), manual (CLI) */\n source?: 'agent' | 'git' | 'manual';\n /** Git commit hash if source is 'git' */\n commitHash?: string;\n /** Related commit hashes — links reasoning memories to the commits they explain */\n relatedCommits?: string[];\n /** Related entity names — explicit cross-references to other memory entities */\n relatedEntities?: string[];\n /** Provenance detail: how this observation entered the system */\n sourceDetail?: 'explicit' | 'hook' | 'git-ingest';\n /** Value category from formation pipeline evaluation */\n valueCategory?: 'core' | 'contextual' | 'ephemeral';\n /** Control-plane admission state for automatic capture and delivery. */\n admissionState?: ObservationAdmissionState;\n /** Short, sanitized explanation for the latest admission decision. */\n admissionReason?: string;\n /** Retrieval scope. Legacy records without a value remain project-visible. */\n visibility?: ObservationVisibility;\n /** Explicit additional readers for a personal record, used by targeted handoffs. */\n sharedWithAgentIds?: string[];\n /** Phase 4a: Agent ID that created this observation (team attribution) */\n createdByAgentId?: string;\n /** Phase 4a: Monotonic write generation — snapshot of storage_generation at write time (watermark coherence) */\n writeGeneration?: number;\n}\n\n// ============================================================\n// Session Lifecycle (inspired by Engram's session management)\n// ============================================================\n\n/** A coding session tracked by Memorix */\nexport interface Session {\n id: string;\n projectId: string;\n startedAt: string;\n endedAt?: string;\n summary?: string;\n status: 'active' | 'completed';\n /** Agent/IDE that started this session */\n agent?: string;\n}\n\n// ============================================================\n// Cross-Agent Compaction Continuity\n// ============================================================\n\n/** Whether a checkpoint is still waiting for host compaction or has completed. */\nexport type CompactionCheckpointPhase = 'pre' | 'complete';\n\n/** Native compaction reason when the host exposes it. */\nexport type CompactionReason = 'manual' | 'auto' | 'unknown';\n\n/** How much first-party compaction evidence the host actually exposed. */\nexport type CompactionCaptureKind = 'preflight' | 'lifecycle' | 'native-summary';\n\n/** Lifecycle state for a persisted compaction checkpoint. */\nexport type CompactionCheckpointStatus = 'active' | 'archived';\n\n/**\n * A source-aware record of one host-native context compaction.\n *\n * This is intentionally not an Observation: a host summary is evidence for\n * continuation, not automatically durable project truth.\n */\nexport interface CompactionCheckpoint {\n id: string;\n projectId: string;\n sessionId: string;\n agent: string;\n phase: CompactionCheckpointPhase;\n captureKind: CompactionCaptureKind;\n reason: CompactionReason;\n sourceEvent: string;\n sourceKey: string;\n summary?: string;\n tokensBefore?: number;\n firstKeptEntryId?: string;\n details?: Record<string, unknown>;\n transcriptAvailable: boolean;\n status: CompactionCheckpointStatus;\n preCapturedAt: string;\n completedAt?: string;\n deliveredAt?: string;\n deliveryCount: number;\n createdAt: string;\n updatedAt: string;\n}\n\n// ============================================================\n// Compact Engine (adopted from claude-mem 3-layer workflow)\n// ============================================================\n\n/** L1 index entry — lightweight, ~50-100 tokens per result */\nexport interface IndexEntry {\n id: number;\n time: string;\n type: ObservationType;\n icon: string;\n title: string;\n tokens: number;\n /** Relevance score from search (time-decayed). Used by compact engine. */\n score?: number;\n /** Project that owns this observation. Needed to disambiguate global results. */\n projectId?: string;\n /** Origin of the memory for source-aware retrieval and display. */\n source?: 'agent' | 'git' | 'manual';\n /** Provenance detail for source-aware display */\n sourceDetail?: 'explicit' | 'hook' | 'git-ingest';\n /** Value category for source-aware ranking */\n valueCategory?: 'core' | 'contextual' | 'ephemeral';\n /** Control-plane admission state when known. */\n admissionState?: ObservationAdmissionState;\n /** Retrieval scope when known. */\n visibility?: ObservationVisibility;\n /** Explainable recall: why this result matched. */\n matchedFields?: string[];\n /** Entity name — used for entity-affinity scoring and workstream deduplication. */\n entityName?: string;\n /** Document type: observation or mini-skill (Phase 3a) */\n documentType?: DocumentType;\n /** Knowledge layer for layer-aware ranking (Phase 3a) */\n knowledgeLayer?: KnowledgeLayer;\n}\n\n/** Explicit reference to an observation, optionally scoped to a project. */\nexport interface ObservationRef {\n id: number;\n projectId?: string;\n}\n\n/** L2 timeline context — observations around an anchor */\nexport interface TimelineContext {\n anchorId: number;\n anchorEntry: IndexEntry | null;\n before: IndexEntry[];\n after: IndexEntry[];\n}\n\n/** Retrieval work allowed for a search request. */\nexport type RetrievalQuality = 'fast' | 'balanced' | 'thorough';\n\n/** Search options for the compact engine */\nexport interface SearchOptions {\n query: string;\n limit?: number;\n type?: ObservationType;\n projectId?: string;\n since?: string;\n until?: string;\n /** Token budget — trim results to fit within this many tokens (0 = unlimited) */\n maxTokens?: number;\n /** Filter by observation status. Default: 'active' (only show active memories) */\n status?: ObservationStatus | 'all';\n /** Filter by observation source: 'agent', 'git', 'manual', or undefined for all */\n source?: 'agent' | 'git' | 'manual';\n /** Internal observability probes can disable access tracking without affecting normal search behavior. */\n trackAccess?: boolean;\n /** Internal reader context for agent-facing visibility filtering. */\n reader?: ObservationReader;\n /**\n * `fast` stays fully local, `balanced` (default) permits embeddings, and\n * `thorough` explicitly permits optional LLM query rewrite and reranking.\n */\n quality?: RetrievalQuality;\n}\n\n/** Topic key family heuristics for suggesting stable topic keys */\nexport const TOPIC_KEY_FAMILIES: Record<string, string[]> = {\n 'architecture': ['architecture', 'design', 'adr', 'structure', 'pattern'],\n 'bug': ['bugfix', 'fix', 'error', 'regression', 'crash', 'problem-solution'],\n 'decision': ['decision', 'trade-off', 'choice', 'strategy'],\n 'config': ['config', 'setup', 'env', 'environment', 'deployment'],\n 'discovery': ['discovery', 'learning', 'insight', 'gotcha'],\n 'pattern': ['pattern', 'convention', 'standard', 'best-practice'],\n};\n\n// ============================================================\n// Orama Document Schema\n// ============================================================\n\n/** The document shape stored in Orama */\nexport interface MemorixDocument {\n id: string;\n observationId: number;\n entityName: string;\n type: string;\n title: string;\n narrative: string;\n facts: string;\n filesModified: string;\n concepts: string;\n tokens: number;\n createdAt: string;\n projectId: string;\n /** Number of times this observation was returned in search results */\n accessCount: number;\n /** ISO timestamp of last access via search/detail */\n lastAccessedAt: string;\n /** Lifecycle status: active, resolved, archived */\n status: string;\n /** Origin: agent, git, manual */\n source: string;\n /** Provenance detail: explicit, hook, or git-ingest */\n sourceDetail?: string;\n /** Value category from formation evaluation */\n valueCategory?: string;\n /** Control-plane admission state for automatic capture and delivery. */\n admissionState?: string;\n /** Short, sanitized explanation for the latest admission decision. */\n admissionReason?: string;\n /** Retrieval scope for agent-facing filtering. */\n visibility?: string;\n /** Agent that owns a personal record, or authored a shared record. */\n createdByAgentId?: string;\n /** Explicit readers for a targeted personal record. */\n sharedWithAgentIds?: string;\n /** Optional vector embedding for semantic/hybrid retrieval */\n embedding?: number[];\n /** Document type: observation or mini-skill (Phase 3a) */\n documentType?: DocumentType;\n /** Knowledge layer for layer-aware ranking (Phase 3a) */\n knowledgeLayer?: KnowledgeLayer;\n}\n\n// ============================================================\n// Rules System (Memorix original — extensible for new agents)\n// ============================================================\n\n/**\n * Supported agent/IDE rule sources.\n * All 7 major AI IDEs are supported.\n */\nexport type RuleSource =\n | 'cursor'\n | 'claude-code'\n | 'codex'\n | 'windsurf'\n | 'antigravity'\n | 'gemini-cli'\n | 'copilot'\n | 'kiro'\n | 'trae'\n | 'memorix';\n\n/** A parsed rule in the unified intermediate representation */\nexport interface UnifiedRule {\n id: string;\n content: string;\n description?: string;\n source: RuleSource;\n scope: 'global' | 'project' | 'path-specific';\n paths?: string[];\n alwaysApply?: boolean;\n priority: number;\n hash: string;\n}\n\n/**\n * Format adapter interface — implement this for each agent/IDE.\n * Adding a new agent (e.g., Kiro) only requires implementing this interface.\n */\nexport interface RuleFormatAdapter {\n /** Unique identifier for this agent format */\n readonly source: RuleSource;\n\n /** File paths/globs this adapter can parse */\n readonly filePatterns: string[];\n\n /** Parse rule files into unified representation */\n parse(filePath: string, content: string): UnifiedRule[];\n\n /** Generate rule file content from unified representation */\n generate(rules: UnifiedRule[]): { filePath: string; content: string }[];\n}\n\n// ============================================================\n// Project Identity\n// ============================================================\n\nexport interface ProjectInfo {\n id: string;\n name: string;\n gitRemote?: string;\n rootPath: string;\n}\n\n/**\n * Diagnostic failure info from project detection.\n * Tells callers exactly WHY detection failed so they can report actionable errors.\n */\nexport type DetectionFailureReason =\n | 'path_not_found'\n | 'not_a_directory'\n | 'no_git'\n | 'git_worktree_error'\n | 'git_safe_directory'\n | 'remote_resolve_failed';\n\nexport interface DetectionFailure {\n reason: DetectionFailureReason;\n path: string;\n detail: string;\n}\n\nexport interface DetectionResult {\n project: ProjectInfo | null;\n failure: DetectionFailure | null;\n}\n\n// ============================================================\n// Memorix Server Configuration\n// ============================================================\n\nexport interface MemorixConfig {\n dataDir: string;\n projectId: string;\n projectName: string;\n enableEmbeddings: boolean;\n enableRulesSync: boolean;\n watchRuleFiles: boolean;\n}\n\nexport const DEFAULT_CONFIG: Partial<MemorixConfig> = {\n enableEmbeddings: false,\n enableRulesSync: false,\n watchRuleFiles: false,\n};\n\n// ============================================================\n// Workspace Sync — Cross-Agent workspace migration\n// ============================================================\n\n/** Supported agent targets for workspace sync */\nexport type AgentTarget =\n | 'windsurf'\n | 'cursor'\n | 'claude-code'\n | 'codex'\n | 'copilot'\n | 'antigravity'\n | 'gemini-cli'\n | 'openclaw'\n | 'hermes'\n | 'omp'\n | 'kiro'\n | 'opencode'\n | 'trae';\n\n/** A unified MCP server entry across all agent config formats */\nexport interface MCPServerEntry {\n name: string;\n /** Command for stdio transport */\n command: string;\n /** Args for stdio transport */\n args: string[];\n /** Environment variables */\n env?: Record<string, string> | null;\n /** URL for HTTP/SSE transport (Codex uses `url`, Windsurf uses `serverUrl`) */\n url?: string;\n /** HTTP headers (Windsurf uses `headers` for HTTP transport) */\n headers?: Record<string, string>;\n /** Whether this server is disabled */\n disabled?: boolean;\n /** Claude Code: force small core tool sets to load before the first prompt */\n alwaysLoad?: boolean;\n}\n\n/** Unified workflow entry */\nexport interface WorkflowEntry {\n name: string;\n description: string;\n content: string;\n source: AgentTarget;\n filePath: string;\n}\n\n/** A skill folder discovered from an agent's skills directory */\nexport interface SkillEntry {\n name: string;\n description: string;\n sourcePath: string;\n sourceAgent: AgentTarget;\n}\n\n/** Conflict when two agents have a skill with the same folder name */\nexport interface SkillConflict {\n name: string;\n kept: SkillEntry;\n skipped: SkillEntry;\n}\n\n/** Result of a workspace sync operation */\nexport interface WorkspaceSyncResult {\n mcpServers: {\n scanned: MCPServerEntry[];\n generated: { filePath: string; content: string }[];\n };\n workflows: {\n scanned: WorkflowEntry[];\n generated: { filePath: string; content: string }[];\n };\n rules: {\n scanned: number;\n generated: number;\n };\n skills: {\n scanned: SkillEntry[];\n conflicts: SkillConflict[];\n copied: string[];\n skipped: string[];\n };\n}\n\n// ============================================================\n// Mini-Skills — Promoted memories that never decay\n// ============================================================\n\n/** A mini-skill promoted from one or more observations */\nexport interface MiniSkill {\n id: number;\n /** Observation IDs this mini-skill was derived from (live refs, best-effort) */\n sourceObservationIds: number[];\n /** Entity the source observations belong to */\n sourceEntity: string;\n /** Short title for the skill */\n title: string;\n /** What the agent should do (imperative instruction) */\n instruction: string;\n /** When this skill should be applied (scenario description) */\n trigger: string;\n /** Key facts extracted from source observations */\n facts: string[];\n /** Project this skill belongs to */\n projectId: string;\n /** ISO timestamp */\n createdAt: string;\n /** How many times this skill was injected in session_start */\n usedCount: number;\n /** Classification tags */\n tags: string[];\n /** Frozen source observation content at promote time (JSON, immutable provenance proof) */\n sourceSnapshot?: string;\n /** ISO timestamp of last modification (Phase 3a: set once at creation) */\n updatedAt?: string;\n}\n\n// ============================================================\n// Source Snapshot — immutable provenance proof for promoted knowledge\n// ============================================================\n\n/** A single observation entry within a source snapshot */\nexport interface SnapshotObservation {\n id: number;\n title: string;\n type: string;\n narrative: string;\n facts: string[];\n entityName: string;\n projectId: string;\n createdAt: string;\n /** Frozen source detail for provenance (explicit / hook / git-ingest) */\n sourceDetail?: string;\n}\n\n/** Frozen source content captured at promote time */\nexport interface SourceSnapshot {\n observations: SnapshotObservation[];\n promotedAt: string;\n}\n\n// ============================================================\n// Knowledge Layer — Phase 3a retrieval classification\n// ============================================================\n\n/** Classification of knowledge for layer-aware ranking */\nexport type KnowledgeLayer = 'project-truth' | 'promoted' | 'evidence';\n\n/** Document type discriminator for Orama index */\nexport type DocumentType = 'observation' | 'mini-skill';\n\n// ============================================================\n// Typed Memory Reference — Phase 3a reference protocol\n// ============================================================\n\n/** A typed reference to a memory object (observation or mini-skill) */\nexport interface MemoryRef {\n kind: 'obs' | 'skill';\n id: number;\n projectId?: string;\n}\n\n/** MCP config format adapter interface */\nexport interface MCPConfigAdapter {\n readonly source: AgentTarget;\n /** Parse MCP server entries from a config file */\n parse(content: string): MCPServerEntry[];\n /** Generate config file content from MCP server entries */\n generate(servers: MCPServerEntry[]): string;\n /** Get the default config file path for this agent */\n getConfigPath(projectRoot?: string): string;\n}\n"],"mappings":";AAsEO,IAAM,oBAAqD;AAAA,EAChE,mBAAmB;AAAA,EACnB,UAAU;AAAA,EACV,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,aAAa;AAAA,EACb,SAAS;AACX;AA0OO,IAAM,qBAA+C;AAAA,EAC1D,gBAAgB,CAAC,gBAAgB,UAAU,OAAO,aAAa,SAAS;AAAA,EACxE,OAAO,CAAC,UAAU,OAAO,SAAS,cAAc,SAAS,kBAAkB;AAAA,EAC3E,YAAY,CAAC,YAAY,aAAa,UAAU,UAAU;AAAA,EAC1D,UAAU,CAAC,UAAU,SAAS,OAAO,eAAe,YAAY;AAAA,EAChE,aAAa,CAAC,aAAa,YAAY,WAAW,QAAQ;AAAA,EAC1D,WAAW,CAAC,WAAW,cAAc,YAAY,eAAe;AAClE;AAoJO,IAAM,iBAAyC;AAAA,EACpD,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,gBAAgB;AAClB;","names":[]}
1
+ {"version":3,"sources":["../src/types.ts"],"sourcesContent":["/**\n * Memorix Core Types\n *\n * Data model sources:\n * - Entity/Relation/KnowledgeGraph: MCP Official Memory Server (v0.6.3)\n * - Observation/ObservationType: claude-mem Progressive Disclosure\n * - UnifiedRule/RuleSource: Memorix original (rules sync)\n *\n * Designed for extensibility: new agent formats (Kiro, Copilot, Antigravity)\n * can be added by extending RuleSource and adding format adapters.\n */\n\n// ============================================================\n// Knowledge Graph (adopted from MCP Official Memory Server)\n// ============================================================\n\n/** A node in the knowledge graph representing a concept, component, or config */\nexport interface Entity {\n name: string;\n entityType: string;\n observations: string[];\n}\n\n/** A directed edge between two entities */\nexport interface Relation {\n from: string;\n to: string;\n relationType: string;\n}\n\n/** The complete knowledge graph */\nexport interface KnowledgeGraph {\n entities: Entity[];\n relations: Relation[];\n}\n\n// ============================================================\n// Observation (adopted from claude-mem Progressive Disclosure)\n// ============================================================\n\n/**\n * Observation type classification using claude-mem's icon-based legend system.\n *\n * Icon mapping:\n * [SESSION] session-request — User's original goal\n * [GOTCHA] gotcha — Critical pitfall / trap\n * [FIX] problem-solution — Bug fix or workaround\n * [INFO] how-it-works — Technical explanation\n * [CHANGE] what-changed — Code/architecture change\n * [DISCOVERY] discovery — New learning or insight\n * [WHY] why-it-exists — Design rationale\n * [DECISION] decision — Architecture decision\n * [TRADEOFF] trade-off — Deliberate compromise\n * [REASONING] reasoning — Why this approach was chosen (System 2 reasoning trace)\n * [PROBE] probe — Operational heartbeat / connectivity check (short-lived, excluded from default search)\n */\nexport type ObservationType =\n | 'session-request'\n | 'gotcha'\n | 'problem-solution'\n | 'how-it-works'\n | 'what-changed'\n | 'discovery'\n | 'why-it-exists'\n | 'decision'\n | 'trade-off'\n | 'reasoning'\n | 'probe';\n\n/** Map from ObservationType to display icon */\nexport const OBSERVATION_ICONS: Record<ObservationType, string> = {\n 'session-request': '[SESSION]',\n 'gotcha': '[GOTCHA]',\n 'problem-solution': '[FIX]',\n 'how-it-works': '[INFO]',\n 'what-changed': '[CHANGE]',\n 'discovery': '[DISCOVERY]',\n 'why-it-exists': '[WHY]',\n 'decision': '[DECISION]',\n 'trade-off': '[TRADEOFF]',\n 'reasoning': '[REASONING]',\n 'probe': '[PROBE]',\n};\n\n/** Observation lifecycle status */\nexport type ObservationStatus = 'active' | 'resolved' | 'archived';\n\n/**\n * Control-plane admission state for automatically captured observations.\n * Candidate and ephemeral records remain inspectable, but only qualified\n * records are eligible for automatic context delivery. Missing state preserves\n * legacy behavior for observations written before this policy existed.\n */\nexport type ObservationAdmissionState = 'ephemeral' | 'candidate' | 'qualified';\n\n/**\n * Who may retrieve an observation through agent-facing memory surfaces.\n * Missing visibility is a legacy record and resolves to `project`.\n */\nexport type ObservationVisibility = 'personal' | 'project' | 'team';\n\n/**\n * Identity available to an agent-facing retrieval call. Internal maintenance\n * deliberately omits this and may inspect all project records for lifecycle work.\n */\nexport interface ObservationReader {\n /** Bound project for a normal project-scoped call. Omit only for explicit global search. */\n projectId?: string;\n /** Stable coordination identity, available after an explicit team join. */\n agentId?: string;\n /** True only when agentId is an active member of the bound project team. */\n isTeamMember?: boolean;\n}\n\n/** Progress tracking for task/feature observations */\nexport interface ProgressInfo {\n feature: string;\n status: 'in-progress' | 'completed' | 'blocked';\n completion?: number;\n}\n\n/** A rich observation record attached to an entity */\nexport interface Observation {\n id: number;\n entityName: string;\n type: ObservationType;\n title: string;\n narrative: string;\n facts: string[];\n filesModified: string[];\n concepts: string[];\n tokens: number;\n createdAt: string;\n updatedAt?: string;\n projectId: string;\n /** Whether the observation contains causal language (because, due to, etc.) */\n hasCausalLanguage?: boolean;\n /** Optional topic key for upsert — same project+topicKey updates existing observation */\n topicKey?: string;\n /** How many times this observation was revised via topic key upsert (starts at 1) */\n revisionCount?: number;\n /** Session ID this observation belongs to */\n sessionId?: string;\n /** Lifecycle status: active (default) → resolved → archived */\n status?: ObservationStatus;\n /** ID of the observation that superseded this one (set when auto-resolved by topicKey upsert) */\n supersededBy?: number;\n /** Progress tracking for task/feature observations */\n progress?: ProgressInfo;\n /** Origin of this observation: agent (IDE hooks/MCP), git (commit ingest), manual (CLI) */\n source?: 'agent' | 'git' | 'manual';\n /** Git commit hash if source is 'git' */\n commitHash?: string;\n /** Related commit hashes — links reasoning memories to the commits they explain */\n relatedCommits?: string[];\n /** Related entity names — explicit cross-references to other memory entities */\n relatedEntities?: string[];\n /** Provenance detail: how this observation entered the system */\n sourceDetail?: 'explicit' | 'hook' | 'git-ingest';\n /** Value category from formation pipeline evaluation */\n valueCategory?: 'core' | 'contextual' | 'ephemeral';\n /** Control-plane admission state for automatic capture and delivery. */\n admissionState?: ObservationAdmissionState;\n /** Short, sanitized explanation for the latest admission decision. */\n admissionReason?: string;\n /** Retrieval scope. Legacy records without a value remain project-visible. */\n visibility?: ObservationVisibility;\n /** Explicit additional readers for a personal record, used by targeted handoffs. */\n sharedWithAgentIds?: string[];\n /** Phase 4a: Agent ID that created this observation (team attribution) */\n createdByAgentId?: string;\n /** Phase 4a: Monotonic write generation — snapshot of storage_generation at write time (watermark coherence) */\n writeGeneration?: number;\n}\n\n// ============================================================\n// Session Lifecycle (inspired by Engram's session management)\n// ============================================================\n\n/** A coding session tracked by Memorix */\nexport interface Session {\n id: string;\n projectId: string;\n startedAt: string;\n endedAt?: string;\n summary?: string;\n status: 'active' | 'completed';\n /** Agent/IDE that started this session */\n agent?: string;\n}\n\n// ============================================================\n// Cross-Agent Compaction Continuity\n// ============================================================\n\n/** Whether a checkpoint is still waiting for host compaction or has completed. */\nexport type CompactionCheckpointPhase = 'pre' | 'complete';\n\n/** Native compaction reason when the host exposes it. */\nexport type CompactionReason = 'manual' | 'auto' | 'unknown';\n\n/** How much first-party compaction evidence the host actually exposed. */\nexport type CompactionCaptureKind = 'preflight' | 'lifecycle' | 'native-summary';\n\n/** Lifecycle state for a persisted compaction checkpoint. */\nexport type CompactionCheckpointStatus = 'active' | 'archived';\n\n/**\n * A source-aware record of one host-native context compaction.\n *\n * This is intentionally not an Observation: a host summary is evidence for\n * continuation, not automatically durable project truth.\n */\nexport interface CompactionCheckpoint {\n id: string;\n projectId: string;\n sessionId: string;\n agent: string;\n phase: CompactionCheckpointPhase;\n captureKind: CompactionCaptureKind;\n reason: CompactionReason;\n sourceEvent: string;\n sourceKey: string;\n summary?: string;\n tokensBefore?: number;\n firstKeptEntryId?: string;\n details?: Record<string, unknown>;\n transcriptAvailable: boolean;\n status: CompactionCheckpointStatus;\n preCapturedAt: string;\n completedAt?: string;\n deliveredAt?: string;\n deliveryCount: number;\n createdAt: string;\n updatedAt: string;\n}\n\n// ============================================================\n// Compact Engine (adopted from claude-mem 3-layer workflow)\n// ============================================================\n\n/** L1 index entry — lightweight, ~50-100 tokens per result */\nexport interface IndexEntry {\n id: number;\n time: string;\n type: ObservationType;\n icon: string;\n title: string;\n tokens: number;\n /** Relevance score from search (time-decayed). Used by compact engine. */\n score?: number;\n /** Project that owns this observation. Needed to disambiguate global results. */\n projectId?: string;\n /** Origin of the memory for source-aware retrieval and display. */\n source?: 'agent' | 'git' | 'manual';\n /** Provenance detail for source-aware display */\n sourceDetail?: 'explicit' | 'hook' | 'git-ingest';\n /** Value category for source-aware ranking */\n valueCategory?: 'core' | 'contextual' | 'ephemeral';\n /** Control-plane admission state when known. */\n admissionState?: ObservationAdmissionState;\n /** Retrieval scope when known. */\n visibility?: ObservationVisibility;\n /** Explainable recall: why this result matched. */\n matchedFields?: string[];\n /** Entity name — used for entity-affinity scoring and workstream deduplication. */\n entityName?: string;\n /** Document type: observation or mini-skill (Phase 3a) */\n documentType?: DocumentType;\n /** Knowledge layer for layer-aware ranking (Phase 3a) */\n knowledgeLayer?: KnowledgeLayer;\n}\n\n/** Explicit reference to an observation, optionally scoped to a project. */\nexport interface ObservationRef {\n id: number;\n projectId?: string;\n}\n\n/** L2 timeline context — observations around an anchor */\nexport interface TimelineContext {\n anchorId: number;\n anchorEntry: IndexEntry | null;\n before: IndexEntry[];\n after: IndexEntry[];\n}\n\n/** Retrieval work allowed for a search request. */\nexport type RetrievalQuality = 'fast' | 'balanced' | 'thorough';\n\n/** Search options for the compact engine */\nexport interface SearchOptions {\n query: string;\n limit?: number;\n type?: ObservationType;\n projectId?: string;\n since?: string;\n until?: string;\n /** Token budget — trim results to fit within this many tokens (0 = unlimited) */\n maxTokens?: number;\n /** Filter by observation status. Default: 'active' (only show active memories) */\n status?: ObservationStatus | 'all';\n /** Filter by observation source: 'agent', 'git', 'manual', or undefined for all */\n source?: 'agent' | 'git' | 'manual';\n /** Internal observability probes can disable access tracking without affecting normal search behavior. */\n trackAccess?: boolean;\n /** Internal reader context for agent-facing visibility filtering. */\n reader?: ObservationReader;\n /**\n * `fast` stays fully local, `balanced` (default) permits embeddings, and\n * `thorough` explicitly permits optional LLM query rewrite and reranking.\n */\n quality?: RetrievalQuality;\n}\n\n/** Topic key family heuristics for suggesting stable topic keys */\nexport const TOPIC_KEY_FAMILIES: Record<string, string[]> = {\n 'architecture': ['architecture', 'design', 'adr', 'structure', 'pattern'],\n 'bug': ['bugfix', 'fix', 'error', 'regression', 'crash', 'problem-solution'],\n 'decision': ['decision', 'trade-off', 'choice', 'strategy'],\n 'config': ['config', 'setup', 'env', 'environment', 'deployment'],\n 'discovery': ['discovery', 'learning', 'insight', 'gotcha'],\n 'pattern': ['pattern', 'convention', 'standard', 'best-practice'],\n};\n\n// ============================================================\n// Orama Document Schema\n// ============================================================\n\n/** The document shape stored in Orama */\nexport interface MemorixDocument {\n id: string;\n observationId: number;\n entityName: string;\n type: string;\n title: string;\n narrative: string;\n facts: string;\n filesModified: string;\n concepts: string;\n tokens: number;\n createdAt: string;\n projectId: string;\n /** Number of times this observation was returned in search results */\n accessCount: number;\n /** ISO timestamp of last access via search/detail */\n lastAccessedAt: string;\n /** Lifecycle status: active, resolved, archived */\n status: string;\n /** Origin: agent, git, manual */\n source: string;\n /** Provenance detail: explicit, hook, or git-ingest */\n sourceDetail?: string;\n /** Value category from formation evaluation */\n valueCategory?: string;\n /** Control-plane admission state for automatic capture and delivery. */\n admissionState?: string;\n /** Short, sanitized explanation for the latest admission decision. */\n admissionReason?: string;\n /** Retrieval scope for agent-facing filtering. */\n visibility?: string;\n /** Agent that owns a personal record, or authored a shared record. */\n createdByAgentId?: string;\n /** Explicit readers for a targeted personal record. */\n sharedWithAgentIds?: string;\n /** Optional vector embedding for semantic/hybrid retrieval */\n embedding?: number[];\n /** Document type: observation or mini-skill (Phase 3a) */\n documentType?: DocumentType;\n /** Knowledge layer for layer-aware ranking (Phase 3a) */\n knowledgeLayer?: KnowledgeLayer;\n}\n\n// ============================================================\n// Rules System (Memorix original — extensible for new agents)\n// ============================================================\n\n/**\n * Supported agent/IDE rule sources.\n * All 7 major AI IDEs are supported.\n */\nexport type RuleSource =\n | 'cursor'\n | 'claude-code'\n | 'codex'\n | 'windsurf'\n | 'antigravity'\n | 'gemini-cli'\n | 'copilot'\n | 'kiro'\n | 'trae'\n | 'memorix';\n\n/** A parsed rule in the unified intermediate representation */\nexport interface UnifiedRule {\n id: string;\n content: string;\n description?: string;\n source: RuleSource;\n scope: 'global' | 'project' | 'path-specific';\n paths?: string[];\n alwaysApply?: boolean;\n priority: number;\n hash: string;\n}\n\n/**\n * Format adapter interface — implement this for each agent/IDE.\n * Adding a new agent (e.g., Kiro) only requires implementing this interface.\n */\nexport interface RuleFormatAdapter {\n /** Unique identifier for this agent format */\n readonly source: RuleSource;\n\n /** File paths/globs this adapter can parse */\n readonly filePatterns: string[];\n\n /** Parse rule files into unified representation */\n parse(filePath: string, content: string): UnifiedRule[];\n\n /** Generate rule file content from unified representation */\n generate(rules: UnifiedRule[]): { filePath: string; content: string }[];\n}\n\n// ============================================================\n// Project Identity\n// ============================================================\n\nexport interface ProjectInfo {\n id: string;\n name: string;\n gitRemote?: string;\n rootPath: string;\n}\n\n/**\n * Diagnostic failure info from project detection.\n * Tells callers exactly WHY detection failed so they can report actionable errors.\n */\nexport type DetectionFailureReason =\n | 'path_not_found'\n | 'not_a_directory'\n | 'no_git'\n | 'git_worktree_error'\n | 'git_safe_directory'\n | 'remote_resolve_failed';\n\nexport interface DetectionFailure {\n reason: DetectionFailureReason;\n path: string;\n detail: string;\n}\n\nexport interface DetectionResult {\n project: ProjectInfo | null;\n failure: DetectionFailure | null;\n}\n\n// ============================================================\n// Memorix Server Configuration\n// ============================================================\n\nexport interface MemorixConfig {\n dataDir: string;\n projectId: string;\n projectName: string;\n enableEmbeddings: boolean;\n enableRulesSync: boolean;\n watchRuleFiles: boolean;\n}\n\nexport const DEFAULT_CONFIG: Partial<MemorixConfig> = {\n enableEmbeddings: false,\n enableRulesSync: false,\n watchRuleFiles: false,\n};\n\n// ============================================================\n// Workspace Sync — Cross-Agent workspace migration\n// ============================================================\n\n/** Supported agent targets for workspace sync */\nexport type AgentTarget =\n | 'windsurf'\n | 'cursor'\n | 'claude-code'\n | 'codex'\n | 'copilot'\n | 'antigravity'\n | 'gemini-cli'\n | 'openclaw'\n | 'hermes'\n | 'omp'\n | 'kiro'\n | 'opencode'\n | 'trae';\n\n/** A unified MCP server entry across all agent config formats */\nexport interface MCPServerEntry {\n name: string;\n /** Command for stdio transport */\n command: string;\n /** Args for stdio transport */\n args: string[];\n /** Environment variables */\n env?: Record<string, string> | null;\n /** URL for HTTP/SSE transport (Codex uses `url`, Windsurf uses `serverUrl`) */\n url?: string;\n /** HTTP headers (Windsurf uses `headers` for HTTP transport) */\n headers?: Record<string, string>;\n /** Whether this server is disabled */\n disabled?: boolean;\n /** Claude Code: force small core tool sets to load before the first prompt */\n alwaysLoad?: boolean;\n}\n\n/** Unified workflow entry */\nexport interface WorkflowEntry {\n name: string;\n description: string;\n content: string;\n source: AgentTarget;\n filePath: string;\n}\n\n/** A skill folder discovered from an agent's skills directory */\nexport interface SkillEntry {\n name: string;\n description: string;\n sourcePath: string;\n sourceAgent: AgentTarget;\n}\n\n/** Conflict when two agents have a skill with the same folder name */\nexport interface SkillConflict {\n name: string;\n kept: SkillEntry;\n skipped: SkillEntry;\n}\n\n/** Result of a workspace sync operation */\nexport interface WorkspaceSyncResult {\n mcpServers: {\n scanned: MCPServerEntry[];\n generated: { filePath: string; content: string }[];\n };\n workflows: {\n scanned: WorkflowEntry[];\n generated: { filePath: string; content: string }[];\n };\n rules: {\n scanned: number;\n generated: number;\n };\n skills: {\n scanned: SkillEntry[];\n conflicts: SkillConflict[];\n copied: string[];\n skipped: string[];\n };\n}\n\n// ============================================================\n// Mini-Skills — Promoted memories that never decay\n// ============================================================\n\n/** A mini-skill promoted from one or more observations */\nexport interface MiniSkill {\n id: number;\n /** Observation IDs this mini-skill was derived from (live refs, best-effort) */\n sourceObservationIds: number[];\n /** Entity the source observations belong to */\n sourceEntity: string;\n /** Short title for the skill */\n title: string;\n /** What the agent should do (imperative instruction) */\n instruction: string;\n /** When this skill should be applied (scenario description) */\n trigger: string;\n /** Key facts extracted from source observations */\n facts: string[];\n /** Project this skill belongs to */\n projectId: string;\n /** ISO timestamp */\n createdAt: string;\n /** How many times this skill was injected in session_start */\n usedCount: number;\n /** Classification tags */\n tags: string[];\n /** Frozen source observation content at promote time (JSON, immutable provenance proof) */\n sourceSnapshot?: string;\n /** ISO timestamp of last modification (Phase 3a: set once at creation) */\n updatedAt?: string;\n}\n\n// ============================================================\n// Source Snapshot — immutable provenance proof for promoted knowledge\n// ============================================================\n\n/** A single observation entry within a source snapshot */\nexport interface SnapshotObservation {\n id: number;\n title: string;\n type: string;\n narrative: string;\n facts: string[];\n entityName: string;\n projectId: string;\n createdAt: string;\n /** Frozen source detail for provenance (explicit / hook / git-ingest) */\n sourceDetail?: string;\n}\n\n/** Frozen source content captured at promote time */\nexport interface SourceSnapshot {\n observations: SnapshotObservation[];\n promotedAt: string;\n}\n\n// ============================================================\n// Knowledge Layer — Phase 3a retrieval classification\n// ============================================================\n\n/** Classification of knowledge for layer-aware ranking */\nexport type KnowledgeLayer = 'project-truth' | 'promoted' | 'evidence';\n\n/** Document type discriminator for Orama index */\nexport type DocumentType = 'observation' | 'mini-skill';\n\n// ============================================================\n// Typed Memory Reference — Phase 3a reference protocol\n// ============================================================\n\n/** A typed reference to a memory object (observation or mini-skill) */\nexport interface MemoryRef {\n kind: 'obs' | 'skill';\n id: number;\n projectId?: string;\n}\n\n/** MCP config format adapter interface */\nexport interface MCPConfigAdapter {\n readonly source: AgentTarget;\n /** Parse MCP server entries from a config file */\n parse(content: string): MCPServerEntry[];\n /** Generate config file content from MCP server entries */\n generate(servers: MCPServerEntry[]): string;\n /** Get the default config file path for this agent */\n getConfigPath(projectRoot?: string): string;\n}\n\n// Durable cognitive memory is intentionally kept in its own module so the\n// legacy Observation contract remains source/provenance focused.\nexport type {\n CreateLongTermMemoryInput,\n LongTermMemory,\n LongTermMemoryEvidence,\n LongTermMemoryEvidenceInput,\n LongTermMemoryEvidenceKind,\n LongTermMemoryEvidenceRelation,\n LongTermMemoryEvent,\n LongTermMemoryEventKind,\n LongTermMemoryKind,\n LongTermMemoryOrigin,\n LongTermMemoryPortability,\n LongTermMemoryReader,\n LongTermMemoryScope,\n LongTermMemorySelection,\n LongTermMemoryState,\n} from './memory/long-term-types.js';\n"],"mappings":";AAsEO,IAAM,oBAAqD;AAAA,EAChE,mBAAmB;AAAA,EACnB,UAAU;AAAA,EACV,oBAAoB;AAAA,EACpB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,aAAa;AAAA,EACb,SAAS;AACX;AA0OO,IAAM,qBAA+C;AAAA,EAC1D,gBAAgB,CAAC,gBAAgB,UAAU,OAAO,aAAa,SAAS;AAAA,EACxE,OAAO,CAAC,UAAU,OAAO,SAAS,cAAc,SAAS,kBAAkB;AAAA,EAC3E,YAAY,CAAC,YAAY,aAAa,UAAU,UAAU;AAAA,EAC1D,UAAU,CAAC,UAAU,SAAS,OAAO,eAAe,YAAY;AAAA,EAChE,aAAa,CAAC,aAAa,YAAY,WAAW,QAAQ;AAAA,EAC1D,WAAW,CAAC,WAAW,cAAc,YAAY,eAAe;AAClE;AAoJO,IAAM,iBAAyC;AAAA,EACpD,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,gBAAgB;AAClB;","names":[]}
@@ -467,7 +467,7 @@ function closeAllDatabases() {
467
467
  _dbCache.delete(key);
468
468
  }
469
469
  }
470
- var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache;
470
+ var BetterSqlite3, CREATE_OBSERVATIONS_TABLE, CREATE_MINI_SKILLS_TABLE, CREATE_SESSIONS_TABLE, CREATE_META_TABLE, CREATE_TEAM_AGENTS_TABLE, CREATE_TEAM_MESSAGES_TABLE, CREATE_TEAM_TASKS_TABLE, CREATE_TEAM_TASK_DEPS_TABLE, CREATE_TEAM_LOCKS_TABLE, CREATE_TEAM_ROLES_TABLE, CREATE_CHAT_TRANSCRIPT_TABLE, CREATE_GRAPH_ENTITIES_TABLE, CREATE_GRAPH_RELATIONS_TABLE, CREATE_CODE_FILES_TABLE, CREATE_CODE_SYMBOLS_TABLE, CREATE_CODE_EDGES_TABLE, CREATE_OBSERVATION_CODE_REFS_TABLE, CREATE_SCHEMA_MIGRATIONS_TABLE, CREATE_CODE_STATE_SNAPSHOTS_TABLE, CREATE_KNOWLEDGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_CLAIM_EVIDENCE_TABLE, CREATE_KNOWLEDGE_CLAIM_EVENTS_TABLE, CREATE_KNOWLEDGE_WORKSPACES_TABLE, CREATE_KNOWLEDGE_PAGES_TABLE, CREATE_KNOWLEDGE_PAGE_CLAIMS_TABLE, CREATE_KNOWLEDGE_PAGE_LINKS_TABLE, CREATE_KNOWLEDGE_PROPOSALS_TABLE, CREATE_KNOWLEDGE_WORKFLOWS_TABLE, CREATE_KNOWLEDGE_WORKFLOW_RUNS_TABLE, CREATE_LONG_TERM_MEMORIES_TABLE, CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE, CREATE_LONG_TERM_MEMORY_EVENTS_TABLE, CREATE_MAINTENANCE_JOBS_TABLE, CREATE_MAINTENANCE_TARGETS_TABLE, CREATE_COMPACTION_CHECKPOINTS_TABLE, CREATE_INDEXES, SCHEMA_MIGRATIONS, _dbCache;
471
471
  var init_sqlite_db = __esm({
472
472
  "src/store/sqlite-db.ts"() {
473
473
  "use strict";
@@ -893,6 +893,57 @@ CREATE TABLE IF NOT EXISTS knowledge_claim_events (
893
893
  " FOREIGN KEY (workflowId) REFERENCES knowledge_workflows(id) ON DELETE CASCADE",
894
894
  ");"
895
895
  ].join("\n");
896
+ CREATE_LONG_TERM_MEMORIES_TABLE = `
897
+ CREATE TABLE IF NOT EXISTS long_term_memories (
898
+ id TEXT PRIMARY KEY,
899
+ originProjectId TEXT NOT NULL,
900
+ ownerId TEXT NOT NULL,
901
+ scope TEXT NOT NULL,
902
+ kind TEXT NOT NULL,
903
+ state TEXT NOT NULL,
904
+ portability TEXT NOT NULL DEFAULT 'project-bound',
905
+ title TEXT NOT NULL,
906
+ content TEXT NOT NULL,
907
+ factsJson TEXT NOT NULL DEFAULT '[]',
908
+ tagsJson TEXT NOT NULL DEFAULT '[]',
909
+ applicability TEXT,
910
+ origin TEXT NOT NULL,
911
+ createdAt TEXT NOT NULL,
912
+ updatedAt TEXT NOT NULL,
913
+ qualifiedAt TEXT,
914
+ approvedAt TEXT,
915
+ archivedAt TEXT,
916
+ supersededBy TEXT,
917
+ lastValidatedAt TEXT,
918
+ accessCount INTEGER NOT NULL DEFAULT 0,
919
+ lastAccessedAt TEXT
920
+ );
921
+ `;
922
+ CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE = `
923
+ CREATE TABLE IF NOT EXISTS long_term_memory_evidence (
924
+ id TEXT PRIMARY KEY,
925
+ memoryId TEXT NOT NULL,
926
+ kind TEXT NOT NULL,
927
+ referenceId TEXT NOT NULL,
928
+ relation TEXT NOT NULL,
929
+ locator TEXT,
930
+ capturedHash TEXT,
931
+ createdAt TEXT NOT NULL,
932
+ FOREIGN KEY (memoryId) REFERENCES long_term_memories(id) ON DELETE CASCADE
933
+ );
934
+ `;
935
+ CREATE_LONG_TERM_MEMORY_EVENTS_TABLE = `
936
+ CREATE TABLE IF NOT EXISTS long_term_memory_events (
937
+ id TEXT PRIMARY KEY,
938
+ memoryId TEXT NOT NULL,
939
+ kind TEXT NOT NULL,
940
+ fromState TEXT,
941
+ toState TEXT,
942
+ detail TEXT,
943
+ createdAt TEXT NOT NULL,
944
+ FOREIGN KEY (memoryId) REFERENCES long_term_memories(id) ON DELETE CASCADE
945
+ );
946
+ `;
896
947
  CREATE_MAINTENANCE_JOBS_TABLE = `
897
948
  CREATE TABLE IF NOT EXISTS maintenance_jobs (
898
949
  id TEXT PRIMARY KEY,
@@ -988,6 +1039,11 @@ CREATE INDEX IF NOT EXISTS idx_knowledge_page_claims_claim ON knowledge_page_cla
988
1039
  CREATE INDEX IF NOT EXISTS idx_knowledge_proposals_workspace_status ON knowledge_proposals(workspaceId, status, createdAt DESC);
989
1040
  CREATE INDEX IF NOT EXISTS idx_knowledge_workflows_workspace_status ON knowledge_workflows(workspaceId, status, updatedAt DESC);
990
1041
  CREATE INDEX IF NOT EXISTS idx_knowledge_workflow_runs_project_workflow ON knowledge_workflow_runs(projectId, workflowId, startedAt DESC);
1042
+ CREATE INDEX IF NOT EXISTS idx_long_term_memories_owner_state ON long_term_memories(ownerId, state, updatedAt DESC);
1043
+ CREATE INDEX IF NOT EXISTS idx_long_term_memories_project_state ON long_term_memories(originProjectId, state, updatedAt DESC);
1044
+ CREATE INDEX IF NOT EXISTS idx_long_term_memories_scope_portability ON long_term_memories(scope, portability, state, updatedAt DESC);
1045
+ CREATE INDEX IF NOT EXISTS idx_long_term_memory_evidence_memory ON long_term_memory_evidence(memoryId, createdAt);
1046
+ CREATE INDEX IF NOT EXISTS idx_long_term_memory_events_memory ON long_term_memory_events(memoryId, createdAt);
991
1047
  CREATE INDEX IF NOT EXISTS idx_maintenance_jobs_ready ON maintenance_jobs(status, run_after);
992
1048
  CREATE INDEX IF NOT EXISTS idx_maintenance_jobs_project ON maintenance_jobs(project_id, status, run_after);
993
1049
  CREATE INDEX IF NOT EXISTS idx_maintenance_targets_updated ON maintenance_targets(updated_at);
@@ -1076,6 +1132,19 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
1076
1132
  db2.exec("CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_session_pending ON compaction_checkpoints(project_id, session_id, agent, phase, status, pre_captured_at DESC)");
1077
1133
  db2.exec("CREATE INDEX IF NOT EXISTS idx_compaction_checkpoints_source ON compaction_checkpoints(project_id, source_key)");
1078
1134
  }
1135
+ },
1136
+ {
1137
+ id: "1.3-long-term-memory",
1138
+ apply: (db2) => {
1139
+ db2.exec(CREATE_LONG_TERM_MEMORIES_TABLE);
1140
+ db2.exec(CREATE_LONG_TERM_MEMORY_EVIDENCE_TABLE);
1141
+ db2.exec(CREATE_LONG_TERM_MEMORY_EVENTS_TABLE);
1142
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_long_term_memories_owner_state ON long_term_memories(ownerId, state, updatedAt DESC)");
1143
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_long_term_memories_project_state ON long_term_memories(originProjectId, state, updatedAt DESC)");
1144
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_long_term_memories_scope_portability ON long_term_memories(scope, portability, state, updatedAt DESC)");
1145
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_long_term_memory_evidence_memory ON long_term_memory_evidence(memoryId, createdAt)");
1146
+ db2.exec("CREATE INDEX IF NOT EXISTS idx_long_term_memory_events_memory ON long_term_memory_events(memoryId, createdAt)");
1147
+ }
1079
1148
  }
1080
1149
  ];
1081
1150
  _dbCache = /* @__PURE__ */ new Map();
@@ -2337,9 +2406,10 @@ function parseBatchLimit(error) {
2337
2406
  }
2338
2407
  return null;
2339
2408
  }
2340
- async function fetchWithRetry(url, apiKey, body, attempt = 0) {
2409
+ async function fetchWithRetry(url, apiKey, body, options = {}, attempt = 0) {
2341
2410
  const controller = new AbortController();
2342
- const timeout = setTimeout(() => controller.abort(), 1e4);
2411
+ const timeoutMs = typeof options.timeoutMs === "number" && Number.isFinite(options.timeoutMs) ? Math.max(100, Math.min(Math.floor(options.timeoutMs), 6e4)) : 1e4;
2412
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
2343
2413
  let response;
2344
2414
  try {
2345
2415
  response = await fetch(url, {
@@ -2354,7 +2424,7 @@ async function fetchWithRetry(url, apiKey, body, attempt = 0) {
2354
2424
  } catch (err) {
2355
2425
  clearTimeout(timeout);
2356
2426
  if (err instanceof Error && err.name === "AbortError") {
2357
- throw new Error(`Embedding API timeout after 10s: ${url}`);
2427
+ throw new Error(`Embedding API timeout after ${timeoutMs}ms: ${url}`);
2358
2428
  }
2359
2429
  throw err;
2360
2430
  }
@@ -2362,13 +2432,13 @@ async function fetchWithRetry(url, apiKey, body, attempt = 0) {
2362
2432
  if (response.ok) {
2363
2433
  return response.json();
2364
2434
  }
2365
- if ((response.status === 429 || response.status >= 500) && attempt < MAX_RETRIES2) {
2435
+ if (options.retry !== false && (response.status === 429 || response.status >= 500) && attempt < MAX_RETRIES2) {
2366
2436
  const delay = BASE_DELAY_MS * Math.pow(2, attempt);
2367
2437
  const retryAfter = response.headers.get("retry-after");
2368
2438
  const waitMs = retryAfter ? parseInt(retryAfter, 10) * 1e3 : delay;
2369
2439
  console.error(`[memorix] Embedding API ${response.status}, retry ${attempt + 1}/${MAX_RETRIES2} in ${waitMs}ms`);
2370
2440
  await new Promise((resolve) => setTimeout(resolve, waitMs));
2371
- return fetchWithRetry(url, apiKey, body, attempt + 1);
2441
+ return fetchWithRetry(url, apiKey, body, options, attempt + 1);
2372
2442
  }
2373
2443
  const errorText2 = await response.text().catch(() => "unknown error");
2374
2444
  throw new Error(`Embedding API error (${response.status}): ${errorText2}`);
@@ -2424,7 +2494,10 @@ var init_api_provider = __esm({
2424
2494
  }
2425
2495
  } else {
2426
2496
  if (!allowNetworkProbe) return null;
2427
- probeDimensions = await _APIEmbeddingProvider.probeAPI(config);
2497
+ probeDimensions = await _APIEmbeddingProvider.probeAPI(config, {
2498
+ timeoutMs: options.requestTimeoutMs,
2499
+ retry: options.retry
2500
+ });
2428
2501
  console.error(`[memorix] API embedding: ${config.model} @ ${config.baseUrl} (${probeDimensions}d)`);
2429
2502
  saveCachedDims(config, probeDimensions).catch(() => {
2430
2503
  });
@@ -2466,7 +2539,7 @@ var init_api_provider = __esm({
2466
2539
  baseUrl = baseUrl.replace(/\/+$/, "");
2467
2540
  return { apiKey, baseUrl, model, requestedDimensions };
2468
2541
  }
2469
- static async probeAPI(config) {
2542
+ static async probeAPI(config, options) {
2470
2543
  const body = {
2471
2544
  model: config.model,
2472
2545
  input: "dimension probe"
@@ -2477,14 +2550,15 @@ var init_api_provider = __esm({
2477
2550
  const response = await fetchWithRetry(
2478
2551
  `${config.baseUrl}/embeddings`,
2479
2552
  config.apiKey,
2480
- body
2553
+ body,
2554
+ options
2481
2555
  );
2482
2556
  if (response.data.length === 0 || !response.data[0].embedding) {
2483
2557
  throw new Error("API probe returned no embeddings; check model name and API key");
2484
2558
  }
2485
2559
  return response.data[0].embedding.length;
2486
2560
  }
2487
- async embed(text) {
2561
+ async embed(text, options) {
2488
2562
  const normalized = normalizeText(text);
2489
2563
  const hash4 = textHash2(normalized, this.cacheKeyNamespace);
2490
2564
  if (diskCacheLoaded) {
@@ -2502,7 +2576,8 @@ var init_api_provider = __esm({
2502
2576
  const response = await fetchWithRetry(
2503
2577
  `${this.config.baseUrl}/embeddings`,
2504
2578
  this.config.apiKey,
2505
- body
2579
+ body,
2580
+ options
2506
2581
  );
2507
2582
  const embedding2 = response.data[0].embedding;
2508
2583
  if (embedding2.length !== this.dimensions) {
@@ -2536,7 +2611,7 @@ var init_api_provider = __esm({
2536
2611
  scheduleDiskSave();
2537
2612
  return embedding;
2538
2613
  }
2539
- async embedBatch(texts) {
2614
+ async embedBatch(texts, options) {
2540
2615
  await ensureDiskCacheLoaded();
2541
2616
  const normalizedTexts = texts.map(normalizeText);
2542
2617
  const results = new Array(texts.length);
@@ -2570,7 +2645,8 @@ var init_api_provider = __esm({
2570
2645
  const response = await fetchWithRetry(
2571
2646
  `${this.config.baseUrl}/embeddings`,
2572
2647
  this.config.apiKey,
2573
- body
2648
+ body,
2649
+ options
2574
2650
  );
2575
2651
  this.trackUsage(response);
2576
2652
  for (const item of response.data) {
@@ -2747,9 +2823,9 @@ function wrapProvider(candidate) {
2747
2823
  return {
2748
2824
  name: candidate.name,
2749
2825
  dimensions: candidate.dimensions,
2750
- async embed(text) {
2826
+ async embed(text, options) {
2751
2827
  try {
2752
- return await candidate.embed(text);
2828
+ return await candidate.embed(text, options);
2753
2829
  } catch (error) {
2754
2830
  if (kind === "api" && getEmbeddingMode2() === "auto" && isTemporaryEmbeddingFailure(error)) {
2755
2831
  warnOnce("[memorix] API embedding temporarily unavailable \u2014 switching to local fallback provider");
@@ -2757,7 +2833,7 @@ function wrapProvider(candidate) {
2757
2833
  if (fallback) {
2758
2834
  provider = wrapProvider(fallback);
2759
2835
  warnOnce(`[memorix] Embedding fallback activated: ${provider.name} (${provider.dimensions}d)`);
2760
- return provider.embed(text);
2836
+ return provider.embed(text, options);
2761
2837
  }
2762
2838
  }
2763
2839
  if (isTemporaryEmbeddingFailure(error)) {
@@ -2766,9 +2842,9 @@ function wrapProvider(candidate) {
2766
2842
  throw error;
2767
2843
  }
2768
2844
  },
2769
- async embedBatch(texts) {
2845
+ async embedBatch(texts, options) {
2770
2846
  try {
2771
- return await candidate.embedBatch(texts);
2847
+ return await candidate.embedBatch(texts, options);
2772
2848
  } catch (error) {
2773
2849
  if (kind === "api" && getEmbeddingMode2() === "auto" && isTemporaryEmbeddingFailure(error)) {
2774
2850
  warnOnce("[memorix] API embedding temporarily unavailable \u2014 switching to local fallback provider");
@@ -2776,7 +2852,7 @@ function wrapProvider(candidate) {
2776
2852
  if (fallback) {
2777
2853
  provider = wrapProvider(fallback);
2778
2854
  warnOnce(`[memorix] Embedding fallback activated: ${provider.name} (${provider.dimensions}d)`);
2779
- return provider.embedBatch(texts);
2855
+ return provider.embedBatch(texts, options);
2780
2856
  }
2781
2857
  }
2782
2858
  if (isTemporaryEmbeddingFailure(error)) {
@@ -2832,14 +2908,14 @@ async function getEmbeddingProvider(options = {}) {
2832
2908
  return provider;
2833
2909
  }
2834
2910
  if (mode === "api") {
2835
- const initialized = await createAPIProvider();
2911
+ const initialized = await createAPIProvider(options);
2836
2912
  if (!initialized) return null;
2837
2913
  provider = wrapProvider(initialized);
2838
2914
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);
2839
2915
  return provider;
2840
2916
  }
2841
2917
  if (hasAPIEmbeddingConfig()) {
2842
- const initialized = await createAPIProvider();
2918
+ const initialized = await createAPIProvider(options);
2843
2919
  if (initialized) {
2844
2920
  provider = wrapProvider(initialized);
2845
2921
  warnOnce(`[memorix] Embedding provider: ${provider.name} (${provider.dimensions}d)`);