@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.
- package/README.md +8 -11
- package/dist/capture/NOTICES.txt +472 -0
- package/dist/capture/worker.js +553 -0
- package/dist/src/acquisition/capture.d.ts +3 -10
- package/dist/src/acquisition/capture.js +28 -202
- package/dist/src/acquisition/child-request.d.ts +40 -0
- package/dist/src/acquisition/child.d.ts +31 -0
- package/dist/src/acquisition/child.js +130 -0
- package/dist/src/acquisition/errors.d.ts +2 -2
- package/dist/src/acquisition/errors.js +15 -4
- package/dist/src/acquisition/index.d.ts +0 -3
- package/dist/src/acquisition/index.js +0 -2
- package/dist/src/acquisition/normalize.d.ts +1 -3
- package/dist/src/acquisition/normalize.js +20 -22
- package/dist/src/app/article.d.ts +1 -2
- package/dist/src/app/article.js +1 -2
- package/dist/src/cli/commands.d.ts +0 -1
- package/dist/src/cli/commands.js +8 -35
- package/dist/src/cli/import.d.ts +1 -3
- package/dist/src/cli/import.js +3 -3
- package/dist/src/cli/main.js +0 -2
- package/dist/src/cli/runtimes.js +2 -3
- package/dist/src/cli/worker.d.ts +1 -4
- package/dist/src/cli/worker.js +0 -4
- package/dist/src/importers/apply.d.ts +0 -2
- package/dist/src/importers/apply.js +2 -2
- package/dist/src/importers/inspect.d.ts +2 -2
- package/dist/src/importers/inspect.js +24 -23
- package/dist/src/metadata/article.d.ts +0 -1
- package/dist/src/metadata/article.js +3 -2
- package/dist/src/pdf/capture.d.ts +7 -16
- package/dist/src/pdf/capture.js +44 -198
- package/dist/src/pdf/handler.d.ts +1 -2
- package/dist/src/pdf/handler.js +0 -1
- package/dist/src/pdf/normalize.d.ts +2 -3
- package/dist/src/pdf/normalize.js +34 -38
- package/dist/src/pdf/tools.d.ts +2 -0
- package/dist/src/pdf/tools.js +21 -0
- package/native/runtime-manifest.json +5 -5
- package/package.json +11 -2
- package/dist/src/acquisition/clip-helper.js +0 -14
- package/dist/src/acquisition/lock.d.ts +0 -1
- package/dist/src/acquisition/lock.js +0 -2
- package/dist/src/acquisition/pins.d.ts +0 -3
- package/dist/src/acquisition/pins.js +0 -21
- package/dist/src/acquisition/runtime.d.ts +0 -48
- package/dist/src/acquisition/runtime.js +0 -273
- package/dist/src/acquisition/verify-helper.d.ts +0 -1
- package/dist/src/acquisition/verify-helper.js +0 -26
- package/dist/src/importers/verify-helper.d.ts +0 -1
- package/dist/src/importers/verify-helper.js +0 -41
- package/dist/src/pdf/capture-helper.d.ts +0 -1
- package/dist/src/pdf/capture-helper.js +0 -15
- package/dist/src/pdf/errors.d.ts +0 -2
- package/dist/src/pdf/errors.js +0 -23
- package/dist/src/pdf/source-identity.d.ts +0 -4
- package/dist/src/pdf/source-identity.js +0 -13
- package/dist/src/pdf/verify-helper.d.ts +0 -1
- package/dist/src/pdf/verify-helper.js +0 -29
- /package/dist/src/acquisition/{clip-helper.d.ts → child-request.js} +0 -0
package/dist/src/cli/commands.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
433
|
-
|
|
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 ||
|
|
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
|
|
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,
|
package/dist/src/cli/import.d.ts
CHANGED
|
@@ -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
|
|
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;
|
package/dist/src/cli/import.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { importManifest } from '../importers/apply.js';
|
|
2
|
-
import {
|
|
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
|
|
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.
|
|
15
|
+
...(options.dryRun ? {} : { verify: ownedBundleVerifier(store.root, options.signal) }),
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
const tally = (m) => Object.entries(m)
|
package/dist/src/cli/main.js
CHANGED
|
@@ -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
|
}
|
package/dist/src/cli/runtimes.js
CHANGED
|
@@ -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
|
|
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: [
|
|
21
|
+
return { captureIds: [], models };
|
|
23
22
|
}
|
|
24
23
|
export async function runtimeGcAction(store, version, dryRun) {
|
|
25
24
|
return collectRuntimes(store, { ...(await installedReferences(version)), dryRun });
|
package/dist/src/cli/worker.d.ts
CHANGED
|
@@ -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 =
|
|
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[]>;
|
package/dist/src/cli/worker.js
CHANGED
|
@@ -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,
|
|
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 ??
|
|
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
|
-
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
|
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
|
|
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 {
|
|
2
|
-
import {
|
|
3
|
-
|
|
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?:
|
|
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 {};
|