@hraness/sponge 0.5.3 → 0.6.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 (60) hide show
  1. package/README.md +8 -11
  2. package/dist/capture/NOTICES.txt +472 -0
  3. package/dist/capture/worker.js +553 -0
  4. package/dist/src/acquisition/capture.d.ts +3 -10
  5. package/dist/src/acquisition/capture.js +28 -202
  6. package/dist/src/acquisition/child-request.d.ts +40 -0
  7. package/dist/src/acquisition/child.d.ts +31 -0
  8. package/dist/src/acquisition/child.js +130 -0
  9. package/dist/src/acquisition/errors.d.ts +2 -2
  10. package/dist/src/acquisition/errors.js +15 -4
  11. package/dist/src/acquisition/index.d.ts +0 -3
  12. package/dist/src/acquisition/index.js +0 -2
  13. package/dist/src/acquisition/normalize.d.ts +1 -3
  14. package/dist/src/acquisition/normalize.js +20 -22
  15. package/dist/src/app/article.d.ts +1 -2
  16. package/dist/src/app/article.js +1 -2
  17. package/dist/src/cli/commands.d.ts +0 -1
  18. package/dist/src/cli/commands.js +8 -35
  19. package/dist/src/cli/import.d.ts +1 -3
  20. package/dist/src/cli/import.js +3 -3
  21. package/dist/src/cli/main.js +0 -2
  22. package/dist/src/cli/runtimes.js +2 -3
  23. package/dist/src/cli/worker.d.ts +1 -4
  24. package/dist/src/cli/worker.js +0 -4
  25. package/dist/src/importers/apply.d.ts +0 -2
  26. package/dist/src/importers/apply.js +2 -2
  27. package/dist/src/importers/inspect.d.ts +2 -2
  28. package/dist/src/importers/inspect.js +24 -23
  29. package/dist/src/metadata/article.d.ts +0 -1
  30. package/dist/src/metadata/article.js +3 -2
  31. package/dist/src/pdf/capture.d.ts +7 -16
  32. package/dist/src/pdf/capture.js +44 -198
  33. package/dist/src/pdf/handler.d.ts +1 -2
  34. package/dist/src/pdf/handler.js +0 -1
  35. package/dist/src/pdf/normalize.d.ts +2 -3
  36. package/dist/src/pdf/normalize.js +34 -38
  37. package/dist/src/pdf/tools.d.ts +2 -0
  38. package/dist/src/pdf/tools.js +21 -0
  39. package/native/runtime-manifest.json +5 -5
  40. package/package.json +11 -2
  41. package/dist/src/acquisition/clip-helper.js +0 -14
  42. package/dist/src/acquisition/lock.d.ts +0 -1
  43. package/dist/src/acquisition/lock.js +0 -2
  44. package/dist/src/acquisition/pins.d.ts +0 -3
  45. package/dist/src/acquisition/pins.js +0 -21
  46. package/dist/src/acquisition/runtime.d.ts +0 -48
  47. package/dist/src/acquisition/runtime.js +0 -273
  48. package/dist/src/acquisition/verify-helper.d.ts +0 -1
  49. package/dist/src/acquisition/verify-helper.js +0 -26
  50. package/dist/src/importers/verify-helper.d.ts +0 -1
  51. package/dist/src/importers/verify-helper.js +0 -41
  52. package/dist/src/pdf/capture-helper.d.ts +0 -1
  53. package/dist/src/pdf/capture-helper.js +0 -15
  54. package/dist/src/pdf/errors.d.ts +0 -2
  55. package/dist/src/pdf/errors.js +0 -23
  56. package/dist/src/pdf/source-identity.d.ts +0 -4
  57. package/dist/src/pdf/source-identity.js +0 -13
  58. package/dist/src/pdf/verify-helper.d.ts +0 -1
  59. package/dist/src/pdf/verify-helper.js +0 -29
  60. /package/dist/src/acquisition/{clip-helper.d.ts → child-request.js} +0 -0
@@ -1,9 +1,9 @@
1
- import { join, isAbsolute } from 'node:path';
1
+ import { isAbsolute } from 'node:path';
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { connectionFor, readConnections } from './config.js';
4
4
  import { pdfSource } from '../pdf/index.js';
5
5
  import { articleSource, inferKind, mediaSource } from '../app/source.js';
6
- import { defaultCapturePins, inspectCaptureRuntime, provisionCapture, captureSetupPlan } from '../acquisition/index.js';
6
+ import { pdfToolsAvailable } from '../pdf/tools.js';
7
7
  import { queueAction } from './queue.js';
8
8
  import { portabilityAction } from './portability.js';
9
9
  import { restoreLibrary } from '../portability/backup.js';
@@ -28,15 +28,6 @@ import { SpongeError, codeOf, publicCode, exitFor, isSpongeCode } from '../error
28
28
  const abs = (v) => typeof v === 'string' && isAbsolute(v);
29
29
  const media = { language: 'value', 'force-local': 'boolean', 'allow-private-network': 'boolean' };
30
30
  const lines = (items) => items.map((item) => `${item.itemId}\t${item.title}`);
31
- /** A required capture runtime, as the categorical code of its inspection failure. */
32
- async function captureRuntime(c) {
33
- try {
34
- return await inspectCaptureRuntime(c.captureRoot, defaultCapturePins);
35
- }
36
- catch (error) {
37
- throw new SpongeError(publicCode(error, 'runtime-missing'), { cause: error });
38
- }
39
- }
40
31
  /** The failure of a job that did not run here: its state, or its recorded reason. */
41
32
  function jobFailure(store, jobId) {
42
33
  const job = store.queue.list().find((j) => j.id === jobId), reason = job?.reason;
@@ -60,13 +51,11 @@ async function drain(c, jobId, connections) {
60
51
  if (job && job.state !== 'queued')
61
52
  throw jobFailure(store, jobId);
62
53
  }
63
- const runtime = await captureRuntime(c);
64
54
  const results = await drainLibrary(store, {
65
55
  asrRuntime: await optionalNative('asr', c.nativeRoot, c.version),
66
56
  mediaRuntime: await optionalNative('media', c.nativeRoot, c.version),
67
57
  language: args.flags.language,
68
58
  forceLocal: args.flags['force-local'] === true,
69
- runtime,
70
59
  jobId,
71
60
  signal,
72
61
  allowPrivateNetwork: args.flags['allow-private-network'] === true,
@@ -166,14 +155,7 @@ export const commands = [
166
155
  await installNative('media').catch((error) => {
167
156
  media = codeOf(error);
168
157
  });
169
- const plan = captureSetupPlan(defaultCapturePins);
170
- process.stderr.write(`Capture setup: ${plan.downloadBytes} pinned artifact bytes, plus frozen dependency downloads. Temporary installation limit: ${plan.stagingBudgetBytes} bytes; retained runtime limit: ${plan.installationBudgetBytes} bytes; dependency installation deadline: ${plan.installationDeadlineMs / 60000} minutes. ${plan.requiredFreeBytes} free bytes required.\n`);
171
- await provisionCapture({
172
- runtimeRoot: join(c.store.root, 'runtime', 'capture'),
173
- pins: defaultCapturePins,
174
- signal: c.signal,
175
- });
176
- // Articles and PDFs run anywhere; the media helper is a native release asset and is best-effort.
158
+ // Articles and PDFs are built in; the media helper is a native release asset and is best-effort.
177
159
  const gc = await setupRuntimeGc(c.store, c.version), ready = media === 'ready'
178
160
  ? 'Capture ready'
179
161
  : media === 'unsupported'
@@ -429,13 +411,8 @@ export const commands = [
429
411
  library: 'open',
430
412
  handler: async (c) => {
431
413
  const { store } = c;
432
- let capture = 'ready';
433
- try {
434
- await inspectCaptureRuntime(c.captureRoot, defaultCapturePins);
435
- }
436
- catch (error) {
437
- capture = publicCode(error, 'runtime-missing');
438
- }
414
+ // Article capture is built in; PDFs need the local Poppler tools.
415
+ const capture = 'ready', pdf = pdfToolsAvailable() ? 'ready' : 'runtime-missing';
439
416
  const states = {};
440
417
  for (const kind of ['asr', 'embedding', 'media']) {
441
418
  try {
@@ -447,8 +424,8 @@ export const commands = [
447
424
  }
448
425
  }
449
426
  const cleanup = store.queue.pendingCleanup(), worker = await workerDoctor(store, c.version), workerBroken = !['ready', 'not-installed', 'unsupported'].includes(worker.worker);
450
- c.emit({ library: 'ready', capture, ...states, pendingCleanup: cleanup, worker }, `Library: ready\nCapture: ${capture}\nASR: ${states.asr}\nEmbedding: ${states.embedding}\nPending cleanup: ${cleanup}\nWorker: ${worker.worker}${Array.isArray(worker.drift) ? ` (${worker.drift.join(', ')})` : ''}${worker.repair ? `\n ${worker.repair}` : ''}`);
451
- return cleanup || capture !== 'ready' || workerBroken ? 4 : 0;
427
+ c.emit({ library: 'ready', capture, pdf, ...states, pendingCleanup: cleanup, worker }, `Library: ready\nCapture: ${capture}\nPDF: ${pdf === 'ready' ? 'ready' : 'Poppler not found (brew install poppler)'}\nASR: ${states.asr}\nEmbedding: ${states.embedding}\nPending cleanup: ${cleanup}\nWorker: ${worker.worker}${Array.isArray(worker.drift) ? ` (${worker.drift.join(', ')})` : ''}${worker.repair ? `\n ${worker.repair}` : ''}`);
428
+ return cleanup || workerBroken ? 4 : 0;
452
429
  },
453
430
  },
454
431
  {
@@ -545,7 +522,6 @@ export const commands = [
545
522
  signal: c.signal,
546
523
  language: args.flags.language,
547
524
  forceLocal: args.flags['force-local'] === true,
548
- resolveCaptureRuntime: () => inspectCaptureRuntime(c.captureRoot, defaultCapturePins),
549
525
  resolveConnection: resolveConnection(connections),
550
526
  }, c.version));
551
527
  return 0;
@@ -568,10 +544,8 @@ export const commands = [
568
544
  const { store, args, signal } = c, dryRun = args.flags.apply !== true, offset = Number(args.flags.offset ?? 0);
569
545
  if (args.positional[0] === 'jungle' && args.positional.length === 2) {
570
546
  // A dry run reads Jungle and the library only; applying reverifies every capture with the released verifier.
571
- const runtime = dryRun ? undefined : await captureRuntime(c);
572
547
  const report = await jungleAction(store, args.positional[1], {
573
548
  dryRun,
574
- runtime,
575
549
  limit: Number(args.flags.limit ?? 1000),
576
550
  offset,
577
551
  signal,
@@ -583,8 +557,7 @@ export const commands = [
583
557
  ? 3
584
558
  : 0;
585
559
  }
586
- const runtime = await captureRuntime(c), report = await importAction(store, args.positional[0], {
587
- runtime,
560
+ const report = await importAction(store, args.positional[0], {
588
561
  dryRun,
589
562
  limit: Number(args.flags.limit ?? 20),
590
563
  offset,
@@ -1,13 +1,11 @@
1
1
  import type { LibraryStore } from '../store/index.js';
2
- import type { CaptureRuntime } from '../acquisition/index.js';
3
2
  import { type ImportOptions, type ImportReport } from '../importers/apply.js';
4
3
  import { type JungleImportReport } from '../importers/jungle.js';
5
4
  /** A source manifest is explicit; default execution produces a private dry-run report. */
6
5
  export declare function importAction(store: LibraryStore, path: string, options: ImportOptions): Promise<ImportReport>;
7
- /** Jungle is read in place; only an applied import needs the capture runtime, to reverify each bundle. */
6
+ /** Jungle is read in place; only an applied import reverifies each bundle. */
8
7
  export declare function jungleAction(store: LibraryStore, path: string, options: {
9
8
  dryRun: boolean;
10
- runtime?: CaptureRuntime;
11
9
  limit: number;
12
10
  offset: number;
13
11
  signal?: AbortSignal;
@@ -1,18 +1,18 @@
1
1
  import { importManifest } from '../importers/apply.js';
2
- import { releasedBundleVerifier } from '../importers/inspect.js';
2
+ import { ownedBundleVerifier } 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
5
  export function importAction(store, path, options) {
6
6
  return importManifest(store, path, options);
7
7
  }
8
- /** Jungle is read in place; only an applied import needs the capture runtime, to reverify each bundle. */
8
+ /** Jungle is read in place; only an applied import reverifies each bundle. */
9
9
  export function jungleAction(store, path, options) {
10
10
  return importJungle(store, path, {
11
11
  dryRun: options.dryRun,
12
12
  limit: options.limit,
13
13
  offset: options.offset,
14
14
  ...(options.signal ? { signal: options.signal } : {}),
15
- ...(options.runtime ? { verify: releasedBundleVerifier(options.runtime, store.root, options.signal) } : {}),
15
+ ...(options.dryRun ? {} : { verify: ownedBundleVerifier(store.root, options.signal) }),
16
16
  });
17
17
  }
18
18
  const tally = (m) => Object.entries(m)
@@ -6,7 +6,6 @@ import { terminalSafe } from './terminal.js';
6
6
  import { parseArguments } from './arguments.js';
7
7
  import { command, usageOf } from './commands.js';
8
8
  import { openLibrary } from '../store/index.js';
9
- import { defaultCapturePins } from '../acquisition/index.js';
10
9
  import { failure } from '../acquisition/errors.js';
11
10
  import { SpongeError, codeOf, publicCode, exitFor, hints, detailHints, debugChain, } from '../errors.js';
12
11
  /** Failures print one categorical JSON line: the public code, its specific `reason` when narrower, and a fixed hint.
@@ -65,7 +64,6 @@ export async function main(argv, version) {
65
64
  return await spec.handler({
66
65
  ...context,
67
66
  store,
68
- captureRoot: join(store.root, 'runtime', 'capture', defaultCapturePins.id),
69
67
  nativeRoot: join(store.root, 'runtime', 'models'),
70
68
  });
71
69
  }
@@ -1,10 +1,9 @@
1
- import { defaultCapturePins } from '../acquisition/index.js';
2
1
  import { loadNativeCatalog, nativeModelPackage } from '../models/catalog.js';
3
2
  import { modelSetupPlan } from '../models/artifacts.js';
4
3
  import { digestFingerprints } from '../models/digest.js';
5
4
  import { collectRuntimes } from '../worker/runtime-gc.js';
6
5
  import { codeOf } from '../errors.js';
7
- /** References of this installed Sponge: its capture pin, its catalog's model packages and every digest pin. */
6
+ /** References of this installed Sponge: its catalog's model packages and every digest pin. Capture is built in, so every capture runtime is superseded. */
8
7
  async function installedReferences(version) {
9
8
  let models = null;
10
9
  try {
@@ -19,7 +18,7 @@ async function installedReferences(version) {
19
18
  catch {
20
19
  /* Without the catalog no model directory is provably superseded. */
21
20
  }
22
- return { captureIds: [defaultCapturePins.id], models };
21
+ return { captureIds: [], models };
23
22
  }
24
23
  export async function runtimeGcAction(store, version, dryRun) {
25
24
  return collectRuntimes(store, { ...(await installedReferences(version)), dryRun });
@@ -12,10 +12,7 @@ export declare function workerDoctor(store: LibraryStore, version: string, envir
12
12
  lastExit?: unknown;
13
13
  }>;
14
14
  type DrainOptions = Parameters<typeof drainLibrary>[1];
15
- export type ServiceDrainOptions = Omit<DrainOptions, 'runtime'> & {
16
- runtime?: DrainOptions['runtime'];
17
- resolveCaptureRuntime?: () => Promise<DrainOptions['runtime']>;
18
- };
15
+ export type ServiceDrainOptions = DrainOptions;
19
16
  /** Dispatch only work that claimNext can admit; delayed retries retain their due time. */
20
17
  export declare function hasDueAcquisition(store: LibraryStore): boolean;
21
18
  export declare function drainServiceQueues(store: LibraryStore, options: ServiceDrainOptions, version: string, signal: AbortSignal): Promise<readonly unknown[]>;
@@ -60,16 +60,12 @@ export async function drainServiceQueues(store, options, version, signal) {
60
60
  let acquisitionError;
61
61
  if (hasDueAcquisition(store)) {
62
62
  try {
63
- const runtime = options.runtime ?? (await options.resolveCaptureRuntime?.());
64
- if (!runtime)
65
- throw new SpongeError('runtime-missing');
66
63
  const models = join(store.root, 'runtime', 'models');
67
64
  // Media jobs report a missing helper themselves; articles and PDFs still drain.
68
65
  const asrRuntime = options.asrRuntime ?? (await optionalNative('asr', models, version));
69
66
  const mediaRuntime = options.mediaRuntime ?? (await optionalNative('media', models, version));
70
67
  results.push(...(await drainLibrary(store, {
71
68
  ...options,
72
- runtime,
73
69
  asrRuntime,
74
70
  mediaRuntime,
75
71
  signal,
@@ -1,9 +1,7 @@
1
1
  import type { LibraryStore } from '../store/index.js';
2
2
  import { type ImportEntry } from './manifest.js';
3
3
  import { type BundleVerifier } from './inspect.js';
4
- import type { CaptureRuntime } from '../acquisition/runtime.js';
5
4
  export interface ImportOptions {
6
- runtime: CaptureRuntime;
7
5
  dryRun?: boolean;
8
6
  limit?: number;
9
7
  offset?: number;
@@ -5,7 +5,7 @@ import { localizeMarkdown } from '../app/markdown.js';
5
5
  import { selectedMetadata } from '../metadata/article.js';
6
6
  import { drainQueue } from '../worker/engine.js';
7
7
  import { readImportManifest, importBundleRoot } from './manifest.js';
8
- import { inspectImportBundle, releasedBundleVerifier } from './inspect.js';
8
+ import { inspectImportBundle, ownedBundleVerifier } from './inspect.js';
9
9
  import { SpongeError, publicCode } from '../errors.js';
10
10
  const errorCode = (error) => {
11
11
  const code = publicCode(error);
@@ -125,7 +125,7 @@ export async function importManifest(store, path, options) {
125
125
  entries: [],
126
126
  nextOffset: offset + limit < manifest.entries.length ? offset + limit : null,
127
127
  };
128
- const verify = options.verify ?? releasedBundleVerifier(options.runtime, store.root, options.signal);
128
+ const verify = options.verify ?? ownedBundleVerifier(store.root, options.signal);
129
129
  for (const entry of manifest.entries.slice(offset, offset + limit)) {
130
130
  if (options.signal?.aborted)
131
131
  throw new SpongeError('cancelled');
@@ -1,5 +1,4 @@
1
1
  import type { Asset, MetadataClaim } from '../../contracts/index.js';
2
- import { type CaptureRuntime } from '../acquisition/runtime.js';
3
2
  export interface ImportedBundle {
4
3
  root: string;
5
4
  kind: 'article' | 'pdf';
@@ -16,6 +15,7 @@ export interface ImportedBundle {
16
15
  importHash: string;
17
16
  }
18
17
  export type BundleVerifier = (root: string, kind: 'article' | 'pdf') => Promise<unknown>;
19
- export declare function releasedBundleVerifier(runtime: CaptureRuntime, libraryRoot: string, signal?: AbortSignal): BundleVerifier;
18
+ /** Bundles are read by the owned child with networking denied; its report carries no document text. */
19
+ export declare function ownedBundleVerifier(libraryRoot: string, signal?: AbortSignal): BundleVerifier;
20
20
  /** An import-time digest never upgrades a missing historical document digest. */
21
21
  export declare function inspectImportBundle(root: string, verify: BundleVerifier): Promise<ImportedBundle>;
@@ -1,4 +1,5 @@
1
- import { fileURLToPath, pathToFileURL } from 'node:url';
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { pathToFileURL } from 'node:url';
2
3
  import { join } from 'node:path';
3
4
  import { limits } from '../../contracts/index.js';
4
5
  import { validateAsset } from '../../contracts/validate.js';
@@ -6,32 +7,32 @@ import { object, metadataFromMarkdown } from '../acquisition/normalize.js';
6
7
  import { readConfined } from '../acquisition/files.js';
7
8
  import { sha256 as hash } from '../util/hash.js';
8
9
  import { withImportVerification } from './custody.js';
9
- import { inspectCaptureRuntime } from '../acquisition/runtime.js';
10
+ import { workerArguments } from '../acquisition/child.js';
10
11
  import { articleMetadata } from '../metadata/article.js';
11
12
  import { bundleBytes } from '../app/bundle-files.js';
12
13
  import { SpongeError } from '../errors.js';
13
- export function releasedBundleVerifier(runtime, libraryRoot, signal) {
14
- return async (root, kind) => {
15
- const checked = await inspectCaptureRuntime(runtime.root, runtime.pins), helper = fileURLToPath(new URL(import.meta.url.endsWith('.ts') ? './verify-helper.ts' : './verify-helper.js', import.meta.url));
16
- return withImportVerification(libraryRoot, async ({ scratchRoot, runProcess }) => {
17
- const args = [helper, checked.root, root, kind];
18
- const result = await runProcess(process.platform === 'darwin' ? '/usr/bin/sandbox-exec' : checked.bun, process.platform === 'darwin'
19
- ? ['-p', '(version 1) (allow default) (deny network*)', checked.bun, ...args]
20
- : args, {
21
- env: { PATH: '/usr/bin:/bin', HOME: checked.root, TMPDIR: scratchRoot, LANG: 'en_US.UTF-8' },
22
- deadlineMs: 45000,
23
- maxOutputBytes: 65536,
24
- signal,
25
- });
26
- if (result.cleanup !== 'settled')
27
- throw new SpongeError('cleanup-required');
28
- if (result.stopped)
29
- throw new SpongeError(result.stopped);
30
- if (result.code !== 0)
31
- throw new SpongeError('unsupported');
32
- return JSON.parse(result.stdout);
14
+ /** Bundles are read by the owned child with networking denied; its report carries no document text. */
15
+ export function ownedBundleVerifier(libraryRoot, signal) {
16
+ return (bundle, format) => withImportVerification(libraryRoot, async ({ scratchRoot, runProcess }) => {
17
+ const requestFile = join(scratchRoot, 'request.json'), request = { schemaVersion: 1, kind: 'verify', format, bundle };
18
+ await writeFile(requestFile, JSON.stringify(request), { mode: 0o600 });
19
+ const args = [...workerArguments(), requestFile];
20
+ const result = await runProcess(process.platform === 'darwin' ? '/usr/bin/sandbox-exec' : process.execPath, process.platform === 'darwin'
21
+ ? ['-p', '(version 1) (allow default) (deny network*)', process.execPath, ...args]
22
+ : args, {
23
+ env: { PATH: '/usr/bin:/bin', HOME: scratchRoot, TMPDIR: scratchRoot, LANG: 'en_US.UTF-8' },
24
+ deadlineMs: 45000,
25
+ maxOutputBytes: 65536,
26
+ signal,
33
27
  });
34
- };
28
+ if (result.cleanup !== 'settled')
29
+ throw new SpongeError('cleanup-required');
30
+ if (result.stopped)
31
+ throw new SpongeError(result.stopped);
32
+ if (result.code !== 0)
33
+ throw new SpongeError('unsupported');
34
+ return JSON.parse(result.stdout);
35
+ });
35
36
  }
36
37
  function imageType(bytes) {
37
38
  if (bytes[0] === 255 && bytes[1] === 216)
@@ -1,5 +1,4 @@
1
1
  import type { MetadataClaim, MetadataWarning } from '../../contracts/index.js';
2
- /** Consume bounded observed Wordcell evidence without fetching linked JSON-LD contexts. */
3
2
  export declare function articleMetadata(input: unknown, observedAt: string): MetadataClaim[];
4
3
  export declare function selectedMetadata(claims: readonly MetadataClaim[], field: string): MetadataClaim | undefined;
5
4
  export declare function articleMetadataWarnings(input: unknown): MetadataWarning[];
@@ -6,11 +6,12 @@ function object(v) {
6
6
  throw new SpongeError('integrity');
7
7
  return v;
8
8
  }
9
- /** Consume bounded observed Wordcell evidence without fetching linked JSON-LD contexts. */
9
+ /** Consume bounded observed page evidence without fetching linked JSON-LD contexts. Imported Wordcell bundles keep their own version. */
10
+ const extractorVersions = new Set(['sponge-metadata-v1', 'wordcell-metadata-v1']);
10
11
  export function articleMetadata(input, observedAt) {
11
12
  const envelope = object(input);
12
13
  articleMetadataWarnings(input);
13
- if (envelope.schemaVersion !== 1 || envelope.extractorVersion !== 'wordcell-metadata-v1')
14
+ if (envelope.schemaVersion !== 1 || !extractorVersions.has(String(envelope.extractorVersion)))
14
15
  throw new SpongeError('schema-newer');
15
16
  if (!Array.isArray(envelope.claims) ||
16
17
  envelope.claims.length > limits.metadataClaims ||
@@ -1,26 +1,17 @@
1
- import type { CaptureResult, ErrorEnvelope } from '../../contracts/index.js';
2
- import { runOwned } from '../acquisition/process.js';
3
- import { type CaptureRuntime } from '../acquisition/runtime.js';
4
- type CaptureConnection = {
5
- kind: 'cdp';
6
- endpoint: string;
7
- };
1
+ import type { runOwned } from '../acquisition/process.js';
2
+ import { type CaptureOutcome } from '../acquisition/child.js';
3
+ export type { CaptureOutcome } from '../acquisition/child.js';
8
4
  export interface PdfCaptureRequest {
9
- runtime: CaptureRuntime;
10
5
  stagingRoot: string;
11
6
  sourceUrl: string;
12
7
  requestId: string;
13
- connection?: CaptureConnection;
8
+ connection?: {
9
+ kind: 'cdp';
10
+ endpoint: string;
11
+ };
14
12
  signal?: AbortSignal;
15
13
  deadlineMs?: number;
16
14
  allowPrivateNetwork?: boolean;
17
15
  runProcess?: typeof runOwned;
18
16
  }
19
- export type CaptureOutcome = {
20
- ok: true;
21
- capture: CaptureResult;
22
- bundleRoot: string;
23
- dispose: () => Promise<void>;
24
- } | ErrorEnvelope;
25
17
  export declare function capturePdf(request: PdfCaptureRequest): Promise<CaptureOutcome>;
26
- export {};