@context-vault/core 2.17.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/dist/capture.d.ts +21 -0
  2. package/dist/capture.d.ts.map +1 -0
  3. package/dist/capture.js +269 -0
  4. package/dist/capture.js.map +1 -0
  5. package/dist/categories.d.ts +6 -0
  6. package/dist/categories.d.ts.map +1 -0
  7. package/dist/categories.js +50 -0
  8. package/dist/categories.js.map +1 -0
  9. package/dist/config.d.ts +4 -0
  10. package/dist/config.d.ts.map +1 -0
  11. package/dist/config.js +190 -0
  12. package/dist/config.js.map +1 -0
  13. package/dist/constants.d.ts +33 -0
  14. package/dist/constants.d.ts.map +1 -0
  15. package/dist/constants.js +23 -0
  16. package/dist/constants.js.map +1 -0
  17. package/dist/db.d.ts +13 -0
  18. package/dist/db.d.ts.map +1 -0
  19. package/dist/db.js +191 -0
  20. package/dist/db.js.map +1 -0
  21. package/dist/embed.d.ts +5 -0
  22. package/dist/embed.d.ts.map +1 -0
  23. package/dist/embed.js +78 -0
  24. package/dist/embed.js.map +1 -0
  25. package/dist/files.d.ts +13 -0
  26. package/dist/files.d.ts.map +1 -0
  27. package/dist/files.js +66 -0
  28. package/dist/files.js.map +1 -0
  29. package/dist/formatters.d.ts +8 -0
  30. package/dist/formatters.d.ts.map +1 -0
  31. package/dist/formatters.js +18 -0
  32. package/dist/formatters.js.map +1 -0
  33. package/dist/frontmatter.d.ts +12 -0
  34. package/dist/frontmatter.d.ts.map +1 -0
  35. package/dist/frontmatter.js +101 -0
  36. package/dist/frontmatter.js.map +1 -0
  37. package/dist/index.d.ts +10 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +297 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/ingest-url.d.ts +20 -0
  42. package/dist/ingest-url.d.ts.map +1 -0
  43. package/dist/ingest-url.js +113 -0
  44. package/dist/ingest-url.js.map +1 -0
  45. package/dist/main.d.ts +14 -0
  46. package/dist/main.d.ts.map +1 -0
  47. package/dist/main.js +25 -0
  48. package/dist/main.js.map +1 -0
  49. package/dist/search.d.ts +18 -0
  50. package/dist/search.d.ts.map +1 -0
  51. package/dist/search.js +238 -0
  52. package/dist/search.js.map +1 -0
  53. package/dist/types.d.ts +176 -0
  54. package/dist/types.d.ts.map +1 -0
  55. package/dist/types.js +2 -0
  56. package/dist/types.js.map +1 -0
  57. package/package.json +66 -17
  58. package/src/capture.ts +308 -0
  59. package/src/categories.ts +54 -0
  60. package/src/{core/config.js → config.ts} +34 -33
  61. package/src/{constants.js → constants.ts} +6 -3
  62. package/src/db.ts +229 -0
  63. package/src/{index/embed.js → embed.ts} +10 -35
  64. package/src/files.ts +80 -0
  65. package/src/{capture/formatters.js → formatters.ts} +13 -11
  66. package/src/{core/frontmatter.js → frontmatter.ts} +27 -33
  67. package/src/index.ts +351 -0
  68. package/src/ingest-url.ts +99 -0
  69. package/src/main.ts +111 -0
  70. package/src/search.ts +285 -0
  71. package/src/types.ts +166 -0
  72. package/src/capture/file-ops.js +0 -97
  73. package/src/capture/import-pipeline.js +0 -46
  74. package/src/capture/importers.js +0 -387
  75. package/src/capture/index.js +0 -236
  76. package/src/capture/ingest-url.js +0 -252
  77. package/src/consolidation/index.js +0 -112
  78. package/src/core/categories.js +0 -72
  79. package/src/core/error-log.js +0 -54
  80. package/src/core/files.js +0 -108
  81. package/src/core/status.js +0 -350
  82. package/src/core/telemetry.js +0 -90
  83. package/src/index/db.js +0 -416
  84. package/src/index/index.js +0 -522
  85. package/src/index.js +0 -66
  86. package/src/retrieve/index.js +0 -500
  87. package/src/server/helpers.js +0 -44
  88. package/src/server/tools/clear-context.js +0 -47
  89. package/src/server/tools/context-status.js +0 -182
  90. package/src/server/tools/create-snapshot.js +0 -231
  91. package/src/server/tools/delete-context.js +0 -60
  92. package/src/server/tools/get-context.js +0 -678
  93. package/src/server/tools/ingest-project.js +0 -244
  94. package/src/server/tools/ingest-url.js +0 -88
  95. package/src/server/tools/list-buckets.js +0 -116
  96. package/src/server/tools/list-context.js +0 -163
  97. package/src/server/tools/save-context.js +0 -609
  98. package/src/server/tools/session-start.js +0 -285
  99. package/src/server/tools/submit-feedback.js +0 -55
  100. package/src/server/tools.js +0 -174
  101. package/src/sync/sync.js +0 -235
package/src/sync/sync.js DELETED
@@ -1,235 +0,0 @@
1
- /**
2
- * sync.js — Bidirectional sync protocol
3
- *
4
- * v1 design:
5
- * - Additive-only — no delete propagation (avoids data loss)
6
- * - Last-write-wins by created_at for conflicts (both have same ID)
7
- * - Push uses POST /api/vault/import/bulk
8
- * - Pull uses GET /api/vault/export + local captureAndIndex()
9
- */
10
-
11
- import { captureAndIndex } from "../capture/index.js";
12
-
13
- /**
14
- * Build a manifest of local vault entries (id → { id, created_at, kind, title }).
15
- *
16
- * @param {import('../server/types.js').BaseCtx} ctx
17
- * @returns {Map<string, { id: string, created_at: string, kind: string, title: string|null }>}
18
- */
19
- export function buildLocalManifest(ctx) {
20
- const rows = ctx.db
21
- .prepare(
22
- "SELECT id, created_at, kind, title FROM vault WHERE (expires_at IS NULL OR expires_at > datetime('now'))",
23
- )
24
- .all();
25
-
26
- const manifest = new Map();
27
- for (const row of rows) {
28
- manifest.set(row.id, {
29
- id: row.id,
30
- created_at: row.created_at,
31
- kind: row.kind,
32
- title: row.title || null,
33
- });
34
- }
35
- return manifest;
36
- }
37
-
38
- /**
39
- * Fetch the remote vault manifest from the hosted API.
40
- *
41
- * @param {string} hostedUrl - Base URL of hosted service
42
- * @param {string} apiKey - Bearer token
43
- * @returns {Promise<Map<string, { id: string, created_at: string, kind: string, title: string|null }>>}
44
- */
45
- export async function fetchRemoteManifest(hostedUrl, apiKey) {
46
- const response = await fetch(`${hostedUrl}/api/vault/manifest`, {
47
- headers: { Authorization: `Bearer ${apiKey}` },
48
- });
49
-
50
- if (!response.ok) {
51
- throw new Error(`Failed to fetch remote manifest: HTTP ${response.status}`);
52
- }
53
-
54
- const data = await response.json();
55
- const manifest = new Map();
56
-
57
- for (const entry of data.entries || []) {
58
- manifest.set(entry.id, {
59
- id: entry.id,
60
- created_at: entry.created_at,
61
- kind: entry.kind,
62
- title: entry.title || null,
63
- });
64
- }
65
-
66
- return manifest;
67
- }
68
-
69
- /**
70
- * @typedef {object} SyncPlan
71
- * @property {string[]} toPush - Entry IDs that exist locally but not remotely
72
- * @property {string[]} toPull - Entry IDs that exist remotely but not locally
73
- * @property {string[]} upToDate - Entry IDs that exist in both
74
- */
75
-
76
- /**
77
- * Compute what needs to be pushed/pulled by comparing manifests.
78
- * Additive-only: entries in both are considered up-to-date.
79
- *
80
- * @param {Map<string, object>} local
81
- * @param {Map<string, object>} remote
82
- * @returns {SyncPlan}
83
- */
84
- export function computeSyncPlan(local, remote) {
85
- const toPush = [];
86
- const toPull = [];
87
- const upToDate = [];
88
-
89
- // Find local-only entries
90
- for (const id of local.keys()) {
91
- if (remote.has(id)) {
92
- upToDate.push(id);
93
- } else {
94
- toPush.push(id);
95
- }
96
- }
97
-
98
- // Find remote-only entries
99
- for (const id of remote.keys()) {
100
- if (!local.has(id)) {
101
- toPull.push(id);
102
- }
103
- }
104
-
105
- return { toPush, toPull, upToDate };
106
- }
107
-
108
- /**
109
- * Execute a sync plan: push local entries to remote, pull remote entries to local.
110
- *
111
- * @param {import('../server/types.js').BaseCtx & Partial<import('../server/types.js').HostedCtxExtensions>} ctx
112
- * @param {{ hostedUrl: string, apiKey: string, plan: SyncPlan, onProgress?: (phase: string, current: number, total: number) => void }} opts
113
- * @returns {Promise<{ pushed: number, pulled: number, failed: number, errors: string[] }>}
114
- */
115
- export async function executeSync(
116
- ctx,
117
- { hostedUrl, apiKey, plan, onProgress },
118
- ) {
119
- let pushed = 0;
120
- let pulled = 0;
121
- let failed = 0;
122
- const errors = [];
123
-
124
- // ── Push: upload local-only entries to remote ──
125
- if (plan.toPush.length > 0) {
126
- const BATCH_SIZE = 50;
127
- const entries = [];
128
-
129
- // Collect full entry data for push
130
- for (const id of plan.toPush) {
131
- const row = ctx.stmts.getEntryById.get(id);
132
- if (!row) continue;
133
-
134
- entries.push({
135
- kind: row.kind,
136
- title: row.title || null,
137
- body: row.body,
138
- tags: row.tags ? JSON.parse(row.tags) : [],
139
- meta: row.meta ? JSON.parse(row.meta) : undefined,
140
- source: row.source || "sync-push",
141
- identity_key: row.identity_key || undefined,
142
- expires_at: row.expires_at || undefined,
143
- });
144
- }
145
-
146
- // Push in batches
147
- for (let i = 0; i < entries.length; i += BATCH_SIZE) {
148
- const batch = entries.slice(i, i + BATCH_SIZE);
149
- if (onProgress) onProgress("push", i + batch.length, entries.length);
150
-
151
- try {
152
- const response = await fetch(`${hostedUrl}/api/vault/import/bulk`, {
153
- method: "POST",
154
- headers: {
155
- "Content-Type": "application/json",
156
- Authorization: `Bearer ${apiKey}`,
157
- },
158
- body: JSON.stringify({ entries: batch }),
159
- });
160
-
161
- if (!response.ok) {
162
- const errData = await response.json().catch(() => ({}));
163
- failed += batch.length;
164
- errors.push(
165
- `Push batch failed: HTTP ${response.status} — ${errData.error || "unknown"}`,
166
- );
167
- continue;
168
- }
169
-
170
- const result = await response.json();
171
- pushed += result.imported || 0;
172
- failed += result.failed || 0;
173
- if (result.errors?.length) {
174
- errors.push(...result.errors);
175
- }
176
- } catch (err) {
177
- failed += batch.length;
178
- errors.push(`Push batch failed: ${err.message}`);
179
- }
180
- }
181
- }
182
-
183
- // ── Pull: download remote-only entries to local ──
184
- if (plan.toPull.length > 0) {
185
- if (onProgress) onProgress("pull", 0, plan.toPull.length);
186
-
187
- try {
188
- const response = await fetch(`${hostedUrl}/api/vault/export`, {
189
- headers: { Authorization: `Bearer ${apiKey}` },
190
- });
191
-
192
- if (!response.ok) {
193
- throw new Error(`Export failed: HTTP ${response.status}`);
194
- }
195
-
196
- const data = await response.json();
197
- const remoteEntries = data.entries || [];
198
-
199
- // Filter to only pull entries we need
200
- const pullIds = new Set(plan.toPull);
201
- const entriesToPull = remoteEntries.filter((e) => pullIds.has(e.id));
202
-
203
- for (let i = 0; i < entriesToPull.length; i++) {
204
- const entry = entriesToPull[i];
205
- if (onProgress) onProgress("pull", i + 1, entriesToPull.length);
206
-
207
- try {
208
- await captureAndIndex(ctx, {
209
- kind: entry.kind,
210
- title: entry.title,
211
- body: entry.body,
212
- meta:
213
- entry.meta && typeof entry.meta === "object"
214
- ? entry.meta
215
- : undefined,
216
- tags: Array.isArray(entry.tags) ? entry.tags : undefined,
217
- source: entry.source || "sync-pull",
218
- identity_key: entry.identity_key,
219
- expires_at: entry.expires_at,
220
- userId: ctx.userId || null,
221
- });
222
- pulled++;
223
- } catch (err) {
224
- failed++;
225
- errors.push(`Pull "${entry.title || entry.id}": ${err.message}`);
226
- }
227
- }
228
- } catch (err) {
229
- failed += plan.toPull.length;
230
- errors.push(`Pull failed: ${err.message}`);
231
- }
232
- }
233
-
234
- return { pushed, pulled, failed, errors };
235
- }