@chude/memory 4.0.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 (184) hide show
  1. package/README.md +294 -0
  2. package/dist/application/index.d.ts +6 -0
  3. package/dist/application/services/ambient-context-service.d.ts +90 -0
  4. package/dist/application/services/backfill-service.d.ts +71 -0
  5. package/dist/application/services/budget-allocator.d.ts +57 -0
  6. package/dist/application/services/embedding-service.d.ts +131 -0
  7. package/dist/application/services/export-service.d.ts +225 -0
  8. package/dist/application/services/extraction-pipeline.d.ts +50 -0
  9. package/dist/application/services/friction-service.d.ts +148 -0
  10. package/dist/application/services/fts-sanitizer.d.ts +25 -0
  11. package/dist/application/services/index.d.ts +34 -0
  12. package/dist/application/services/llm-extractor.d.ts +96 -0
  13. package/dist/application/services/memory-file-sync-service.d.ts +58 -0
  14. package/dist/application/services/pattern-extractor.d.ts +95 -0
  15. package/dist/application/services/recovery-service.d.ts +81 -0
  16. package/dist/application/services/rrf-fusion.d.ts +53 -0
  17. package/dist/application/services/smart-context-service.d.ts +126 -0
  18. package/dist/application/services/sync-service.d.ts +157 -0
  19. package/dist/application/services/temporal-decay.d.ts +62 -0
  20. package/dist/domain/entities/backfill-state.d.ts +56 -0
  21. package/dist/domain/entities/entity.d.ts +131 -0
  22. package/dist/domain/entities/extraction-state.d.ts +128 -0
  23. package/dist/domain/entities/fact.d.ts +59 -0
  24. package/dist/domain/entities/friction-entry.d.ts +84 -0
  25. package/dist/domain/entities/index.d.ts +15 -0
  26. package/dist/domain/entities/link.d.ts +74 -0
  27. package/dist/domain/entities/memory-file.d.ts +78 -0
  28. package/dist/domain/entities/message.d.ts +70 -0
  29. package/dist/domain/entities/session.d.ts +93 -0
  30. package/dist/domain/entities/tool-use.d.ts +85 -0
  31. package/dist/domain/errors/error-codes.d.ts +37 -0
  32. package/dist/domain/errors/index.d.ts +8 -0
  33. package/dist/domain/errors/memory-error.d.ts +52 -0
  34. package/dist/domain/errors/unknown-error.d.ts +9 -0
  35. package/dist/domain/index.d.ts +11 -0
  36. package/dist/domain/ports/embedding.d.ts +96 -0
  37. package/dist/domain/ports/extraction.d.ts +13 -0
  38. package/dist/domain/ports/index.d.ts +14 -0
  39. package/dist/domain/ports/redactor.d.ts +17 -0
  40. package/dist/domain/ports/repositories.d.ts +658 -0
  41. package/dist/domain/ports/services.d.ts +180 -0
  42. package/dist/domain/ports/signals.d.ts +82 -0
  43. package/dist/domain/ports/sources.d.ts +122 -0
  44. package/dist/domain/ports/types.d.ts +150 -0
  45. package/dist/domain/services/content-extractor.d.ts +61 -0
  46. package/dist/domain/services/index.d.ts +8 -0
  47. package/dist/domain/services/path-decoder.d.ts +56 -0
  48. package/dist/domain/services/query-parser.d.ts +47 -0
  49. package/dist/domain/value-objects/embedding-config.d.ts +56 -0
  50. package/dist/domain/value-objects/embedding-result.d.ts +46 -0
  51. package/dist/domain/value-objects/index.d.ts +10 -0
  52. package/dist/domain/value-objects/project-path.d.ts +92 -0
  53. package/dist/domain/value-objects/search-query.d.ts +30 -0
  54. package/dist/domain/value-objects/search-result.d.ts +92 -0
  55. package/dist/index.d.ts +15 -0
  56. package/dist/index.js +1548 -0
  57. package/dist/infrastructure/database/connection.d.ts +161 -0
  58. package/dist/infrastructure/database/event-log.d.ts +22 -0
  59. package/dist/infrastructure/database/health-checker.d.ts +248 -0
  60. package/dist/infrastructure/database/index.d.ts +11 -0
  61. package/dist/infrastructure/database/repositories/backfill-state-repository.d.ts +19 -0
  62. package/dist/infrastructure/database/repositories/embedding-repository.d.ts +121 -0
  63. package/dist/infrastructure/database/repositories/entity-repository.d.ts +73 -0
  64. package/dist/infrastructure/database/repositories/extraction-log-repository.d.ts +17 -0
  65. package/dist/infrastructure/database/repositories/extraction-state-repository.d.ts +52 -0
  66. package/dist/infrastructure/database/repositories/fact-repository.d.ts +25 -0
  67. package/dist/infrastructure/database/repositories/friction-repository.d.ts +41 -0
  68. package/dist/infrastructure/database/repositories/index.d.ts +17 -0
  69. package/dist/infrastructure/database/repositories/link-repository.d.ts +64 -0
  70. package/dist/infrastructure/database/repositories/memory-file-repository.d.ts +28 -0
  71. package/dist/infrastructure/database/repositories/message-repository.d.ts +87 -0
  72. package/dist/infrastructure/database/repositories/session-repository.d.ts +125 -0
  73. package/dist/infrastructure/database/repositories/tool-use-repository.d.ts +72 -0
  74. package/dist/infrastructure/database/schema.d.ts +203 -0
  75. package/dist/infrastructure/database/services/context-service.d.ts +93 -0
  76. package/dist/infrastructure/database/services/hybrid-search-service.d.ts +156 -0
  77. package/dist/infrastructure/database/services/index.d.ts +10 -0
  78. package/dist/infrastructure/database/services/search-service.d.ts +57 -0
  79. package/dist/infrastructure/database/services/stats-service.d.ts +36 -0
  80. package/dist/infrastructure/embedding/background-embedder.d.ts +125 -0
  81. package/dist/infrastructure/embedding/embedding-provider-factory.d.ts +44 -0
  82. package/dist/infrastructure/embedding/index.d.ts +5 -0
  83. package/dist/infrastructure/embedding/ollama-provider.d.ts +41 -0
  84. package/dist/infrastructure/embedding/openai-provider.d.ts +38 -0
  85. package/dist/infrastructure/embedding/transformers-js-provider.d.ts +34 -0
  86. package/dist/infrastructure/external/index.d.ts +7 -0
  87. package/dist/infrastructure/external/qmd-runner.d.ts +36 -0
  88. package/dist/infrastructure/hooks/auto-memory-writer.d.ts +52 -0
  89. package/dist/infrastructure/hooks/config-manager.d.ts +237 -0
  90. package/dist/infrastructure/hooks/git-syncer.d.ts +44 -0
  91. package/dist/infrastructure/hooks/hook-runner.d.ts +126 -0
  92. package/dist/infrastructure/hooks/index.d.ts +12 -0
  93. package/dist/infrastructure/hooks/log-writer.d.ts +106 -0
  94. package/dist/infrastructure/hooks/settings-manager.d.ts +163 -0
  95. package/dist/infrastructure/hooks/sync-hook-script.d.ts +83 -0
  96. package/dist/infrastructure/hooks/sync-logger-adapter.d.ts +17 -0
  97. package/dist/infrastructure/index.d.ts +11 -0
  98. package/dist/infrastructure/llm/anthropic-extractor.d.ts +20 -0
  99. package/dist/infrastructure/llm/claude-cli-extractor.d.ts +14 -0
  100. package/dist/infrastructure/llm/claude-summary-generator.d.ts +14 -0
  101. package/dist/infrastructure/llm/extraction-helper.d.ts +16 -0
  102. package/dist/infrastructure/llm/ollama-extractor.d.ts +20 -0
  103. package/dist/infrastructure/llm/openai-extractor.d.ts +23 -0
  104. package/dist/infrastructure/migration.d.ts +103 -0
  105. package/dist/infrastructure/parsers/event-classifier.d.ts +111 -0
  106. package/dist/infrastructure/parsers/index.d.ts +8 -0
  107. package/dist/infrastructure/parsers/jsonl-parser.d.ts +25 -0
  108. package/dist/infrastructure/parsers/timestamp.d.ts +18 -0
  109. package/dist/infrastructure/paths.d.ts +129 -0
  110. package/dist/infrastructure/providers/provider-defaults.d.ts +11 -0
  111. package/dist/infrastructure/providers/provider-registry.d.ts +28 -0
  112. package/dist/infrastructure/security/pattern-redactor.d.ts +6 -0
  113. package/dist/infrastructure/signals/adapters.d.ts +27 -0
  114. package/dist/infrastructure/signals/checkpoint-manager.d.ts +83 -0
  115. package/dist/infrastructure/signals/index.d.ts +8 -0
  116. package/dist/infrastructure/signals/signal-handler.d.ts +113 -0
  117. package/dist/infrastructure/sources/index.d.ts +8 -0
  118. package/dist/infrastructure/sources/memory-file-scanner.d.ts +23 -0
  119. package/dist/infrastructure/sources/project-name-resolver.d.ts +67 -0
  120. package/dist/infrastructure/sources/session-source.d.ts +70 -0
  121. package/dist/presentation/cli/command-result.d.ts +10 -0
  122. package/dist/presentation/cli/commands/_helpers/capture-json.d.ts +36 -0
  123. package/dist/presentation/cli/commands/_helpers/deprecation-warning.d.ts +41 -0
  124. package/dist/presentation/cli/commands/backfill.d.ts +56 -0
  125. package/dist/presentation/cli/commands/browse.d.ts +55 -0
  126. package/dist/presentation/cli/commands/completion.d.ts +61 -0
  127. package/dist/presentation/cli/commands/context.d.ts +53 -0
  128. package/dist/presentation/cli/commands/doctor.d.ts +55 -0
  129. package/dist/presentation/cli/commands/export.d.ts +36 -0
  130. package/dist/presentation/cli/commands/extract.d.ts +40 -0
  131. package/dist/presentation/cli/commands/facts.d.ts +17 -0
  132. package/dist/presentation/cli/commands/friction/dashboard.d.ts +18 -0
  133. package/dist/presentation/cli/commands/friction/index.d.ts +12 -0
  134. package/dist/presentation/cli/commands/friction/list.d.ts +12 -0
  135. package/dist/presentation/cli/commands/friction/log.d.ts +12 -0
  136. package/dist/presentation/cli/commands/friction/purge.d.ts +12 -0
  137. package/dist/presentation/cli/commands/friction/resolve.d.ts +12 -0
  138. package/dist/presentation/cli/commands/friction/types.d.ts +86 -0
  139. package/dist/presentation/cli/commands/friction/wontfix.d.ts +12 -0
  140. package/dist/presentation/cli/commands/import.d.ts +38 -0
  141. package/dist/presentation/cli/commands/index.d.ts +51 -0
  142. package/dist/presentation/cli/commands/install.d.ts +67 -0
  143. package/dist/presentation/cli/commands/list.d.ts +61 -0
  144. package/dist/presentation/cli/commands/migrate.d.ts +36 -0
  145. package/dist/presentation/cli/commands/purge.d.ts +100 -0
  146. package/dist/presentation/cli/commands/query.d.ts +51 -0
  147. package/dist/presentation/cli/commands/related.d.ts +47 -0
  148. package/dist/presentation/cli/commands/remote.d.ts +36 -0
  149. package/dist/presentation/cli/commands/search.d.ts +100 -0
  150. package/dist/presentation/cli/commands/show.d.ts +51 -0
  151. package/dist/presentation/cli/commands/stats.d.ts +38 -0
  152. package/dist/presentation/cli/commands/status.d.ts +152 -0
  153. package/dist/presentation/cli/commands/sync/ambient.d.ts +22 -0
  154. package/dist/presentation/cli/commands/sync/background.d.ts +23 -0
  155. package/dist/presentation/cli/commands/sync/embedding-pass.d.ts +32 -0
  156. package/dist/presentation/cli/commands/sync/helpers.d.ts +25 -0
  157. package/dist/presentation/cli/commands/sync/index.d.ts +17 -0
  158. package/dist/presentation/cli/commands/sync/memory-files.d.ts +26 -0
  159. package/dist/presentation/cli/commands/sync/types.d.ts +163 -0
  160. package/dist/presentation/cli/commands/uninstall.d.ts +44 -0
  161. package/dist/presentation/cli/db-startup.d.ts +61 -0
  162. package/dist/presentation/cli/formatters/ai-formatter.d.ts +38 -0
  163. package/dist/presentation/cli/formatters/color.d.ts +82 -0
  164. package/dist/presentation/cli/formatters/context-formatter.d.ts +55 -0
  165. package/dist/presentation/cli/formatters/dto-helpers.d.ts +176 -0
  166. package/dist/presentation/cli/formatters/envelope.d.ts +136 -0
  167. package/dist/presentation/cli/formatters/error-formatter.d.ts +41 -0
  168. package/dist/presentation/cli/formatters/friction-dashboard.d.ts +46 -0
  169. package/dist/presentation/cli/formatters/index.d.ts +17 -0
  170. package/dist/presentation/cli/formatters/list-formatter.d.ts +48 -0
  171. package/dist/presentation/cli/formatters/output-formatter.d.ts +98 -0
  172. package/dist/presentation/cli/formatters/related-formatter.d.ts +57 -0
  173. package/dist/presentation/cli/formatters/show-formatter.d.ts +63 -0
  174. package/dist/presentation/cli/formatters/stats-formatter.d.ts +54 -0
  175. package/dist/presentation/cli/formatters/text-width.d.ts +37 -0
  176. package/dist/presentation/cli/formatters/timestamp-formatter.d.ts +38 -0
  177. package/dist/presentation/cli/index.d.ts +10 -0
  178. package/dist/presentation/cli/index.js +1664 -0
  179. package/dist/presentation/cli/parsers/date-parser.d.ts +28 -0
  180. package/dist/presentation/cli/parsers/index.d.ts +6 -0
  181. package/dist/presentation/cli/pickers/index.d.ts +6 -0
  182. package/dist/presentation/cli/pickers/session-picker.d.ts +59 -0
  183. package/dist/presentation/cli/progress-reporter.d.ts +199 -0
  184. package/package.json +94 -0
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Hook Runner
3
+ *
4
+ * Background process spawner for sync operations.
5
+ * Spawns detached processes that survive parent termination.
6
+ *
7
+ * Also provides entity extraction for SessionStop hooks.
8
+ *
9
+ * Design:
10
+ * - Detached process runs in own process group
11
+ * - Parent can exit without waiting (unref)
12
+ * - Output redirected to sync.log for debugging
13
+ * - MEMORY_HOOK env var allows sync to detect hook invocation
14
+ * - Entity extraction runs after session sync when hook is triggered
15
+ */
16
+ import type { Database } from "bun:sqlite";
17
+ /**
18
+ * LogWriter interface for hook execution logging.
19
+ */
20
+ export interface LogWriter {
21
+ debug(message: string): void;
22
+ warn(message: string): void;
23
+ }
24
+ /**
25
+ * Options for spawnBackgroundSync
26
+ */
27
+ export interface SpawnOptions {
28
+ /** Override CLI command (default: "aidev") */
29
+ command?: string;
30
+ /** Include --quiet flag (default: true) */
31
+ quiet?: boolean;
32
+ /** Override log directory (for testing) */
33
+ logDir?: string;
34
+ }
35
+ /**
36
+ * Result of spawn operation
37
+ */
38
+ export interface SpawnResult {
39
+ /** Process ID of spawned child, or undefined if spawn failed */
40
+ pid: number | undefined;
41
+ }
42
+ /**
43
+ * Get the path to the sync log file
44
+ *
45
+ * @returns Path to logs/sync.log
46
+ */
47
+ export declare function getLogPath(): string;
48
+ /**
49
+ * Ensure the log directory exists
50
+ *
51
+ * Creates the directory recursively if it doesn't exist.
52
+ * Safe to call multiple times.
53
+ *
54
+ * @param logDir Optional custom log directory path
55
+ */
56
+ export declare function ensureLogDirectory(logDir?: string): void;
57
+ /**
58
+ * Spawn a background sync process for the given session
59
+ *
60
+ * Creates a detached child process that:
61
+ * - Runs independently of the parent process
62
+ * - Survives parent termination
63
+ * - Logs output to sync.log
64
+ *
65
+ * The spawned command runs:
66
+ * `aidev memory sync --session <sessionId> [--quiet]`
67
+ *
68
+ * Key implementation details:
69
+ * - detached: true - Process runs in own process group
70
+ * - stdio: Redirect stdout/stderr to log file (stdin ignored)
71
+ * - unref() - Parent can exit without waiting
72
+ * - MEMORY_HOOK=1 - Sync can detect hook invocation
73
+ *
74
+ * @param sessionId Session identifier to sync
75
+ * @param options Configuration options
76
+ * @returns Spawn result with PID (if successful)
77
+ */
78
+ export declare function spawnBackgroundSync(sessionId: string, options?: SpawnOptions): SpawnResult;
79
+ /**
80
+ * Result of entity extraction operation
81
+ */
82
+ export interface EntityExtractionResult {
83
+ /** Number of entities extracted and saved */
84
+ entitiesExtracted: number;
85
+ /** Whether extraction succeeded */
86
+ success: boolean;
87
+ /** Error message if extraction failed */
88
+ error?: string | undefined;
89
+ /** Session summary text (if extracted) */
90
+ summary?: string | undefined;
91
+ }
92
+ /**
93
+ * Options for entity extraction
94
+ */
95
+ export interface EntityExtractionOptions {
96
+ /** Log writer for debug output (optional) */
97
+ logWriter?: LogWriter;
98
+ }
99
+ /**
100
+ * Extract entities from a session using LLM.
101
+ *
102
+ * This function is called during SessionStop hook processing after
103
+ * messages have been synced. It:
104
+ * 1. Retrieves messages for the session
105
+ * 2. Uses LlmExtractor to extract entities
106
+ * 3. Persists entities via EntityRepository
107
+ * 4. Links entities to the session
108
+ *
109
+ * LLM extraction failures are logged but don't fail the sync.
110
+ *
111
+ * @param sessionId Session identifier
112
+ * @param db Database instance
113
+ * @param options Optional configuration
114
+ * @returns Extraction result with entity count
115
+ */
116
+ export declare function extractEntitiesFromSession(sessionId: string, db: Database, options?: EntityExtractionOptions): Promise<EntityExtractionResult>;
117
+ /**
118
+ * Check if the current process was invoked by a hook.
119
+ *
120
+ * The hook runner sets MEMORY_HOOK=1 when spawning sync processes.
121
+ * This allows the sync command to detect hook invocation and enable
122
+ * additional processing like LLM extraction.
123
+ *
124
+ * @returns true if invoked by hook, false otherwise
125
+ */
126
+ export declare function isInvokedByHook(): boolean;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Hooks Infrastructure Module
3
+ *
4
+ * Configuration management, logging, and hook runner for hook system.
5
+ * Exports config-manager, log-writer, and hook-runner utilities.
6
+ */
7
+ export { loadConfig, saveConfig, getConfigPath, getConfigDir, resolveEmbeddingApiKey, DEFAULT_CONFIG, DEFAULT_EMBEDDING_CONFIG, type MemoryConfig, type EmbeddingConfigData, type ApiKeyResolution, } from "./config-manager.js";
8
+ export { logSync, rotateLogsIfNeeded, readRecentLogs, getLogPath, getLogDir, type LogEntry, type LogEntryInput, } from "./log-writer.js";
9
+ export { spawnBackgroundSync, getLogPath as getHookLogPath, ensureLogDirectory, type SpawnOptions, type SpawnResult, } from "./hook-runner.js";
10
+ export { type HookInput, readStdinJson } from "./sync-hook-script.js";
11
+ export { FileSyncLogger } from "./sync-logger-adapter.js";
12
+ export { getClaudeSettingsPath, getBackupPath, getHookScriptPath, loadClaudeSettings, backupSettings, restoreFromBackup, installHooks, uninstallHooks, checkHooksInstalled, type HookEntry, type HookConfig, type ClaudeSettings, type HookStatus, type OperationResult, type PathOverrides, } from "./settings-manager.js";
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Log Writer
3
+ *
4
+ * Structured JSON log writer with rotation support.
5
+ * Logs stored at the XDG data path via centralized paths module.
6
+ *
7
+ * Features:
8
+ * - Append-only JSON lines format (machine-parseable)
9
+ * - Automatic directory creation
10
+ * - Date-based log rotation
11
+ * - Recent log reading for status display
12
+ *
13
+ * Each function accepts an optional `path` argument. When omitted, the
14
+ * production XDG-resolved path is used. When provided, that path is used
15
+ * directly (used by tests to point at a temp file). This avoids
16
+ * module-level mutable state and the test-pollution risk that comes with
17
+ * it; see scripts/check-test-isolation.ts.
18
+ */
19
+ /**
20
+ * Log entry structure for sync operations
21
+ *
22
+ * Includes all relevant fields for debugging and monitoring:
23
+ * - timestamp: ISO 8601 format
24
+ * - level: Log severity
25
+ * - message: Human-readable description
26
+ * - sessionId: Optional session identifier
27
+ * - durationMs: Optional operation duration
28
+ * - error: Optional error message
29
+ * - hookEvent: Optional hook trigger (SessionEnd or PreCompact)
30
+ */
31
+ export interface LogEntry {
32
+ /** ISO 8601 timestamp */
33
+ timestamp: string;
34
+ /** Log severity level */
35
+ level: "debug" | "info" | "warn" | "error";
36
+ /** Human-readable message */
37
+ message: string;
38
+ /** Session identifier (if applicable) */
39
+ sessionId?: string | undefined;
40
+ /** Operation duration in milliseconds */
41
+ durationMs?: number | undefined;
42
+ /** Error message (if applicable) */
43
+ error?: string | undefined;
44
+ /** Hook event that triggered this (SessionEnd or PreCompact) */
45
+ hookEvent?: string | undefined;
46
+ }
47
+ /**
48
+ * Input type for logSync (timestamp added automatically)
49
+ */
50
+ export type LogEntryInput = Omit<LogEntry, "timestamp">;
51
+ /**
52
+ * Get the directory containing the log file.
53
+ *
54
+ * @param logPathOverride Optional explicit log file path. The directory
55
+ * is derived from this path. Used by tests.
56
+ * @returns Path to the logs directory
57
+ */
58
+ export declare function getLogDir(logPathOverride?: string): string;
59
+ /**
60
+ * Get the path to the sync log file.
61
+ *
62
+ * @param logPathOverride Optional explicit log file path. Used by tests.
63
+ * @returns Path to sync.log
64
+ */
65
+ export declare function getLogPath(logPathOverride?: string): string;
66
+ /**
67
+ * Write a log entry to the sync log
68
+ *
69
+ * Creates the log directory if it doesn't exist.
70
+ * Adds timestamp automatically in ISO 8601 format.
71
+ * Appends as JSON line (newline-delimited JSON).
72
+ *
73
+ * Handles write errors gracefully to never break sync operations.
74
+ *
75
+ * @param entry Log entry data (without timestamp)
76
+ * @param logPathOverride Optional explicit log file path (used by tests)
77
+ */
78
+ export declare function logSync(entry: LogEntryInput, logPathOverride?: string): void;
79
+ /**
80
+ * Rotate logs if they exceed the retention period
81
+ *
82
+ * Checks the sync.log file modification time.
83
+ * If older than retentionDays, renames to sync.log.YYYY-MM-DD.
84
+ * This clears the main log for fresh writes.
85
+ *
86
+ * Handles missing file gracefully (no-op).
87
+ *
88
+ * @param retentionDays Number of days before rotation
89
+ * @param logPathOverride Optional explicit log file path (used by tests)
90
+ */
91
+ export declare function rotateLogsIfNeeded(retentionDays: number, logPathOverride?: string): void;
92
+ /**
93
+ * Read recent log entries for status display
94
+ *
95
+ * Reads the sync.log file and parses JSON lines.
96
+ * Returns the last `limit` entries.
97
+ *
98
+ * Handles gracefully:
99
+ * - Missing file (returns empty array)
100
+ * - Malformed lines (skips them)
101
+ *
102
+ * @param limit Maximum number of entries to return (default 100)
103
+ * @param logPathOverride Optional explicit log file path (used by tests)
104
+ * @returns Array of parsed log entries
105
+ */
106
+ export declare function readRecentLogs(limit?: number, logPathOverride?: string): LogEntry[];
@@ -0,0 +1,163 @@
1
+ /**
2
+ * Settings Manager
3
+ *
4
+ * Safe manipulation of Claude Code settings.json for hook installation.
5
+ * Provides backup/restore capabilities and idempotent operations.
6
+ *
7
+ * Features:
8
+ * - Install hooks into ~/.claude/settings.json
9
+ * - Create backups before modifications
10
+ * - Restore from backup on uninstall
11
+ * - Check installation status
12
+ * - Idempotent installation (won't duplicate)
13
+ */
14
+ /**
15
+ * Hook entry in Claude Code settings
16
+ */
17
+ export interface HookEntry {
18
+ /** Hook type - always "command" for shell commands */
19
+ type: "command";
20
+ /** Shell command to execute */
21
+ command: string;
22
+ /** Timeout in seconds */
23
+ timeout?: number;
24
+ }
25
+ /**
26
+ * Hook configuration block
27
+ */
28
+ export interface HookConfig {
29
+ /** Matcher for PreCompact: "auto" or "manual" */
30
+ matcher?: string;
31
+ /** Array of hook entries */
32
+ hooks: HookEntry[];
33
+ }
34
+ /**
35
+ * Claude Code settings.json structure
36
+ */
37
+ export interface ClaudeSettings {
38
+ /** Hook configurations by event name */
39
+ hooks?: {
40
+ /** SessionEnd hook configurations */
41
+ SessionEnd?: HookConfig[];
42
+ /** PreCompact hook configurations */
43
+ PreCompact?: HookConfig[];
44
+ /** Other hook types */
45
+ [key: string]: HookConfig[] | undefined;
46
+ };
47
+ /** Other settings */
48
+ [key: string]: unknown;
49
+ }
50
+ /**
51
+ * Hook installation status
52
+ */
53
+ export interface HookStatus {
54
+ /** SessionEnd hook is installed */
55
+ sessionEnd: boolean;
56
+ /** PreCompact hook is installed */
57
+ preCompact: boolean;
58
+ /** Hook script file exists */
59
+ hookScriptExists: boolean;
60
+ /** Backup file exists */
61
+ backupExists: boolean;
62
+ }
63
+ /**
64
+ * Operation result
65
+ */
66
+ export interface OperationResult {
67
+ /** Operation succeeded */
68
+ success: boolean;
69
+ /** Human-readable message */
70
+ message: string;
71
+ }
72
+ /**
73
+ * Path overrides for testing
74
+ *
75
+ * When set, these paths will be used instead of the default locations.
76
+ * This allows tests to operate in isolated directories.
77
+ */
78
+ export interface PathOverrides {
79
+ /** Override ~/.claude/settings.json */
80
+ settingsPath?: string;
81
+ /** Override backups/settings.json.backup */
82
+ backupPath?: string;
83
+ /** Override hooks/sync-hook.js */
84
+ hookScriptPath?: string;
85
+ }
86
+ /**
87
+ * Get the path to Claude Code settings.json.
88
+ *
89
+ * @param overrides Optional path overrides (used by tests)
90
+ * @returns Path to ~/.claude/settings.json
91
+ */
92
+ export declare function getClaudeSettingsPath(overrides?: PathOverrides): string;
93
+ /**
94
+ * Get the path to the settings backup file.
95
+ *
96
+ * @param overrides Optional path overrides (used by tests)
97
+ * @returns Path to backups/settings.json.backup
98
+ */
99
+ export declare function getBackupPath(overrides?: PathOverrides): string;
100
+ /**
101
+ * Get the path to the hook script.
102
+ *
103
+ * @param overrides Optional path overrides (used by tests)
104
+ * @returns Path to hooks/sync-hook.js
105
+ */
106
+ export declare function getHookScriptPath(overrides?: PathOverrides): string;
107
+ /**
108
+ * Load Claude Code settings from disk
109
+ *
110
+ * Returns empty object if file doesn't exist or is invalid.
111
+ *
112
+ * @returns Parsed settings object
113
+ */
114
+ export declare function loadClaudeSettings(overrides?: PathOverrides): ClaudeSettings;
115
+ /**
116
+ * Backup current settings.json
117
+ *
118
+ * Creates a copy of the current settings to the backups directory.
119
+ * Safe to call even if settings don't exist.
120
+ *
121
+ * @returns true if backup was created, false if no settings to backup
122
+ */
123
+ export declare function backupSettings(overrides?: PathOverrides): boolean;
124
+ /**
125
+ * Restore settings.json from backup
126
+ *
127
+ * Replaces current settings with the backup copy.
128
+ * Safe to call even if backup doesn't exist.
129
+ *
130
+ * @returns true if restore was successful, false if no backup exists
131
+ */
132
+ export declare function restoreFromBackup(overrides?: PathOverrides): boolean;
133
+ /**
134
+ * Install memory hooks into Claude Code settings
135
+ *
136
+ * Adds SessionEnd and PreCompact hooks to settings.json.
137
+ * Creates backup before modifying.
138
+ * Idempotent - won't duplicate if already installed.
139
+ *
140
+ * @returns Operation result with success status and message
141
+ */
142
+ export declare function installHooks(overrides?: PathOverrides): OperationResult;
143
+ /**
144
+ * Uninstall memory hooks from Claude Code settings
145
+ *
146
+ * Removes SessionEnd and PreCompact hooks containing the memory marker.
147
+ * Preserves other hooks and settings.
148
+ *
149
+ * @returns Operation result with success status and message
150
+ */
151
+ export declare function uninstallHooks(overrides?: PathOverrides): OperationResult;
152
+ /**
153
+ * Check if memory hooks are installed
154
+ *
155
+ * Returns status of each component:
156
+ * - SessionEnd hook in settings.json
157
+ * - PreCompact hook in settings.json
158
+ * - Hook script file exists
159
+ * - Backup file exists
160
+ *
161
+ * @returns Hook installation status
162
+ */
163
+ export declare function checkHooksInstalled(overrides?: PathOverrides): HookStatus;
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * Sync Hook Script
4
+ *
5
+ * Entry point for Claude Code hooks (SessionEnd, PreCompact).
6
+ * Reads hook input from stdin, checks configuration, and spawns
7
+ * background sync process.
8
+ *
9
+ * Design:
10
+ * - Always exits 0 (never blocks Claude Code)
11
+ * - Logs all operations for debugging
12
+ * - Checks config before processing
13
+ * - Graceful handling of missing session_id
14
+ * - Hook event name tracked in logs
15
+ *
16
+ * Usage in settings.json:
17
+ * ```json
18
+ * {
19
+ * "hooks": {
20
+ * "SessionEnd": [{
21
+ * "hooks": [{
22
+ * "type": "command",
23
+ * "command": "bun ~/.local/share/memory/hooks/sync-hook.js",
24
+ * "timeout": 5
25
+ * }]
26
+ * }]
27
+ * }
28
+ * }
29
+ * ```
30
+ */
31
+ import type { MemoryConfig } from "./config-manager.js";
32
+ import { logSync } from "./log-writer.js";
33
+ import { spawnBackgroundSync } from "./hook-runner.js";
34
+ /**
35
+ * Hook input from Claude Code
36
+ *
37
+ * Sent via stdin as JSON when hooks fire.
38
+ * Fields vary by hook event type.
39
+ */
40
+ export interface HookInput {
41
+ /** Session identifier */
42
+ session_id?: string;
43
+ /** Path to session JSONL transcript */
44
+ transcript_path?: string;
45
+ /** Which hook event fired */
46
+ hook_event_name: string;
47
+ /** SessionEnd reason: "clear", "logout", "prompt_input_exit", "other" */
48
+ reason?: string;
49
+ /** PreCompact trigger: "manual" or "auto" */
50
+ trigger?: string;
51
+ /** Current working directory */
52
+ cwd?: string;
53
+ /** Permission mode ("default", etc.) */
54
+ permission_mode?: string;
55
+ }
56
+ export interface SyncHookDeps {
57
+ loadConfig: () => MemoryConfig;
58
+ readInput: () => Promise<HookInput>;
59
+ log: typeof logSync;
60
+ spawnSync: typeof spawnBackgroundSync;
61
+ writeStdout: (message: string) => void;
62
+ exit: (code: number) => void;
63
+ }
64
+ /**
65
+ * Read JSON from stdin
66
+ *
67
+ * Collects all chunks until EOF, then parses as JSON.
68
+ * Handles errors gracefully.
69
+ *
70
+ * @returns Parsed hook input
71
+ * @throws Error if stdin is empty or JSON is invalid
72
+ */
73
+ type HookInputStream = Pick<NodeJS.ReadStream, "setEncoding" | "on">;
74
+ export declare function readJsonFromStream(stream: HookInputStream): Promise<HookInput>;
75
+ export declare function readStdinJson(): Promise<HookInput>;
76
+ export declare function createDefaultSyncHookDeps(): SyncHookDeps;
77
+ export declare function executeSyncHook(deps: SyncHookDeps): Promise<void>;
78
+ export declare function runSyncHookMain(deps?: SyncHookDeps, onFatal?: (entry: {
79
+ level: "error";
80
+ message: string;
81
+ error?: string | undefined;
82
+ }) => void): Promise<void>;
83
+ export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Domain Port Adapter for Sync Logging
3
+ *
4
+ * Wraps the logSync() free function from log-writer into a
5
+ * class-based adapter implementing the ISyncLogger domain port.
6
+ */
7
+ import type { ISyncLogger } from "../../domain/ports/signals.js";
8
+ type SyncLogEntry = Parameters<ISyncLogger["log"]>[0];
9
+ /**
10
+ * Adapter wrapping the file-based structured logger.
11
+ */
12
+ export declare class FileSyncLogger implements ISyncLogger {
13
+ private readonly writeLog;
14
+ constructor(writeLog?: (entry: SyncLogEntry) => void);
15
+ log(entry: SyncLogEntry): void;
16
+ }
17
+ export {};
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Infrastructure Layer
3
+ *
4
+ * Adapters implementing domain ports.
5
+ * Database, filesystem, and external service integrations.
6
+ */
7
+ export * from "./database/index.js";
8
+ export * from "./hooks/index.js";
9
+ export * from "./parsers/index.js";
10
+ export * from "./signals/index.js";
11
+ export * from "./sources/index.js";
@@ -0,0 +1,20 @@
1
+ /**
2
+ * AnthropicExtractionProvider
3
+ *
4
+ * Infrastructure adapter connecting directly to the Anthropic API
5
+ * using the official SDK.
6
+ */
7
+ import type { IExtractionProvider } from "../../domain/ports/extraction.js";
8
+ import type { Message } from "../../domain/entities/message.js";
9
+ import type { CandidateFact } from "../../domain/entities/fact.js";
10
+ export interface AnthropicExtractorConfig {
11
+ apiKey: string;
12
+ model?: string | undefined;
13
+ }
14
+ export declare class AnthropicExtractionProvider implements IExtractionProvider {
15
+ readonly providerId = "anthropic";
16
+ readonly modelName: string;
17
+ private readonly anthropic;
18
+ constructor(config: AnthropicExtractorConfig);
19
+ extract(messages: Message[]): Promise<CandidateFact[]>;
20
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * ClaudeCliExtractionProvider
3
+ *
4
+ * Infrastructure adapter that shells out to claude -p (print mode)
5
+ * within active Claude Code environments to perform structured fact extraction.
6
+ */
7
+ import type { IExtractionProvider } from "../../domain/ports/extraction.js";
8
+ import type { Message } from "../../domain/entities/message.js";
9
+ import type { CandidateFact } from "../../domain/entities/fact.js";
10
+ export declare class ClaudeCliExtractionProvider implements IExtractionProvider {
11
+ readonly providerId = "claude-cli";
12
+ readonly modelName = "claude-cli-print";
13
+ extract(messages: Message[]): Promise<CandidateFact[]>;
14
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * ClaudeSummaryGenerator
3
+ *
4
+ * Infrastructure adapter that shells out to claude -p (print mode)
5
+ * for generating structured daily log summaries from session content.
6
+ *
7
+ * Strips CLAUDECODE env var to prevent nested session detection
8
+ * when running inside a Claude Code session.
9
+ */
10
+ import type { ISummaryGenerator } from "../../domain/ports/index.js";
11
+ export declare class ClaudeSummaryGenerator implements ISummaryGenerator {
12
+ generateSummary(content: string, sessionId: string, projectName: string, startTime: string, endTime: string): Promise<string>;
13
+ private buildPrompt;
14
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Extraction Helper
3
+ *
4
+ * Common functions for preparing fact-extraction prompts and robustly parsing
5
+ * structured JSON arrays from LLM response texts.
6
+ */
7
+ import type { Message } from "../../domain/entities/message.js";
8
+ import type { CandidateFact } from "../../domain/entities/fact.js";
9
+ /**
10
+ * Builds the standardized fact extraction instruction prompt.
11
+ */
12
+ export declare function buildExtractionPrompt(messages: Message[]): string;
13
+ /**
14
+ * Robustly parses and cleans a JSON array of CandidateFacts from the raw LLM output.
15
+ */
16
+ export declare function parseLlmResponse(text: string): CandidateFact[];
@@ -0,0 +1,20 @@
1
+ /**
2
+ * OllamaExtractionProvider
3
+ *
4
+ * Infrastructure adapter connecting to local Ollama API completions endpoint
5
+ * via standard fetch request.
6
+ */
7
+ import type { IExtractionProvider } from "../../domain/ports/extraction.js";
8
+ import type { Message } from "../../domain/entities/message.js";
9
+ import type { CandidateFact } from "../../domain/entities/fact.js";
10
+ export interface OllamaExtractorConfig {
11
+ baseUrl?: string | undefined;
12
+ model?: string | undefined;
13
+ }
14
+ export declare class OllamaExtractionProvider implements IExtractionProvider {
15
+ readonly providerId = "ollama";
16
+ readonly modelName: string;
17
+ private readonly baseUrl;
18
+ constructor(config: OllamaExtractorConfig);
19
+ extract(messages: Message[]): Promise<CandidateFact[]>;
20
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * OpenAiExtractionProvider
3
+ *
4
+ * Infrastructure adapter connecting to OpenAI Chat Completions endpoint
5
+ * via standard fetch request.
6
+ */
7
+ import type { IExtractionProvider } from "../../domain/ports/extraction.js";
8
+ import type { Message } from "../../domain/entities/message.js";
9
+ import type { CandidateFact } from "../../domain/entities/fact.js";
10
+ export interface OpenAiExtractorConfig {
11
+ apiKey: string;
12
+ model?: string | undefined;
13
+ baseUrl?: string | undefined;
14
+ providerId?: string | undefined;
15
+ }
16
+ export declare class OpenAiExtractionProvider implements IExtractionProvider {
17
+ readonly providerId: string;
18
+ readonly modelName: string;
19
+ private readonly apiKey;
20
+ private readonly baseUrl;
21
+ constructor(config: OpenAiExtractorConfig);
22
+ extract(messages: Message[]): Promise<CandidateFact[]>;
23
+ }