eklavya 1.18.3 → 1.19.1

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 (132) hide show
  1. package/README.md +1 -1
  2. package/dist/assets/dashboard.html +570 -15
  3. package/dist/assets/tutor/SKILL.md +5 -5
  4. package/dist/assets/tutor/references/focus-and-level.md +34 -5
  5. package/dist/assets/tutor/references/grading.md +1 -1
  6. package/dist/cli.js +753 -41
  7. package/dist/cli.js.map +1 -1
  8. package/dist/config-path.js +156 -0
  9. package/dist/config-path.js.map +1 -0
  10. package/dist/config.js +448 -31
  11. package/dist/config.js.map +1 -1
  12. package/dist/dashboard.js +357 -1
  13. package/dist/dashboard.js.map +1 -1
  14. package/dist/eval/retrieval-score.js +77 -0
  15. package/dist/eval/retrieval-score.js.map +1 -0
  16. package/dist/hooks/capture-tool.js +107 -0
  17. package/dist/hooks/capture-tool.js.map +1 -0
  18. package/dist/hooks/checkpoint-quiz.js +2 -2
  19. package/dist/hooks/checkpoint-quiz.js.map +1 -1
  20. package/dist/hooks/lib.js +4 -30
  21. package/dist/hooks/lib.js.map +1 -1
  22. package/dist/hooks/memory-lib.js +181 -0
  23. package/dist/hooks/memory-lib.js.map +1 -0
  24. package/dist/hooks/pre-tool-gate.js +2 -2
  25. package/dist/hooks/pre-tool-gate.js.map +1 -1
  26. package/dist/hooks/prompt-submit-nudge.js +57 -20
  27. package/dist/hooks/prompt-submit-nudge.js.map +1 -1
  28. package/dist/hooks/session-start.js +110 -80
  29. package/dist/hooks/session-start.js.map +1 -1
  30. package/dist/hooks/stop-quiz-check.js +58 -38
  31. package/dist/hooks/stop-quiz-check.js.map +1 -1
  32. package/dist/hooks/subagent-start.js +2 -2
  33. package/dist/hooks/subagent-start.js.map +1 -1
  34. package/dist/install.js +37 -0
  35. package/dist/install.js.map +1 -1
  36. package/dist/memory/capture.js +123 -0
  37. package/dist/memory/capture.js.map +1 -0
  38. package/dist/memory/code.js +186 -0
  39. package/dist/memory/code.js.map +1 -0
  40. package/dist/memory/collections.js +87 -0
  41. package/dist/memory/collections.js.map +1 -0
  42. package/dist/memory/embed.js +81 -0
  43. package/dist/memory/embed.js.map +1 -0
  44. package/dist/memory/hosts.js +71 -0
  45. package/dist/memory/hosts.js.map +1 -0
  46. package/dist/memory/identity.js +74 -0
  47. package/dist/memory/identity.js.map +1 -0
  48. package/dist/memory/import.js +916 -0
  49. package/dist/memory/import.js.map +1 -0
  50. package/dist/memory/learning.js +148 -0
  51. package/dist/memory/learning.js.map +1 -0
  52. package/dist/memory/notify.js +220 -0
  53. package/dist/memory/notify.js.map +1 -0
  54. package/dist/memory/privacy.js +117 -0
  55. package/dist/memory/privacy.js.map +1 -0
  56. package/dist/memory/provider.js +155 -0
  57. package/dist/memory/provider.js.map +1 -0
  58. package/dist/memory/recall.js +327 -0
  59. package/dist/memory/recall.js.map +1 -0
  60. package/dist/memory/replay.js +174 -0
  61. package/dist/memory/replay.js.map +1 -0
  62. package/dist/memory/search.js +143 -0
  63. package/dist/memory/search.js.map +1 -0
  64. package/dist/memory/spool.js +93 -0
  65. package/dist/memory/spool.js.map +1 -0
  66. package/dist/memory/store.js +399 -0
  67. package/dist/memory/store.js.map +1 -0
  68. package/dist/memory/summarize.js +178 -0
  69. package/dist/memory/summarize.js.map +1 -0
  70. package/dist/memory/sync.js +595 -0
  71. package/dist/memory/sync.js.map +1 -0
  72. package/dist/memory/tokens.js +55 -0
  73. package/dist/memory/tokens.js.map +1 -0
  74. package/dist/memory/worker.js +207 -0
  75. package/dist/memory/worker.js.map +1 -0
  76. package/dist/migrations/009_memory.sql +226 -0
  77. package/dist/migrations/010_import.sql +26 -0
  78. package/dist/migrations/011_sync.sql +76 -0
  79. package/dist/migrations/012_job_backoff.sql +13 -0
  80. package/dist/migrations/013_batch_provenance.sql +18 -0
  81. package/dist/migrations/014_batch_events_index.sql +18 -0
  82. package/dist/packs.js +26 -12
  83. package/dist/packs.js.map +1 -1
  84. package/dist/paths.js +60 -0
  85. package/dist/paths.js.map +1 -1
  86. package/dist/plugin/.claude-plugin/plugin.json +1 -1
  87. package/dist/plugin/agents/tutor.md +3 -1
  88. package/dist/plugin/cli/CLAUDE.md +32 -8
  89. package/dist/plugin/cli/eklavya-gate +80 -9
  90. package/dist/plugin/hooks/CLAUDE.md +44 -19
  91. package/dist/plugin/hooks/hooks.json +10 -0
  92. package/dist/plugin/scripts/install-git-hook.sh +2 -1
  93. package/dist/plugin/skills/CLAUDE.md +29 -17
  94. package/dist/plugin/skills/gate/SKILL.md +1 -1
  95. package/dist/plugin/skills/level/SKILL.md +3 -3
  96. package/dist/plugin/skills/memory/SKILL.md +88 -0
  97. package/dist/plugin/skills/mode/SKILL.md +24 -16
  98. package/dist/plugin/skills/pack/SKILL.md +8 -4
  99. package/dist/plugin/skills/progress/SKILL.md +1 -1
  100. package/dist/plugin/skills/quiz/SKILL.md +2 -2
  101. package/dist/plugin/skills/setup/SKILL.md +25 -11
  102. package/dist/plugin/skills/tutor/SKILL.md +5 -5
  103. package/dist/plugin/skills/tutor/references/focus-and-level.md +34 -5
  104. package/dist/plugin/skills/tutor/references/grading.md +1 -1
  105. package/dist/session.js +1 -1
  106. package/dist/statusline.js +20 -6
  107. package/dist/statusline.js.map +1 -1
  108. package/dist/store.js +2 -2
  109. package/dist/store.js.map +1 -1
  110. package/dist/surface.js +1 -1
  111. package/dist/time.js +41 -0
  112. package/dist/time.js.map +1 -0
  113. package/dist/tools/code_tools.js +73 -0
  114. package/dist/tools/code_tools.js.map +1 -0
  115. package/dist/tools/collection_tools.js +92 -0
  116. package/dist/tools/collection_tools.js.map +1 -0
  117. package/dist/tools/config_tools.js +165 -32
  118. package/dist/tools/config_tools.js.map +1 -1
  119. package/dist/tools/get_learner_profile.js +2 -1
  120. package/dist/tools/get_learner_profile.js.map +1 -1
  121. package/dist/tools/get_session_quiz_plan.js +15 -9
  122. package/dist/tools/get_session_quiz_plan.js.map +1 -1
  123. package/dist/tools/index.js +15 -0
  124. package/dist/tools/index.js.map +1 -1
  125. package/dist/tools/memory_read_tools.js +277 -0
  126. package/dist/tools/memory_read_tools.js.map +1 -0
  127. package/dist/tools/memory_write_tools.js +115 -0
  128. package/dist/tools/memory_write_tools.js.map +1 -0
  129. package/dist/tools/types.js +1 -1
  130. package/dist/tools/types.js.map +1 -1
  131. package/dist/user-skill/eklavya/SKILL.md +95 -25
  132. package/package.json +2 -1
@@ -0,0 +1,123 @@
1
+ import { nowIso } from '../time.js';
2
+ import { eventUid, relativeToProject } from './identity.js';
3
+ import { DEFAULT_PRIVACY, isOwnTraffic, pathExcluded, redact, toolExcluded } from './privacy.js';
4
+ import { appendEvent } from './store.js';
5
+ import { spoolEvent, takeSpooled } from './spool.js';
6
+ /** Per-event body cap. Evidence is a pointer to work, not a copy of the repo. */
7
+ const MAX_BODY = 4000;
8
+ /**
9
+ * `minimal` keeps the shape of a session — what was asked, what was decided,
10
+ * where it started and stopped — and drops the per-file traffic that makes up
11
+ * most of the volume.
12
+ */
13
+ const MINIMAL_KINDS = ['prompt', 'assistant', 'lifecycle', 'note'];
14
+ export function policyFrom(config) {
15
+ return {
16
+ excludePaths: [...DEFAULT_PRIVACY.excludePaths, ...config.privacy.exclude_paths],
17
+ excludeTools: [...DEFAULT_PRIVACY.excludeTools, ...config.privacy.exclude_tools],
18
+ redactPatterns: config.privacy.redact_patterns,
19
+ };
20
+ }
21
+ /** Everything but the write: pure, so the exclusion rules are testable alone. */
22
+ export function prepare(config, identity, event) {
23
+ if (!config.memory.enabled || config.memory.capture === 'off')
24
+ return null;
25
+ if (config.memory.capture === 'minimal' && !MINIMAL_KINDS.includes(event.kind))
26
+ return null;
27
+ const policy = policyFrom(config);
28
+ if (toolExcluded(event.tool, policy))
29
+ return null;
30
+ if (isOwnTraffic(event.tool, event.body))
31
+ return null;
32
+ const files = (event.files ?? []).filter((f) => !pathExcluded(f, policy));
33
+ // A file event whose only file was excluded is the excluded file. Keeping the
34
+ // event for its body would re-admit through the back door what the path rule
35
+ // just shut out.
36
+ if ((event.kind === 'file_edit' || event.kind === 'file_read') && (event.files?.length ?? 0) > 0 && files.length === 0) {
37
+ return null;
38
+ }
39
+ const cleaned = redact(event.body.slice(0, MAX_BODY), policy);
40
+ const occurredAt = event.occurredAt ?? nowIso();
41
+ return {
42
+ eventUid: eventUid({
43
+ host: identity.host,
44
+ sessionId: identity.sessionId,
45
+ agentId: identity.agentId,
46
+ kind: event.kind,
47
+ tool: event.tool,
48
+ occurredAt,
49
+ body: cleaned.text,
50
+ }),
51
+ project: identity.project,
52
+ checkout: identity.checkout,
53
+ sessionId: identity.sessionId,
54
+ agentId: identity.agentId,
55
+ host: identity.host,
56
+ source: event.source ?? 'hook',
57
+ kind: event.kind,
58
+ tool: event.tool ?? null,
59
+ title: event.title ? redact(event.title, policy).text : null,
60
+ body: cleaned.text,
61
+ files: files.map((f) => relativeToProject(f, identity.project)),
62
+ occurredAt,
63
+ redacted: cleaned.redacted,
64
+ };
65
+ }
66
+ export function capture(db, config, identity, event) {
67
+ const input = prepare(config, identity, event);
68
+ if (!input)
69
+ return 'excluded';
70
+ const { inserted } = appendEvent(db, input);
71
+ return inserted ? 'stored' : 'duplicate';
72
+ }
73
+ /**
74
+ * Capture when the database may not be reachable. The sanitised record — never
75
+ * the raw one — is what reaches the spool, so a degraded path cannot write a
76
+ * secret that the healthy path would have removed.
77
+ */
78
+ export function captureOrSpool(db, config, identity, event) {
79
+ const input = prepare(config, identity, event);
80
+ if (!input)
81
+ return 'excluded';
82
+ if (db) {
83
+ try {
84
+ const { inserted } = appendEvent(db, input);
85
+ return inserted ? 'stored' : 'duplicate';
86
+ }
87
+ catch {
88
+ // Fall through to the spool: a locked or unwritable database is exactly
89
+ // what it exists for.
90
+ }
91
+ }
92
+ return spoolEvent(input);
93
+ }
94
+ /** Replays whatever the spool holds. Idempotent through `event_uid`. */
95
+ export function drainSpool(db) {
96
+ const records = takeSpooled();
97
+ let replayed = 0;
98
+ let skipped = 0;
99
+ for (const record of records) {
100
+ const input = record;
101
+ // A spool line is data this process wrote earlier, but a truncated write or
102
+ // a hand-edited file is still possible; anything without an identity cannot
103
+ // be replayed idempotently and is discarded rather than guessed at.
104
+ if (!input || typeof input !== 'object' || !input.eventUid || !input.project) {
105
+ skipped++;
106
+ continue;
107
+ }
108
+ try {
109
+ const { inserted } = appendEvent(db, input);
110
+ if (inserted)
111
+ replayed++;
112
+ else
113
+ skipped++;
114
+ }
115
+ catch {
116
+ // Put it back rather than lose it; the next drain tries again.
117
+ spoolEvent(input);
118
+ skipped++;
119
+ }
120
+ }
121
+ return { replayed, skipped };
122
+ }
123
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/memory/capture.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAyB,MAAM,eAAe,CAAC;AACnF,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAsB,MAAM,cAAc,CAAC;AACrH,OAAO,EAAE,WAAW,EAAsB,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAiCrD,iFAAiF;AACjF,MAAM,QAAQ,GAAG,IAAI,CAAC;AAEtB;;;;GAIG;AACH,MAAM,aAAa,GAAgB,CAAC,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;AAEhF,MAAM,UAAU,UAAU,CAAC,MAAqB;IAC9C,OAAO;QACL,YAAY,EAAE,CAAC,GAAG,eAAe,CAAC,YAAY,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;QAChF,YAAY,EAAE,CAAC,GAAG,eAAe,CAAC,YAAY,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC;QAChF,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,eAAe;KAC/C,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,OAAO,CACrB,MAAqB,EACrB,QAA0B,EAC1B,KAAgB;IAEhB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAC3E,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAE5F,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAClD,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtD,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1E,8EAA8E;IAC9E,6EAA6E;IAC7E,iBAAiB;IACjB,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvH,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;IAC9D,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,MAAM,EAAE,CAAC;IAEhD,OAAO;QACL,QAAQ,EAAE,QAAQ,CAAC;YACjB,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,UAAU;YACV,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC;QACF,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;QAC3B,SAAS,EAAE,QAAQ,CAAC,SAAS;QAC7B,OAAO,EAAE,QAAQ,CAAC,OAAO;QACzB,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,MAAM;QAC9B,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;QACxB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;QAC5D,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC/D,UAAU;QACV,QAAQ,EAAE,OAAO,CAAC,QAAQ;KAC3B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,EAAM,EACN,MAAqB,EACrB,QAA0B,EAC1B,KAAgB;IAEhB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO,UAAU,CAAC;IAC9B,MAAM,EAAE,QAAQ,EAAE,GAAG,WAAW,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5C,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,EAAa,EACb,MAAqB,EACrB,QAA0B,EAC1B,KAAgB;IAEhB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC/C,IAAI,CAAC,KAAK;QAAE,OAAO,UAAU,CAAC;IAC9B,IAAI,EAAE,EAAE,CAAC;QACP,IAAI,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,GAAG,WAAW,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC5C,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;YACxE,sBAAsB;QACxB,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,UAAU,CAAC,EAAM;IAC/B,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,MAAuB,CAAC;QACtC,4EAA4E;QAC5E,4EAA4E;QAC5E,oEAAoE;QACpE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YAC7E,OAAO,EAAE,CAAC;YACV,SAAS;QACX,CAAC;QACD,IAAI,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,GAAG,WAAW,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;YAC5C,IAAI,QAAQ;gBAAE,QAAQ,EAAE,CAAC;;gBACpB,OAAO,EAAE,CAAC;QACjB,CAAC;QAAC,MAAM,CAAC;YACP,+DAA+D;YAC/D,UAAU,CAAC,KAAK,CAAC,CAAC;YAClB,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC"}
@@ -0,0 +1,186 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ const LANGUAGES = {
4
+ '.ts': tsLike('typescript'),
5
+ '.tsx': tsLike('typescript'),
6
+ '.js': tsLike('javascript'),
7
+ '.jsx': tsLike('javascript'),
8
+ '.mjs': tsLike('javascript'),
9
+ '.cjs': tsLike('javascript'),
10
+ '.py': {
11
+ language: 'python',
12
+ lineComment: ['#'],
13
+ patterns: [
14
+ { kind: 'class', re: /^\s*class\s+([A-Za-z_]\w*)/ },
15
+ { kind: 'function', re: /^\s*(?:async\s+)?def\s+([A-Za-z_]\w*)/ },
16
+ ],
17
+ },
18
+ '.go': {
19
+ language: 'go',
20
+ lineComment: ['//'],
21
+ patterns: [
22
+ { kind: 'function', re: /^\s*func\s+(?:\([^)]*\)\s*)?([A-Za-z_]\w*)/ },
23
+ { kind: 'type', re: /^\s*type\s+([A-Za-z_]\w*)/ },
24
+ ],
25
+ },
26
+ '.rs': {
27
+ language: 'rust',
28
+ lineComment: ['//'],
29
+ patterns: [
30
+ { kind: 'function', re: /^\s*(?:pub\s+)?(?:async\s+)?fn\s+([A-Za-z_]\w*)/ },
31
+ { kind: 'struct', re: /^\s*(?:pub\s+)?struct\s+([A-Za-z_]\w*)/ },
32
+ { kind: 'enum', re: /^\s*(?:pub\s+)?enum\s+([A-Za-z_]\w*)/ },
33
+ { kind: 'trait', re: /^\s*(?:pub\s+)?trait\s+([A-Za-z_]\w*)/ },
34
+ { kind: 'impl', re: /^\s*impl(?:<[^>]*>)?\s+([A-Za-z_][\w:<>]*)/ },
35
+ ],
36
+ },
37
+ '.java': {
38
+ language: 'java',
39
+ lineComment: ['//'],
40
+ patterns: [
41
+ { kind: 'class', re: /^\s*(?:public\s+|private\s+|protected\s+|abstract\s+|final\s+|static\s+)*class\s+([A-Za-z_]\w*)/ },
42
+ { kind: 'interface', re: /^\s*(?:public\s+)?interface\s+([A-Za-z_]\w*)/ },
43
+ { kind: 'method', re: /^\s*(?:public|private|protected)\s+(?:static\s+)?[\w<>\[\],.\s]+\s+([A-Za-z_]\w*)\s*\(/ },
44
+ ],
45
+ },
46
+ '.rb': {
47
+ language: 'ruby',
48
+ lineComment: ['#'],
49
+ patterns: [
50
+ { kind: 'class', re: /^\s*class\s+([A-Za-z_]\w*)/ },
51
+ { kind: 'module', re: /^\s*module\s+([A-Za-z_]\w*)/ },
52
+ { kind: 'method', re: /^\s*def\s+([A-Za-z_?!.]\w*[?!]?)/ },
53
+ ],
54
+ },
55
+ '.sql': {
56
+ language: 'sql',
57
+ lineComment: ['--'],
58
+ patterns: [
59
+ { kind: 'table', re: /^\s*CREATE\s+(?:VIRTUAL\s+)?TABLE(?:\s+IF\s+NOT\s+EXISTS)?\s+([A-Za-z_]\w*)/i },
60
+ { kind: 'index', re: /^\s*CREATE\s+(?:UNIQUE\s+)?INDEX(?:\s+IF\s+NOT\s+EXISTS)?\s+([A-Za-z_]\w*)/i },
61
+ { kind: 'trigger', re: /^\s*CREATE\s+TRIGGER(?:\s+IF\s+NOT\s+EXISTS)?\s+([A-Za-z_]\w*)/i },
62
+ ],
63
+ },
64
+ };
65
+ function tsLike(language) {
66
+ return {
67
+ language,
68
+ lineComment: ['//', '*', '/*'],
69
+ patterns: [
70
+ { kind: 'class', re: /^\s*(?:export\s+)?(?:abstract\s+)?class\s+([A-Za-z_$][\w$]*)/ },
71
+ { kind: 'interface', re: /^\s*(?:export\s+)?interface\s+([A-Za-z_$][\w$]*)/ },
72
+ { kind: 'type', re: /^\s*(?:export\s+)?type\s+([A-Za-z_$][\w$]*)/ },
73
+ { kind: 'enum', re: /^\s*(?:export\s+)?(?:const\s+)?enum\s+([A-Za-z_$][\w$]*)/ },
74
+ { kind: 'function', re: /^\s*(?:export\s+)?(?:default\s+)?(?:async\s+)?function\s*\*?\s+([A-Za-z_$][\w$]*)/ },
75
+ { kind: 'const', re: /^\s*(?:export\s+)?(?:const|let)\s+([A-Za-z_$][\w$]*)\s*[:=]/ },
76
+ ],
77
+ };
78
+ }
79
+ export function languageOf(file) {
80
+ return LANGUAGES[path.extname(file).toLowerCase()]?.language ?? null;
81
+ }
82
+ const MAX_BYTES = 2 * 1024 * 1024;
83
+ const MAX_SYMBOLS = 400;
84
+ export function outline(file) {
85
+ const spec = LANGUAGES[path.extname(file).toLowerCase()];
86
+ if (!spec)
87
+ return null;
88
+ let text;
89
+ try {
90
+ if (fs.statSync(file).size > MAX_BYTES)
91
+ return null;
92
+ text = fs.readFileSync(file, 'utf8');
93
+ }
94
+ catch {
95
+ return null;
96
+ }
97
+ const lines = text.split('\n');
98
+ const symbols = [];
99
+ for (let i = 0; i < lines.length && symbols.length < MAX_SYMBOLS; i++) {
100
+ const line = lines[i];
101
+ const trimmed = line.trim();
102
+ if (!trimmed || spec.lineComment.some((c) => trimmed.startsWith(c)))
103
+ continue;
104
+ for (const { kind, re } of spec.patterns) {
105
+ const match = re.exec(line);
106
+ if (match?.[1]) {
107
+ symbols.push({ name: match[1], kind, line: i + 1, text: trimmed.slice(0, 200) });
108
+ break;
109
+ }
110
+ }
111
+ }
112
+ return {
113
+ file,
114
+ language: spec.language,
115
+ lines: lines.length,
116
+ symbols,
117
+ truncated: symbols.length >= MAX_SYMBOLS,
118
+ };
119
+ }
120
+ const SKIP_DIRS = new Set(['node_modules', '.git', 'dist', 'build', 'coverage', '.next', 'vendor', '__pycache__']);
121
+ function* walk(root, depth = 0) {
122
+ if (depth > 12)
123
+ return;
124
+ let entries;
125
+ try {
126
+ entries = fs.readdirSync(root, { withFileTypes: true });
127
+ }
128
+ catch {
129
+ return;
130
+ }
131
+ for (const entry of entries) {
132
+ if (entry.name.startsWith('.') && entry.name !== '.eklavya')
133
+ continue;
134
+ const full = path.join(root, entry.name);
135
+ if (entry.isDirectory()) {
136
+ if (SKIP_DIRS.has(entry.name))
137
+ continue;
138
+ yield* walk(full, depth + 1);
139
+ }
140
+ else if (entry.isFile() && LANGUAGES[path.extname(entry.name).toLowerCase()]) {
141
+ yield full;
142
+ }
143
+ }
144
+ }
145
+ /**
146
+ * Finds a declaration by name across a tree, with the containing symbol.
147
+ *
148
+ * Declaration-first rather than every mention: an agent asking "where is
149
+ * `recordReceipt`" wants the one line that defines it, and a list of its 40
150
+ * call sites is the answer to a different question.
151
+ */
152
+ export function findSymbol(root, name, limit = 20) {
153
+ const needle = name.toLowerCase();
154
+ const hits = [];
155
+ for (const file of walk(root)) {
156
+ const parsed = outline(file);
157
+ if (!parsed)
158
+ continue;
159
+ for (const symbol of parsed.symbols) {
160
+ if (!symbol.name.toLowerCase().includes(needle))
161
+ continue;
162
+ hits.push({ file: path.relative(root, file), line: symbol.line, text: symbol.text, symbol: symbol.name });
163
+ if (hits.length >= limit)
164
+ return hits;
165
+ }
166
+ }
167
+ return hits;
168
+ }
169
+ /** The lines around a symbol's declaration: "show me this, not the whole file". */
170
+ export function expand(file, line, before = 5, after = 25) {
171
+ try {
172
+ const lines = fs.readFileSync(file, 'utf8').split('\n');
173
+ const start = Math.max(0, line - 1 - before);
174
+ // `after` counts lines AFTER the declaration, so the declaration's own line
175
+ // does not eat one of them -- `before: 2, after: 2` is five lines, centred.
176
+ const end = Math.min(lines.length, line + after);
177
+ return lines
178
+ .slice(start, end)
179
+ .map((text, i) => `${String(start + i + 1).padStart(5)} ${text}`)
180
+ .join('\n');
181
+ }
182
+ catch {
183
+ return null;
184
+ }
185
+ }
186
+ //# sourceMappingURL=code.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code.js","sourceRoot":"","sources":["../../src/memory/code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AA0C7B,MAAM,SAAS,GAAqC;IAClD,KAAK,EAAE,MAAM,CAAC,YAAY,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC,YAAY,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC;IAC5B,KAAK,EAAE;QACL,QAAQ,EAAE,QAAQ;QAClB,WAAW,EAAE,CAAC,GAAG,CAAC;QAClB,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,4BAA4B,EAAE;YACnD,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,uCAAuC,EAAE;SAClE;KACF;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,CAAC,IAAI,CAAC;QACnB,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,4CAA4C,EAAE;YACtE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,2BAA2B,EAAE;SAClD;KACF;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM;QAChB,WAAW,EAAE,CAAC,IAAI,CAAC;QACnB,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,iDAAiD,EAAE;YAC3E,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,wCAAwC,EAAE;YAChE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,sCAAsC,EAAE;YAC5D,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,uCAAuC,EAAE;YAC9D,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,4CAA4C,EAAE;SACnE;KACF;IACD,OAAO,EAAE;QACP,QAAQ,EAAE,MAAM;QAChB,WAAW,EAAE,CAAC,IAAI,CAAC;QACnB,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,iGAAiG,EAAE;YACxH,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,8CAA8C,EAAE;YACzE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,wFAAwF,EAAE;SACjH;KACF;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM;QAChB,WAAW,EAAE,CAAC,GAAG,CAAC;QAClB,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,4BAA4B,EAAE;YACnD,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,6BAA6B,EAAE;YACrD,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,kCAAkC,EAAE;SAC3D;KACF;IACD,MAAM,EAAE;QACN,QAAQ,EAAE,KAAK;QACf,WAAW,EAAE,CAAC,IAAI,CAAC;QACnB,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,8EAA8E,EAAE;YACrG,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,6EAA6E,EAAE;YACpG,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,iEAAiE,EAAE;SAC3F;KACF;CACF,CAAC;AAEF,SAAS,MAAM,CAAC,QAAgB;IAC9B,OAAO;QACL,QAAQ;QACR,WAAW,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC;QAC9B,QAAQ,EAAE;YACR,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,8DAA8D,EAAE;YACrF,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,kDAAkD,EAAE;YAC7E,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,6CAA6C,EAAE;YACnE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,0DAA0D,EAAE;YAChF,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,mFAAmF,EAAE;YAC7G,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,6DAA6D,EAAE;SACrF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE,QAAQ,IAAI,IAAI,CAAC;AACvE,CAAC;AAED,MAAM,SAAS,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC;AAClC,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB,MAAM,UAAU,OAAO,CAAC,IAAY;IAClC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IACzD,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvB,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,SAAS;YAAE,OAAO,IAAI,CAAC;QACpD,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE,CAAC;QACtE,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAAE,SAAS;QAC9E,KAAK,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACf,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBACjF,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI;QACJ,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,KAAK,EAAE,KAAK,CAAC,MAAM;QACnB,OAAO;QACP,SAAS,EAAE,OAAO,CAAC,MAAM,IAAI,WAAW;KACzC,CAAC;AACJ,CAAC;AASD,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC;AAEnH,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAY,EAAE,KAAK,GAAG,CAAC;IACpC,IAAI,KAAK,GAAG,EAAE;QAAE,OAAO;IACvB,IAAI,OAAoB,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;YAAE,SAAS;QACtE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,SAAS;YACxC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QAC/B,CAAC;aAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YAC/E,MAAM,IAAI,CAAC;QACb,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,IAAY,EAAE,KAAK,GAAG,EAAE;IAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAClC,MAAM,IAAI,GAAc,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,SAAS;YAC1D,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC1G,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK;gBAAE,OAAO,IAAI,CAAC;QACxC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,MAAM,CAAC,IAAY,EAAE,IAAY,EAAE,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG,EAAE;IACvE,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QAC7C,4EAA4E;QAC5E,4EAA4E;QAC5E,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC;QACjD,OAAO,KAAK;aACT,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC;aACjB,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;aACjE,IAAI,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,87 @@
1
+ import { nowIso } from '../time.js';
2
+ import { search } from './search.js';
3
+ import { timeline } from './store.js';
4
+ export function createCollection(db, opts) {
5
+ return Number(db
6
+ .prepare(`INSERT INTO memory_collections (name, description, filter, project, status, created_at)
7
+ VALUES (?, ?, ?, ?, 'ready', ?)
8
+ ON CONFLICT(name) DO UPDATE SET
9
+ description = excluded.description,
10
+ filter = excluded.filter,
11
+ project = excluded.project`)
12
+ .run(opts.name, opts.description ?? null, JSON.stringify(opts.filter), opts.project ?? null, nowIso())
13
+ .lastInsertRowid) || collectionByName(db, opts.name).id;
14
+ }
15
+ export function collectionByName(db, name) {
16
+ return db.prepare('SELECT * FROM memory_collections WHERE name = ?').get(name);
17
+ }
18
+ export function listCollections(db) {
19
+ return db.prepare('SELECT * FROM memory_collections ORDER BY name').all();
20
+ }
21
+ export function deleteCollection(db, name) {
22
+ return db.prepare('DELETE FROM memory_collections WHERE name = ?').run(name).changes > 0;
23
+ }
24
+ /**
25
+ * Re-runs a collection's query and swaps in the result.
26
+ *
27
+ * The swap is conditional and that is the point: a rebuild that finds nothing
28
+ * where there used to be something is far more likely to be a broken index or
29
+ * a mistyped filter than a genuine emptying, and overwriting on that guess
30
+ * destroys the collection. It keeps the last good set, marks the collection
31
+ * `failed`, and says why. `force` is for the developer who really did mean it.
32
+ */
33
+ export function rebuildCollection(db, config, name, opts = {}) {
34
+ const collection = collectionByName(db, name);
35
+ if (!collection)
36
+ return null;
37
+ let filter;
38
+ try {
39
+ filter = JSON.parse(collection.filter);
40
+ }
41
+ catch {
42
+ return { name, members: 0, previous: memberCount(db, collection.id), kept: true, reason: 'unreadable_filter' };
43
+ }
44
+ const previous = memberCount(db, collection.id);
45
+ const searchFilter = {
46
+ project: filter.project ?? collection.project ?? null,
47
+ allProjects: filter.allProjects ?? false,
48
+ type: filter.type ?? null,
49
+ tag: filter.tag ?? null,
50
+ since: filter.since ?? null,
51
+ limit: filter.limit ?? 100,
52
+ };
53
+ const found = filter.query
54
+ ? search(db, filter.query, filter.mode ?? config.retrieval.mode, searchFilter).map((h) => h.entry)
55
+ : timeline(db, {
56
+ project: searchFilter.allProjects ? null : searchFilter.project,
57
+ type: searchFilter.type,
58
+ since: searchFilter.since,
59
+ limit: searchFilter.limit,
60
+ });
61
+ if (found.length === 0 && previous > 0 && !opts.force) {
62
+ db.prepare("UPDATE memory_collections SET status = 'failed' WHERE id = ?").run(collection.id);
63
+ return { name, members: previous, previous, kept: true, reason: 'empty_rebuild_refused' };
64
+ }
65
+ db.transaction(() => {
66
+ db.prepare('DELETE FROM memory_collection_items WHERE collection_id = ?').run(collection.id);
67
+ const insert = db.prepare('INSERT OR REPLACE INTO memory_collection_items (collection_id, entry_id, rank) VALUES (?, ?, ?)');
68
+ found.forEach((entry, index) => insert.run(collection.id, entry.id, found.length - index));
69
+ db.prepare("UPDATE memory_collections SET built_at = ?, status = 'ready' WHERE id = ?").run(nowIso(), collection.id);
70
+ })();
71
+ return { name, members: found.length, previous, kept: false };
72
+ }
73
+ export function collectionEntries(db, name, limit = 50) {
74
+ const collection = collectionByName(db, name);
75
+ if (!collection)
76
+ return [];
77
+ return db
78
+ .prepare(`SELECT e.* FROM memory_entries e
79
+ JOIN memory_collection_items i ON i.entry_id = e.id
80
+ WHERE i.collection_id = ? AND e.deleted_at IS NULL
81
+ ORDER BY i.rank DESC LIMIT ?`)
82
+ .all(collection.id, limit);
83
+ }
84
+ function memberCount(db, collectionId) {
85
+ return db.prepare('SELECT COUNT(*) AS n FROM memory_collection_items WHERE collection_id = ?').get(collectionId).n;
86
+ }
87
+ //# sourceMappingURL=collections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collections.js","sourceRoot":"","sources":["../../src/memory/collections.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Local semantic vectors (ADR-03).
3
+ *
4
+ * `local-hash-v1` is a dependency-free hashed bag of tokens and character
5
+ * 4-grams, L2-normalised, compared by cosine. The n-grams are what make it more
6
+ * than keyword matching: `migrations`, `migration` and `migrating` land in
7
+ * overlapping buckets, and so do typos. It does *not* know that `cookie` and
8
+ * `session token` are related — that needs a trained model, and the manual says
9
+ * so rather than calling this neural parity.
10
+ *
11
+ * Every vector stores the embedder that produced it, because comparing a
12
+ * hashed vector with a provider embedding is meaningless arithmetic.
13
+ */
14
+ export const LOCAL_EMBEDDER = 'local-hash-v1';
15
+ export const LOCAL_DIM = 256;
16
+ function fnv1a(s) {
17
+ let h = 0x811c9dc5;
18
+ for (let i = 0; i < s.length; i++) {
19
+ h ^= s.charCodeAt(i);
20
+ h = Math.imul(h, 0x01000193) >>> 0;
21
+ }
22
+ return h >>> 0;
23
+ }
24
+ function tokenize(text) {
25
+ return text
26
+ .toLowerCase()
27
+ .split(/[^\p{L}\p{N}_]+/u)
28
+ .filter((t) => t.length > 1);
29
+ }
30
+ export function embedLocal(text, dim = LOCAL_DIM) {
31
+ const vec = new Float32Array(dim);
32
+ const tokens = tokenize(text);
33
+ for (const token of tokens) {
34
+ vec[fnv1a(token) % dim] += 1;
35
+ // Character n-grams, weighted lower: they generalise over morphology but
36
+ // are noisier than the whole token, so they should not outvote it.
37
+ const padded = `^${token}$`;
38
+ for (let i = 0; i + 4 <= padded.length; i++) {
39
+ vec[fnv1a(padded.slice(i, i + 4)) % dim] += 0.35;
40
+ }
41
+ }
42
+ // Sublinear damping, as TF-IDF does: a word repeated twenty times is not
43
+ // twenty times more about the document than a word used once. `log1p` rather
44
+ // than `1 + log`, which goes negative below 1 -- a single n-gram hit weighs
45
+ // 0.35, and a negative weight makes two related documents score as opposites.
46
+ for (let i = 0; i < dim; i++) {
47
+ const v = vec[i];
48
+ if (v > 0)
49
+ vec[i] = Math.log1p(v);
50
+ }
51
+ return normalise(vec);
52
+ }
53
+ export function normalise(vec) {
54
+ let sum = 0;
55
+ for (const v of vec)
56
+ sum += v * v;
57
+ const norm = Math.sqrt(sum);
58
+ if (norm === 0)
59
+ return vec;
60
+ for (let i = 0; i < vec.length; i++)
61
+ vec[i] = vec[i] / norm;
62
+ return vec;
63
+ }
64
+ /** Both arguments must already be normalised, which `embedLocal` guarantees. */
65
+ export function cosine(a, b) {
66
+ const n = Math.min(a.length, b.length);
67
+ let dot = 0;
68
+ for (let i = 0; i < n; i++)
69
+ dot += a[i] * b[i];
70
+ return dot;
71
+ }
72
+ export function toBlob(vec) {
73
+ return Buffer.from(vec.buffer, vec.byteOffset, vec.byteLength);
74
+ }
75
+ export function fromBlob(blob) {
76
+ // Copy rather than view: better-sqlite3's buffer is not guaranteed aligned
77
+ // for Float32Array, and an unaligned view throws.
78
+ const copy = Buffer.from(blob);
79
+ return new Float32Array(copy.buffer, copy.byteOffset, copy.byteLength / 4);
80
+ }
81
+ //# sourceMappingURL=embed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed.js","sourceRoot":"","sources":["../../src/memory/embed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Host capability descriptors (PRD CAP-01, EXT-01; ADR-06).
3
+ *
4
+ * The rule this file enforces is "record capabilities rather than fabricate
5
+ * missing events". A host that cannot tell us a tool failed must not have a
6
+ * memory that quietly implies every tool succeeded, and a host nobody has run
7
+ * a fixture through must not be advertised as supported.
8
+ *
9
+ * `status` is the honest axis. `proven` means there is a transcript fixture and
10
+ * a passing test in this repository. `unverified` means the adapter is written
11
+ * from documentation and nobody has run it. Nothing is listed here that has no
12
+ * adapter at all — the parity ledger tracks those.
13
+ */
14
+ export const HOSTS = {
15
+ 'claude-code': {
16
+ id: 'claude-code',
17
+ label: 'Claude Code',
18
+ status: 'proven',
19
+ hooks: true,
20
+ transcripts: true,
21
+ toolOutcomes: true,
22
+ agentIdentity: true,
23
+ humanDisplay: true,
24
+ modelContext: true,
25
+ },
26
+ cursor: {
27
+ id: 'cursor',
28
+ label: 'Cursor',
29
+ status: 'unverified',
30
+ hooks: false,
31
+ transcripts: false,
32
+ toolOutcomes: false,
33
+ agentIdentity: false,
34
+ humanDisplay: false,
35
+ // The MCP server works, so explicit tool calls are captured. Nothing else
36
+ // is: with no hooks there is no seam to capture a prompt or an edit at.
37
+ modelContext: false,
38
+ notes: 'MCP tools only. No hooks, so nothing is captured that the model does not explicitly log.',
39
+ },
40
+ cowork: {
41
+ id: 'cowork',
42
+ label: 'Claude Cowork',
43
+ status: 'unverified',
44
+ hooks: true,
45
+ transcripts: false,
46
+ toolOutcomes: true,
47
+ agentIdentity: true,
48
+ humanDisplay: true,
49
+ modelContext: true,
50
+ notes: 'No git commits, so the commit gate never fires there; `surface.ts` already says so at session start.',
51
+ },
52
+ };
53
+ export function capabilitiesOf(host) {
54
+ return (HOSTS[host ?? 'claude-code'] ?? {
55
+ id: host ?? 'unknown',
56
+ label: host ?? 'unknown host',
57
+ status: 'unverified',
58
+ hooks: false,
59
+ transcripts: false,
60
+ toolOutcomes: false,
61
+ agentIdentity: false,
62
+ humanDisplay: false,
63
+ modelContext: false,
64
+ notes: 'Unrecognised host: assume nothing is delivered that was not explicitly logged.',
65
+ });
66
+ }
67
+ /** The hosts an install may honestly claim to support today. */
68
+ export function provenHosts() {
69
+ return Object.values(HOSTS).filter((h) => h.status === 'proven');
70
+ }
71
+ //# sourceMappingURL=hosts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hosts.js","sourceRoot":"","sources":["../../src/memory/hosts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAuBH,MAAM,CAAC,MAAM,KAAK,GAAqC;IACrD,aAAa,EAAE;QACb,EAAE,EAAE,aAAa;QACjB,KAAK,EAAE,aAAa;QACpB,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,IAAI;QACjB,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;KACnB;IACD,MAAM,EAAE;QACN,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,QAAQ;QACf,MAAM,EAAE,YAAY;QACpB,KAAK,EAAE,KAAK;QACZ,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,KAAK;QACpB,YAAY,EAAE,KAAK;QACnB,0EAA0E;QAC1E,wEAAwE;QACxE,YAAY,EAAE,KAAK;QACnB,KAAK,EAAE,0FAA0F;KAClG;IACD,MAAM,EAAE;QACN,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,eAAe;QACtB,MAAM,EAAE,YAAY;QACpB,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;QAClB,KAAK,EAAE,sGAAsG;KAC9G;CACF,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,IAA+B;IAC5D,OAAO,CACL,KAAK,CAAC,IAAI,IAAI,aAAa,CAAC,IAAI;QAC9B,EAAE,EAAE,IAAI,IAAI,SAAS;QACrB,KAAK,EAAE,IAAI,IAAI,cAAc;QAC7B,MAAM,EAAE,YAAY;QACpB,KAAK,EAAE,KAAK;QACZ,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,KAAK;QACnB,aAAa,EAAE,KAAK;QACpB,YAAY,EAAE,KAAK;QACnB,YAAY,EAAE,KAAK;QACnB,KAAK,EAAE,gFAAgF;KACxF,CACF,CAAC;AACJ,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,WAAW;IACzB,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;AACnE,CAAC"}