trove-cli 0.0.0-stage → 0.2.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 (210) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +200 -2
  3. package/dist/adapters/file-source.d.ts +31 -0
  4. package/dist/adapters/file-source.js +97 -0
  5. package/dist/adapters/file-source.js.map +1 -0
  6. package/dist/adapters/index.d.ts +34 -0
  7. package/dist/adapters/index.js +146 -0
  8. package/dist/adapters/index.js.map +1 -0
  9. package/dist/adapters/opencode.d.ts +30 -0
  10. package/dist/adapters/opencode.js +135 -0
  11. package/dist/adapters/opencode.js.map +1 -0
  12. package/dist/cli.d.ts +58 -0
  13. package/dist/cli.js +972 -0
  14. package/dist/cli.js.map +1 -0
  15. package/dist/config.d.ts +81 -0
  16. package/dist/config.js +99 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/core/archive.d.ts +27 -0
  19. package/dist/core/archive.js +101 -0
  20. package/dist/core/archive.js.map +1 -0
  21. package/dist/core/chunker.d.ts +28 -0
  22. package/dist/core/chunker.js +67 -0
  23. package/dist/core/chunker.js.map +1 -0
  24. package/dist/core/clean.d.ts +36 -0
  25. package/dist/core/clean.js +182 -0
  26. package/dist/core/clean.js.map +1 -0
  27. package/dist/core/collect.d.ts +39 -0
  28. package/dist/core/collect.js +194 -0
  29. package/dist/core/collect.js.map +1 -0
  30. package/dist/core/concurrency.d.ts +2 -0
  31. package/dist/core/concurrency.js +16 -0
  32. package/dist/core/concurrency.js.map +1 -0
  33. package/dist/core/cursor.d.ts +31 -0
  34. package/dist/core/cursor.js +31 -0
  35. package/dist/core/cursor.js.map +1 -0
  36. package/dist/core/events/claude.d.ts +7 -0
  37. package/dist/core/events/claude.js +287 -0
  38. package/dist/core/events/claude.js.map +1 -0
  39. package/dist/core/events/codex.d.ts +6 -0
  40. package/dist/core/events/codex.js +149 -0
  41. package/dist/core/events/codex.js.map +1 -0
  42. package/dist/core/events/doubao.d.ts +9 -0
  43. package/dist/core/events/doubao.js +151 -0
  44. package/dist/core/events/doubao.js.map +1 -0
  45. package/dist/core/events/index.d.ts +6 -0
  46. package/dist/core/events/index.js +20 -0
  47. package/dist/core/events/index.js.map +1 -0
  48. package/dist/core/events/opencode.d.ts +7 -0
  49. package/dist/core/events/opencode.js +189 -0
  50. package/dist/core/events/opencode.js.map +1 -0
  51. package/dist/core/events/schema.d.ts +83 -0
  52. package/dist/core/events/schema.js +35 -0
  53. package/dist/core/events/schema.js.map +1 -0
  54. package/dist/core/layout.d.ts +26 -0
  55. package/dist/core/layout.js +122 -0
  56. package/dist/core/layout.js.map +1 -0
  57. package/dist/core/lessons/analyze.d.ts +40 -0
  58. package/dist/core/lessons/analyze.js +107 -0
  59. package/dist/core/lessons/analyze.js.map +1 -0
  60. package/dist/core/lessons/audit.d.ts +51 -0
  61. package/dist/core/lessons/audit.js +57 -0
  62. package/dist/core/lessons/audit.js.map +1 -0
  63. package/dist/core/lessons/compaction.d.ts +5 -0
  64. package/dist/core/lessons/compaction.js +58 -0
  65. package/dist/core/lessons/compaction.js.map +1 -0
  66. package/dist/core/lessons/config.d.ts +15 -0
  67. package/dist/core/lessons/config.js +31 -0
  68. package/dist/core/lessons/config.js.map +1 -0
  69. package/dist/core/lessons/existing.d.ts +4 -0
  70. package/dist/core/lessons/existing.js +22 -0
  71. package/dist/core/lessons/existing.js.map +1 -0
  72. package/dist/core/lessons/extract.d.ts +21 -0
  73. package/dist/core/lessons/extract.js +106 -0
  74. package/dist/core/lessons/extract.js.map +1 -0
  75. package/dist/core/lessons/frontmatter.d.ts +29 -0
  76. package/dist/core/lessons/frontmatter.js +87 -0
  77. package/dist/core/lessons/frontmatter.js.map +1 -0
  78. package/dist/core/lessons/graph.d.ts +256 -0
  79. package/dist/core/lessons/graph.js +86 -0
  80. package/dist/core/lessons/graph.js.map +1 -0
  81. package/dist/core/lessons/jev.d.ts +36 -0
  82. package/dist/core/lessons/jev.js +100 -0
  83. package/dist/core/lessons/jev.js.map +1 -0
  84. package/dist/core/lessons/layout.d.ts +2 -0
  85. package/dist/core/lessons/layout.js +56 -0
  86. package/dist/core/lessons/layout.js.map +1 -0
  87. package/dist/core/lessons/learn.d.ts +38 -0
  88. package/dist/core/lessons/learn.js +190 -0
  89. package/dist/core/lessons/learn.js.map +1 -0
  90. package/dist/core/lessons/llm.d.ts +42 -0
  91. package/dist/core/lessons/llm.js +106 -0
  92. package/dist/core/lessons/llm.js.map +1 -0
  93. package/dist/core/lessons/memo.d.ts +19 -0
  94. package/dist/core/lessons/memo.js +170 -0
  95. package/dist/core/lessons/memo.js.map +1 -0
  96. package/dist/core/lessons/merge.d.ts +39 -0
  97. package/dist/core/lessons/merge.js +79 -0
  98. package/dist/core/lessons/merge.js.map +1 -0
  99. package/dist/core/lessons/queue.d.ts +6 -0
  100. package/dist/core/lessons/queue.js +52 -0
  101. package/dist/core/lessons/queue.js.map +1 -0
  102. package/dist/core/lessons/recent.d.ts +21 -0
  103. package/dist/core/lessons/recent.js +111 -0
  104. package/dist/core/lessons/recent.js.map +1 -0
  105. package/dist/core/lessons/schema.d.ts +26 -0
  106. package/dist/core/lessons/schema.js +64 -0
  107. package/dist/core/lessons/schema.js.map +1 -0
  108. package/dist/core/lessons/select.d.ts +19 -0
  109. package/dist/core/lessons/select.js +55 -0
  110. package/dist/core/lessons/select.js.map +1 -0
  111. package/dist/core/lessons/sidecar.d.ts +23 -0
  112. package/dist/core/lessons/sidecar.js +171 -0
  113. package/dist/core/lessons/sidecar.js.map +1 -0
  114. package/dist/core/lessons/storage.d.ts +21 -0
  115. package/dist/core/lessons/storage.js +65 -0
  116. package/dist/core/lessons/storage.js.map +1 -0
  117. package/dist/core/lessons/usage.d.ts +31 -0
  118. package/dist/core/lessons/usage.js +91 -0
  119. package/dist/core/lessons/usage.js.map +1 -0
  120. package/dist/core/lessons/write.d.ts +18 -0
  121. package/dist/core/lessons/write.js +131 -0
  122. package/dist/core/lessons/write.js.map +1 -0
  123. package/dist/core/library/build.d.ts +22 -0
  124. package/dist/core/library/build.js +163 -0
  125. package/dist/core/library/build.js.map +1 -0
  126. package/dist/core/library/group.d.ts +14 -0
  127. package/dist/core/library/group.js +129 -0
  128. package/dist/core/library/group.js.map +1 -0
  129. package/dist/core/library/index-file.d.ts +7 -0
  130. package/dist/core/library/index-file.js +250 -0
  131. package/dist/core/library/index-file.js.map +1 -0
  132. package/dist/core/library/schema.d.ts +78 -0
  133. package/dist/core/library/schema.js +37 -0
  134. package/dist/core/library/schema.js.map +1 -0
  135. package/dist/core/library/skills.d.ts +26 -0
  136. package/dist/core/library/skills.js +168 -0
  137. package/dist/core/library/skills.js.map +1 -0
  138. package/dist/core/library/sync.d.ts +48 -0
  139. package/dist/core/library/sync.js +271 -0
  140. package/dist/core/library/sync.js.map +1 -0
  141. package/dist/core/lock.d.ts +6 -0
  142. package/dist/core/lock.js +56 -0
  143. package/dist/core/lock.js.map +1 -0
  144. package/dist/core/pull.d.ts +23 -0
  145. package/dist/core/pull.js +147 -0
  146. package/dist/core/pull.js.map +1 -0
  147. package/dist/core/push.d.ts +29 -0
  148. package/dist/core/push.js +170 -0
  149. package/dist/core/push.js.map +1 -0
  150. package/dist/core/remote-layout.d.ts +67 -0
  151. package/dist/core/remote-layout.js +94 -0
  152. package/dist/core/remote-layout.js.map +1 -0
  153. package/dist/core/sessions.d.ts +29 -0
  154. package/dist/core/sessions.js +96 -0
  155. package/dist/core/sessions.js.map +1 -0
  156. package/dist/core/state.d.ts +94 -0
  157. package/dist/core/state.js +62 -0
  158. package/dist/core/state.js.map +1 -0
  159. package/dist/core/sync.d.ts +48 -0
  160. package/dist/core/sync.js +140 -0
  161. package/dist/core/sync.js.map +1 -0
  162. package/dist/core/time-window.d.ts +8 -0
  163. package/dist/core/time-window.js +36 -0
  164. package/dist/core/time-window.js.map +1 -0
  165. package/dist/daemon.d.ts +73 -0
  166. package/dist/daemon.js +272 -0
  167. package/dist/daemon.js.map +1 -0
  168. package/dist/format.d.ts +4 -0
  169. package/dist/format.js +28 -0
  170. package/dist/format.js.map +1 -0
  171. package/dist/main.d.ts +2 -0
  172. package/dist/main.js +9 -0
  173. package/dist/main.js.map +1 -0
  174. package/dist/paths.d.ts +19 -0
  175. package/dist/paths.js +19 -0
  176. package/dist/paths.js.map +1 -0
  177. package/dist/progress-console.d.ts +12 -0
  178. package/dist/progress-console.js +42 -0
  179. package/dist/progress-console.js.map +1 -0
  180. package/dist/progress.d.ts +7 -0
  181. package/dist/progress.js +6 -0
  182. package/dist/progress.js.map +1 -0
  183. package/dist/remote/create-remote.d.ts +20 -0
  184. package/dist/remote/create-remote.js +86 -0
  185. package/dist/remote/create-remote.js.map +1 -0
  186. package/dist/remote/prompt.d.ts +17 -0
  187. package/dist/remote/prompt.js +111 -0
  188. package/dist/remote/prompt.js.map +1 -0
  189. package/dist/remote/s3-sigv4.d.ts +28 -0
  190. package/dist/remote/s3-sigv4.js +100 -0
  191. package/dist/remote/s3-sigv4.js.map +1 -0
  192. package/dist/remote/s3-store.d.ts +75 -0
  193. package/dist/remote/s3-store.js +438 -0
  194. package/dist/remote/s3-store.js.map +1 -0
  195. package/dist/remote/s3-vendors.d.ts +31 -0
  196. package/dist/remote/s3-vendors.js +47 -0
  197. package/dist/remote/s3-vendors.js.map +1 -0
  198. package/dist/remote/store.d.ts +44 -0
  199. package/dist/remote/store.js +2 -0
  200. package/dist/remote/store.js.map +1 -0
  201. package/dist/remote/webdav-store.d.ts +41 -0
  202. package/dist/remote/webdav-store.js +285 -0
  203. package/dist/remote/webdav-store.js.map +1 -0
  204. package/dist/sqlite.d.ts +3 -0
  205. package/dist/sqlite.js +12 -0
  206. package/dist/sqlite.js.map +1 -0
  207. package/dist/status.d.ts +82 -0
  208. package/dist/status.js +162 -0
  209. package/dist/status.js.map +1 -0
  210. package/package.json +43 -4
@@ -0,0 +1,171 @@
1
+ import { parseFrontmatter, stripFrontmatter } from './frontmatter.js';
2
+ export const SIDECAR_DIRS = [
3
+ { path: '', name: '学习沉淀概览', brief: '从 AI 会话沉淀的可复用经验与偏好,按偏好、实体、经验、决策、资源五类分层组织。' },
4
+ { path: 'preferences', name: '用户偏好', brief: '用户偏好配置库,聚焦用户画像、编码风格、写作风格、对话风格与最近事项等个人偏好,回答时自动套用。' },
5
+ { path: 'entities', name: '实体库', brief: '实体库,卡片式记录项目、人物、组织、工具与技术栈等长期有效的事实。' },
6
+ { path: 'experiences', name: '经验库', brief: '经验库,沉淀调试模式、操作流程、陷阱坑与纠正教训等可复用经验。' },
7
+ { path: 'events', name: '决策记录', brief: '决策记录,归档用户拍板的方向与取舍及当时的背景。' },
8
+ { path: 'resources', name: '资料库', brief: '资料库,收录文档、代码仓库与链接等外部资料。' },
9
+ ];
10
+ const COMPONENT = 'ExtractionPipeline';
11
+ const THRESHOLD = 0.1;
12
+ /** 各目录下需要稳定列出的子目录(带中文标签);叶子目录(偏好/经验/决策)只列直接文件。 */
13
+ const SUBDIRS = {
14
+ '': [
15
+ { name: 'preferences', label: '用户偏好' },
16
+ { name: 'entities', label: '实体库' },
17
+ { name: 'experiences', label: '经验库' },
18
+ { name: 'events', label: '决策记录' },
19
+ { name: 'resources', label: '资料库' },
20
+ ],
21
+ entities: [
22
+ { name: 'projects', label: '项目' },
23
+ { name: 'people', label: '人物' },
24
+ { name: 'organizations', label: '组织' },
25
+ { name: 'tools', label: '工具' },
26
+ { name: 'tech', label: '技术栈' },
27
+ ],
28
+ resources: [
29
+ { name: 'docs', label: '文档' },
30
+ { name: 'repos', label: '仓库' },
31
+ { name: 'links', label: '链接' },
32
+ ],
33
+ };
34
+ function joinRel(path, name) {
35
+ return path ? `${path}/${name}` : name;
36
+ }
37
+ function directoryField(path) {
38
+ return path ? `lessons/${path}/` : 'lessons/';
39
+ }
40
+ function sidecarDir(path) {
41
+ return SIDECAR_DIRS.find((d) => d.path === path);
42
+ }
43
+ /** 从 L1 提取 Brief(H1 之后、首个 ## 之前的那段话),作为 L0 正文的唯一来源。 */
44
+ export function extractBrief(overviewText) {
45
+ const body = stripFrontmatter(overviewText) ?? overviewText;
46
+ const lines = body.split('\n');
47
+ let i = 0;
48
+ while (i < lines.length && (lines[i].trim() === '' || lines[i].startsWith('# ')))
49
+ i++;
50
+ const out = [];
51
+ while (i < lines.length && !lines[i].startsWith('##')) {
52
+ out.push(lines[i]);
53
+ i++;
54
+ }
55
+ return out.join('\n').trim();
56
+ }
57
+ /** 强制重建根 + 5 大类目录的 sidecar;返回写入的相对路径。 */
58
+ export async function refreshSidecars(storage, opts = {}) {
59
+ const written = [];
60
+ // 自底向上:叶子类目录在前,根在后。
61
+ for (const d of [...SIDECAR_DIRS].reverse()) {
62
+ written.push(...(await refreshOne(storage, d, opts)));
63
+ }
64
+ return written;
65
+ }
66
+ /** 写入记忆后标记目录变脏:L0/L1 未跨 10% 阈值时只递增 pending,否则整目录刷新。 */
67
+ export async function touchSidecars(storage, dirPaths, opts = {}) {
68
+ const written = [];
69
+ for (const p of dirPaths) {
70
+ const d = sidecarDir(p);
71
+ const overviewPath = joinRel(p, '.overview.md');
72
+ const existing = await storage.read(overviewPath);
73
+ if (existing === null) {
74
+ written.push(...(await refreshOne(storage, d, opts)));
75
+ continue;
76
+ }
77
+ const pending = fieldInt(existing, 'pending_child_changes') + 1;
78
+ const total = fieldInt(existing, 'total_entries');
79
+ if (total === 0 || pending / total >= THRESHOLD) {
80
+ written.push(...(await refreshOne(storage, d, opts)));
81
+ }
82
+ else {
83
+ await storage.write(overviewPath, setField(existing, 'pending_child_changes', pending));
84
+ written.push(overviewPath);
85
+ }
86
+ }
87
+ return written;
88
+ }
89
+ async function refreshOne(storage, d, opts) {
90
+ const nav = await buildNav(storage, d);
91
+ const meta = {
92
+ component: COMPONENT,
93
+ trigger: opts.trigger ?? 'manual_refresh',
94
+ totalEntries: nav.length,
95
+ pendingChildChanges: 0,
96
+ updatedAt: (opts.now ?? (() => new Date()))().toISOString(),
97
+ };
98
+ const overviewPath = joinRel(d.path, '.overview.md');
99
+ const abstractPath = joinRel(d.path, '.abstract.md');
100
+ const overview = renderOverview(d, nav, meta);
101
+ const abstract = renderAbstract(d, overview, meta);
102
+ await storage.write(overviewPath, overview);
103
+ await storage.write(abstractPath, abstract);
104
+ return [overviewPath, abstractPath];
105
+ }
106
+ async function buildNav(storage, d) {
107
+ const lines = [];
108
+ for (const sub of SUBDIRS[d.path] ?? []) {
109
+ const count = (await storage.list(joinRel(d.path, sub.name))).filter((f) => !isSidecarOrIndex(f)).length;
110
+ lines.push(`- \`${sub.name}/\`: ${sub.label}(${count} 个文件)`);
111
+ }
112
+ for (const f of await directFiles(storage, d.path)) {
113
+ lines.push(`- \`${f}\`: ${await describeFile(storage, joinRel(d.path, f))}`);
114
+ }
115
+ return lines;
116
+ }
117
+ async function directFiles(storage, path) {
118
+ const files = await storage.list(path);
119
+ const prefix = path ? `${path}/` : '';
120
+ const out = [];
121
+ for (const f of files) {
122
+ const rel = prefix ? (f.startsWith(prefix) ? f.slice(prefix.length) : '') : f;
123
+ if (!rel || rel.startsWith('.') || rel === 'INDEX.md' || rel === 'README.md' || rel.includes('/') || !rel.endsWith('.md'))
124
+ continue;
125
+ out.push(rel);
126
+ }
127
+ return out.sort();
128
+ }
129
+ async function describeFile(storage, path) {
130
+ const text = (await storage.read(path)) ?? '';
131
+ const title = parseFrontmatter(text)?.title;
132
+ if (title)
133
+ return title;
134
+ const body = stripFrontmatter(text) ?? text;
135
+ const first = body.split('\n').find((l) => l.trim())?.trim() ?? '';
136
+ return first.length > 60 ? `${first.slice(0, 60)}…` : first;
137
+ }
138
+ function isSidecarOrIndex(path) {
139
+ const base = path.split('/').pop();
140
+ return base === '.abstract.md' || base === '.overview.md' || base === 'INDEX.md';
141
+ }
142
+ function renderOverview(d, nav, meta) {
143
+ return (renderSidecarFrontmatter(directoryField(d.path), meta) +
144
+ `# ${d.name}\n\n${d.brief}\n\n## Quick Navigation\n${nav.join('\n')}\n`);
145
+ }
146
+ function renderAbstract(d, overview, meta) {
147
+ return renderSidecarFrontmatter(directoryField(d.path), meta) + `${extractBrief(overview)}\n`;
148
+ }
149
+ function renderSidecarFrontmatter(directory, meta) {
150
+ return [
151
+ '---',
152
+ `directory: ${directory}`,
153
+ 'generated_by:',
154
+ ` component: ${meta.component}`,
155
+ ` trigger: ${meta.trigger}`,
156
+ 'freshness:',
157
+ ` total_entries: ${meta.totalEntries}`,
158
+ ` pending_child_changes: ${meta.pendingChildChanges}`,
159
+ `updated_at: ${meta.updatedAt}`,
160
+ '---',
161
+ '',
162
+ ].join('\n');
163
+ }
164
+ function fieldInt(text, key) {
165
+ const m = text.match(new RegExp(`^\\s*${key}:\\s*(\\d+)\\s*$`, 'm'));
166
+ return m ? Number(m[1]) : 0;
167
+ }
168
+ function setField(text, key, value) {
169
+ return text.replace(new RegExp(`^(\\s*${key}:)\\s*\\d+\\s*$`, 'm'), `$1 ${value}`);
170
+ }
171
+ //# sourceMappingURL=sidecar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidecar.js","sourceRoot":"","sources":["../../../src/core/lessons/sidecar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ export interface StorageAdapter {
2
+ /** 读取文本;不存在返回 null。 */
3
+ read(path: string): Promise<string | null>;
4
+ /** 覆盖写入文本(自动建父目录)。 */
5
+ write(path: string, text: string): Promise<void>;
6
+ exists(path: string): Promise<boolean>;
7
+ /** 删除文件;不存在静默成功。 */
8
+ delete(path: string): Promise<void>;
9
+ /** 递归列出 prefix 下的相对文件路径(`/` 分隔);不存在返回空数组。 */
10
+ list(prefix?: string): Promise<string[]>;
11
+ }
12
+ export declare class LocalStorageAdapter implements StorageAdapter {
13
+ private root;
14
+ constructor(root: string);
15
+ private abs;
16
+ read(path: string): Promise<string | null>;
17
+ exists(path: string): Promise<boolean>;
18
+ write(path: string, text: string): Promise<void>;
19
+ delete(path: string): Promise<void>;
20
+ list(prefix?: string): Promise<string[]>;
21
+ }
@@ -0,0 +1,65 @@
1
+ /** lessons 落盘的最小文本读写抽象。本地实现直接 fs;远端由现有 sync 引擎(RemoteStore)承担,不在此重复。 */
2
+ import { randomUUID } from 'node:crypto';
3
+ import { constants } from 'node:fs';
4
+ import { access, mkdir, readFile, readdir, rename, rm, writeFile } from 'node:fs/promises';
5
+ import { dirname, join } from 'node:path';
6
+ export class LocalStorageAdapter {
7
+ root;
8
+ constructor(root) {
9
+ this.root = root;
10
+ }
11
+ abs(path) {
12
+ return join(this.root, path);
13
+ }
14
+ async read(path) {
15
+ try {
16
+ return await readFile(this.abs(path), 'utf8');
17
+ }
18
+ catch (err) {
19
+ if (err.code === 'ENOENT')
20
+ return null;
21
+ throw err;
22
+ }
23
+ }
24
+ async exists(path) {
25
+ try {
26
+ await access(this.abs(path), constants.F_OK);
27
+ return true;
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }
33
+ async write(path, text) {
34
+ const abs = this.abs(path);
35
+ await mkdir(dirname(abs), { recursive: true });
36
+ const tmp = `${abs}.tmp-${randomUUID()}`;
37
+ await writeFile(tmp, text, 'utf8');
38
+ await rename(tmp, abs);
39
+ }
40
+ async delete(path) {
41
+ await rm(this.abs(path), { force: true });
42
+ }
43
+ async list(prefix = '') {
44
+ const out = [];
45
+ const walk = async (dir, rel) => {
46
+ let entries;
47
+ try {
48
+ entries = await readdir(dir, { withFileTypes: true });
49
+ }
50
+ catch {
51
+ return; // 目录不存在
52
+ }
53
+ for (const e of entries) {
54
+ const p = rel ? `${rel}/${e.name}` : e.name;
55
+ if (e.isDirectory())
56
+ await walk(join(dir, e.name), p);
57
+ else if (e.isFile())
58
+ out.push(p);
59
+ }
60
+ };
61
+ await walk(this.abs(prefix), prefix);
62
+ return out;
63
+ }
64
+ }
65
+ //# sourceMappingURL=storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.js","sourceRoot":"","sources":["../../../src/core/lessons/storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /** 单次 LLM 调用的用量与来源任务(如 learn:summarize)。 */
2
+ export interface LlmUsage {
3
+ task: string;
4
+ model: string;
5
+ promptTokens: number;
6
+ completionTokens: number;
7
+ totalTokens: number;
8
+ }
9
+ export interface UsageRecord extends LlmUsage {
10
+ /** 记录时间,ISO-8601;由 sink 写入时打点。 */
11
+ at: string;
12
+ }
13
+ export type UsageSink = (usage: LlmUsage) => void | Promise<void>;
14
+ /** 追加写 sink:目录不存在自建,单行 JSON;写失败由调用方决定是否忽略。 */
15
+ export declare function createUsageSink(path: string, now?: () => Date): UsageSink;
16
+ /** 读取台账;文件不存在或单行损坏都跳过,不阻断统计。 */
17
+ export declare function readUsageRecords(path: string): Promise<UsageRecord[]>;
18
+ export interface UsageBucket {
19
+ calls: number;
20
+ promptTokens: number;
21
+ completionTokens: number;
22
+ totalTokens: number;
23
+ }
24
+ export interface UsageSummary {
25
+ total: UsageBucket;
26
+ byTask: Record<string, UsageBucket>;
27
+ byModel: Record<string, UsageBucket>;
28
+ }
29
+ export declare function summarizeUsage(records: Iterable<UsageRecord>): UsageSummary;
30
+ /** CLI 展示:总计 + 按任务/模型分组。 */
31
+ export declare function formatUsageSummary(summary: UsageSummary, since?: string): string[];
@@ -0,0 +1,91 @@
1
+ /** trove 自身调用 LLM 的 token 用量台账:一次调用一行,只追加到 usage.jsonl。 */
2
+ import { appendFile, mkdir, readFile } from 'node:fs/promises';
3
+ import { dirname } from 'node:path';
4
+ /** 追加写 sink:目录不存在自建,单行 JSON;写失败由调用方决定是否忽略。 */
5
+ export function createUsageSink(path, now = () => new Date()) {
6
+ // shortcut: 台账只追加不轮转,单行约 150B;增长到数十万行影响读取时再加轮转。
7
+ return async (usage) => {
8
+ const record = { at: now().toISOString(), ...usage };
9
+ await mkdir(dirname(path), { recursive: true });
10
+ await appendFile(path, `${JSON.stringify(record)}\n`, 'utf8');
11
+ };
12
+ }
13
+ /** 读取台账;文件不存在或单行损坏都跳过,不阻断统计。 */
14
+ export async function readUsageRecords(path) {
15
+ let text;
16
+ try {
17
+ text = await readFile(path, 'utf8');
18
+ }
19
+ catch (err) {
20
+ if (err.code === 'ENOENT')
21
+ return [];
22
+ throw err;
23
+ }
24
+ const out = [];
25
+ for (const line of text.split('\n')) {
26
+ if (!line.trim())
27
+ continue;
28
+ try {
29
+ const r = JSON.parse(line);
30
+ if (typeof r.at !== 'string' || typeof r.task !== 'string' || typeof r.model !== 'string')
31
+ continue;
32
+ out.push({
33
+ at: r.at,
34
+ task: r.task,
35
+ model: r.model,
36
+ promptTokens: nonNegative(r.promptTokens),
37
+ completionTokens: nonNegative(r.completionTokens),
38
+ totalTokens: nonNegative(r.totalTokens),
39
+ });
40
+ }
41
+ catch {
42
+ // 损坏行跳过
43
+ }
44
+ }
45
+ return out;
46
+ }
47
+ export function summarizeUsage(records) {
48
+ const total = emptyBucket();
49
+ const byTask = {};
50
+ const byModel = {};
51
+ for (const r of records) {
52
+ addTo(total, r);
53
+ addTo((byTask[r.task] ??= emptyBucket()), r);
54
+ addTo((byModel[r.model] ??= emptyBucket()), r);
55
+ }
56
+ return { total, byTask, byModel };
57
+ }
58
+ const NUMBER = new Intl.NumberFormat('en-US');
59
+ /** CLI 展示:总计 + 按任务/模型分组。 */
60
+ export function formatUsageSummary(summary, since = 'all') {
61
+ if (summary.total.calls === 0)
62
+ return ['暂无 LLM 用量记录'];
63
+ return [
64
+ `LLM 用量(${since}): ${NUMBER.format(summary.total.calls)} 次调用 · ` +
65
+ `输入 ${NUMBER.format(summary.total.promptTokens)} · 输出 ${NUMBER.format(summary.total.completionTokens)} · ` +
66
+ `合计 ${NUMBER.format(summary.total.totalTokens)} tokens`,
67
+ '按任务:',
68
+ ...formatBuckets(summary.byTask),
69
+ '按模型:',
70
+ ...formatBuckets(summary.byModel),
71
+ ];
72
+ }
73
+ function formatBuckets(buckets) {
74
+ return Object.entries(buckets)
75
+ .sort(([an, a], [bn, b]) => b.totalTokens - a.totalTokens || an.localeCompare(bn))
76
+ .map(([name, b]) => ` ${name} · ${NUMBER.format(b.calls)} 次 · 输入 ${NUMBER.format(b.promptTokens)} · ` +
77
+ `输出 ${NUMBER.format(b.completionTokens)} · 合计 ${NUMBER.format(b.totalTokens)}`);
78
+ }
79
+ function emptyBucket() {
80
+ return { calls: 0, promptTokens: 0, completionTokens: 0, totalTokens: 0 };
81
+ }
82
+ function addTo(bucket, r) {
83
+ bucket.calls++;
84
+ bucket.promptTokens += r.promptTokens;
85
+ bucket.completionTokens += r.completionTokens;
86
+ bucket.totalTokens += r.totalTokens;
87
+ }
88
+ function nonNegative(v) {
89
+ return typeof v === 'number' && Number.isFinite(v) && v >= 0 ? v : 0;
90
+ }
91
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/core/lessons/usage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /** 阶段 7:把阶段 6 的操作落盘为 .md 文件,并同步 INDEX.md 与 .overview.md。 */
2
+ import type { MemoryOp } from './merge.js';
3
+ import type { StorageAdapter } from './storage.js';
4
+ export interface WriteDeps {
5
+ storage: StorageAdapter;
6
+ /** 可控时钟,便于测试 updated_at 变化;缺省用系统时间。 */
7
+ now?: () => Date;
8
+ /** 记忆来源会话标识(harness:session 或 session id),写入 frontmatter.source。 */
9
+ source?: string;
10
+ }
11
+ export interface ApplyResult {
12
+ added: string[];
13
+ updated: string[];
14
+ appended: string[];
15
+ archived: string[];
16
+ skipped: string[];
17
+ }
18
+ export declare function applyOperations(ops: MemoryOp[], deps: WriteDeps): Promise<ApplyResult>;
@@ -0,0 +1,131 @@
1
+ import { renderFrontmatter } from './frontmatter.js';
2
+ import { INDEX_TEMPLATE } from './layout.js';
3
+ import { touchSidecars } from './sidecar.js';
4
+ const SECTION = {
5
+ preferences: 'Preferences',
6
+ entities: 'Entities',
7
+ experiences: 'Experiences',
8
+ events: 'Events',
9
+ resources: 'Resources',
10
+ };
11
+ export async function applyOperations(ops, deps) {
12
+ const now = () => (deps.now ?? (() => new Date()))().toISOString();
13
+ const res = { added: [], updated: [], appended: [], archived: [], skipped: [] };
14
+ for (const op of ops) {
15
+ if (op.op === 'add') {
16
+ await deps.storage.write(op.path, renderFile(op.type, op.title, op.content, { createdAt: now(), updatedAt: now() }, deps.source));
17
+ res.added.push(op.path);
18
+ if (op.supersedePath && (await archiveFile(op.supersedePath, op.path, deps.storage))) {
19
+ res.archived.push(op.supersedePath);
20
+ }
21
+ }
22
+ else if (op.op === 'patch') {
23
+ const existing = await deps.storage.read(op.path);
24
+ const createdAt = existing ? (extractField(existing, 'created_at') ?? now()) : now();
25
+ await deps.storage.write(op.path, renderFile(op.type, op.title, op.content, { createdAt, updatedAt: now() }, deps.source));
26
+ res.updated.push(op.path);
27
+ }
28
+ else if (op.op === 'append') {
29
+ const existing = (await deps.storage.read(op.path)) ?? '';
30
+ const sep = existing && !existing.endsWith('\n') ? '\n' : '';
31
+ await deps.storage.write(op.path, existing + sep + op.content + '\n');
32
+ res.appended.push(op.path);
33
+ }
34
+ else {
35
+ res.skipped.push(op.title);
36
+ }
37
+ }
38
+ await updateIndex(ops, deps.storage);
39
+ await touchSidecars(deps.storage, affectedDirs(ops), { trigger: 'memory_write', now: deps.now });
40
+ return res;
41
+ }
42
+ function renderFile(type, title, content, o, source) {
43
+ return renderFrontmatter({ type, title, tags: deriveTags(type), createdAt: o.createdAt, updatedAt: o.updatedAt, source }) + '\n' + content + '\n';
44
+ }
45
+ function deriveTags(type) {
46
+ return type.split('/');
47
+ }
48
+ function deriveSummary(content) {
49
+ const first = content.split('\n').find((l) => l.trim())?.trim() ?? '';
50
+ return first.length > 80 ? `${first.slice(0, 80)}…` : first;
51
+ }
52
+ async function archiveFile(oldPath, newPath, storage) {
53
+ const oldText = await storage.read(oldPath);
54
+ if (oldText === null)
55
+ return false;
56
+ await storage.write(`archive/${oldPath}`, withSupersededBy(oldText, newPath));
57
+ await storage.delete(oldPath);
58
+ return true;
59
+ }
60
+ function withSupersededBy(text, newPath) {
61
+ const closing = text.indexOf('\n---');
62
+ if (closing === -1)
63
+ return text;
64
+ const line = `\nsuperseded_by: ${JSON.stringify(newPath)}`;
65
+ return text.slice(0, closing) + line + text.slice(closing);
66
+ }
67
+ function extractField(text, key) {
68
+ const m = text.match(new RegExp(`^${key}: (.+)$`, 'm'));
69
+ if (!m)
70
+ return undefined;
71
+ const raw = m[1].trim();
72
+ try {
73
+ return JSON.parse(raw);
74
+ }
75
+ catch {
76
+ return raw;
77
+ }
78
+ }
79
+ async function updateIndex(ops, storage) {
80
+ let text = (await storage.read('INDEX.md')) ?? INDEX_TEMPLATE;
81
+ for (const op of ops) {
82
+ if (op.op === 'add') {
83
+ if (op.supersedePath)
84
+ text = removeIndexRow(text, op.supersedePath);
85
+ text = addIndexRow(text, op);
86
+ }
87
+ else if (op.op === 'patch') {
88
+ text = patchIndexRow(text, op);
89
+ }
90
+ // append / skip 不进 INDEX
91
+ }
92
+ await storage.write('INDEX.md', text);
93
+ }
94
+ function indexRow(o) {
95
+ return `- ${o.title} — ${deriveSummary(o.content)} (${o.path}) · tags: ${deriveTags(o.type).join(', ')}`;
96
+ }
97
+ function addIndexRow(text, o) {
98
+ const section = SECTION[o.type.split('/')[0]];
99
+ if (!section)
100
+ return text;
101
+ const lines = text.split('\n');
102
+ const idx = lines.findIndex((l) => l === `## ${section}`);
103
+ if (idx === -1)
104
+ return text;
105
+ lines.splice(idx + 1, 0, indexRow(o));
106
+ return lines.join('\n');
107
+ }
108
+ function patchIndexRow(text, o) {
109
+ const lines = text.split('\n');
110
+ const i = lines.findIndex((l) => l.includes(`(${o.path})`));
111
+ if (i === -1)
112
+ return addIndexRow(text, o);
113
+ lines[i] = indexRow(o);
114
+ return lines.join('\n');
115
+ }
116
+ function removeIndexRow(text, path) {
117
+ return text.split('\n').filter((l) => !l.includes(`(${path})`)).join('\n');
118
+ }
119
+ /** 本次写入涉及的顶层目录(根 + 各类目),用于触发对应 sidecar 的脏标记与刷新。 */
120
+ function affectedDirs(ops) {
121
+ const dirs = new Set(['']);
122
+ for (const op of ops) {
123
+ if (op.op === 'add' || op.op === 'patch' || op.op === 'append') {
124
+ const top = op.type.split('/')[0];
125
+ if (top)
126
+ dirs.add(top);
127
+ }
128
+ }
129
+ return [...dirs];
130
+ }
131
+ //# sourceMappingURL=write.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/core/lessons/write.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAkB7C,MAAM,OAAO,GAA2B;IACtC,WAAW,EAAE,aAAa;IAC1B,QAAQ,EAAE,UAAU;IACpB,WAAW,EAAE,aAAa;IAC1B,MAAM,EAAE,QAAQ;IAChB,SAAS,EAAE,WAAW;CACvB,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,GAAe,EAAE,IAAe;IACpE,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC;IACnE,MAAM,GAAG,GAAgB,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;IAE7F,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,EAAE,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;YACpB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAClI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YACxB,IAAI,EAAE,CAAC,aAAa,IAAI,CAAC,MAAM,WAAW,CAAC,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;gBACrF,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC;YACtC,CAAC;QACH,CAAC;aAAM,IAAI,EAAE,CAAC,EAAE,KAAK,OAAO,EAAE,CAAC;YAC7B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;YAClD,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE,YAAY,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;YACrF,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAC3H,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,EAAE,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1D,MAAM,GAAG,GAAG,QAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,GAAG,GAAG,EAAE,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;YACtE,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,MAAM,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACjG,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,KAAa,EAAE,OAAe,EAAE,CAA2C,EAAE,MAAe;IAC5H,OAAO,iBAAiB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,OAAO,GAAG,IAAI,CAAC;AACpJ,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AAED,SAAS,aAAa,CAAC,OAAe;IACpC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACtE,OAAO,KAAK,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AAC9D,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,OAAe,EAAE,OAAuB;IAClF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACnC,MAAM,OAAO,CAAC,KAAK,CAAC,WAAW,OAAO,EAAE,EAAE,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAC9E,MAAM,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY,EAAE,OAAe;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,OAAO,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,IAAI,GAAG,oBAAoB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;IAC3D,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,GAAW;IAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC;IACxD,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,CAAC;IACb,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,GAAe,EAAE,OAAuB;IACjE,IAAI,IAAI,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,cAAc,CAAC;IAC9D,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,EAAE,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;YACpB,IAAI,EAAE,CAAC,aAAa;gBAAE,IAAI,GAAG,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC;YACpE,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC/B,CAAC;aAAM,IAAI,EAAE,CAAC,EAAE,KAAK,OAAO,EAAE,CAAC;YAC7B,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACjC,CAAC;QACD,yBAAyB;IAC3B,CAAC;IACD,MAAM,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,QAAQ,CAAC,CAAiE;IACjF,OAAO,KAAK,CAAC,CAAC,KAAK,MAAM,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,aAAa,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC3G,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,CAAiE;IAClG,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;IAC/C,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,MAAM,OAAO,EAAE,CAAC,CAAC;IAC1D,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5B,KAAK,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,aAAa,CAAC,IAAY,EAAE,CAAiE;IACpG,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IAC5D,IAAI,CAAC,KAAK,CAAC,CAAC;QAAE,OAAO,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1C,KAAK,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACvB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,cAAc,CAAC,IAAY,EAAE,IAAY;IAChD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC7E,CAAC;AAED,mDAAmD;AACnD,SAAS,YAAY,CAAC,GAAe;IACnC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IACnC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,EAAE,CAAC,EAAE,KAAK,KAAK,IAAI,EAAE,CAAC,EAAE,KAAK,OAAO,IAAI,EAAE,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YAC/D,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAClC,IAAI,GAAG;gBAAE,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AACnB,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { State } from '../state.js';
2
+ export declare const MAPPER_VERSION = "events@4";
3
+ export interface BuildOptions {
4
+ vaultRoot: string;
5
+ deviceId: string;
6
+ state: State;
7
+ now?: () => number;
8
+ }
9
+ export interface BuildResult {
10
+ sessions: number;
11
+ events: number;
12
+ skills: number;
13
+ written: number;
14
+ }
15
+ export declare function shardRelPath(deviceId: string): string;
16
+ /**
17
+ * 把本设备 raw 归档构建成 library:
18
+ * library/sessions/<harness>/<session>/<device>.jsonl (每设备一份)
19
+ * library/index/<device>.json (本设备索引分片)
20
+ * 然后重建统一索引。
21
+ */
22
+ export declare function buildLibrary(opts: BuildOptions): Promise<BuildResult>;