@hraness/sponge 0.2.6 → 0.3.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 +21 -9
- package/bin/sponge.js +8 -7
- package/dist/contracts/index.js +24 -6
- package/dist/contracts/validate.js +106 -29
- package/dist/migrations/008.d.ts +3 -0
- package/dist/migrations/008.js +5 -0
- package/dist/migrations/009.d.ts +3 -0
- package/dist/migrations/009.js +8 -0
- package/dist/migrations/010.d.ts +3 -0
- package/dist/migrations/010.js +11 -0
- package/dist/migrations/index.d.ts +15 -0
- package/dist/migrations/index.js +39 -0
- package/dist/src/acquisition/capture.js +87 -28
- package/dist/src/acquisition/cleanup.d.ts +0 -4
- package/dist/src/acquisition/cleanup.js +3 -5
- package/dist/src/acquisition/errors.js +17 -2
- package/dist/src/acquisition/files.d.ts +0 -1
- package/dist/src/acquisition/files.js +14 -11
- package/dist/src/acquisition/index.d.ts +2 -3
- package/dist/src/acquisition/index.js +1 -2
- package/dist/src/acquisition/lock.js +1 -1
- package/dist/src/acquisition/normalize.js +57 -18
- package/dist/src/acquisition/pins.js +22 -4
- package/dist/src/acquisition/process.js +67 -29
- package/dist/src/acquisition/runtime.d.ts +5 -7
- package/dist/src/acquisition/runtime.js +129 -68
- package/dist/src/acquisition/verify-helper.js +10 -3
- package/dist/src/annotations/quote.js +40 -12
- package/dist/src/annotations/store.d.ts +0 -1
- package/dist/src/annotations/store.js +66 -14
- package/dist/src/app/article.d.ts +2 -1
- package/dist/src/app/article.js +66 -70
- package/dist/src/app/bundle-files.d.ts +0 -4
- package/dist/src/app/bundle-files.js +11 -14
- package/dist/src/app/markdown.js +18 -6
- package/dist/src/app/source.d.ts +0 -4
- package/dist/src/app/source.js +18 -14
- package/dist/src/cli/arguments.d.ts +2 -8
- package/dist/src/cli/arguments.js +67 -80
- package/dist/src/cli/commands.d.ts +42 -0
- package/dist/src/cli/commands.js +795 -0
- package/dist/src/cli/config.js +12 -9
- package/dist/src/cli/digest.d.ts +1 -1
- package/dist/src/cli/digest.js +38 -16
- package/dist/src/cli/import.js +25 -4
- package/dist/src/cli/indexing.d.ts +2 -0
- package/dist/src/cli/indexing.js +26 -9
- package/dist/src/cli/main.js +47 -386
- package/dist/src/cli/portability.d.ts +0 -2
- package/dist/src/cli/portability.js +13 -8
- package/dist/src/cli/queue.js +12 -8
- package/dist/src/cli/runtimes.d.ts +1 -3
- package/dist/src/cli/runtimes.js +13 -6
- package/dist/src/cli/terminal.js +1 -1
- package/dist/src/cli/worker.d.ts +7 -0
- package/dist/src/cli/worker.js +54 -15
- package/dist/src/derivations/kinds.d.ts +34 -0
- package/dist/src/derivations/kinds.js +14 -0
- package/dist/src/derivations/types.d.ts +48 -0
- package/dist/src/derivations/types.js +1 -0
- package/dist/src/digest/derivation.d.ts +25 -0
- package/dist/src/digest/derivation.js +124 -0
- package/dist/src/digest/editorial.d.ts +9 -46
- package/dist/src/digest/editorial.js +57 -49
- package/dist/src/digest/endpoint.js +63 -27
- package/dist/src/digest/pipeline.d.ts +49 -28
- package/dist/src/digest/pipeline.js +369 -102
- package/dist/src/digest/schema.d.ts +11 -25
- package/dist/src/digest/schema.js +86 -18
- package/dist/src/errors.d.ts +46 -0
- package/dist/src/errors.js +117 -0
- package/dist/src/identity/query-policy.d.ts +0 -5
- package/dist/src/identity/query-policy.js +61 -9
- package/dist/src/identity/uri.d.ts +6 -5
- package/dist/src/identity/uri.js +37 -18
- package/dist/src/identity/visibility.d.ts +11 -1
- package/dist/src/identity/visibility.js +81 -17
- package/dist/src/importers/apply.js +104 -36
- package/dist/src/importers/custody.js +27 -9
- package/dist/src/importers/inspect.js +125 -38
- package/dist/src/importers/jungle-digest.d.ts +3 -6
- package/dist/src/importers/jungle-digest.js +196 -69
- package/dist/src/importers/jungle-store.d.ts +19 -6
- package/dist/src/importers/jungle-store.js +124 -28
- package/dist/src/importers/jungle.d.ts +14 -14
- package/dist/src/importers/jungle.js +142 -31
- package/dist/src/importers/manifest.js +57 -21
- package/dist/src/importers/verify-helper.js +18 -4
- package/dist/src/indexing/image.js +29 -10
- package/dist/src/indexing/index.d.ts +37 -6
- package/dist/src/indexing/index.js +360 -124
- package/dist/src/indexing/jobs.js +156 -47
- package/dist/src/indexing/prune-run.d.ts +2 -0
- package/dist/src/indexing/prune-run.js +69 -26
- package/dist/src/indexing/prune.d.ts +12 -3
- package/dist/src/indexing/prune.js +85 -35
- package/dist/src/indexing/runner.d.ts +2 -1
- package/dist/src/indexing/runner.js +83 -40
- package/dist/src/indexing/upgrade.d.ts +9 -0
- package/dist/src/indexing/upgrade.js +79 -0
- package/dist/src/inference/asr/bridge.js +6 -2
- package/dist/src/inference/asr/protocol.js +109 -19
- package/dist/src/inference/asr/runtime.js +58 -21
- package/dist/src/inference/asr/windows.js +9 -5
- package/dist/src/inference/embedding/index.d.ts +2 -6
- package/dist/src/inference/embedding/index.js +89 -29
- package/dist/src/ingest/attempt.d.ts +29 -0
- package/dist/src/ingest/attempt.js +55 -0
- package/dist/src/media/capture-helper.js +7 -2
- package/dist/src/media/capture.d.ts +2 -1
- package/dist/src/media/capture.js +124 -43
- package/dist/src/media/handler.d.ts +4 -2
- package/dist/src/media/handler.js +88 -70
- package/dist/src/media/transcribe.js +63 -21
- package/dist/src/metadata/article.js +49 -17
- package/dist/src/models/artifacts.d.ts +10 -8
- package/dist/src/models/artifacts.js +237 -106
- package/dist/src/models/catalog.d.ts +2 -5
- package/dist/src/models/catalog.js +94 -25
- package/dist/src/models/download.js +55 -15
- package/dist/src/models/runtime.d.ts +0 -2
- package/dist/src/models/runtime.js +69 -33
- package/dist/src/pdf/capture-helper.js +3 -1
- package/dist/src/pdf/capture.d.ts +2 -1
- package/dist/src/pdf/capture.js +95 -27
- package/dist/src/pdf/errors.js +12 -1
- package/dist/src/pdf/handler.d.ts +2 -1
- package/dist/src/pdf/handler.js +70 -71
- package/dist/src/pdf/index.d.ts +1 -3
- package/dist/src/pdf/index.js +0 -2
- package/dist/src/pdf/input.js +12 -7
- package/dist/src/pdf/normalize.js +80 -21
- package/dist/src/pdf/source-identity.js +3 -2
- package/dist/src/pdf/source.js +12 -8
- package/dist/src/pdf/verify-helper.js +15 -3
- package/dist/src/portability/backup.d.ts +2 -9
- package/dist/src/portability/backup.js +106 -22
- package/dist/src/portability/database.js +51 -17
- package/dist/src/portability/export.js +35 -9
- package/dist/src/portability/files.d.ts +1 -4
- package/dist/src/portability/files.js +127 -67
- package/dist/src/portability/gc.js +65 -22
- package/dist/src/publish/component.js +1 -1
- package/dist/src/publish/feed.d.ts +2 -2
- package/dist/src/publish/feed.js +75 -29
- package/dist/src/publish/identity.d.ts +5 -1
- package/dist/src/publish/identity.js +31 -11
- package/dist/src/publish/index.d.ts +2 -3
- package/dist/src/publish/index.js +34 -21
- package/dist/src/publish/projection.d.ts +2 -9
- package/dist/src/publish/projection.js +21 -14
- package/dist/src/search/extension.js +3 -1
- package/dist/src/search/hybrid.d.ts +3 -8
- package/dist/src/search/hybrid.js +45 -11
- package/dist/src/search/lexical.js +18 -4
- package/dist/src/search/query.js +56 -25
- package/dist/src/search/vector.js +37 -10
- package/dist/src/service/launch-agent.d.ts +5 -3
- package/dist/src/service/launch-agent.js +272 -83
- package/dist/src/service/lifetime.js +47 -14
- package/dist/src/service/loop.d.ts +3 -3
- package/dist/src/service/loop.js +47 -19
- package/dist/src/store/annotations.d.ts +32 -0
- package/dist/src/store/annotations.js +44 -0
- package/dist/src/store/backups.d.ts +18 -0
- package/dist/src/store/backups.js +110 -0
- package/dist/src/store/blobs.d.ts +24 -0
- package/dist/src/store/blobs.js +139 -0
- package/dist/src/store/changes.d.ts +5 -12
- package/dist/src/store/changes.js +108 -56
- package/dist/src/store/context.d.ts +15 -0
- package/dist/src/store/context.js +19 -0
- package/dist/src/store/derivations.d.ts +42 -0
- package/dist/src/store/derivations.js +104 -0
- package/dist/src/store/files.d.ts +0 -2
- package/dist/src/store/files.js +19 -24
- package/dist/src/store/ids.d.ts +30 -0
- package/dist/src/store/ids.js +34 -0
- package/dist/src/store/imports.d.ts +26 -0
- package/dist/src/store/imports.js +57 -0
- package/dist/src/store/index.d.ts +3 -186
- package/dist/src/store/index.js +2 -809
- package/dist/src/store/lease.d.ts +20 -0
- package/dist/src/store/lease.js +62 -0
- package/dist/src/store/library.d.ts +75 -0
- package/dist/src/store/library.js +174 -0
- package/dist/src/store/open.d.ts +7 -0
- package/dist/src/store/open.js +183 -0
- package/dist/src/store/queue.d.ts +65 -0
- package/dist/src/store/queue.js +327 -0
- package/dist/src/store/revisions.d.ts +12 -0
- package/dist/src/store/revisions.js +189 -0
- package/dist/src/store/search-index.d.ts +63 -0
- package/dist/src/store/search-index.js +190 -0
- package/dist/src/store/sync-ready.d.ts +6 -0
- package/dist/src/store/sync-ready.js +121 -0
- package/dist/src/store/types.d.ts +1 -5
- package/dist/src/store/types.js +1 -8
- package/dist/src/util/canonical.d.ts +2 -0
- package/dist/src/util/canonical.js +17 -0
- package/dist/src/util/exact.d.ts +2 -0
- package/dist/src/util/exact.js +9 -0
- package/dist/src/util/fsync.d.ts +4 -0
- package/dist/src/util/fsync.js +22 -0
- package/dist/src/util/hash.d.ts +4 -0
- package/dist/src/util/hash.js +8 -0
- package/dist/src/worker/basic.d.ts +0 -1
- package/dist/src/worker/basic.js +23 -7
- package/dist/src/worker/custody.d.ts +4 -1
- package/dist/src/worker/custody.js +111 -38
- package/dist/src/worker/engine.d.ts +2 -1
- package/dist/src/worker/engine.js +42 -20
- package/dist/src/worker/identity.js +13 -5
- package/dist/src/worker/journal.d.ts +1 -1
- package/dist/src/worker/journal.js +54 -24
- package/dist/src/worker/lock.d.ts +18 -0
- package/dist/src/worker/lock.js +196 -0
- package/dist/src/worker/runtime-gc.d.ts +4 -3
- package/dist/src/worker/runtime-gc.js +68 -41
- package/dist/src/worker/supervisor-child.js +19 -6
- package/dist/src/worker/supervisor.js +41 -8
- package/native/runtime-manifest.json +4 -4
- package/package.json +10 -2
- package/dist/src/digest/store.d.ts +0 -57
- package/dist/src/digest/store.js +0 -79
- package/dist/src/store/foundation.d.ts +0 -7
- package/dist/src/store/foundation.js +0 -7
|
@@ -4,35 +4,79 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
import { release } from 'node:os';
|
|
5
5
|
import { asrIdentity } from '../inference/asr/protocol.js';
|
|
6
6
|
import { embeddingIdentity } from '../inference/embedding/index.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
const fail = () => {
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
import { exactKeys } from '../util/exact.js';
|
|
8
|
+
import { SpongeError } from '../errors.js';
|
|
9
|
+
export const nativeAssetNames = {
|
|
10
|
+
'asr-helper': 'sponge-speech-macos26-arm64',
|
|
11
|
+
'embedding-helper': 'sponge-embedding-macos26-arm64',
|
|
12
|
+
'embedding-library': 'libCLiteRTLM_mac.dylib',
|
|
13
|
+
notices: 'native-NOTICES.txt',
|
|
14
|
+
};
|
|
15
|
+
const fail = () => {
|
|
16
|
+
throw new SpongeError('integrity');
|
|
17
|
+
};
|
|
18
|
+
const object = (value, keys) => exactKeys(value, keys, fail);
|
|
18
19
|
const sha = (v) => typeof v === 'string' && /^[a-f0-9]{64}$/u.test(v);
|
|
19
|
-
function version(v) {
|
|
20
|
+
function version(v) {
|
|
21
|
+
return (typeof v === 'string' &&
|
|
22
|
+
/^(0|[1-9]\d{0,15})\.(0|[1-9]\d{0,15})\.(0|[1-9]\d{0,15})$/u.test(v) &&
|
|
23
|
+
v.split('.').every((n) => Number.isSafeInteger(Number(n))));
|
|
24
|
+
}
|
|
20
25
|
/** Package-embedded release hashes are authority; local probe helper hashes never enter this catalog. */
|
|
21
26
|
export function parseNativeCatalog(value, expectedVersion) {
|
|
22
|
-
const r = object(value, [
|
|
23
|
-
|
|
27
|
+
const r = object(value, [
|
|
28
|
+
'schemaVersion',
|
|
29
|
+
'packageVersion',
|
|
30
|
+
'sourceCommit',
|
|
31
|
+
'platform',
|
|
32
|
+
'architecture',
|
|
33
|
+
'minimumMacOS',
|
|
34
|
+
'artifacts',
|
|
35
|
+
'build',
|
|
36
|
+
]);
|
|
37
|
+
if (r.schemaVersion !== 1 ||
|
|
38
|
+
!version(expectedVersion) ||
|
|
39
|
+
r.packageVersion !== expectedVersion ||
|
|
40
|
+
typeof r.sourceCommit !== 'string' ||
|
|
41
|
+
!/^[a-f0-9]{40}$/u.test(r.sourceCommit) ||
|
|
42
|
+
r.platform !== 'darwin' ||
|
|
43
|
+
r.architecture !== 'arm64' ||
|
|
44
|
+
r.minimumMacOS !== '26.0' ||
|
|
45
|
+
!Array.isArray(r.artifacts) ||
|
|
46
|
+
r.artifacts.length !== 4)
|
|
24
47
|
fail();
|
|
25
48
|
const roles = new Set();
|
|
26
|
-
const artifacts = r.artifacts.map((value) => {
|
|
27
|
-
|
|
28
|
-
|
|
49
|
+
const artifacts = r.artifacts.map((value) => {
|
|
50
|
+
const a = object(value, ['role', 'name', 'bytes', 'sha256']);
|
|
51
|
+
if (typeof a.role !== 'string' ||
|
|
52
|
+
!Object.hasOwn(nativeAssetNames, a.role) ||
|
|
53
|
+
roles.has(a.role) ||
|
|
54
|
+
a.name !== nativeAssetNames[a.role] ||
|
|
55
|
+
typeof a.bytes !== 'number' ||
|
|
56
|
+
!Number.isSafeInteger(a.bytes) ||
|
|
57
|
+
a.bytes < 1 ||
|
|
58
|
+
a.bytes >
|
|
59
|
+
(a.role === 'embedding-library' ? 160 * 1024 ** 2 : a.role === 'notices' ? 1024 ** 2 : 32 * 1024 ** 2) ||
|
|
60
|
+
!sha(a.sha256))
|
|
61
|
+
fail();
|
|
62
|
+
roles.add(a.role);
|
|
63
|
+
if (a.role === 'embedding-library' && a.sha256 !== embeddingIdentity.librarySha256)
|
|
64
|
+
fail();
|
|
65
|
+
return a;
|
|
66
|
+
});
|
|
29
67
|
const build = object(r.build, ['asrSourceSha256', 'embeddingSourceSha256', 'swiftVersion', 'clangVersion']);
|
|
30
|
-
if (!sha(build.asrSourceSha256) ||
|
|
68
|
+
if (!sha(build.asrSourceSha256) ||
|
|
69
|
+
!sha(build.embeddingSourceSha256) ||
|
|
70
|
+
['swiftVersion', 'clangVersion'].some((k) => typeof build[k] !== 'string' || !build[k] || Buffer.byteLength(String(build[k])) > 2048))
|
|
31
71
|
fail();
|
|
32
72
|
return { ...r, artifacts, build };
|
|
33
73
|
}
|
|
34
|
-
export function nativePlatformSupported(platform = process.platform, architecture = process.arch, kernel = release()) {
|
|
35
|
-
|
|
74
|
+
export function nativePlatformSupported(platform = process.platform, architecture = process.arch, kernel = release()) {
|
|
75
|
+
return (platform === 'darwin' && architecture === 'arm64' && /^\d+\./u.test(kernel) && Number(kernel.split('.')[0]) >= 25);
|
|
76
|
+
}
|
|
77
|
+
export function nativeCatalogPath() {
|
|
78
|
+
return fileURLToPath(new URL(import.meta.url.endsWith('.ts') ? '../../native/runtime-manifest.json' : '../../../native/runtime-manifest.json', import.meta.url));
|
|
79
|
+
}
|
|
36
80
|
export async function loadNativeCatalog(expectedVersion, path = nativeCatalogPath()) {
|
|
37
81
|
let file;
|
|
38
82
|
try {
|
|
@@ -40,8 +84,8 @@ export async function loadNativeCatalog(expectedVersion, path = nativeCatalogPat
|
|
|
40
84
|
}
|
|
41
85
|
catch (error) {
|
|
42
86
|
if (error.code === 'ENOENT')
|
|
43
|
-
throw new
|
|
44
|
-
throw new
|
|
87
|
+
throw new SpongeError('runtime-missing');
|
|
88
|
+
throw new SpongeError('integrity');
|
|
45
89
|
}
|
|
46
90
|
try {
|
|
47
91
|
const stat = await file.stat();
|
|
@@ -65,7 +109,32 @@ export function nativeModelPackage(catalog, kind) {
|
|
|
65
109
|
if (kind !== 'asr' && kind !== 'embedding')
|
|
66
110
|
fail();
|
|
67
111
|
const roles = kind === 'asr' ? ['asr-helper', 'notices'] : ['embedding-helper', 'embedding-library', 'notices'];
|
|
68
|
-
const artifacts = roles.map(
|
|
69
|
-
|
|
70
|
-
|
|
112
|
+
const artifacts = roles.map((role) => {
|
|
113
|
+
const a = catalog.artifacts.find((a) => a.role === role);
|
|
114
|
+
return {
|
|
115
|
+
name: role === 'asr-helper' ? 'sponge-speech' : role === 'embedding-helper' ? 'sponge-embedding' : a.name,
|
|
116
|
+
url: `https://github.com/hraness/sponge/releases/download/v${catalog.packageVersion}/${a.name}`,
|
|
117
|
+
sha256: a.sha256,
|
|
118
|
+
bytes: a.bytes,
|
|
119
|
+
...(role.endsWith('helper') ? { executable: true } : {}),
|
|
120
|
+
};
|
|
121
|
+
});
|
|
122
|
+
artifacts.push(kind === 'asr'
|
|
123
|
+
? {
|
|
124
|
+
name: 'whistle.cact',
|
|
125
|
+
url: 'https://huggingface.co/Cactus-Compute/whistle/resolve/ca5287601bef25af26dcf2e1b2bdc0843a7c19e5/whistle.cact',
|
|
126
|
+
sha256: asrIdentity.modelSha256,
|
|
127
|
+
bytes: asrIdentity.modelBytes,
|
|
128
|
+
}
|
|
129
|
+
: {
|
|
130
|
+
name: 'embeddinggemma-2-text-vision-440m.litertlm',
|
|
131
|
+
url: 'https://huggingface.co/litert-community/embeddinggemma-2-text-vision-440m-litert-lm/resolve/e301f74d5551b0c2641bd5cb4652a76239d5c5f8/embeddinggemma-2-text-vision-440m.litertlm',
|
|
132
|
+
sha256: embeddingIdentity.modelSha256,
|
|
133
|
+
bytes: 387710976,
|
|
134
|
+
});
|
|
135
|
+
return {
|
|
136
|
+
id: `sponge-${kind}-${catalog.packageVersion}-macos26-arm64`,
|
|
137
|
+
license: 'Sponge helpers: proprietary; Needle, Whistle, LiteRT-LM and model: Apache-2.0; see native-NOTICES.txt',
|
|
138
|
+
artifacts,
|
|
139
|
+
};
|
|
71
140
|
}
|
|
@@ -1,14 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SpongeError } from '../errors.js';
|
|
2
2
|
const api = 'https://api.github.com/repos/hraness/sponge';
|
|
3
3
|
const nativeUrl = /^https:\/\/github\.com\/hraness\/sponge\/releases\/download\/(v(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*))\/([A-Za-z0-9_.-]+)$/;
|
|
4
|
-
const cdnHosts = new Set([
|
|
4
|
+
const cdnHosts = new Set([
|
|
5
|
+
'release-assets.githubusercontent.com',
|
|
6
|
+
'objects.githubusercontent.com',
|
|
7
|
+
'github-releases.githubusercontent.com',
|
|
8
|
+
]);
|
|
5
9
|
const redirectCodes = new Set([301, 302, 303, 307, 308]);
|
|
6
10
|
export const nativeDownloadAuthGuidance = 'Set GH_TOKEN or GITHUB_TOKEN with Contents: read access to hraness/sponge, then retry setup. Credentials are never saved.';
|
|
7
|
-
function fail(code) {
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
function fail(code) {
|
|
12
|
+
throw new SpongeError(code);
|
|
13
|
+
}
|
|
14
|
+
async function discard(response) {
|
|
15
|
+
try {
|
|
16
|
+
await response.body?.cancel();
|
|
17
|
+
}
|
|
18
|
+
catch { }
|
|
10
19
|
}
|
|
11
|
-
catch { } }
|
|
12
20
|
async function boundedJson(response) {
|
|
13
21
|
if (!response.body)
|
|
14
22
|
fail('integrity');
|
|
@@ -27,7 +35,7 @@ async function boundedJson(response) {
|
|
|
27
35
|
return value;
|
|
28
36
|
}
|
|
29
37
|
catch (error) {
|
|
30
|
-
if (error instanceof
|
|
38
|
+
if (error instanceof SpongeError)
|
|
31
39
|
throw error;
|
|
32
40
|
fail('integrity');
|
|
33
41
|
}
|
|
@@ -43,7 +51,7 @@ function credential(env) {
|
|
|
43
51
|
* Manual CDN redirects always discard auth; returned bytes still pass package hashes.
|
|
44
52
|
* Public model downloads never read credentials or receive authorization headers. */
|
|
45
53
|
export function nativeArtifactFetch(manifest, options = {}) {
|
|
46
|
-
const transport = options.fetch ?? globalThis.fetch, env = options.env ?? process.env, artifacts = new Map(manifest.artifacts.map(a => [a.url, a]));
|
|
54
|
+
const transport = options.fetch ?? globalThis.fetch, env = options.env ?? process.env, artifacts = new Map(manifest.artifacts.map((a) => [a.url, a]));
|
|
47
55
|
const request = async (url, signal, headers) => {
|
|
48
56
|
if (signal?.aborted)
|
|
49
57
|
fail('cancelled');
|
|
@@ -57,7 +65,11 @@ export function nativeArtifactFetch(manifest, options = {}) {
|
|
|
57
65
|
}
|
|
58
66
|
};
|
|
59
67
|
const download = async (artifact, tag, name, signal) => {
|
|
60
|
-
const token = credential(env), auth = {
|
|
68
|
+
const token = credential(env), auth = {
|
|
69
|
+
Authorization: `Bearer ${token}`,
|
|
70
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
71
|
+
Accept: 'application/vnd.github+json',
|
|
72
|
+
};
|
|
61
73
|
const metadataResponse = await request(`${api}/releases/tags/${tag}`, signal, auth);
|
|
62
74
|
if (!metadataResponse.ok) {
|
|
63
75
|
await discard(metadataResponse);
|
|
@@ -66,13 +78,28 @@ export function nativeArtifactFetch(manifest, options = {}) {
|
|
|
66
78
|
fail('unavailable');
|
|
67
79
|
}
|
|
68
80
|
const release = await boundedJson(metadataResponse);
|
|
69
|
-
if (release.tag_name !== tag ||
|
|
81
|
+
if (release.tag_name !== tag ||
|
|
82
|
+
release.immutable !== true ||
|
|
83
|
+
release.draft !== false ||
|
|
84
|
+
release.prerelease !== false ||
|
|
85
|
+
!Number.isSafeInteger(release.id) ||
|
|
86
|
+
Number(release.id) <= 0 ||
|
|
87
|
+
release.url !== `${api}/releases/${release.id}` ||
|
|
88
|
+
release.html_url !== `https://github.com/hraness/sponge/releases/tag/${tag}` ||
|
|
89
|
+
!Array.isArray(release.assets) ||
|
|
90
|
+
release.assets.length > 1000)
|
|
70
91
|
fail('integrity');
|
|
71
|
-
const matches = release.assets.filter(a => a && typeof a === 'object' && a.name === name);
|
|
92
|
+
const matches = release.assets.filter((a) => a && typeof a === 'object' && a.name === name);
|
|
72
93
|
if (matches.length !== 1)
|
|
73
94
|
fail('integrity');
|
|
74
95
|
const asset = matches[0];
|
|
75
|
-
if (!Number.isSafeInteger(asset.id) ||
|
|
96
|
+
if (!Number.isSafeInteger(asset.id) ||
|
|
97
|
+
asset.id <= 0 ||
|
|
98
|
+
asset.state !== 'uploaded' ||
|
|
99
|
+
asset.size !== artifact.bytes ||
|
|
100
|
+
asset.digest !== `sha256:${artifact.sha256}` ||
|
|
101
|
+
asset.url !== `${api}/releases/assets/${asset.id}` ||
|
|
102
|
+
asset.browser_download_url !== artifact.url)
|
|
76
103
|
fail('integrity');
|
|
77
104
|
let response = await request(asset.url, signal, { ...auth, Accept: 'application/octet-stream' });
|
|
78
105
|
for (let redirects = 0; redirectCodes.has(response.status); redirects++) {
|
|
@@ -87,7 +114,12 @@ export function nativeArtifactFetch(manifest, options = {}) {
|
|
|
87
114
|
catch {
|
|
88
115
|
fail('integrity');
|
|
89
116
|
}
|
|
90
|
-
if (next.protocol !== 'https:' ||
|
|
117
|
+
if (next.protocol !== 'https:' ||
|
|
118
|
+
next.username ||
|
|
119
|
+
next.password ||
|
|
120
|
+
next.port ||
|
|
121
|
+
next.hash ||
|
|
122
|
+
!cdnHosts.has(next.hostname))
|
|
91
123
|
fail('integrity');
|
|
92
124
|
response = await request(next.href, signal); // No credential or GitHub API headers cross this boundary.
|
|
93
125
|
}
|
|
@@ -101,7 +133,7 @@ export function nativeArtifactFetch(manifest, options = {}) {
|
|
|
101
133
|
};
|
|
102
134
|
return (async (input, init) => {
|
|
103
135
|
const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url, artifact = artifacts.get(url), signal = init?.signal ?? undefined;
|
|
104
|
-
if (!artifact || init?.headers || init?.body || init?.method && init.method !== 'GET')
|
|
136
|
+
if (!artifact || init?.headers || init?.body || (init?.method && init.method !== 'GET'))
|
|
105
137
|
fail('integrity');
|
|
106
138
|
if (signal?.aborted)
|
|
107
139
|
fail('cancelled');
|
|
@@ -133,7 +165,15 @@ export function nativeArtifactFetch(manifest, options = {}) {
|
|
|
133
165
|
catch {
|
|
134
166
|
fail('integrity');
|
|
135
167
|
}
|
|
136
|
-
if (next.protocol !== 'https:' ||
|
|
168
|
+
if (next.protocol !== 'https:' ||
|
|
169
|
+
next.username ||
|
|
170
|
+
next.password ||
|
|
171
|
+
next.port ||
|
|
172
|
+
next.hash ||
|
|
173
|
+
!(next.hostname === 'huggingface.co' ||
|
|
174
|
+
next.hostname.endsWith('.huggingface.co') ||
|
|
175
|
+
next.hostname === 'hf.co' ||
|
|
176
|
+
next.hostname.endsWith('.hf.co')))
|
|
137
177
|
fail('integrity');
|
|
138
178
|
currentUrl = next.href;
|
|
139
179
|
response = await request(currentUrl, signal);
|
|
@@ -14,8 +14,6 @@ export declare function nativeSetupPlan(kind: NativeKind, version: string): Prom
|
|
|
14
14
|
export declare function setupNativeRuntime(cacheRoot: string, catalog: NativeCatalog, kind: NativeKind, options?: {
|
|
15
15
|
signal?: AbortSignal;
|
|
16
16
|
}): Promise<AsrRuntime | EmbeddingRuntime>;
|
|
17
|
-
export declare function inspectAsrRuntime(cacheRoot: string, catalog: NativeCatalog): Promise<AsrRuntime>;
|
|
18
|
-
export declare function inspectEmbeddingRuntime(cacheRoot: string, catalog: NativeCatalog): Promise<EmbeddingRuntime>;
|
|
19
17
|
export declare function provisionNative(kind: 'asr', cacheRoot: string, version: string, signal?: AbortSignal): Promise<AsrRuntime>;
|
|
20
18
|
export declare function provisionNative(kind: 'embedding', cacheRoot: string, version: string, signal?: AbortSignal): Promise<EmbeddingRuntime>;
|
|
21
19
|
export declare function provisionNative(kind: NativeKind, cacheRoot: string, version: string, signal?: AbortSignal): Promise<AsrRuntime | EmbeddingRuntime>;
|
|
@@ -2,36 +2,72 @@ import { mkdir } from 'node:fs/promises';
|
|
|
2
2
|
import { dirname } from 'node:path';
|
|
3
3
|
import { privateRoot } from '../acquisition/files.js';
|
|
4
4
|
import { nativeArtifactFetch } from './download.js';
|
|
5
|
-
import {
|
|
6
|
-
import { nativePlatformSupported, nativeModelPackage,
|
|
7
|
-
|
|
8
|
-
function
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
if (
|
|
18
|
-
throw
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
5
|
+
import { inspectInstalledModelPackage, provisionModelPackage, recoverModelPackage, modelSetupPlan, } from './artifacts.js';
|
|
6
|
+
import { nativePlatformSupported, nativeModelPackage, loadNativeCatalog, } from './catalog.js';
|
|
7
|
+
import { SpongeError } from '../errors.js';
|
|
8
|
+
export async function nativeSetupPlan(kind, version) {
|
|
9
|
+
const catalog = await loadNativeCatalog(version);
|
|
10
|
+
return {
|
|
11
|
+
...modelSetupPlan(nativeModelPackage(catalog, kind)),
|
|
12
|
+
supported: nativePlatformSupported(),
|
|
13
|
+
minimumMacOS: '26.0',
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function supported() {
|
|
17
|
+
if (!nativePlatformSupported())
|
|
18
|
+
throw new SpongeError('unsupported');
|
|
19
|
+
}
|
|
20
|
+
function asr(c, p) {
|
|
21
|
+
return {
|
|
22
|
+
helper: p['sponge-speech'],
|
|
23
|
+
helperSha256: c.artifacts.find((a) => a.role === 'asr-helper').sha256,
|
|
24
|
+
model: p['whistle.cact'],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function embedding(c, p) {
|
|
28
|
+
return {
|
|
29
|
+
helper: p['sponge-embedding'],
|
|
30
|
+
helperSha256: c.artifacts.find((a) => a.role === 'embedding-helper').sha256,
|
|
31
|
+
library: p['libCLiteRTLM_mac.dylib'],
|
|
32
|
+
model: p['embeddinggemma-2-text-vision-440m.litertlm'],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export async function setupNativeRuntime(cacheRoot, catalog, kind, options = {}) {
|
|
36
|
+
supported();
|
|
37
|
+
if (options.signal?.aborted)
|
|
38
|
+
throw new SpongeError('cancelled');
|
|
39
|
+
const manifest = nativeModelPackage(catalog, kind);
|
|
40
|
+
await privateRoot(dirname(cacheRoot));
|
|
41
|
+
try {
|
|
42
|
+
await mkdir(cacheRoot, { mode: 0o700 });
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error.code !== 'EEXIST')
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
await privateRoot(cacheRoot);
|
|
49
|
+
await recoverModelPackage(cacheRoot, manifest);
|
|
50
|
+
const paths = await provisionModelPackage(cacheRoot, manifest, { ...options, fetch: nativeArtifactFetch(manifest) });
|
|
51
|
+
return kind === 'asr' ? asr(catalog, paths) : embedding(catalog, paths);
|
|
52
|
+
}
|
|
53
|
+
async function installed(cacheRoot, catalog, kind) {
|
|
54
|
+
const paths = await inspectInstalledModelPackage(cacheRoot, nativeModelPackage(catalog, kind));
|
|
55
|
+
if (!paths)
|
|
56
|
+
throw new SpongeError('runtime-missing');
|
|
57
|
+
return paths;
|
|
58
|
+
}
|
|
59
|
+
async function inspectAsrRuntime(cacheRoot, catalog) {
|
|
60
|
+
supported();
|
|
61
|
+
return asr(catalog, await installed(cacheRoot, catalog, 'asr'));
|
|
62
|
+
}
|
|
63
|
+
async function inspectEmbeddingRuntime(cacheRoot, catalog) {
|
|
64
|
+
supported();
|
|
65
|
+
return embedding(catalog, await installed(cacheRoot, catalog, 'embedding'));
|
|
66
|
+
}
|
|
67
|
+
export async function provisionNative(kind, cacheRoot, version, signal) {
|
|
68
|
+
return setupNativeRuntime(cacheRoot, await loadNativeCatalog(version), kind, { signal });
|
|
69
|
+
}
|
|
70
|
+
export async function inspectNative(kind, cacheRoot, version) {
|
|
71
|
+
const catalog = await loadNativeCatalog(version);
|
|
72
|
+
return kind === 'asr' ? inspectAsrRuntime(cacheRoot, catalog) : inspectEmbeddingRuntime(cacheRoot, catalog);
|
|
73
|
+
}
|
|
@@ -3,7 +3,9 @@ const runtime = process.argv[2], args = process.argv.slice(3);
|
|
|
3
3
|
try {
|
|
4
4
|
const { runPdfAcquisition } = await import(import.meta.resolve('@hraness/ghostget/pdf-acquisition', `${runtime}/package.json`));
|
|
5
5
|
const { runPdfToolCommand } = await import(import.meta.resolve('@hraness/wordcell/pdf', `${runtime}/package.json`));
|
|
6
|
-
process.exitCode = await runPdfAcquisition(args, process.env, { stdout: (value) => process.stdout.write(value), stderr: (value) => process.stderr.write(value) }, {
|
|
6
|
+
process.exitCode = await runPdfAcquisition(args, process.env, { stdout: (value) => process.stdout.write(value), stderr: (value) => process.stderr.write(value) }, {
|
|
7
|
+
runTool: (specification) => runPdfToolCommand({ ...specification, processGroup: 'inherit' }),
|
|
8
|
+
});
|
|
7
9
|
}
|
|
8
10
|
catch {
|
|
9
11
|
process.stdout.write(JSON.stringify({ ok: false, code: 'unknown' }));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CaptureResult, ErrorEnvelope } from '../../contracts/index.js';
|
|
2
2
|
import { runOwned } from '../acquisition/process.js';
|
|
3
3
|
import { type CaptureRuntime } from '../acquisition/runtime.js';
|
|
4
|
-
|
|
4
|
+
type CaptureConnection = {
|
|
5
5
|
kind: 'account';
|
|
6
6
|
stateHome: string;
|
|
7
7
|
accountId: string;
|
|
@@ -27,3 +27,4 @@ export type CaptureOutcome = {
|
|
|
27
27
|
dispose: () => Promise<void>;
|
|
28
28
|
} | ErrorEnvelope;
|
|
29
29
|
export declare function capturePdf(request: PdfCaptureRequest): Promise<CaptureOutcome>;
|
|
30
|
+
export {};
|
package/dist/src/pdf/capture.js
CHANGED
|
@@ -4,13 +4,14 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
import { limits } from '../../contracts/index.js';
|
|
5
5
|
import { privateRoot, physicalBytes } from '../acquisition/files.js';
|
|
6
6
|
import { runOwned, isolatedEnvironment } from '../acquisition/process.js';
|
|
7
|
-
import { inspectCaptureRuntime
|
|
8
|
-
import { settleCaptureRoot
|
|
7
|
+
import { inspectCaptureRuntime } from '../acquisition/runtime.js';
|
|
8
|
+
import { settleCaptureRoot } from '../acquisition/cleanup.js';
|
|
9
9
|
import { failure } from '../acquisition/errors.js';
|
|
10
10
|
import { object } from '../acquisition/normalize.js';
|
|
11
11
|
import { normalizePdfBundle } from './normalize.js';
|
|
12
12
|
import { copyPdfInput } from './input.js';
|
|
13
13
|
import { pdfFailure } from './errors.js';
|
|
14
|
+
import { SpongeError, publicCode, codeOf } from '../errors.js';
|
|
14
15
|
export async function capturePdf(request) {
|
|
15
16
|
const { requestId, signal } = request;
|
|
16
17
|
if (!/^[a-zA-Z0-9_-]{1,128}$/.test(requestId))
|
|
@@ -18,7 +19,10 @@ export async function capturePdf(request) {
|
|
|
18
19
|
let url;
|
|
19
20
|
try {
|
|
20
21
|
url = new URL(request.sourceUrl);
|
|
21
|
-
if (!['http:', 'https:', 'file:'].includes(url.protocol) ||
|
|
22
|
+
if (!['http:', 'https:', 'file:'].includes(url.protocol) ||
|
|
23
|
+
url.username ||
|
|
24
|
+
url.password ||
|
|
25
|
+
request.sourceUrl.length > 16384)
|
|
22
26
|
throw Error();
|
|
23
27
|
}
|
|
24
28
|
catch {
|
|
@@ -31,7 +35,7 @@ export async function capturePdf(request) {
|
|
|
31
35
|
runtime = await inspectCaptureRuntime(request.runtime.root, request.runtime.pins);
|
|
32
36
|
}
|
|
33
37
|
catch (error) {
|
|
34
|
-
return failure(requestId, error
|
|
38
|
+
return failure(requestId, publicCode(error, 'runtime-missing'), 'setup');
|
|
35
39
|
}
|
|
36
40
|
let base;
|
|
37
41
|
try {
|
|
@@ -51,7 +55,27 @@ export async function capturePdf(request) {
|
|
|
51
55
|
if (request.connection?.kind === 'cdp' || request.allowPrivateNetwork)
|
|
52
56
|
return failure(requestId, 'unsupported');
|
|
53
57
|
const captureHelper = fileURLToPath(new URL(import.meta.url.endsWith('.ts') ? './capture-helper.ts' : './capture-helper.js', import.meta.url));
|
|
54
|
-
const args = [
|
|
58
|
+
const args = [
|
|
59
|
+
captureHelper,
|
|
60
|
+
runtime.root,
|
|
61
|
+
request.sourceUrl,
|
|
62
|
+
'--slug',
|
|
63
|
+
'document',
|
|
64
|
+
'--timeout-ms',
|
|
65
|
+
String(deadline),
|
|
66
|
+
'--max-pdf-bytes',
|
|
67
|
+
String(limits.pdfBytes),
|
|
68
|
+
'--max-pages',
|
|
69
|
+
'500',
|
|
70
|
+
'--max-images',
|
|
71
|
+
String(limits.imagesPerItem),
|
|
72
|
+
'--max-asset-bytes',
|
|
73
|
+
String(limits.imageBytes),
|
|
74
|
+
'--max-total-asset-bytes',
|
|
75
|
+
String(500 * 1024 ** 2),
|
|
76
|
+
'--quiet',
|
|
77
|
+
'--json',
|
|
78
|
+
];
|
|
55
79
|
let selectedState;
|
|
56
80
|
if (request.connection?.kind === 'account') {
|
|
57
81
|
if (!/^[a-zA-Z0-9_.-]{1,128}$/.test(request.connection.accountId))
|
|
@@ -73,32 +97,45 @@ export async function capturePdf(request) {
|
|
|
73
97
|
if (signal?.aborted)
|
|
74
98
|
abort();
|
|
75
99
|
let cleanup = 'settled', keep = false, quota = false, checking = false;
|
|
76
|
-
const monitor = setInterval(async () => {
|
|
77
|
-
|
|
78
|
-
|
|
100
|
+
const monitor = setInterval(async () => {
|
|
101
|
+
if (checking)
|
|
102
|
+
return;
|
|
103
|
+
checking = true;
|
|
104
|
+
try {
|
|
105
|
+
if ((await physicalBytes(root)) > limits.stagingBytes) {
|
|
106
|
+
quota = true;
|
|
107
|
+
controller.abort();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
79
111
|
quota = true;
|
|
80
112
|
controller.abort();
|
|
81
113
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
finally {
|
|
88
|
-
checking = false;
|
|
89
|
-
} }, 100);
|
|
114
|
+
finally {
|
|
115
|
+
checking = false;
|
|
116
|
+
}
|
|
117
|
+
}, 100);
|
|
90
118
|
const started = Date.now();
|
|
91
119
|
try {
|
|
92
120
|
await mkdir(home, { mode: 0o700 });
|
|
93
121
|
await mkdir(output, { mode: 0o700 });
|
|
94
|
-
await writeFile(join(root, 'ownership.json'), JSON.stringify({ schemaVersion: 1, requestId, state: 'acquiring' }), {
|
|
122
|
+
await writeFile(join(root, 'ownership.json'), JSON.stringify({ schemaVersion: 1, requestId, state: 'acquiring' }), {
|
|
123
|
+
mode: 0o600,
|
|
124
|
+
});
|
|
95
125
|
let sourceHash;
|
|
96
126
|
if (url.protocol === 'file:') {
|
|
97
127
|
sourceHash = await copyPdfInput(fileURLToPath(url), join(root, 'input.pdf'), controller.signal);
|
|
98
128
|
args[2] = join(root, 'input.pdf');
|
|
99
129
|
}
|
|
100
130
|
cleanup = 'pending';
|
|
101
|
-
const result = await (request.runProcess ?? runOwned)(runtime.bun, args, {
|
|
131
|
+
const result = await (request.runProcess ?? runOwned)(runtime.bun, args, {
|
|
132
|
+
cwd: root,
|
|
133
|
+
env,
|
|
134
|
+
signal: controller.signal,
|
|
135
|
+
deadlineMs: Math.max(1, deadline - (Date.now() - started)),
|
|
136
|
+
maxOutputBytes: limits.metadataBytes,
|
|
137
|
+
graceMs: 5000,
|
|
138
|
+
});
|
|
102
139
|
cleanup = result.cleanup;
|
|
103
140
|
let summary;
|
|
104
141
|
try {
|
|
@@ -119,11 +156,19 @@ export async function capturePdf(request) {
|
|
|
119
156
|
if (result.code !== 0 || object(summary).ok !== true)
|
|
120
157
|
return upstream;
|
|
121
158
|
const outputDirectory = object(summary).outputDirectory;
|
|
122
|
-
if (typeof outputDirectory !== 'string' ||
|
|
159
|
+
if (typeof outputDirectory !== 'string' ||
|
|
160
|
+
!outputDirectory.startsWith(output + '/') ||
|
|
161
|
+
(await realpath(outputDirectory)) !== outputDirectory)
|
|
123
162
|
return failure(requestId, 'integrity', 'verification');
|
|
124
163
|
const helper = fileURLToPath(new URL(import.meta.url.endsWith('.ts') ? './verify-helper.ts' : './verify-helper.js', import.meta.url));
|
|
125
164
|
cleanup = 'pending';
|
|
126
|
-
const checked = await (request.runProcess ?? runOwned)(runtime.bun, [helper, runtime.root, outputDirectory, request.sourceUrl], {
|
|
165
|
+
const checked = await (request.runProcess ?? runOwned)(runtime.bun, [helper, runtime.root, outputDirectory, request.sourceUrl], {
|
|
166
|
+
cwd: root,
|
|
167
|
+
env,
|
|
168
|
+
signal: controller.signal,
|
|
169
|
+
deadlineMs: Math.max(1, deadline - (Date.now() - started)),
|
|
170
|
+
maxOutputBytes: limits.helperFrameBytes,
|
|
171
|
+
});
|
|
127
172
|
cleanup = checked.cleanup;
|
|
128
173
|
if (cleanup !== 'settled')
|
|
129
174
|
return failure(requestId, 'cleanup-required', 'cleanup');
|
|
@@ -131,26 +176,49 @@ export async function capturePdf(request) {
|
|
|
131
176
|
return failure(requestId, checked.stopped);
|
|
132
177
|
if (checked.code !== 0)
|
|
133
178
|
return failure(requestId, 'integrity', 'verification');
|
|
134
|
-
const capture = await normalizePdfBundle({
|
|
179
|
+
const capture = await normalizePdfBundle({
|
|
180
|
+
bundleRoot: outputDirectory,
|
|
181
|
+
inspection: JSON.parse(checked.stdout),
|
|
182
|
+
summary,
|
|
183
|
+
requestId,
|
|
184
|
+
sourceUrl: request.sourceUrl,
|
|
185
|
+
wordcellVersion: runtime.pins.wordcell.version,
|
|
186
|
+
...(sourceHash ? { sourceHash } : {}),
|
|
187
|
+
});
|
|
135
188
|
if (controller.signal.aborted)
|
|
136
189
|
return failure(requestId, quota ? 'limit-exceeded' : 'cancelled');
|
|
137
|
-
await writeFile(join(root, 'ownership.json'), JSON.stringify({ schemaVersion: 1, requestId, state: 'verified' }), {
|
|
190
|
+
await writeFile(join(root, 'ownership.json'), JSON.stringify({ schemaVersion: 1, requestId, state: 'verified' }), {
|
|
191
|
+
mode: 0o600,
|
|
192
|
+
});
|
|
138
193
|
keep = true;
|
|
139
|
-
return {
|
|
140
|
-
|
|
194
|
+
return {
|
|
195
|
+
ok: true,
|
|
196
|
+
capture,
|
|
197
|
+
bundleRoot: outputDirectory,
|
|
198
|
+
dispose: async () => {
|
|
199
|
+
if ((await settleCaptureRoot(root, requestId)) === 'pending')
|
|
200
|
+
throw new SpongeError('cleanup-required');
|
|
201
|
+
},
|
|
202
|
+
};
|
|
141
203
|
}
|
|
142
204
|
catch (error) {
|
|
143
205
|
if (cleanup !== 'settled')
|
|
144
206
|
return failure(requestId, 'cleanup-required', 'cleanup');
|
|
145
|
-
const
|
|
207
|
+
const raw = codeOf(error), code = raw === 'integrity' ||
|
|
208
|
+
raw === 'limit-exceeded' ||
|
|
209
|
+
raw === 'schema-newer' ||
|
|
210
|
+
raw === 'invalid-input' ||
|
|
211
|
+
raw === 'cancelled'
|
|
212
|
+
? raw
|
|
213
|
+
: 'unclassified';
|
|
146
214
|
return failure(requestId, code, 'verification');
|
|
147
215
|
}
|
|
148
216
|
finally {
|
|
149
217
|
clearInterval(monitor);
|
|
150
218
|
while (checking)
|
|
151
|
-
await new Promise(r => setTimeout(r, 5));
|
|
219
|
+
await new Promise((r) => setTimeout(r, 5));
|
|
152
220
|
signal?.removeEventListener('abort', abort);
|
|
153
|
-
if (!keep && cleanup === 'settled' && await settleCaptureRoot(root, requestId) === 'pending')
|
|
221
|
+
if (!keep && cleanup === 'settled' && (await settleCaptureRoot(root, requestId)) === 'pending')
|
|
154
222
|
return failure(requestId, 'cleanup-required', 'cleanup');
|
|
155
223
|
}
|
|
156
224
|
}
|