@hraness/sponge 0.2.5 → 0.3.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 (227) hide show
  1. package/README.md +23 -10
  2. package/bin/sponge.js +8 -7
  3. package/dist/contracts/index.js +24 -6
  4. package/dist/contracts/validate.js +106 -29
  5. package/dist/migrations/008.d.ts +3 -0
  6. package/dist/migrations/008.js +5 -0
  7. package/dist/migrations/009.d.ts +3 -0
  8. package/dist/migrations/009.js +8 -0
  9. package/dist/migrations/010.d.ts +3 -0
  10. package/dist/migrations/010.js +11 -0
  11. package/dist/migrations/index.d.ts +15 -0
  12. package/dist/migrations/index.js +39 -0
  13. package/dist/src/acquisition/capture.js +87 -28
  14. package/dist/src/acquisition/cleanup.d.ts +0 -4
  15. package/dist/src/acquisition/cleanup.js +3 -5
  16. package/dist/src/acquisition/errors.js +17 -2
  17. package/dist/src/acquisition/files.d.ts +0 -1
  18. package/dist/src/acquisition/files.js +14 -11
  19. package/dist/src/acquisition/index.d.ts +2 -3
  20. package/dist/src/acquisition/index.js +1 -2
  21. package/dist/src/acquisition/lock.js +1 -1
  22. package/dist/src/acquisition/normalize.js +57 -18
  23. package/dist/src/acquisition/pins.js +22 -4
  24. package/dist/src/acquisition/process.js +67 -29
  25. package/dist/src/acquisition/runtime.d.ts +5 -7
  26. package/dist/src/acquisition/runtime.js +129 -68
  27. package/dist/src/acquisition/verify-helper.js +10 -3
  28. package/dist/src/annotations/quote.js +40 -12
  29. package/dist/src/annotations/store.d.ts +0 -1
  30. package/dist/src/annotations/store.js +66 -14
  31. package/dist/src/app/article.d.ts +2 -1
  32. package/dist/src/app/article.js +66 -70
  33. package/dist/src/app/bundle-files.d.ts +0 -4
  34. package/dist/src/app/bundle-files.js +11 -14
  35. package/dist/src/app/markdown.js +18 -6
  36. package/dist/src/app/source.d.ts +0 -4
  37. package/dist/src/app/source.js +18 -14
  38. package/dist/src/cli/arguments.d.ts +2 -8
  39. package/dist/src/cli/arguments.js +67 -80
  40. package/dist/src/cli/commands.d.ts +42 -0
  41. package/dist/src/cli/commands.js +795 -0
  42. package/dist/src/cli/config.js +12 -9
  43. package/dist/src/cli/digest.d.ts +1 -1
  44. package/dist/src/cli/digest.js +39 -17
  45. package/dist/src/cli/import.js +25 -4
  46. package/dist/src/cli/indexing.d.ts +2 -0
  47. package/dist/src/cli/indexing.js +26 -9
  48. package/dist/src/cli/main.js +47 -386
  49. package/dist/src/cli/portability.d.ts +0 -2
  50. package/dist/src/cli/portability.js +13 -8
  51. package/dist/src/cli/queue.js +12 -8
  52. package/dist/src/cli/runtimes.d.ts +1 -3
  53. package/dist/src/cli/runtimes.js +13 -6
  54. package/dist/src/cli/terminal.js +1 -1
  55. package/dist/src/cli/worker.d.ts +7 -0
  56. package/dist/src/cli/worker.js +54 -15
  57. package/dist/src/derivations/kinds.d.ts +34 -0
  58. package/dist/src/derivations/kinds.js +14 -0
  59. package/dist/src/derivations/types.d.ts +48 -0
  60. package/dist/src/derivations/types.js +1 -0
  61. package/dist/src/digest/derivation.d.ts +25 -0
  62. package/dist/src/digest/derivation.js +124 -0
  63. package/dist/src/digest/editorial.d.ts +10 -46
  64. package/dist/src/digest/editorial.js +73 -59
  65. package/dist/src/digest/endpoint.js +63 -27
  66. package/dist/src/digest/pipeline.d.ts +53 -32
  67. package/dist/src/digest/pipeline.js +357 -125
  68. package/dist/src/digest/schema.d.ts +44 -17
  69. package/dist/src/digest/schema.js +132 -44
  70. package/dist/src/errors.d.ts +46 -0
  71. package/dist/src/errors.js +117 -0
  72. package/dist/src/identity/query-policy.d.ts +0 -5
  73. package/dist/src/identity/query-policy.js +61 -9
  74. package/dist/src/identity/uri.d.ts +6 -5
  75. package/dist/src/identity/uri.js +37 -18
  76. package/dist/src/identity/visibility.d.ts +11 -1
  77. package/dist/src/identity/visibility.js +81 -17
  78. package/dist/src/importers/apply.js +104 -36
  79. package/dist/src/importers/custody.js +27 -9
  80. package/dist/src/importers/inspect.js +125 -38
  81. package/dist/src/importers/jungle-digest.d.ts +31 -24
  82. package/dist/src/importers/jungle-digest.js +217 -115
  83. package/dist/src/importers/jungle-store.d.ts +20 -11
  84. package/dist/src/importers/jungle-store.js +136 -41
  85. package/dist/src/importers/jungle.d.ts +32 -16
  86. package/dist/src/importers/jungle.js +145 -32
  87. package/dist/src/importers/manifest.js +57 -21
  88. package/dist/src/importers/verify-helper.js +18 -4
  89. package/dist/src/indexing/image.js +29 -10
  90. package/dist/src/indexing/index.d.ts +37 -6
  91. package/dist/src/indexing/index.js +360 -124
  92. package/dist/src/indexing/jobs.js +156 -47
  93. package/dist/src/indexing/prune-run.d.ts +2 -0
  94. package/dist/src/indexing/prune-run.js +69 -26
  95. package/dist/src/indexing/prune.d.ts +12 -3
  96. package/dist/src/indexing/prune.js +85 -35
  97. package/dist/src/indexing/runner.d.ts +2 -1
  98. package/dist/src/indexing/runner.js +83 -40
  99. package/dist/src/indexing/upgrade.d.ts +9 -0
  100. package/dist/src/indexing/upgrade.js +79 -0
  101. package/dist/src/inference/asr/bridge.js +6 -2
  102. package/dist/src/inference/asr/protocol.js +109 -19
  103. package/dist/src/inference/asr/runtime.js +58 -21
  104. package/dist/src/inference/asr/windows.js +9 -5
  105. package/dist/src/inference/embedding/index.d.ts +2 -6
  106. package/dist/src/inference/embedding/index.js +89 -29
  107. package/dist/src/ingest/attempt.d.ts +29 -0
  108. package/dist/src/ingest/attempt.js +55 -0
  109. package/dist/src/media/capture-helper.js +7 -2
  110. package/dist/src/media/capture.d.ts +2 -1
  111. package/dist/src/media/capture.js +124 -43
  112. package/dist/src/media/handler.d.ts +4 -2
  113. package/dist/src/media/handler.js +88 -70
  114. package/dist/src/media/transcribe.js +63 -21
  115. package/dist/src/metadata/article.js +49 -17
  116. package/dist/src/models/artifacts.d.ts +10 -8
  117. package/dist/src/models/artifacts.js +237 -106
  118. package/dist/src/models/catalog.d.ts +2 -5
  119. package/dist/src/models/catalog.js +94 -25
  120. package/dist/src/models/download.js +55 -15
  121. package/dist/src/models/runtime.d.ts +0 -2
  122. package/dist/src/models/runtime.js +69 -33
  123. package/dist/src/pdf/capture-helper.js +3 -1
  124. package/dist/src/pdf/capture.d.ts +2 -1
  125. package/dist/src/pdf/capture.js +95 -27
  126. package/dist/src/pdf/errors.js +12 -1
  127. package/dist/src/pdf/handler.d.ts +2 -1
  128. package/dist/src/pdf/handler.js +70 -71
  129. package/dist/src/pdf/index.d.ts +1 -3
  130. package/dist/src/pdf/index.js +0 -2
  131. package/dist/src/pdf/input.js +12 -7
  132. package/dist/src/pdf/normalize.js +80 -21
  133. package/dist/src/pdf/source-identity.js +3 -2
  134. package/dist/src/pdf/source.js +12 -8
  135. package/dist/src/pdf/verify-helper.js +15 -3
  136. package/dist/src/portability/backup.d.ts +2 -9
  137. package/dist/src/portability/backup.js +108 -22
  138. package/dist/src/portability/database.js +51 -17
  139. package/dist/src/portability/export.js +35 -9
  140. package/dist/src/portability/files.d.ts +1 -4
  141. package/dist/src/portability/files.js +127 -67
  142. package/dist/src/portability/gc.js +65 -22
  143. package/dist/src/publish/component.js +1 -1
  144. package/dist/src/publish/feed.d.ts +2 -2
  145. package/dist/src/publish/feed.js +75 -29
  146. package/dist/src/publish/identity.d.ts +5 -1
  147. package/dist/src/publish/identity.js +31 -11
  148. package/dist/src/publish/index.d.ts +2 -3
  149. package/dist/src/publish/index.js +34 -21
  150. package/dist/src/publish/projection.d.ts +2 -9
  151. package/dist/src/publish/projection.js +21 -14
  152. package/dist/src/search/extension.js +3 -1
  153. package/dist/src/search/hybrid.d.ts +3 -8
  154. package/dist/src/search/hybrid.js +45 -11
  155. package/dist/src/search/lexical.js +18 -4
  156. package/dist/src/search/query.js +56 -25
  157. package/dist/src/search/vector.js +37 -10
  158. package/dist/src/service/launch-agent.d.ts +5 -3
  159. package/dist/src/service/launch-agent.js +272 -83
  160. package/dist/src/service/lifetime.js +47 -14
  161. package/dist/src/service/loop.d.ts +3 -3
  162. package/dist/src/service/loop.js +47 -19
  163. package/dist/src/store/annotations.d.ts +32 -0
  164. package/dist/src/store/annotations.js +44 -0
  165. package/dist/src/store/backups.d.ts +18 -0
  166. package/dist/src/store/backups.js +110 -0
  167. package/dist/src/store/blobs.d.ts +24 -0
  168. package/dist/src/store/blobs.js +139 -0
  169. package/dist/src/store/changes.d.ts +5 -12
  170. package/dist/src/store/changes.js +108 -56
  171. package/dist/src/store/context.d.ts +15 -0
  172. package/dist/src/store/context.js +19 -0
  173. package/dist/src/store/derivations.d.ts +42 -0
  174. package/dist/src/store/derivations.js +104 -0
  175. package/dist/src/store/files.d.ts +0 -2
  176. package/dist/src/store/files.js +19 -24
  177. package/dist/src/store/ids.d.ts +30 -0
  178. package/dist/src/store/ids.js +34 -0
  179. package/dist/src/store/imports.d.ts +26 -0
  180. package/dist/src/store/imports.js +57 -0
  181. package/dist/src/store/index.d.ts +3 -186
  182. package/dist/src/store/index.js +2 -809
  183. package/dist/src/store/lease.d.ts +20 -0
  184. package/dist/src/store/lease.js +62 -0
  185. package/dist/src/store/library.d.ts +75 -0
  186. package/dist/src/store/library.js +174 -0
  187. package/dist/src/store/open.d.ts +7 -0
  188. package/dist/src/store/open.js +183 -0
  189. package/dist/src/store/queue.d.ts +65 -0
  190. package/dist/src/store/queue.js +327 -0
  191. package/dist/src/store/revisions.d.ts +12 -0
  192. package/dist/src/store/revisions.js +189 -0
  193. package/dist/src/store/search-index.d.ts +63 -0
  194. package/dist/src/store/search-index.js +190 -0
  195. package/dist/src/store/sync-ready.d.ts +6 -0
  196. package/dist/src/store/sync-ready.js +121 -0
  197. package/dist/src/store/types.d.ts +1 -5
  198. package/dist/src/store/types.js +1 -8
  199. package/dist/src/util/canonical.d.ts +2 -0
  200. package/dist/src/util/canonical.js +17 -0
  201. package/dist/src/util/exact.d.ts +2 -0
  202. package/dist/src/util/exact.js +9 -0
  203. package/dist/src/util/fsync.d.ts +4 -0
  204. package/dist/src/util/fsync.js +22 -0
  205. package/dist/src/util/hash.d.ts +4 -0
  206. package/dist/src/util/hash.js +8 -0
  207. package/dist/src/worker/basic.d.ts +0 -1
  208. package/dist/src/worker/basic.js +23 -7
  209. package/dist/src/worker/custody.d.ts +4 -1
  210. package/dist/src/worker/custody.js +111 -38
  211. package/dist/src/worker/engine.d.ts +2 -1
  212. package/dist/src/worker/engine.js +42 -20
  213. package/dist/src/worker/identity.js +13 -5
  214. package/dist/src/worker/journal.d.ts +1 -1
  215. package/dist/src/worker/journal.js +54 -24
  216. package/dist/src/worker/lock.d.ts +18 -0
  217. package/dist/src/worker/lock.js +196 -0
  218. package/dist/src/worker/runtime-gc.d.ts +4 -3
  219. package/dist/src/worker/runtime-gc.js +68 -41
  220. package/dist/src/worker/supervisor-child.js +19 -6
  221. package/dist/src/worker/supervisor.js +41 -8
  222. package/native/runtime-manifest.json +4 -4
  223. package/package.json +10 -2
  224. package/dist/src/digest/store.d.ts +0 -57
  225. package/dist/src/digest/store.js +0 -77
  226. package/dist/src/store/foundation.d.ts +0 -7
  227. package/dist/src/store/foundation.js +0 -7
@@ -1,8 +1,8 @@
1
1
  import { lstat } from 'node:fs/promises';
2
2
  import { readConfined } from '../acquisition/files.js';
3
3
  import { join } from 'node:path';
4
- import { createHash } from 'node:crypto';
5
- import { InputError } from '../app/source.js';
4
+ import { sha256 } from '../util/hash.js';
5
+ import { SpongeError } from '../errors.js';
6
6
  /** Local references only. Tokens, cookies and passwords never belong in this file. */
7
7
  export async function readConnections(root) {
8
8
  const path = join(root, 'connections.json');
@@ -10,7 +10,7 @@ export async function readConnections(root) {
10
10
  try {
11
11
  const stat = await lstat(path);
12
12
  if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1 || stat.size > 65536 || (stat.mode & 0o077) !== 0)
13
- throw new InputError();
13
+ throw new SpongeError('invalid-input');
14
14
  bytes = await readConfined(root, 'connections.json', 65536);
15
15
  }
16
16
  catch (error) {
@@ -23,23 +23,26 @@ export async function readConnections(root) {
23
23
  config = JSON.parse(bytes.toString('utf8'));
24
24
  }
25
25
  catch {
26
- throw new InputError();
26
+ throw new SpongeError('invalid-input');
27
27
  }
28
28
  if (config?.schemaVersion !== 1 || !Array.isArray(config.connections) || config.connections.length > 100)
29
- throw new InputError();
29
+ throw new SpongeError('invalid-input');
30
30
  const ids = new Set();
31
31
  return config.connections.map((entry) => {
32
32
  if (!entry || typeof entry.id !== 'string' || !/^[a-zA-Z0-9_-]{1,64}$/.test(entry.id) || ids.has(entry.id))
33
- throw new InputError();
33
+ throw new SpongeError('invalid-input');
34
34
  ids.add(entry.id);
35
35
  let capture;
36
- if (entry.kind === 'account' && typeof entry.stateHome === 'string' && entry.stateHome.startsWith('/') && typeof entry.accountId === 'string')
36
+ if (entry.kind === 'account' &&
37
+ typeof entry.stateHome === 'string' &&
38
+ entry.stateHome.startsWith('/') &&
39
+ typeof entry.accountId === 'string')
37
40
  capture = { kind: 'account', stateHome: entry.stateHome, accountId: entry.accountId };
38
41
  else if (entry.kind === 'cdp' && typeof entry.endpoint === 'string')
39
42
  capture = { kind: 'cdp', endpoint: entry.endpoint };
40
43
  else
41
- throw new InputError();
42
- const realm = 'connection:' + createHash('sha256').update(JSON.stringify([entry.id, capture])).digest('hex');
44
+ throw new SpongeError('invalid-input');
45
+ const realm = 'connection:' + sha256(JSON.stringify([entry.id, capture]));
43
46
  return { id: entry.id, realm, capture };
44
47
  });
45
48
  }
@@ -1,4 +1,4 @@
1
- import type { Derivation, DigestReview } from '../store/foundation.js';
1
+ import type { Derivation, DigestReview } from '../digest/derivation.js';
2
2
  /** Review targets: `all`, `gist`, `idea:N` or `quote:N.M` (0-based), comma-separated. */
3
3
  export declare const reviewSpec: RegExp;
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { InputError } from '../app/source.js';
1
+ import { SpongeError } from '../errors.js';
2
2
  /** Review targets: `all`, `gist`, `idea:N` or `quote:N.M` (0-based), comma-separated. */
3
3
  export const reviewSpec = /^(?:all|gist|idea:\d{1,2}|quote:\d{1,2}\.\d)(?:,(?:all|gist|idea:\d{1,2}|quote:\d{1,2}\.\d)){0,63}$/;
4
4
  /**
@@ -7,19 +7,27 @@ export const reviewSpec = /^(?:all|gist|idea:\d{1,2}|quote:\d{1,2}\.\d)(?:,(?:al
7
7
  */
8
8
  export function reviewFromSpec(d, accept, reject) {
9
9
  if (accept === undefined && reject === undefined)
10
- throw new InputError();
11
- const ideas = d.output.ideas, review = { gist: d.review.gist, ideas: ideas.map((_, i) => d.review.ideas?.[i] ?? null), quotes: ideas.map((idea, i) => idea.quotes.map((_, j) => d.review.quotes?.[i]?.[j] ?? null)) };
12
- const parse = (spec) => { if (spec === undefined)
13
- return []; if (!reviewSpec.test(spec))
14
- throw new InputError(); return [...new Set(spec.split(','))]; };
10
+ throw new SpongeError('invalid-input');
11
+ const ideas = d.output.ideas, review = {
12
+ gist: d.review.gist,
13
+ ideas: ideas.map((_, i) => d.review.ideas?.[i] ?? null),
14
+ quotes: ideas.map((idea, i) => idea.quotes.map((_, j) => d.review.quotes?.[i]?.[j] ?? null)),
15
+ };
16
+ const parse = (spec) => {
17
+ if (spec === undefined)
18
+ return [];
19
+ if (!reviewSpec.test(spec))
20
+ throw new SpongeError('invalid-input');
21
+ return [...new Set(spec.split(','))];
22
+ };
15
23
  const a = parse(accept), r = parse(reject);
16
- if (a.some(t => r.includes(t)))
17
- throw new InputError();
24
+ if (a.some((t) => r.includes(t)))
25
+ throw new SpongeError('invalid-input');
18
26
  const set = (target, status) => {
19
27
  if (target === 'all') {
20
28
  review.gist = status;
21
29
  review.ideas = review.ideas.map(() => status);
22
- review.quotes = review.quotes.map(q => q.map(() => status));
30
+ review.quotes = review.quotes.map((q) => q.map(() => status));
23
31
  return;
24
32
  }
25
33
  if (target === 'gist') {
@@ -28,20 +36,26 @@ export function reviewFromSpec(d, accept, reject) {
28
36
  }
29
37
  const [, kind, i, j] = /^(idea|quote):(\d+)(?:\.(\d+))?$/.exec(target), n = Number(i);
30
38
  if (n >= ideas.length)
31
- throw new InputError();
39
+ throw new SpongeError('invalid-input');
32
40
  if (kind === 'idea') {
33
41
  review.ideas[n] = status;
34
42
  return;
35
43
  }
36
44
  if (Number(j) >= ideas[n].quotes.length)
37
- throw new InputError();
45
+ throw new SpongeError('invalid-input');
38
46
  review.quotes[n][Number(j)] = status;
39
47
  };
40
- for (const [targets, status] of [[a, 'accepted'], [r, 'rejected']])
48
+ for (const [targets, status] of [
49
+ [a, 'accepted'],
50
+ [r, 'rejected'],
51
+ ])
41
52
  for (const t of targets)
42
53
  if (t === 'all')
43
54
  set(t, status);
44
- for (const [targets, status] of [[a, 'accepted'], [r, 'rejected']])
55
+ for (const [targets, status] of [
56
+ [a, 'accepted'],
57
+ [r, 'rejected'],
58
+ ])
45
59
  for (const t of targets)
46
60
  if (t !== 'all')
47
61
  set(t, status);
@@ -51,13 +65,21 @@ const mark = (s) => s === 'accepted' ? '[accepted]' : s === 'rejected' ? '[rejec
51
65
  /** Plain-text digest with the review targets `sponge review` accepts. */
52
66
  export function digestText(d) {
53
67
  const o = d.output, producer = d.producer;
54
- const lines = [`Digest ${d.id} (${o.form}${producer?.model?.model ? `, ${producer.model.model}` : ''}${producer?.promptVersion ? `, ${producer.promptVersion}` : ''})`, '', `gist ${mark(d.review.gist)} ${o.gist.lead}`];
68
+ const lines = [
69
+ `Digest ${d.id} (${o.form}${producer?.model?.model ? `, ${producer.model.model}` : ''}${producer?.promptVersion ? `, ${producer.promptVersion}` : ''})`,
70
+ '',
71
+ `gist ${mark(d.review.gist)} ${o.gist.lead}`,
72
+ ];
55
73
  if (o.gist.context)
56
74
  lines.push(` ${o.gist.context}`);
57
75
  o.ideas.forEach((idea, i) => {
58
- lines.push('', `idea:${i} ${mark(d.review.ideas?.[i])} ${idea.claim}`, ` ${idea.kind}; ${idea.voice.type === 'author' ? 'author' : `${idea.voice.type}: ${idea.voice.name}`}`, ` ${idea.detail}`);
59
- idea.quotes.forEach((q, j) => lines.push(` quote:${i}.${j} ${mark(d.review.quotes?.[i]?.[j])} “${q.text.replace(/\s+/g, ' ')}”${q.speaker ? ` (${q.speaker})` : ''}`));
76
+ lines.push('', `idea:${i} ${mark(d.review.ideas?.[i])} ${idea.claim}`, ...(idea.kind || idea.voice
77
+ ? [
78
+ ` ${[idea.kind, idea.voice && (idea.voice.type === 'author' ? 'author' : `${idea.voice.type}: ${idea.voice.name}`)].filter(Boolean).join('; ')}`,
79
+ ]
80
+ : []), ` ${idea.detail}`);
81
+ idea.quotes.forEach((q, j) => lines.push(` quote:${i}.${j} ${mark(d.review.quotes?.[i]?.[j])} “${q.text.replace(/\s+/g, ' ')}”${(q.attribution ?? q.speaker) ? ` (${q.attribution ?? q.speaker})` : ''}`));
60
82
  });
61
- lines.push('', `Tags: ${o.tags.join(', ')}`);
83
+ lines.push('', `Tags: ${o.tags.join(', ') || 'none'}`);
62
84
  return lines.join('\n');
63
85
  }
@@ -2,12 +2,33 @@ import { importManifest } from '../importers/apply.js';
2
2
  import { releasedBundleVerifier } from '../importers/inspect.js';
3
3
  import { importJungle } from '../importers/jungle.js';
4
4
  /** A source manifest is explicit; default execution produces a private dry-run report. */
5
- export function importAction(store, path, options) { return importManifest(store, path, options); }
5
+ export function importAction(store, path, options) {
6
+ return importManifest(store, path, options);
7
+ }
6
8
  /** Jungle is read in place; only an applied import needs the capture runtime, to reverify each bundle. */
7
9
  export function jungleAction(store, path, options) {
8
- return importJungle(store, path, { dryRun: options.dryRun, limit: options.limit, offset: options.offset, ...(options.signal ? { signal: options.signal } : {}), ...(options.runtime ? { verify: releasedBundleVerifier(options.runtime, store.root, options.signal) } : {}) });
10
+ return importJungle(store, path, {
11
+ dryRun: options.dryRun,
12
+ limit: options.limit,
13
+ offset: options.offset,
14
+ ...(options.signal ? { signal: options.signal } : {}),
15
+ ...(options.runtime ? { verify: releasedBundleVerifier(options.runtime, store.root, options.signal) } : {}),
16
+ });
9
17
  }
10
- const tally = (m) => Object.entries(m).sort().map(([k, n]) => `${k} ${n}`).join(', ') || 'none';
18
+ const tally = (m) => Object.entries(m)
19
+ .sort()
20
+ .map(([k, n]) => `${k} ${n}`)
21
+ .join(', ') || 'none';
11
22
  export function jungleText(r) {
12
- return [`Jungle ${r.dryRun ? 'dry run (captures verified on --apply)' : 'import'}: ${r.entries.length} of ${r.notes} notes`, `Items: ${r.counts.newItems} new, ${r.counts.existingItems} existing`, `Editorial: ${tally(r.counts.editorial)}`, `Digest v1: ${tally(r.counts.v1)}`, `Visibility: ${tally(r.counts.visibility)}`, `Skipped: ${tally(r.counts.skipped)}`, ...(r.nextOffset !== null ? [`Next offset: ${r.nextOffset}`] : [])].join('\n');
23
+ return [
24
+ `Jungle ${r.dryRun ? 'dry run (captures verified on --apply)' : 'import'}: ${r.entries.length} of ${r.notes} notes`,
25
+ `Items: ${r.counts.newItems} new, ${r.counts.existingItems} existing`,
26
+ `Editorial: ${tally(r.counts.editorial)}`,
27
+ `Digest v2: ${tally(r.counts.digest)}`,
28
+ ...(Object.keys(r.counts.digestIssues).length ? [`Not convertible because: ${tally(r.counts.digestIssues)}`] : []),
29
+ `Quotes: ${r.counts.quotes.assigned} assigned, dropped ${tally(r.counts.quotes.dropped)}`,
30
+ `Visibility: ${tally(r.counts.visibility)}`,
31
+ `Skipped: ${tally(r.counts.skipped)}`,
32
+ ...(r.nextOffset !== null ? [`Next offset: ${r.nextOffset}`] : []),
33
+ ].join('\n');
13
34
  }
@@ -8,3 +8,5 @@ export declare function indexAction(store: LibraryStore, action: string, id: str
8
8
  dryRun?: boolean;
9
9
  vacuum?: boolean;
10
10
  }): Promise<Record<string, unknown>>;
11
+ /** `index status` with no generation: the active one's coverage and what is still to embed. */
12
+ export declare function overviewText(result: ReturnType<LibraryStore['index']['overview']>): string;
@@ -1,24 +1,41 @@
1
1
  import { indexSpace } from '../inference/embedding/index.js';
2
2
  import { drainIndexQueue } from '../indexing/runner.js';
3
- import { StoreError } from '../store/index.js';
4
- import { NativeCatalogError } from '../models/catalog.js';
5
3
  import { pruneIndex } from '../indexing/prune-run.js';
4
+ import { SpongeError } from '../errors.js';
6
5
  export async function indexAction(store, action, id, options = {}) {
7
6
  if (action === 'status')
8
- return { generation: store.indexStatus(id) };
7
+ return id ? { generation: store.index.status(id) } : store.index.overview(options.profile);
9
8
  if (action === 'rollback') {
10
- const generation = store.indexStatus(id);
9
+ const generation = store.index.status(id);
11
10
  if (!['active', 'retired'].includes(generation.state))
12
- throw new StoreError('invalid-input');
13
- return { generation: store.activateIndex(id) };
11
+ throw new SpongeError('invalid-input');
12
+ return { generation: store.index.activate(id) };
14
13
  }
15
14
  if (action === 'prune')
16
15
  return { prune: await pruneIndex(store, { keep: options.keep, dryRun: options.dryRun, vacuum: options.vacuum }) };
17
16
  if (!options.runtime)
18
- throw new NativeCatalogError('runtime-missing');
17
+ throw new SpongeError('runtime-missing');
19
18
  if (action === 'create') {
20
- const space = indexSpace(options.runtime.helperSha256), generation = store.createIndexGeneration({ profileId: options.profile ?? 'default', fingerprint: space.fingerprint, identity: space.identity, dimensions: space.dimensions });
21
- return { generation, job: store.submitIndexJob(generation.id) };
19
+ const space = indexSpace(options.runtime.helperSha256), generation = store.index.create({
20
+ profileId: options.profile ?? 'default',
21
+ fingerprint: space.fingerprint,
22
+ identity: space.identity,
23
+ dimensions: space.dimensions,
24
+ });
25
+ return { generation, job: store.index.submitJob(generation.id) };
22
26
  }
23
27
  return { results: await drainIndexQueue(store, { runtime: options.runtime, signal: options.signal }) };
24
28
  }
29
+ /** `index status` with no generation: the active one's coverage and what is still to embed. */
30
+ export function overviewText(result) {
31
+ const { generation: g, job } = result;
32
+ if (!g)
33
+ return 'No active index. Run sponge index create, then sponge index run.';
34
+ return [
35
+ `Active generation: ${g.id} (${g.profileId})`,
36
+ `Items: ${g.items}`,
37
+ `Chunks and images: ${g.completed} of ${g.expected} embedded, ${g.pending} pending`,
38
+ `Job: ${job ? `${job.id} ${job.state}${job.reason ? ` (${job.reason})` : ''}` : 'none'}`,
39
+ ...(g.pending ? ['Run sponge index run (or let the worker) to embed only the pending ones.'] : []),
40
+ ].join('\n');
41
+ }