@theseus-whale/dsh-continuity 0.0.0-stage → 4.12.2

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 (258) hide show
  1. package/INSTALL.md +25 -0
  2. package/PANEL.md +92 -0
  3. package/README.md +286 -2
  4. package/RELEASE-NOTES.md +732 -0
  5. package/bin/bc-acceptance-full.mjs +91 -0
  6. package/bin/bc-acceptance-tight.mjs +66 -0
  7. package/bin/bc-acceptance.mjs +22 -0
  8. package/bin/bc-add-keywords.mjs +21 -0
  9. package/bin/bc-demo.mjs +47 -0
  10. package/bin/bc-expand-hint.mjs +179 -0
  11. package/bin/bc-ingest-index.mjs +35 -0
  12. package/bin/bc-ingest.mjs +31 -0
  13. package/bin/bc-label-demo.mjs +18 -0
  14. package/bin/bc-relabel.mjs +150 -0
  15. package/bin/bc-sessionize.mjs +59 -0
  16. package/bin/coref_pipeline.py +47 -0
  17. package/bin/coref_service.py +57 -0
  18. package/bin/debug_ckip.py +16 -0
  19. package/bin/debug_ner_zh.py +18 -0
  20. package/bin/doctor.mjs +275 -0
  21. package/bin/en_ner_error_audit.py +33 -0
  22. package/bin/eval-label-rules.mjs +342 -0
  23. package/bin/export-turns.py +68 -0
  24. package/bin/extract-user-paragraph.mjs +14 -0
  25. package/bin/extraction-composite-smoke.mjs +28 -0
  26. package/bin/extraction-latency.mjs +58 -0
  27. package/bin/extraction-user-smoke.mjs +28 -0
  28. package/bin/extraction_service.py +164 -0
  29. package/bin/facet-active-experiment.mjs +110 -0
  30. package/bin/facet-covid.mjs +8 -0
  31. package/bin/facet-curve.mjs +27 -0
  32. package/bin/facet-embedding-train.mjs +20 -0
  33. package/bin/facet-embedding-validate.mjs +83 -0
  34. package/bin/facet-eval-roleplay.mjs +42 -0
  35. package/bin/facet-eval.mjs +38 -0
  36. package/bin/facet-fold.mjs +31 -0
  37. package/bin/facet-load.mjs +16 -0
  38. package/bin/facet-mlp-scan.mjs +45 -0
  39. package/bin/facet-mvp.mjs +34 -0
  40. package/bin/facet-online-experiments.mjs +78 -0
  41. package/bin/facet-online-race.mjs +99 -0
  42. package/bin/facet-online-validate.mjs +51 -0
  43. package/bin/facet-panel.mjs +22 -0
  44. package/bin/facet-passage.mjs +41 -0
  45. package/bin/facet-random-validate.mjs +48 -0
  46. package/bin/facet-roleplay.mjs +33 -0
  47. package/bin/facet-scan.mjs +56 -0
  48. package/bin/facet-segment.mjs +34 -0
  49. package/bin/facet-train.mjs +19 -0
  50. package/bin/facet-validate.mjs +103 -0
  51. package/bin/facet-zeroshot.mjs +14 -0
  52. package/bin/install-templates.mjs +72 -0
  53. package/bin/memory-bench.mjs +53 -0
  54. package/bin/memory-build-summary.mjs +43 -0
  55. package/bin/memory-build-vector.mjs +31 -0
  56. package/bin/memory-build.mjs +41 -0
  57. package/bin/memory-calibration.mjs +70 -0
  58. package/bin/memory-closed-loop.mjs +119 -0
  59. package/bin/memory-dry-run.mjs +70 -0
  60. package/bin/memory-eval.mjs +104 -0
  61. package/bin/memory-event-alias-test.mjs +89 -0
  62. package/bin/memory-extraction-bench.mjs +58 -0
  63. package/bin/memory-load-gate-replay.mjs +137 -0
  64. package/bin/memory-loop-test.mjs +90 -0
  65. package/bin/memory-pre-turn-harness.mjs +63 -0
  66. package/bin/memory-query.mjs +39 -0
  67. package/bin/memory-replay-hints.mjs +84 -0
  68. package/bin/memory-scale.mjs +58 -0
  69. package/bin/memory-scenario-test.mjs +146 -0
  70. package/bin/memory-user-loop.mjs +95 -0
  71. package/bin/ner_bench_tiny_zh.py +59 -0
  72. package/bin/ner_bench_zh.py +60 -0
  73. package/bin/ner_conll_en.py +139 -0
  74. package/bin/ner_direct_en.py +123 -0
  75. package/bin/ner_direct_zh.py +100 -0
  76. package/bin/ner_pipeline.py +208 -0
  77. package/bin/noise-selfcheck.mjs +50 -0
  78. package/bin/pack-integrity.mjs +47 -0
  79. package/bin/panel-check.mjs +57 -0
  80. package/bin/plugin-integrity.mjs +74 -0
  81. package/bin/preview-live.mjs +13 -0
  82. package/bin/public-install-check.mjs +222 -0
  83. package/bin/relabel-apply.mjs +272 -0
  84. package/bin/relabel-dry-run.mjs +381 -0
  85. package/bin/relik_pipeline.py +39 -0
  86. package/bin/relik_service.py +52 -0
  87. package/bin/srl_pipeline.py +55 -0
  88. package/bin/srl_service.py +68 -0
  89. package/bin/summary-index.mjs +151 -0
  90. package/bin/summary-query.mjs +79 -0
  91. package/bin/vec-check.mjs +27 -0
  92. package/bin/zh_ner_error_audit.py +36 -0
  93. package/bin/zh_ner_slot_eval.py +38 -0
  94. package/client.js +760 -0
  95. package/cordis.patch.yml +378 -0
  96. package/docs/API-NOTES.md +1743 -0
  97. package/docs/ARCHITECTURE.md +355 -0
  98. package/docs/CACHE.md +253 -0
  99. package/docs/CONDUCT.md +30 -0
  100. package/docs/CREATOR-HANDOFF.md +102 -0
  101. package/docs/EXPERIMENT.md +136 -0
  102. package/docs/FACET-MVP-REPORT.md +473 -0
  103. package/docs/GUIDE-0.4.66.md +195 -0
  104. package/docs/GUIDE.md +127 -0
  105. package/docs/MECHANISM.md +243 -0
  106. package/docs/NEW-INSTANCE-HANDOFF.md +219 -0
  107. package/docs/README.md +37 -0
  108. package/docs/SESSION-LAYOUT.md +151 -0
  109. package/docs/history-map.md +249 -0
  110. package/docs/relabel-migration-wiring.md +366 -0
  111. package/guides/00-READ-FIRST.md +206 -0
  112. package/guides/01-INSTALL.md +207 -0
  113. package/guides/02-TABLES.md +225 -0
  114. package/guides/03-AUDIT.md +201 -0
  115. package/guides/04-REBUILD.md +306 -0
  116. package/guides/05-FIRST-RUN.md +191 -0
  117. package/guides/06-EMBEDDING.md +146 -0
  118. package/guides/07-PTC-AND-ASSETS.md +221 -0
  119. package/icon.svg +7 -0
  120. package/locale/en.json +6 -0
  121. package/locale/zh.json +6 -0
  122. package/models/README.md +13 -0
  123. package/models/Xenova/bge-small-zh-v1.5/config.json +31 -0
  124. package/models/Xenova/bge-small-zh-v1.5/onnx/model_quantized.onnx +0 -0
  125. package/models/Xenova/bge-small-zh-v1.5/tokenizer.json +21278 -0
  126. package/models/Xenova/bge-small-zh-v1.5/tokenizer_config.json +15 -0
  127. package/package.json +139 -4
  128. package/src/asset-tool.mjs +237 -0
  129. package/src/assets.mjs +244 -0
  130. package/src/backfill.mjs +74 -0
  131. package/src/backup.mjs +80 -0
  132. package/src/deadend.mjs +95 -0
  133. package/src/deleted-store.mjs +35 -0
  134. package/src/engine.mjs +3831 -0
  135. package/src/facets/classifier.mjs +146 -0
  136. package/src/facets/embedding-service.mjs +53 -0
  137. package/src/facets/embedding-worker.mjs +27 -0
  138. package/src/facets/embedding.mjs +163 -0
  139. package/src/facets/extract.mjs +80 -0
  140. package/src/facets/fold-plan.mjs +84 -0
  141. package/src/facets/hybrid.mjs +29 -0
  142. package/src/facets/index.mjs +113 -0
  143. package/src/facets/linear-probe.mjs +43 -0
  144. package/src/facets/load.mjs +37 -0
  145. package/src/facets/mlp-probe.mjs +54 -0
  146. package/src/facets/mlp-service.mjs +53 -0
  147. package/src/facets/mlp-worker.mjs +26 -0
  148. package/src/facets/online-knn.mjs +58 -0
  149. package/src/facets/online-models.mjs +227 -0
  150. package/src/facets/panel-state.mjs +23 -0
  151. package/src/facets/panel.mjs +73 -0
  152. package/src/facets/random.mjs +26 -0
  153. package/src/facets/scanner.mjs +35 -0
  154. package/src/facets/schema.mjs +75 -0
  155. package/src/facets/seed-examples.mjs +58 -0
  156. package/src/facets/sensitivity.mjs +98 -0
  157. package/src/facets/service.mjs +53 -0
  158. package/src/facets/store.mjs +39 -0
  159. package/src/facets/worker.mjs +23 -0
  160. package/src/folds-store.mjs +109 -0
  161. package/src/groups.mjs +167 -0
  162. package/src/handoff-tool.mjs +51 -0
  163. package/src/handoff.mjs +127 -0
  164. package/src/index.mjs +649 -0
  165. package/src/inject-policy.mjs +17 -0
  166. package/src/learning.mjs +88 -0
  167. package/src/memory/alias-proposal.mjs +40 -0
  168. package/src/memory/bc-audit.mjs +245 -0
  169. package/src/memory/bc-index-updater.mjs +404 -0
  170. package/src/memory/bc-index.mjs +48 -0
  171. package/src/memory/bc-label.mjs +220 -0
  172. package/src/memory/bc-panel-state.mjs +107 -0
  173. package/src/memory/bc-pre-step.mjs +463 -0
  174. package/src/memory/bc-recall.mjs +470 -0
  175. package/src/memory/bc-shift.mjs +123 -0
  176. package/src/memory/bc-store.mjs +41 -0
  177. package/src/memory/bm25.mjs +112 -0
  178. package/src/memory/calibration.mjs +54 -0
  179. package/src/memory/chatter.mjs +29 -0
  180. package/src/memory/cmap-file.mjs +107 -0
  181. package/src/memory/concepts-file.mjs +41 -0
  182. package/src/memory/coref-slots.mjs +40 -0
  183. package/src/memory/event-alias-ledger.mjs +87 -0
  184. package/src/memory/event-log.mjs +95 -0
  185. package/src/memory/event-model.mjs +132 -0
  186. package/src/memory/event-segmenter.mjs +36 -0
  187. package/src/memory/event-summary-tree.mjs +122 -0
  188. package/src/memory/extraction-adapter.mjs +76 -0
  189. package/src/memory/extraction-composite.mjs +75 -0
  190. package/src/memory/extraction-core.mjs +76 -0
  191. package/src/memory/extraction-pre-step.mjs +161 -0
  192. package/src/memory/extraction-provider.mjs +300 -0
  193. package/src/memory/extraction-score.mjs +36 -0
  194. package/src/memory/facet-stabilizer.mjs +59 -0
  195. package/src/memory/history-map.mjs +139 -0
  196. package/src/memory/language-router.mjs +30 -0
  197. package/src/memory/load-gate.mjs +161 -0
  198. package/src/memory/mechanical-note.mjs +104 -0
  199. package/src/memory/onboarding.mjs +163 -0
  200. package/src/memory/persona.mjs +78 -0
  201. package/src/memory/planner.mjs +249 -0
  202. package/src/memory/pre-turn.mjs +80 -0
  203. package/src/memory/query-aliases.mjs +39 -0
  204. package/src/memory/recall-cue.mjs +43 -0
  205. package/src/memory/recall.mjs +65 -0
  206. package/src/memory/referent-candidates.mjs +55 -0
  207. package/src/memory/referent-ledger.mjs +86 -0
  208. package/src/memory/relabel-migrate.mjs +376 -0
  209. package/src/memory/relik-adapter.mjs +25 -0
  210. package/src/memory/special-keywords.mjs +60 -0
  211. package/src/memory/structured-adapters.mjs +75 -0
  212. package/src/memory/summary-index.mjs +335 -0
  213. package/src/memory/summary-tree.mjs +110 -0
  214. package/src/memory/term-extractor.mjs +44 -0
  215. package/src/memory/tokenize.mjs +9 -0
  216. package/src/memory/vector-index.mjs +54 -0
  217. package/src/memory/window-summary.mjs +133 -0
  218. package/src/mood.mjs +133 -0
  219. package/src/peer-tool.mjs +63 -0
  220. package/src/peer.mjs +144 -0
  221. package/src/policy.mjs +170 -0
  222. package/src/preflight.mjs +113 -0
  223. package/src/provenance.mjs +94 -0
  224. package/src/range.mjs +75 -0
  225. package/src/recall-exact-tool.mjs +267 -0
  226. package/src/recall-tool.mjs +521 -0
  227. package/src/recheck.mjs +99 -0
  228. package/src/save-start.mjs +29 -0
  229. package/src/session-guard.mjs +140 -0
  230. package/src/session-log-tool.mjs +322 -0
  231. package/src/session-log.mjs +606 -0
  232. package/src/skills.mjs +111 -0
  233. package/src/split-range.mjs +115 -0
  234. package/src/state.mjs +198 -0
  235. package/src/t0.mjs +149 -0
  236. package/src/tag-confirm.mjs +78 -0
  237. package/src/tag-detect.mjs +42 -0
  238. package/src/tag-maintenance.mjs +285 -0
  239. package/src/tag-reject.mjs +73 -0
  240. package/src/tags-store.mjs +94 -0
  241. package/src/tags.mjs +692 -0
  242. package/src/threads-backend.mjs +26 -0
  243. package/src/threads-core.mjs +1887 -0
  244. package/src/threads-store.mjs +207 -0
  245. package/src/threads-tool.mjs +522 -0
  246. package/src/threads.mjs +929 -0
  247. package/src/tool-preview.mjs +427 -0
  248. package/src/topic.mjs +63 -0
  249. package/src/training.mjs +75 -0
  250. package/src/turn-tag.mjs +62 -0
  251. package/src/user-turn.mjs +39 -0
  252. package/templates/cmap.md +11 -0
  253. package/templates/concepts.md +12 -0
  254. package/templates/habits.md +40 -0
  255. package/templates/keywords.md +6 -0
  256. package/templates/rebuild.md +134 -0
  257. package/templates/rules-safe.md +184 -0
  258. package/templates/rules.md +177 -0
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Build the middle-layer summary index from one raw session.
4
+ *
5
+ * Phase 0/1:
6
+ * - imports existing compaction/summary records (native checkpoint + gist)
7
+ * - plans missing windows by seq/token gaps
8
+ * - dry-run by default; --apply writes summaries/index.json
9
+ *
10
+ * Usage:
11
+ * node bin/summary-index.mjs --raw <session.v4.jsonl.zstd> [--out <index.json>] [--json]
12
+ * node bin/summary-index.mjs --raw ... --apply [--session-dir <dir>]
13
+ */
14
+ import fs from 'node:fs';
15
+ import path from 'node:path';
16
+ import zlib from 'node:zlib';
17
+ import { buildSummaryIndex, summaryIndexPath } from '../src/memory/summary-index.mjs';
18
+ import { buildWindowSummary } from '../src/memory/window-summary.mjs';
19
+
20
+ function arg(name, fallback = null) {
21
+ const i = process.argv.indexOf(`--${name}`);
22
+ return i >= 0 ? process.argv[i + 1] ?? fallback : fallback;
23
+ }
24
+
25
+ function readRawLines(file) {
26
+ if (!/\.zstd$/i.test(file)) {
27
+ return fs.readFileSync(file, 'utf8').replace(/^\uFEFF/, '').split(/\r?\n/).filter(Boolean);
28
+ }
29
+ const buf = fs.readFileSync(file);
30
+ const magic = Buffer.from([0x28, 0xb5, 0x2f, 0xfd]);
31
+ const starts = [];
32
+ for (let at = 0; ;) {
33
+ const found = buf.indexOf(magic, at);
34
+ if (found < 0) break;
35
+ starts.push(found);
36
+ at = found + magic.length;
37
+ }
38
+ const lines = [];
39
+ for (const start of starts) {
40
+ let out;
41
+ try { out = zlib.zstdDecompressSync(buf.subarray(start)); } catch { continue; }
42
+ lines.push(...out.toString('utf8').split(/\r?\n/).filter(Boolean));
43
+ }
44
+ return lines;
45
+ }
46
+
47
+ const raw = arg('raw');
48
+ if (!raw) {
49
+ console.error('用法: node bin/summary-index.mjs --raw <session.v4.jsonl[.zstd]> [--out <index.json>] [--apply] [--json]');
50
+ process.exit(2);
51
+ }
52
+ if (!fs.existsSync(raw)) {
53
+ console.error(`raw not found: ${raw}`);
54
+ process.exit(2);
55
+ }
56
+
57
+ const sessionDirArg = arg('session-dir');
58
+ const sessionDir = sessionDirArg ?? path.dirname(raw);
59
+ const sessionId = arg('session-id', path.basename(sessionDir));
60
+ const windowTokens = Math.max(1000, Number(arg('window-tokens', 40000)) || 40000);
61
+ const outArg = arg('out');
62
+ const out = outArg ?? (sessionDirArg ? summaryIndexPath(sessionDirArg) : null);
63
+ const apply = process.argv.includes('--apply');
64
+ const extractPending = process.argv.includes('--extract-pending');
65
+ const printJson = process.argv.includes('--json');
66
+ if (apply && !out) {
67
+ console.error('--apply requires explicit --session-dir (Continuity session dir) or --out');
68
+ process.exit(2);
69
+ }
70
+
71
+ const events = [];
72
+ const seen = new Set();
73
+ for (const line of readRawLines(raw)) {
74
+ let event;
75
+ try { event = JSON.parse(line.replace(/^\uFEFF/, '')); } catch { continue; }
76
+ const seq = Number(event?.seq);
77
+ if (Number.isInteger(seq)) {
78
+ if (seen.has(seq)) continue;
79
+ seen.add(seq);
80
+ }
81
+ events.push(event);
82
+ }
83
+ events.sort((a, b) => Number(a.seq) - Number(b.seq));
84
+
85
+ const bootstrapFile = path.join(sessionDir, 'summaries', 'bootstrap-ranges.json');
86
+ let bootstrapRanges = [];
87
+ try {
88
+ if (fs.existsSync(bootstrapFile)) {
89
+ const parsed = JSON.parse(fs.readFileSync(bootstrapFile, 'utf8'));
90
+ if (Array.isArray(parsed?.ranges)) bootstrapRanges = parsed.ranges;
91
+ }
92
+ } catch { /* malformed sidecar is ignored; index still builds */ }
93
+
94
+ const baseIndex = buildSummaryIndex({ sessionId, events, windowTokens, bootstrapRanges });
95
+ const windowSummaries = extractPending
96
+ ? baseIndex.pendingWindows.map((pending) => buildWindowSummary({
97
+ events,
98
+ fromSeq: pending.fromSeq,
99
+ toSeq: pending.toSeq,
100
+ maxTokens: 800,
101
+ }))
102
+ : [];
103
+ const windowRanges = windowSummaries.map((summary) => ({
104
+ fromSeq: summary.fromSeq,
105
+ toSeq: summary.toSeq,
106
+ tokens: summary.approxTokens,
107
+ hash: summary.hash,
108
+ at: new Date().toISOString(),
109
+ }));
110
+ const index = windowSummaries.length > 0
111
+ ? buildSummaryIndex({ sessionId, events, windowTokens, bootstrapRanges, windowRanges, windowRecords: windowSummaries })
112
+ : baseIndex;
113
+ if (apply && extractPending) {
114
+ const windowDir = path.join(path.dirname(out), 'windows');
115
+ fs.mkdirSync(windowDir, { recursive: true });
116
+ for (const summary of windowSummaries) {
117
+ fs.writeFileSync(
118
+ path.join(windowDir, `${summary.fromSeq}-${summary.toSeq}.json`),
119
+ JSON.stringify(summary, null, 2),
120
+ 'utf8',
121
+ );
122
+ }
123
+ }
124
+ if (apply) {
125
+ fs.mkdirSync(path.dirname(out), { recursive: true });
126
+ const tmp = `${out}.tmp-${process.pid}`;
127
+ fs.writeFileSync(tmp, JSON.stringify(index, null, 2), 'utf8');
128
+ fs.renameSync(tmp, out);
129
+ }
130
+
131
+ if (printJson) {
132
+ console.log(JSON.stringify(index, null, 2));
133
+ } else {
134
+ console.log(JSON.stringify({
135
+ sessionId: index.sessionId,
136
+ raw: path.resolve(raw),
137
+ out: apply ? path.resolve(out) : null,
138
+ apply,
139
+ windowTokens: index.windowTokens,
140
+ maxSummarySeq: index.maxSummarySeq,
141
+ coveredThroughSeq: index.coveredThroughSeq,
142
+ latestSummaryAt: index.latestSummaryAt,
143
+ records: index.records.length,
144
+ checkpoints: index.records.filter((record) => record.kind === 'checkpoint').length,
145
+ gists: index.records.filter((record) => record.kind === 'gist').length,
146
+ pendingWindows: index.pendingWindows.length,
147
+ pending: index.pendingWindows.slice(0, 8),
148
+ extractedWindows: windowSummaries.length,
149
+ coverage: index.coverage,
150
+ }, null, 2));
151
+ }
@@ -0,0 +1,79 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Read-only query over the Continuity summary index.
4
+ * This is a first step for recall's summaryHits; no model, no writes.
5
+ *
6
+ * Usage:
7
+ * node bin/summary-query.mjs --index <index.json> --query "..." [--limit 5] [--json]
8
+ * node bin/summary-query.mjs --session-dir <dir> --query "..."
9
+ */
10
+ import fs from 'node:fs';
11
+ import path from 'node:path';
12
+ import { summaryIndexPath } from '../src/memory/summary-index.mjs';
13
+
14
+ function arg(name, fallback = null) {
15
+ const i = process.argv.indexOf(`--${name}`);
16
+ return i >= 0 ? process.argv[i + 1] ?? fallback : fallback;
17
+ }
18
+
19
+ const sessionDir = arg('session-dir');
20
+ const indexFile = arg('index', sessionDir ? summaryIndexPath(sessionDir) : null);
21
+ const query = String(arg('query', '')).trim();
22
+ const limit = Math.min(Math.max(Number(arg('limit', 5)) || 5, 1), 50);
23
+ const json = process.argv.includes('--json');
24
+ if (!indexFile || !fs.existsSync(indexFile)) {
25
+ console.error('summary index not found; pass --index or --session-dir');
26
+ process.exit(2);
27
+ }
28
+ if (!query) {
29
+ console.error('query required');
30
+ process.exit(2);
31
+ }
32
+
33
+ const index = JSON.parse(fs.readFileSync(indexFile, 'utf8').replace(/^\uFEFF/, ''));
34
+ const q = query.normalize('NFKC').toLowerCase();
35
+ const qChars = [...q];
36
+ const cjkQuery = /[\u3400-\u9fff]/.test(q);
37
+ const records = Array.isArray(index.records) ? index.records : [];
38
+ const scored = [];
39
+ for (const record of records) {
40
+ const text = String(record.text ?? '').normalize('NFKC').toLowerCase();
41
+ if (!text) continue;
42
+ let score = 0;
43
+ const exact = text.includes(q);
44
+ if (exact) score += 100;
45
+ if (cjkQuery && qChars.length >= 2) {
46
+ const covered = qChars.filter((ch) => text.includes(ch)).length;
47
+ if (covered === qChars.length) score += 5;
48
+ }
49
+ if (score > 0) scored.push({ record, score, exact });
50
+ }
51
+ scored.sort((a, b) => b.score - a.score || b.record.toSeq - a.record.toSeq);
52
+ const hits = scored.slice(0, limit).map(({ record, score, exact }) => ({
53
+ id: record.id,
54
+ kind: record.kind,
55
+ fromSeq: record.fromSeq,
56
+ toSeq: record.toSeq,
57
+ fromTurn: record.fromTurn,
58
+ toTurn: record.toTurn,
59
+ threads: record.threads,
60
+ approxTokens: record.approxTokens,
61
+ score: Number(score.toFixed(2)),
62
+ exact,
63
+ excerpt: String(record.text ?? '').slice(0, 500),
64
+ }));
65
+ const result = {
66
+ index: path.resolve(indexFile),
67
+ query,
68
+ total: scored.length,
69
+ shown: hits.length,
70
+ hits,
71
+ };
72
+ if (json) console.log(JSON.stringify(result, null, 2));
73
+ else {
74
+ console.log(`query=${query} total=${result.total} shown=${result.shown}`);
75
+ for (const hit of hits) {
76
+ console.log(`\n[${hit.kind}] ${hit.id} · turn ${hit.fromTurn ?? '?'}-${hit.toTurn ?? '?'} · seq ${hit.fromSeq}-${hit.toSeq} · score ${hit.score}`);
77
+ console.log(hit.excerpt.replace(/\s+/g, ' ').slice(0, 300));
78
+ }
79
+ }
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Check whether the local embedding runtime produces a usable vector.
4
+ *
5
+ * Run from the installed package:
6
+ * node bin/vec-check.mjs
7
+ */
8
+ import { embedTexts } from '../src/facets/embedding.mjs';
9
+
10
+ try {
11
+ const [vector] = await embedTexts(['连续性记忆审计自检']);
12
+ const dim = Array.isArray(vector) ? vector.length : 0;
13
+ const finite = Array.isArray(vector) && vector.every((value) => Number.isFinite(value));
14
+ console.log(JSON.stringify({
15
+ ok: dim > 0 && finite,
16
+ dimensions: dim,
17
+ first3: Array.isArray(vector) ? vector.slice(0, 3) : [],
18
+ }, null, 2));
19
+ if (dim === 0 || !finite) process.exit(1);
20
+ } catch (error) {
21
+ console.error(JSON.stringify({
22
+ ok: false,
23
+ error: String(error?.message ?? error),
24
+ hint: 'run pnpm approve-builds, then pnpm rebuild onnxruntime-node sharp in the DSH profile',
25
+ }, null, 2));
26
+ process.exit(1);
27
+ }
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+ import json
3
+ import sys
4
+ from collections import Counter
5
+
6
+ src, out = sys.argv[1], sys.argv[2]
7
+ data = json.load(open(src, encoding="utf-8"))
8
+ rows = data["rows"]
9
+ gold_count = Counter()
10
+ pred_count = Counter()
11
+ fp = []
12
+ fn = []
13
+ for row in rows:
14
+ gold = {(g["entity"], g["label"]) for g in row["gold"]}
15
+ pred = {(p["text"].replace(" ", ""), p["label"]) for p in row["pred"]}
16
+ for item in gold:
17
+ gold_count[item[1]] += 1
18
+ for item in pred:
19
+ pred_count[item[1]] += 1
20
+ for item in pred - gold:
21
+ fp.append({"text": item[0], "label": item[1], "sentence": row["text"]})
22
+ for item in gold - pred:
23
+ fn.append({"text": item[0], "label": item[1], "sentence": row["text"]})
24
+
25
+ summary = {
26
+ "n": data["n"],
27
+ "score": data["score"],
28
+ "gold_by_label": dict(gold_count),
29
+ "pred_by_label": dict(pred_count),
30
+ "fp_by_label": dict(Counter(x["label"] for x in fp)),
31
+ "fn_by_label": dict(Counter(x["label"] for x in fn)),
32
+ "fp_samples": fp[:20],
33
+ "fn_samples": fn[:20],
34
+ }
35
+ json.dump(summary, open(out, "w", encoding="utf-8"), ensure_ascii=False, indent=2)
36
+ print(json.dumps({k: v for k, v in summary.items() if not k.endswith("samples")}, ensure_ascii=False, indent=2))
@@ -0,0 +1,38 @@
1
+ # -*- coding: utf-8 -*-
2
+ import json
3
+ import sys
4
+
5
+ MAP = {
6
+ "name": "PERSON",
7
+ "address": "PLACE",
8
+ "scene": "PLACE",
9
+ "company": "ORG",
10
+ "organization": "ORG",
11
+ "government": "ORG",
12
+ "book": "WORK",
13
+ "movie": "WORK",
14
+ "game": "WORK",
15
+ "position": "ROLE",
16
+ }
17
+
18
+
19
+ def coarse(label):
20
+ return MAP.get(label, label)
21
+
22
+
23
+ data = json.load(open(sys.argv[1], encoding="utf-8"))
24
+ tp = fp = fn = 0
25
+ for row in data["rows"]:
26
+ gold = {(g["entity"], coarse(g["label"])) for g in row["gold"]}
27
+ pred = {(p["text"].replace(" ", ""), coarse(p["label"])) for p in row["pred"]}
28
+ tp += len(gold & pred)
29
+ fp += len(pred - gold)
30
+ fn += len(gold - pred)
31
+ precision = 0 if tp + fp == 0 else tp / (tp + fp)
32
+ recall = 0 if tp + fn == 0 else tp / (tp + fn)
33
+ f1 = 0 if precision + recall == 0 else 2 * precision * recall / (precision + recall)
34
+ print(json.dumps({
35
+ "n": data["n"],
36
+ "exact_label_f1": data["score"]["f1"],
37
+ "coarse_slot": {"tp": tp, "fp": fp, "fn": fn, "precision": round(precision, 4), "recall": round(recall, 4), "f1": round(f1, 4)},
38
+ }, ensure_ascii=False, indent=2))