lifeos 1.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 (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +202 -0
  3. package/README.md +202 -0
  4. package/assets/lifeos-rules.en.md +162 -0
  5. package/assets/lifeos-rules.zh.md +162 -0
  6. package/assets/lifeos.yaml +56 -0
  7. package/assets/prompts/AI_LLMResearch_Prompt.en.md +120 -0
  8. package/assets/prompts/AI_LLMResearch_Prompt.zh.md +120 -0
  9. package/assets/prompts/Art_ChinesePainting_Prompt.en.md +147 -0
  10. package/assets/prompts/Art_ChinesePainting_Prompt.zh.md +148 -0
  11. package/assets/prompts/Cryptography_Prompt.en.md +148 -0
  12. package/assets/prompts/Cryptography_Prompt.zh.md +147 -0
  13. package/assets/prompts/History_ChineseCulture_Prompt.en.md +98 -0
  14. package/assets/prompts/History_ChineseCulture_Prompt.zh.md +98 -0
  15. package/assets/prompts/Math_HigherMathematics_Prompt.en.md +117 -0
  16. package/assets/prompts/Math_HigherMathematics_Prompt.zh.md +116 -0
  17. package/assets/schema/Frontmatter_Schema.md +139 -0
  18. package/assets/skills/_shared/completion-report.en.md +30 -0
  19. package/assets/skills/_shared/completion-report.zh.md +30 -0
  20. package/assets/skills/_shared/dual-agent-orchestrator.en.md +40 -0
  21. package/assets/skills/_shared/dual-agent-orchestrator.zh.md +40 -0
  22. package/assets/skills/_shared/learning-lifecycle.en.md +53 -0
  23. package/assets/skills/_shared/learning-lifecycle.zh.md +53 -0
  24. package/assets/skills/_shared/lifecycle.en.md +84 -0
  25. package/assets/skills/_shared/lifecycle.zh.md +84 -0
  26. package/assets/skills/_shared/memory-protocol.en.md +36 -0
  27. package/assets/skills/_shared/memory-protocol.zh.md +36 -0
  28. package/assets/skills/_shared/template-loading.en.md +26 -0
  29. package/assets/skills/_shared/template-loading.zh.md +26 -0
  30. package/assets/skills/archive/SKILL.en.md +300 -0
  31. package/assets/skills/archive/SKILL.zh.md +300 -0
  32. package/assets/skills/ask/SKILL.en.md +164 -0
  33. package/assets/skills/ask/SKILL.zh.md +164 -0
  34. package/assets/skills/brainstorm/SKILL.en.md +242 -0
  35. package/assets/skills/brainstorm/SKILL.zh.md +242 -0
  36. package/assets/skills/brainstorm/references/action-options.en.md +65 -0
  37. package/assets/skills/brainstorm/references/action-options.zh.md +65 -0
  38. package/assets/skills/knowledge/SKILL.en.md +202 -0
  39. package/assets/skills/knowledge/SKILL.zh.md +202 -0
  40. package/assets/skills/project/SKILL.en.md +133 -0
  41. package/assets/skills/project/SKILL.zh.md +133 -0
  42. package/assets/skills/project/references/execution-agent-prompt.en.md +148 -0
  43. package/assets/skills/project/references/execution-agent-prompt.zh.md +148 -0
  44. package/assets/skills/project/references/planning-agent-prompt.en.md +162 -0
  45. package/assets/skills/project/references/planning-agent-prompt.zh.md +162 -0
  46. package/assets/skills/read-pdf/SKILL.en.md +199 -0
  47. package/assets/skills/read-pdf/SKILL.zh.md +199 -0
  48. package/assets/skills/read-pdf/scripts/read_pdf.py +354 -0
  49. package/assets/skills/research/SKILL.en.md +107 -0
  50. package/assets/skills/research/SKILL.zh.md +107 -0
  51. package/assets/skills/research/references/execution-agent-prompt.en.md +166 -0
  52. package/assets/skills/research/references/execution-agent-prompt.zh.md +166 -0
  53. package/assets/skills/research/references/planning-agent-prompt.en.md +129 -0
  54. package/assets/skills/research/references/planning-agent-prompt.zh.md +129 -0
  55. package/assets/skills/revise/SKILL.en.md +258 -0
  56. package/assets/skills/revise/SKILL.zh.md +258 -0
  57. package/assets/skills/revise/references/grading-protocol.en.md +99 -0
  58. package/assets/skills/revise/references/grading-protocol.zh.md +99 -0
  59. package/assets/skills/today/SKILL.en.md +211 -0
  60. package/assets/skills/today/SKILL.zh.md +211 -0
  61. package/assets/templates/en/Daily_Template.md +25 -0
  62. package/assets/templates/en/Draft_Template.md +29 -0
  63. package/assets/templates/en/Knowledge_Template.md +86 -0
  64. package/assets/templates/en/Project_Template.md +110 -0
  65. package/assets/templates/en/Research_Template.md +46 -0
  66. package/assets/templates/en/Retrospective_Template.md +89 -0
  67. package/assets/templates/en/Revise_Template.md +24 -0
  68. package/assets/templates/en/Wiki_Template.md +35 -0
  69. package/assets/templates/zh/Daily_Template.md +26 -0
  70. package/assets/templates/zh/Draft_Template.md +29 -0
  71. package/assets/templates/zh/Knowledge_Template.md +86 -0
  72. package/assets/templates/zh/Project_Template.md +110 -0
  73. package/assets/templates/zh/Research_Template.md +46 -0
  74. package/assets/templates/zh/Retrospective_Template.md +89 -0
  75. package/assets/templates/zh/Revise_Template.md +24 -0
  76. package/assets/templates/zh/Wiki_Template.md +35 -0
  77. package/bin/lifeos.js +24 -0
  78. package/dist/active-docs/citations.d.ts +20 -0
  79. package/dist/active-docs/citations.js +74 -0
  80. package/dist/active-docs/citations.js.map +1 -0
  81. package/dist/active-docs/derived-memory.d.ts +57 -0
  82. package/dist/active-docs/derived-memory.js +161 -0
  83. package/dist/active-docs/derived-memory.js.map +1 -0
  84. package/dist/active-docs/index.d.ts +51 -0
  85. package/dist/active-docs/index.js +165 -0
  86. package/dist/active-docs/index.js.map +1 -0
  87. package/dist/active-docs/long-term-profile.d.ts +24 -0
  88. package/dist/active-docs/long-term-profile.js +75 -0
  89. package/dist/active-docs/long-term-profile.js.map +1 -0
  90. package/dist/active-docs/taskboard.d.ts +12 -0
  91. package/dist/active-docs/taskboard.js +146 -0
  92. package/dist/active-docs/taskboard.js.map +1 -0
  93. package/dist/active-docs/userprofile.d.ts +12 -0
  94. package/dist/active-docs/userprofile.js +169 -0
  95. package/dist/active-docs/userprofile.js.map +1 -0
  96. package/dist/cli/commands/doctor.d.ts +9 -0
  97. package/dist/cli/commands/doctor.js +125 -0
  98. package/dist/cli/commands/doctor.js.map +1 -0
  99. package/dist/cli/commands/init.d.ts +1 -0
  100. package/dist/cli/commands/init.js +129 -0
  101. package/dist/cli/commands/init.js.map +1 -0
  102. package/dist/cli/commands/rename.d.ts +7 -0
  103. package/dist/cli/commands/rename.js +188 -0
  104. package/dist/cli/commands/rename.js.map +1 -0
  105. package/dist/cli/commands/upgrade.d.ts +6 -0
  106. package/dist/cli/commands/upgrade.js +66 -0
  107. package/dist/cli/commands/upgrade.js.map +1 -0
  108. package/dist/cli/index.d.ts +1 -0
  109. package/dist/cli/index.js +52 -0
  110. package/dist/cli/index.js.map +1 -0
  111. package/dist/cli/utils/assets.d.ts +3 -0
  112. package/dist/cli/utils/assets.js +20 -0
  113. package/dist/cli/utils/assets.js.map +1 -0
  114. package/dist/cli/utils/install-assets.d.ts +39 -0
  115. package/dist/cli/utils/install-assets.js +141 -0
  116. package/dist/cli/utils/install-assets.js.map +1 -0
  117. package/dist/cli/utils/lang.d.ts +1 -0
  118. package/dist/cli/utils/lang.js +32 -0
  119. package/dist/cli/utils/lang.js.map +1 -0
  120. package/dist/cli/utils/managed-assets.d.ts +9 -0
  121. package/dist/cli/utils/managed-assets.js +20 -0
  122. package/dist/cli/utils/managed-assets.js.map +1 -0
  123. package/dist/cli/utils/mcp-register.d.ts +2 -0
  124. package/dist/cli/utils/mcp-register.js +132 -0
  125. package/dist/cli/utils/mcp-register.js.map +1 -0
  126. package/dist/cli/utils/sync-vault.d.ts +14 -0
  127. package/dist/cli/utils/sync-vault.js +132 -0
  128. package/dist/cli/utils/sync-vault.js.map +1 -0
  129. package/dist/cli/utils/ui.d.ts +14 -0
  130. package/dist/cli/utils/ui.js +78 -0
  131. package/dist/cli/utils/ui.js.map +1 -0
  132. package/dist/cli/utils/version.d.ts +1 -0
  133. package/dist/cli/utils/version.js +4 -0
  134. package/dist/cli/utils/version.js.map +1 -0
  135. package/dist/config.d.ts +127 -0
  136. package/dist/config.js +356 -0
  137. package/dist/config.js.map +1 -0
  138. package/dist/core.d.ts +106 -0
  139. package/dist/core.js +286 -0
  140. package/dist/core.js.map +1 -0
  141. package/dist/db/consolidation.d.ts +14 -0
  142. package/dist/db/consolidation.js +28 -0
  143. package/dist/db/consolidation.js.map +1 -0
  144. package/dist/db/index.d.ts +22 -0
  145. package/dist/db/index.js +39 -0
  146. package/dist/db/index.js.map +1 -0
  147. package/dist/db/schema.d.ts +7 -0
  148. package/dist/db/schema.js +175 -0
  149. package/dist/db/schema.js.map +1 -0
  150. package/dist/index.d.ts +3 -0
  151. package/dist/index.js +5 -0
  152. package/dist/index.js.map +1 -0
  153. package/dist/server.d.ts +6 -0
  154. package/dist/server.js +303 -0
  155. package/dist/server.js.map +1 -0
  156. package/dist/services/capture.d.ts +101 -0
  157. package/dist/services/capture.js +297 -0
  158. package/dist/services/capture.js.map +1 -0
  159. package/dist/services/enhance.d.ts +51 -0
  160. package/dist/services/enhance.js +184 -0
  161. package/dist/services/enhance.js.map +1 -0
  162. package/dist/services/layer0.d.ts +24 -0
  163. package/dist/services/layer0.js +90 -0
  164. package/dist/services/layer0.js.map +1 -0
  165. package/dist/services/maintenance.d.ts +27 -0
  166. package/dist/services/maintenance.js +73 -0
  167. package/dist/services/maintenance.js.map +1 -0
  168. package/dist/services/retrieval.d.ts +120 -0
  169. package/dist/services/retrieval.js +571 -0
  170. package/dist/services/retrieval.js.map +1 -0
  171. package/dist/services/startup.d.ts +28 -0
  172. package/dist/services/startup.js +112 -0
  173. package/dist/services/startup.js.map +1 -0
  174. package/dist/skill-context/ask-global.d.ts +8 -0
  175. package/dist/skill-context/ask-global.js +21 -0
  176. package/dist/skill-context/ask-global.js.map +1 -0
  177. package/dist/skill-context/base.d.ts +48 -0
  178. package/dist/skill-context/base.js +5 -0
  179. package/dist/skill-context/base.js.map +1 -0
  180. package/dist/skill-context/daily-global.d.ts +8 -0
  181. package/dist/skill-context/daily-global.js +25 -0
  182. package/dist/skill-context/daily-global.js.map +1 -0
  183. package/dist/skill-context/index.d.ts +32 -0
  184. package/dist/skill-context/index.js +171 -0
  185. package/dist/skill-context/index.js.map +1 -0
  186. package/dist/skill-context/knowledge-strict.d.ts +8 -0
  187. package/dist/skill-context/knowledge-strict.js +26 -0
  188. package/dist/skill-context/knowledge-strict.js.map +1 -0
  189. package/dist/skill-context/review-strict.d.ts +8 -0
  190. package/dist/skill-context/review-strict.js +26 -0
  191. package/dist/skill-context/review-strict.js.map +1 -0
  192. package/dist/skill-context/revise-strict.d.ts +8 -0
  193. package/dist/skill-context/revise-strict.js +26 -0
  194. package/dist/skill-context/revise-strict.js.map +1 -0
  195. package/dist/skill-context/seed-profiles.d.ts +21 -0
  196. package/dist/skill-context/seed-profiles.js +80 -0
  197. package/dist/skill-context/seed-profiles.js.map +1 -0
  198. package/dist/types.d.ts +165 -0
  199. package/dist/types.js +76 -0
  200. package/dist/types.js.map +1 -0
  201. package/dist/utils/context-policy.d.ts +57 -0
  202. package/dist/utils/context-policy.js +333 -0
  203. package/dist/utils/context-policy.js.map +1 -0
  204. package/dist/utils/scan-state.d.ts +41 -0
  205. package/dist/utils/scan-state.js +79 -0
  206. package/dist/utils/scan-state.js.map +1 -0
  207. package/dist/utils/segmenter.d.ts +19 -0
  208. package/dist/utils/segmenter.js +75 -0
  209. package/dist/utils/segmenter.js.map +1 -0
  210. package/dist/utils/shared.d.ts +103 -0
  211. package/dist/utils/shared.js +313 -0
  212. package/dist/utils/shared.js.map +1 -0
  213. package/dist/utils/vault-indexer.d.ts +53 -0
  214. package/dist/utils/vault-indexer.js +256 -0
  215. package/dist/utils/vault-indexer.js.map +1 -0
  216. package/package.json +59 -0
@@ -0,0 +1,297 @@
1
+ /**
2
+ * capture.ts — 捕获服务。
3
+ *
4
+ * Handles event logging, file change notifications, auto-capture,
5
+ * and session bridge helpers.
6
+ */
7
+ import { createHash, randomUUID } from 'node:crypto';
8
+ import { relative } from 'node:path';
9
+ import { ENTRY_TYPE_LABELS, KEY_ENTRY_TYPES, daysAgo } from '../types.js';
10
+ import { buildSearchTokens } from '../utils/segmenter.js';
11
+ import { inferTemporaryPreference, normalizeRuleSummary, parseDetailObject, resolveRuleKey, resolveSessionId, } from '../utils/shared.js';
12
+ import { indexSingleFile } from '../utils/vault-indexer.js';
13
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
14
+ /**
15
+ * Build a 16-char entry hash from entry type, summary, and normalized detail.
16
+ */
17
+ function buildEntryHash(entryType, summary, normalizedDetail) {
18
+ const raw = `${entryType}:${summary}:${normalizedDetail}`;
19
+ return createHash('sha256').update(raw, 'utf-8').digest('hex').slice(0, 16);
20
+ }
21
+ /**
22
+ * Normalize detail for rule events (decision/correction/preference).
23
+ * Adds content, normalized_summary, rule_key, structured_by fields.
24
+ * For preferences, also adds temporary inference fields.
25
+ */
26
+ function normalizeRuleEventDetail(entryType, summary, rawDetail) {
27
+ const detailObj = parseDetailObject(rawDetail);
28
+ const normalizedSummary = normalizeRuleSummary(summary);
29
+ const ruleKey = resolveRuleKey(entryType, summary, detailObj);
30
+ const normalized = {
31
+ ...detailObj,
32
+ content: rawDetail ?? summary,
33
+ normalized_summary: normalizedSummary,
34
+ rule_key: ruleKey,
35
+ structured_by: 'service_v05',
36
+ };
37
+ // For preference events, infer temporary status
38
+ if (entryType === 'preference') {
39
+ const tempResult = inferTemporaryPreference(summary, detailObj);
40
+ normalized.temporary = tempResult.temporary;
41
+ if (tempResult.expiresInDays != null) {
42
+ normalized.expires_in_days = tempResult.expiresInDays;
43
+ }
44
+ if (tempResult.expiresAt != null) {
45
+ normalized.expires_at = tempResult.expiresAt;
46
+ }
47
+ if (tempResult.temporarySource != null) {
48
+ normalized.temporary_source = tempResult.temporarySource;
49
+ }
50
+ }
51
+ return { detailStr: JSON.stringify(normalized), ruleKey };
52
+ }
53
+ /**
54
+ * Find the latest event_id with the given rule_key (excluding superseded ones).
55
+ */
56
+ function findLatestByRuleKey(db, ruleKey, excludeEventId) {
57
+ let sql = `
58
+ SELECT event_id FROM session_log
59
+ WHERE rule_key = ?
60
+ `;
61
+ const params = [ruleKey];
62
+ if (excludeEventId) {
63
+ sql += ' AND event_id != ?';
64
+ params.push(excludeEventId);
65
+ }
66
+ sql += ' ORDER BY timestamp DESC LIMIT 1';
67
+ const row = db.prepare(sql).get(params);
68
+ return row ? row.event_id : null;
69
+ }
70
+ // ─── logEvent ─────────────────────────────────────────────────────────────────
71
+ /**
72
+ * Log a single event into session_log.
73
+ * Handles detail normalization for rule events and auto-supersedes.
74
+ */
75
+ export function logEvent(db, opts) {
76
+ const { entryType, importance, summary, scope, sessionId, skillName, sourceRefs, relatedFiles, relatedEntities, supersedes: explicitSupersedes, } = opts;
77
+ const resolvedSessionId = resolveSessionId(sessionId);
78
+ const eventId = randomUUID();
79
+ const timestamp = new Date().toISOString();
80
+ // Normalize detail and resolve rule_key for rule events
81
+ let finalDetail = opts.detail ?? null;
82
+ let ruleKey = null;
83
+ if (KEY_ENTRY_TYPES.has(entryType)) {
84
+ const normalized = normalizeRuleEventDetail(entryType, summary, opts.detail);
85
+ finalDetail = normalized.detailStr;
86
+ ruleKey = normalized.ruleKey;
87
+ }
88
+ // Build entry hash
89
+ const entryHash = buildEntryHash(entryType, summary, finalDetail ?? '');
90
+ // Build search hints
91
+ const searchHints = buildSearchTokens(summary, finalDetail, relatedEntities ?? null, scope ?? null);
92
+ // Serialize arrays
93
+ const sourceRefsJson = sourceRefs ? JSON.stringify(sourceRefs) : null;
94
+ const relatedFilesJson = relatedFiles ? JSON.stringify(relatedFiles) : null;
95
+ const relatedEntitiesJson = relatedEntities ? JSON.stringify(relatedEntities) : null;
96
+ // Auto-supersede: find latest event with same rule_key
97
+ let supersedesId = explicitSupersedes ?? null;
98
+ if (!supersedesId && ruleKey) {
99
+ supersedesId = findLatestByRuleKey(db, ruleKey, eventId);
100
+ }
101
+ db.prepare(`
102
+ INSERT INTO session_log
103
+ (event_id, session_id, timestamp, entry_type, importance, scope, skill_name,
104
+ summary, detail, source_refs, related_files, related_entities,
105
+ supersedes, entry_hash, search_hints, rule_key)
106
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
107
+ `).run(eventId, resolvedSessionId, timestamp, entryType, importance, scope ?? null, skillName ?? null, summary, finalDetail, sourceRefsJson, relatedFilesJson, relatedEntitiesJson, supersedesId, entryHash, searchHints, ruleKey);
108
+ return { eventId, timestamp, status: 'ok' };
109
+ }
110
+ // ─── autoCaptureEvents ────────────────────────────────────────────────────────
111
+ /** Default importance per bucket type */
112
+ const BUCKET_IMPORTANCE = {
113
+ correction: 4,
114
+ decision: 4,
115
+ preference: 3,
116
+ };
117
+ /**
118
+ * Batch capture corrections/decisions/preferences.
119
+ * Deduplicates by entry_hash across both existing DB records and current batch.
120
+ */
121
+ export function autoCaptureEvents(db, payload, sessionId) {
122
+ const buckets = [
123
+ { entryType: 'correction', items: payload.corrections ?? [] },
124
+ { entryType: 'decision', items: payload.decisions ?? [] },
125
+ { entryType: 'preference', items: payload.preferences ?? [] },
126
+ ];
127
+ const captured = [];
128
+ // Track hashes seen in this batch to deduplicate within the same call
129
+ const batchHashes = new Set();
130
+ for (const { entryType, items } of buckets) {
131
+ for (const item of items) {
132
+ const summary = (item.summary ?? '').trim();
133
+ if (!summary)
134
+ continue;
135
+ const importance = item.importance ?? BUCKET_IMPORTANCE[entryType] ?? 3;
136
+ // Pre-compute the hash to check for duplicates
137
+ // For rule events, detail gets normalized — compute approximate hash
138
+ let previewDetail = item.detail ?? null;
139
+ if (KEY_ENTRY_TYPES.has(entryType)) {
140
+ const normalized = normalizeRuleEventDetail(entryType, summary, previewDetail);
141
+ previewDetail = normalized.detailStr;
142
+ }
143
+ const hash = buildEntryHash(entryType, summary, previewDetail ?? '');
144
+ // Skip if already seen in this batch
145
+ if (batchHashes.has(hash))
146
+ continue;
147
+ batchHashes.add(hash);
148
+ // Skip if already exists in DB
149
+ const existing = db
150
+ .prepare('SELECT event_id FROM session_log WHERE entry_hash = ? LIMIT 1')
151
+ .get([hash]);
152
+ if (existing)
153
+ continue;
154
+ const result = logEvent(db, {
155
+ entryType,
156
+ importance,
157
+ summary,
158
+ detail: item.detail,
159
+ scope: item.scope,
160
+ relatedFiles: item.relatedFiles,
161
+ sessionId,
162
+ });
163
+ captured.push({ eventId: result.eventId, entryType, summary });
164
+ }
165
+ }
166
+ return { capturedCount: captured.length, events: captured };
167
+ }
168
+ /**
169
+ * Notify the system that a file has changed.
170
+ * Re-indexes the file and updates the enhance queue if applicable.
171
+ */
172
+ export function notifyFileChanged(db, vaultRoot, filePath) {
173
+ // Normalize to relative path
174
+ const relPath = filePath.startsWith(vaultRoot)
175
+ ? relative(vaultRoot, filePath).replace(/\\/g, '/')
176
+ : filePath.replace(/\\/g, '/');
177
+ let indexResult;
178
+ try {
179
+ const dbPath = db.name; // better-sqlite3 exposes .name as the db file path
180
+ indexResult = indexSingleFile(vaultRoot, dbPath, relPath);
181
+ }
182
+ catch {
183
+ return { action: 'error', filePath: relPath };
184
+ }
185
+ if (indexResult.status === 'removed' || indexResult.status === 'skipped') {
186
+ // Remove from enhance queue if present
187
+ db.prepare('DELETE FROM enhance_queue WHERE file_path = ?').run(relPath);
188
+ return { action: indexResult.status, filePath: relPath };
189
+ }
190
+ // File was indexed — check if it should be queued for enhancement
191
+ if (indexResult.status === 'indexed') {
192
+ try {
193
+ // Check if file is already pending in enhance queue
194
+ const existing = db
195
+ .prepare("SELECT file_path FROM enhance_queue WHERE file_path = ? AND status = 'pending'")
196
+ .get([relPath]);
197
+ if (!existing) {
198
+ const now = new Date().toISOString();
199
+ db.prepare(`
200
+ INSERT OR REPLACE INTO enhance_queue
201
+ (file_path, priority, queued_at, source, status, attempts)
202
+ VALUES (?, ?, ?, 'notify', 'pending', 0)
203
+ `).run(relPath, 5, now);
204
+ }
205
+ }
206
+ catch (e) {
207
+ console.warn('[lifeos] enhance queue update failed:', e);
208
+ }
209
+ return { action: 'indexed', filePath: relPath };
210
+ }
211
+ return { action: 'unchanged', filePath: relPath };
212
+ }
213
+ // ─── latestSessionBridge ─────────────────────────────────────────────────────
214
+ /**
215
+ * Query the most recent session_bridge event.
216
+ * Optionally filter by session_id.
217
+ */
218
+ export function latestSessionBridge(db, sessionId) {
219
+ let sql = `
220
+ SELECT event_id, session_id, summary, detail, timestamp
221
+ FROM session_log
222
+ WHERE entry_type = 'session_bridge'
223
+ `;
224
+ const params = [];
225
+ if (sessionId) {
226
+ sql += ' AND session_id = ?';
227
+ params.push(sessionId);
228
+ }
229
+ sql += ' ORDER BY timestamp DESC LIMIT 1';
230
+ const row = db.prepare(sql).get(params);
231
+ if (!row)
232
+ return null;
233
+ return {
234
+ eventId: row.event_id,
235
+ sessionId: row.session_id,
236
+ summary: row.summary,
237
+ detail: row.detail,
238
+ timestamp: row.timestamp,
239
+ };
240
+ }
241
+ // ─── collectSessionBridgeSeedEvents ──────────────────────────────────────────
242
+ /**
243
+ * Collect the most recent key events for a session to use as bridge seeds.
244
+ * Returns decisions, corrections, milestones, and skill_completions.
245
+ */
246
+ export function collectSessionBridgeSeedEvents(db, sessionId, limit = 10) {
247
+ const sql = `
248
+ SELECT entry_type, summary, importance
249
+ FROM session_log
250
+ WHERE session_id = ?
251
+ AND entry_type IN ('decision', 'correction', 'preference', 'milestone', 'skill_completion')
252
+ ORDER BY importance DESC, timestamp DESC
253
+ LIMIT ?
254
+ `;
255
+ const rows = db.prepare(sql).all([sessionId, limit]);
256
+ return rows.map((r) => ({
257
+ entryType: r.entry_type,
258
+ summary: r.summary,
259
+ importance: r.importance,
260
+ }));
261
+ }
262
+ // ─── buildAutoSessionBridge ───────────────────────────────────────────────────
263
+ /**
264
+ * Generate a bridge text summary from a list of seed events.
265
+ * Used to create session_bridge entries that persist context across sessions.
266
+ */
267
+ export function buildAutoSessionBridge(events) {
268
+ if (events.length === 0) {
269
+ return '上次会话无关键事件记录。';
270
+ }
271
+ const lines = ['上次会话关键事件:'];
272
+ for (const event of events) {
273
+ const label = ENTRY_TYPE_LABELS[event.entryType] ?? event.entryType;
274
+ lines.push(`- [${label}] ${event.summary}`);
275
+ }
276
+ return lines.join('\n');
277
+ }
278
+ /**
279
+ * Scan for files in the vault that have been modified in the last 24 hours.
280
+ * Uses the vault_index table modified_at field.
281
+ */
282
+ export function scanRecentlyModifiedFiles(db, _vaultRoot) {
283
+ const cutoff = daysAgo(1);
284
+ const rows = db
285
+ .prepare(`
286
+ SELECT file_path, modified_at
287
+ FROM vault_index
288
+ WHERE modified_at >= ?
289
+ ORDER BY modified_at DESC
290
+ `)
291
+ .all([cutoff]);
292
+ return rows.map((r) => ({
293
+ filePath: r.file_path,
294
+ modifiedAt: r.modified_at,
295
+ }));
296
+ }
297
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/services/capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * enhance.ts — 增强服务。
3
+ *
4
+ * Processes the enhance queue: generates semantic summaries and enhanced
5
+ * search terms for indexed vault files.
6
+ */
7
+ import type Database from 'better-sqlite3';
8
+ import type { VaultIndexRow } from '../types.js';
9
+ /**
10
+ * Generate a natural language description of a vault_index record.
11
+ * Used to populate the semantic_summary column.
12
+ */
13
+ export declare function generateSemanticSummary(record: VaultIndexRow): string;
14
+ /**
15
+ * Add a file to the enhance queue.
16
+ * If the file is already queued with a higher priority, it is skipped.
17
+ */
18
+ export declare function queueFileForEnhance(db: Database.Database, filePath: string, priority: number, source: string, now?: Date | string | null): void;
19
+ /**
20
+ * Return the first matching enhance priority for a file path,
21
+ * checking each prefix in the enhancePriority map in insertion order.
22
+ * Returns null if no prefix matches.
23
+ */
24
+ export declare function matchEnhancePriority(filePath: string, enhancePriority: Record<string, number>): number | null;
25
+ /**
26
+ * Queue a list of changed file paths for enhancement, using the configured
27
+ * priority map. Files with no matching prefix are skipped.
28
+ * Returns the number of files actually queued.
29
+ */
30
+ export declare function enqueueChangedPathsForEnhance(db: Database.Database, changedPaths: string[], enhancePriority: Record<string, number>, now?: Date | string | null): number;
31
+ /**
32
+ * Generate enhanced search term tokens for a vault_index record.
33
+ * Combines title, aliases, domain, type, status, section heads, and summary
34
+ * into a deduplicated list of tokens via the segmenter.
35
+ */
36
+ export declare function generateEnhancedSearchTerms(record: VaultIndexRow): string[];
37
+ /**
38
+ * Merge base search hints (JSON array or raw string) with extra terms,
39
+ * deduplicating while preserving insertion order.
40
+ * Returns a JSON array string.
41
+ */
42
+ export declare function mergeSearchHints(baseHints: string | string[] | null | undefined, extraTerms: string[]): string;
43
+ /**
44
+ * Process up to `limit` pending items from the enhance queue.
45
+ * For each item, generates semantic summary and enhanced search hints,
46
+ * then marks the item as done (or error on failure).
47
+ */
48
+ export declare function processEnhanceQueue(db: Database.Database, _vaultRoot: string, limit?: number): {
49
+ processed: number;
50
+ errors: number;
51
+ };
@@ -0,0 +1,184 @@
1
+ /**
2
+ * enhance.ts — 增强服务。
3
+ *
4
+ * Processes the enhance queue: generates semantic summaries and enhanced
5
+ * search terms for indexed vault files.
6
+ */
7
+ import { queryOne } from '../db/index.js';
8
+ import { ENHANCE_STATUS_LABELS, NOTE_TYPE_LABELS } from '../types.js';
9
+ import { tokenize } from '../utils/segmenter.js';
10
+ import { coerceNow, loadsJsonList, normalizeWikilinkValue } from '../utils/shared.js';
11
+ // ─── generateSemanticSummary ──────────────────────────────────────────────────
12
+ /**
13
+ * Generate a natural language description of a vault_index record.
14
+ * Used to populate the semantic_summary column.
15
+ */
16
+ export function generateSemanticSummary(record) {
17
+ const title = String(record.title ?? '').trim();
18
+ const noteType = String(record.type ?? '').trim();
19
+ const domain = normalizeWikilinkValue(record.domain);
20
+ const status = String(record.status ?? '').trim();
21
+ const summary = String(record.summary ?? '')
22
+ .trim()
23
+ .replace(/\n/g, ' ');
24
+ const subject = title || '该条目';
25
+ let s1 = `${subject}是一份${NOTE_TYPE_LABELS[noteType] ?? '笔记'}`;
26
+ if (domain)
27
+ s1 += `,主要关联 ${domain} 领域`;
28
+ s1 += '。';
29
+ let s2 = ENHANCE_STATUS_LABELS[status] ? `当前状态为${ENHANCE_STATUS_LABELS[status]}` : '';
30
+ if (summary && !s2)
31
+ s2 = summary.slice(0, 48);
32
+ if (s2 && !s2.endsWith('。'))
33
+ s2 += '。';
34
+ return `${s1}${s2}`.trim() || `${subject}是一条待补充增强摘要的记忆条目。`;
35
+ }
36
+ // ─── queueFileForEnhance ──────────────────────────────────────────────────────
37
+ /**
38
+ * Add a file to the enhance queue.
39
+ * If the file is already queued with a higher priority, it is skipped.
40
+ */
41
+ export function queueFileForEnhance(db, filePath, priority, source, now) {
42
+ const queuedAt = coerceNow(now).toISOString();
43
+ const existing = db
44
+ .prepare('SELECT priority FROM enhance_queue WHERE file_path = ?')
45
+ .get(filePath);
46
+ if (existing && existing.priority > priority)
47
+ return;
48
+ db.prepare(`
49
+ INSERT OR REPLACE INTO enhance_queue
50
+ (file_path, priority, queued_at, source, status, attempts, last_attempt_at, error_message)
51
+ VALUES (?, ?, ?, ?, 'pending', 0, NULL, NULL)
52
+ `).run(filePath, priority, queuedAt, source);
53
+ }
54
+ // ─── matchEnhancePriority ─────────────────────────────────────────────────────
55
+ /**
56
+ * Return the first matching enhance priority for a file path,
57
+ * checking each prefix in the enhancePriority map in insertion order.
58
+ * Returns null if no prefix matches.
59
+ */
60
+ export function matchEnhancePriority(filePath, enhancePriority) {
61
+ for (const [prefix, priority] of Object.entries(enhancePriority)) {
62
+ if (filePath.startsWith(prefix))
63
+ return priority;
64
+ }
65
+ return null;
66
+ }
67
+ // ─── enqueueChangedPathsForEnhance ────────────────────────────────────────────
68
+ /**
69
+ * Queue a list of changed file paths for enhancement, using the configured
70
+ * priority map. Files with no matching prefix are skipped.
71
+ * Returns the number of files actually queued.
72
+ */
73
+ export function enqueueChangedPathsForEnhance(db, changedPaths, enhancePriority, now) {
74
+ let queued = 0;
75
+ for (const fp of changedPaths) {
76
+ const priority = matchEnhancePriority(fp, enhancePriority);
77
+ if (priority === null)
78
+ continue;
79
+ queueFileForEnhance(db, fp, priority, 'startup_scan', now);
80
+ queued++;
81
+ }
82
+ return queued;
83
+ }
84
+ // ─── generateEnhancedSearchTerms ─────────────────────────────────────────────
85
+ /**
86
+ * Generate enhanced search term tokens for a vault_index record.
87
+ * Combines title, aliases, domain, type, status, section heads, and summary
88
+ * into a deduplicated list of tokens via the segmenter.
89
+ */
90
+ export function generateEnhancedSearchTerms(record) {
91
+ const extras = [];
92
+ const title = String(record.title ?? '').trim();
93
+ const noteType = String(record.type ?? '').trim();
94
+ const status = String(record.status ?? '').trim();
95
+ const domain = normalizeWikilinkValue(record.domain);
96
+ const aliases = loadsJsonList(record.aliases);
97
+ const sectionHeads = loadsJsonList(record.section_heads)
98
+ .map((h) => h.replace(/^#{1,6}\s*/, '').trim())
99
+ .filter(Boolean);
100
+ const summary = String(record.summary ?? '').trim();
101
+ if (title)
102
+ extras.push(title);
103
+ extras.push(...aliases);
104
+ if (domain)
105
+ extras.push(domain);
106
+ if (noteType)
107
+ extras.push(noteType);
108
+ if (status)
109
+ extras.push(status);
110
+ extras.push(...sectionHeads.slice(0, 5));
111
+ extras.push(...summary.split('\n').slice(0, 2));
112
+ if (noteType === 'project')
113
+ extras.push('项目', '计划', '进展', '任务', '当前状态');
114
+ else if (noteType === 'note')
115
+ extras.push('概念', '定义', '知识点', '章节', '复习');
116
+ else if (noteType === 'research')
117
+ extras.push('研究', '报告', '结论', '发现');
118
+ if (status === 'done')
119
+ extras.push('完成', '复盘');
120
+ return tokenize(extras.filter(Boolean).join(' '));
121
+ }
122
+ // ─── mergeSearchHints ─────────────────────────────────────────────────────────
123
+ /**
124
+ * Merge base search hints (JSON array or raw string) with extra terms,
125
+ * deduplicating while preserving insertion order.
126
+ * Returns a JSON array string.
127
+ */
128
+ export function mergeSearchHints(baseHints, extraTerms) {
129
+ const merged = [];
130
+ const seen = new Set();
131
+ for (const term of [...loadsJsonList(baseHints), ...extraTerms.filter(Boolean)]) {
132
+ const normalized = term.trim();
133
+ if (!normalized || seen.has(normalized))
134
+ continue;
135
+ seen.add(normalized);
136
+ merged.push(normalized);
137
+ }
138
+ return JSON.stringify(merged);
139
+ }
140
+ // ─── processEnhanceQueue ──────────────────────────────────────────────────────
141
+ /**
142
+ * Process up to `limit` pending items from the enhance queue.
143
+ * For each item, generates semantic summary and enhanced search hints,
144
+ * then marks the item as done (or error on failure).
145
+ */
146
+ export function processEnhanceQueue(db, _vaultRoot, limit = 5) {
147
+ const rows = db
148
+ .prepare(`
149
+ SELECT file_path, priority FROM enhance_queue
150
+ WHERE status = 'pending'
151
+ ORDER BY priority DESC, queued_at ASC
152
+ LIMIT ?
153
+ `)
154
+ .all(limit);
155
+ let processed = 0;
156
+ let errors = 0;
157
+ for (const row of rows) {
158
+ try {
159
+ const record = queryOne(db, 'SELECT * FROM vault_index WHERE file_path = ?', row.file_path);
160
+ if (!record) {
161
+ db.prepare("UPDATE enhance_queue SET status = 'done' WHERE file_path = ?").run(row.file_path);
162
+ continue;
163
+ }
164
+ const semanticSummary = generateSemanticSummary(record);
165
+ const enhancedTerms = generateEnhancedSearchTerms(record);
166
+ const mergedHints = mergeSearchHints(record.search_hints, enhancedTerms);
167
+ db.prepare(`
168
+ UPDATE vault_index SET semantic_summary = ?, search_hints = ? WHERE file_path = ?
169
+ `).run(semanticSummary, mergedHints, row.file_path);
170
+ db.prepare("UPDATE enhance_queue SET status = 'done' WHERE file_path = ?").run(row.file_path);
171
+ processed++;
172
+ }
173
+ catch {
174
+ db.prepare(`
175
+ UPDATE enhance_queue
176
+ SET status = 'error', attempts = attempts + 1, error_message = 'enhance failed'
177
+ WHERE file_path = ?
178
+ `).run(row.file_path);
179
+ errors++;
180
+ }
181
+ }
182
+ return { processed, errors };
183
+ }
184
+ //# sourceMappingURL=enhance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enhance.js","sourceRoot":"","sources":["../../src/services/enhance.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * layer0.ts — Layer 0 上下文摘要构建器。
3
+ *
4
+ * Builds the Layer 0 summary from UserProfile.md and TaskBoard.md,
5
+ * trimmed to configured token budgets.
6
+ */
7
+ import type { ContextPolicy } from '../utils/context-policy.js';
8
+ /**
9
+ * Extract the content between <!-- BEGIN AUTO:marker --> and <!-- END AUTO:marker -->
10
+ * comment blocks in a markdown document. Returns empty string if not found.
11
+ */
12
+ export declare function extractAutoSection(content: string, marker: string): string;
13
+ /**
14
+ * Trim text to at most `budget` estimated tokens.
15
+ * Returns empty string when budget is 0 or text is blank.
16
+ * Appends '...' continuation marker when text is cut.
17
+ */
18
+ export declare function trimToBudget(text: string, budget: number): string;
19
+ /**
20
+ * Build the Layer 0 summary string from UserProfile.md and TaskBoard.md.
21
+ * Reads AUTO sections, trims to configured token budgets, and optionally
22
+ * appends the last session bridge text.
23
+ */
24
+ export declare function buildLayer0Summary(vaultRoot: string, policy: ContextPolicy, lastSessionBridge?: string | null): string;