@semiont/jobs 0.6.8 → 0.6.9
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/dist/index.d.ts +29 -23
- package/dist/index.js +24 -54
- package/dist/index.js.map +1 -1
- package/dist/worker-main.js +67 -108
- package/dist/worker-main.js.map +1 -1
- package/package.json +8 -8
package/dist/worker-main.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { replyChannelsFor, createTomlConfigLoader, JOB_TYPES, didToAgent, baseUrl, STARTUP_FETCH_RETRY, retryWithBackoff, serviceAccountToken, isTransientFetchError, isObject, isString, isNumber, RETRY_RULES, getPrimaryMediaType, isGenerationJobParams, capabilitiesOf, assembleAnnotation, findClaimSpan, busRequest, BusRequestError, textSourceOf, yieldsGeometryOf, decodeRepresentation, GENERATABLE_MEDIA_TYPES, locate, createFragmentSelector, deriveViews, isResourceId, estimateTokens, reconcileSelector, getLocaleEnglishName, cutChunk, chunkText } from '@semiont/core';
|
|
2
2
|
import { archivistContentReads, extractPdfTextLayer, withinByteBudget, MAX_PDF_BYTES } from '@semiont/content';
|
|
3
3
|
import { withSpan, SpanKind, recordJobOutcome, recordAnchorOutcome, recordDetectionCall } from '@semiont/observability';
|
|
4
4
|
import { createInferenceClient, answerLimitsRequests, StructuredReadError } from '@semiont/inference';
|
|
@@ -3766,9 +3766,9 @@ var require_mapOneOrManyArgs = __commonJS({
|
|
|
3766
3766
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3767
3767
|
exports.mapOneOrManyArgs = void 0;
|
|
3768
3768
|
var map_1 = require_map();
|
|
3769
|
-
var
|
|
3769
|
+
var isArray = Array.isArray;
|
|
3770
3770
|
function callOrApply(fn, args) {
|
|
3771
|
-
return
|
|
3771
|
+
return isArray(args) ? fn.apply(void 0, __spreadArray([], __read(args))) : fn(args);
|
|
3772
3772
|
}
|
|
3773
3773
|
function mapOneOrManyArgs(fn) {
|
|
3774
3774
|
return map_1.map(function(args) {
|
|
@@ -3913,14 +3913,14 @@ var require_argsArgArrayOrObject = __commonJS({
|
|
|
3913
3913
|
"../../node_modules/rxjs/dist/cjs/internal/util/argsArgArrayOrObject.js"(exports) {
|
|
3914
3914
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3915
3915
|
exports.argsArgArrayOrObject = void 0;
|
|
3916
|
-
var
|
|
3916
|
+
var isArray = Array.isArray;
|
|
3917
3917
|
var getPrototypeOf = Object.getPrototypeOf;
|
|
3918
3918
|
var objectProto = Object.prototype;
|
|
3919
3919
|
var getKeys = Object.keys;
|
|
3920
3920
|
function argsArgArrayOrObject(args) {
|
|
3921
3921
|
if (args.length === 1) {
|
|
3922
3922
|
var first_1 = args[0];
|
|
3923
|
-
if (
|
|
3923
|
+
if (isArray(first_1)) {
|
|
3924
3924
|
return { args: first_1, keys: null };
|
|
3925
3925
|
}
|
|
3926
3926
|
if (isPOJO(first_1)) {
|
|
@@ -4668,9 +4668,9 @@ var require_argsOrArgArray = __commonJS({
|
|
|
4668
4668
|
"../../node_modules/rxjs/dist/cjs/internal/util/argsOrArgArray.js"(exports) {
|
|
4669
4669
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4670
4670
|
exports.argsOrArgArray = void 0;
|
|
4671
|
-
var
|
|
4671
|
+
var isArray = Array.isArray;
|
|
4672
4672
|
function argsOrArgArray(args) {
|
|
4673
|
-
return args.length === 1 &&
|
|
4673
|
+
return args.length === 1 && isArray(args[0]) ? args[0] : args;
|
|
4674
4674
|
}
|
|
4675
4675
|
exports.argsOrArgArray = argsOrArgArray;
|
|
4676
4676
|
}
|
|
@@ -9208,19 +9208,6 @@ var require_cjs = __commonJS({
|
|
|
9208
9208
|
|
|
9209
9209
|
// src/job-claim-adapter.ts
|
|
9210
9210
|
var import_rxjs = __toESM(require_cjs());
|
|
9211
|
-
function readUnitCursors(raw, completedUnits) {
|
|
9212
|
-
if (!isObject(raw)) return {};
|
|
9213
|
-
const done = new Set(completedUnits);
|
|
9214
|
-
const cursors = {};
|
|
9215
|
-
for (const [unit, value] of Object.entries(raw)) {
|
|
9216
|
-
if (done.has(unit) || !isObject(value)) continue;
|
|
9217
|
-
const { next, size, found, emitted } = value;
|
|
9218
|
-
if (!isNumber(next) || !isNumber(size) || next < 0 || size < 1) continue;
|
|
9219
|
-
if (!isNumber(found) || !isNumber(emitted) || found < 0 || emitted < 0) continue;
|
|
9220
|
-
cursors[unit] = { next, size, found, emitted };
|
|
9221
|
-
}
|
|
9222
|
-
return cursors;
|
|
9223
|
-
}
|
|
9224
9211
|
function createJobClaimAdapter(options) {
|
|
9225
9212
|
const { bus, jobTypes } = options;
|
|
9226
9213
|
const activeJob$ = new import_rxjs.BehaviorSubject(null);
|
|
@@ -9239,9 +9226,9 @@ function createJobClaimAdapter(options) {
|
|
|
9239
9226
|
let activeSince = null;
|
|
9240
9227
|
const iso = (t) => t === null ? null : new Date(t).toISOString();
|
|
9241
9228
|
const claimNext = async () => {
|
|
9242
|
-
let
|
|
9229
|
+
let claimed;
|
|
9243
9230
|
try {
|
|
9244
|
-
|
|
9231
|
+
claimed = await busRequest(bus, "job:claim", { types: jobTypes }, 1e4);
|
|
9245
9232
|
} catch (error) {
|
|
9246
9233
|
if (error instanceof BusRequestError) {
|
|
9247
9234
|
if (error.code === "bus.none-pending") return { declined: true };
|
|
@@ -9249,25 +9236,19 @@ function createJobClaimAdapter(options) {
|
|
|
9249
9236
|
}
|
|
9250
9237
|
return { refused: { code: null, message: error instanceof Error ? error.message : String(error) } };
|
|
9251
9238
|
}
|
|
9252
|
-
|
|
9253
|
-
return { refused: { code: null, message: "claimed record carries no job id or type" } };
|
|
9254
|
-
}
|
|
9255
|
-
const completedUnits = isArray(record.metadata?.completedUnits) ? record.metadata.completedUnits.filter(isString) : [];
|
|
9256
|
-
const unitCursors = readUnitCursors(record.metadata?.unitCursors, completedUnits);
|
|
9257
|
-
const params = record.params ?? {};
|
|
9239
|
+
const { metadata, params } = claimed;
|
|
9258
9240
|
return {
|
|
9259
9241
|
job: {
|
|
9260
|
-
jobId:
|
|
9261
|
-
type:
|
|
9262
|
-
resourceId:
|
|
9263
|
-
userId: record.metadata?.userId ?? "",
|
|
9242
|
+
jobId: metadata.id,
|
|
9243
|
+
type: metadata.type,
|
|
9244
|
+
resourceId: params.resourceId,
|
|
9264
9245
|
params,
|
|
9265
|
-
|
|
9266
|
-
|
|
9267
|
-
|
|
9268
|
-
|
|
9269
|
-
retryCount:
|
|
9270
|
-
maxRetries:
|
|
9246
|
+
// Both appear on the record once an attempt has checkpointed, and a
|
|
9247
|
+
// finished unit has no cursor: the dispatcher drops it at the merge.
|
|
9248
|
+
completedUnits: metadata.completedUnits ?? [],
|
|
9249
|
+
unitCursors: metadata.unitCursors ?? {},
|
|
9250
|
+
retryCount: metadata.retryCount,
|
|
9251
|
+
maxRetries: metadata.maxRetries
|
|
9271
9252
|
}
|
|
9272
9253
|
};
|
|
9273
9254
|
};
|
|
@@ -9384,10 +9365,8 @@ function createJobClaimAdapter(options) {
|
|
|
9384
9365
|
function willRetryAfter(metadata, failureClass) {
|
|
9385
9366
|
return failureClass !== "deterministic" && metadata.retryCount < metadata.maxRetries;
|
|
9386
9367
|
}
|
|
9387
|
-
|
|
9388
|
-
|
|
9389
|
-
return KNOWN_JOB_TYPES.has(value);
|
|
9390
|
-
}
|
|
9368
|
+
|
|
9369
|
+
// src/types.ts
|
|
9391
9370
|
function asJobParams(params) {
|
|
9392
9371
|
if (typeof params.resourceId !== "string") {
|
|
9393
9372
|
throw new Error("Job params are missing a resourceId");
|
|
@@ -10752,8 +10731,6 @@ function compileTypst(source) {
|
|
|
10752
10731
|
rmSync(dir, { recursive: true, force: true });
|
|
10753
10732
|
}
|
|
10754
10733
|
}
|
|
10755
|
-
|
|
10756
|
-
// src/workers/generation/citation-resolver.ts
|
|
10757
10734
|
var CITATION_TOKEN = /\[\[([^\s[\]/]+)(?:\/([^\s[\]/]+))?\]\]/g;
|
|
10758
10735
|
function collectContextResourceIds(context) {
|
|
10759
10736
|
const ids = /* @__PURE__ */ new Set();
|
|
@@ -10779,7 +10756,7 @@ function resolveCitationTokens(content, validResourceIds, logger2) {
|
|
|
10779
10756
|
const annotationId = match[2];
|
|
10780
10757
|
clean += content.slice(last, match.index).replace(/[ \t]+$/, "");
|
|
10781
10758
|
last = match.index + token.length;
|
|
10782
|
-
if (!validResourceIds.has(citedResourceId)) {
|
|
10759
|
+
if (!isResourceId(citedResourceId) || !validResourceIds.has(citedResourceId)) {
|
|
10783
10760
|
logger2.warn("Citation token references an id absent from the provided context \u2014 dropped", {
|
|
10784
10761
|
resourceId: citedResourceId
|
|
10785
10762
|
});
|
|
@@ -11373,12 +11350,7 @@ async function processGenerationJob(inferenceClient, params, onProgress, logger2
|
|
|
11373
11350
|
title,
|
|
11374
11351
|
format: outputMediaType,
|
|
11375
11352
|
citations: citations2,
|
|
11376
|
-
|
|
11377
|
-
kind: "generation",
|
|
11378
|
-
resourceId: "",
|
|
11379
|
-
resourceName: title,
|
|
11380
|
-
truncated: generated2.truncated
|
|
11381
|
-
}
|
|
11353
|
+
truncated: generated2.truncated
|
|
11382
11354
|
};
|
|
11383
11355
|
}
|
|
11384
11356
|
onProgress(5, { code: "generating-resource" });
|
|
@@ -11414,12 +11386,7 @@ async function processGenerationJob(inferenceClient, params, onProgress, logger2
|
|
|
11414
11386
|
title,
|
|
11415
11387
|
format: outputMediaType,
|
|
11416
11388
|
citations,
|
|
11417
|
-
|
|
11418
|
-
kind: "generation",
|
|
11419
|
-
resourceId: "",
|
|
11420
|
-
resourceName: title,
|
|
11421
|
-
truncated: generated.truncated
|
|
11422
|
-
}
|
|
11389
|
+
truncated: generated.truncated
|
|
11423
11390
|
};
|
|
11424
11391
|
}
|
|
11425
11392
|
|
|
@@ -11503,11 +11470,11 @@ var CommitDurabilityError = class extends Error {
|
|
|
11503
11470
|
durability;
|
|
11504
11471
|
name = "CommitDurabilityError";
|
|
11505
11472
|
};
|
|
11506
|
-
async function probeDurability(session, resourceId
|
|
11473
|
+
async function probeDurability(session, resourceId, annotations) {
|
|
11507
11474
|
const last = annotations[annotations.length - 1];
|
|
11508
11475
|
if (!last) return "probe-unreachable";
|
|
11509
11476
|
try {
|
|
11510
|
-
await session.client.browse.annotation(resourceId
|
|
11477
|
+
await session.client.browse.annotation(resourceId, last.id).fresh();
|
|
11511
11478
|
return "probe-confirmed";
|
|
11512
11479
|
} catch (error) {
|
|
11513
11480
|
const code = isObject(error) && isString(error.code) ? error.code : void 0;
|
|
@@ -11564,32 +11531,30 @@ function startWorkerProcess(config) {
|
|
|
11564
11531
|
completedUnitsByJob.delete(job.jobId);
|
|
11565
11532
|
unitCursorsByJob.delete(job.jobId);
|
|
11566
11533
|
const failAnnotationId = referenceIdOf(job);
|
|
11567
|
-
|
|
11568
|
-
|
|
11569
|
-
|
|
11570
|
-
|
|
11571
|
-
|
|
11572
|
-
|
|
11573
|
-
|
|
11574
|
-
|
|
11575
|
-
|
|
11576
|
-
|
|
11577
|
-
|
|
11578
|
-
|
|
11579
|
-
|
|
11580
|
-
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
11586
|
-
|
|
11587
|
-
|
|
11588
|
-
|
|
11589
|
-
|
|
11590
|
-
|
|
11591
|
-
});
|
|
11592
|
-
}
|
|
11534
|
+
emitEvent(session, "job:fail", {
|
|
11535
|
+
resourceId: job.resourceId,
|
|
11536
|
+
jobId: job.jobId,
|
|
11537
|
+
jobType: job.type,
|
|
11538
|
+
...failAnnotationId ? { annotationId: failAnnotationId } : {},
|
|
11539
|
+
error: message,
|
|
11540
|
+
...completedUnits && completedUnits.length > 0 ? { completedUnits } : {},
|
|
11541
|
+
// Where each unfinished unit got to. Absent rather than `{}` when
|
|
11542
|
+
// nothing was reached: an empty object would claim units were
|
|
11543
|
+
// tracked and none progressed.
|
|
11544
|
+
...unitCursors && Object.keys(unitCursors).length > 0 ? { unitCursors } : {},
|
|
11545
|
+
...failureClass !== void 0 ? { failureClass } : {},
|
|
11546
|
+
// What the commit path OBSERVED about durability, when the failure
|
|
11547
|
+
// came from a commit at all. Present only on that path: absent means
|
|
11548
|
+
// the question never arose, never that durability was ruled out.
|
|
11549
|
+
...error instanceof CommitDurabilityError ? { durability: error.durability } : {},
|
|
11550
|
+
// Whether this failure is the END, answered by the same predicate
|
|
11551
|
+
// the queue applies at failJob (JOB-RESTART-SAFETY P5). Without
|
|
11552
|
+
// it a client cannot tell a recovering run from a dead one: it
|
|
11553
|
+
// sees job:fail either way and would end its stream on a job the
|
|
11554
|
+
// queue is about to re-run.
|
|
11555
|
+
willRetry: willRetryAfter(job, failureClass)
|
|
11556
|
+
}).catch(() => {
|
|
11557
|
+
});
|
|
11593
11558
|
adapter.failJob(job.jobId, message);
|
|
11594
11559
|
}).finally(() => {
|
|
11595
11560
|
if (activeCancel?.jobId === job.jobId) activeCancel = null;
|
|
@@ -11623,17 +11588,11 @@ async function handleJob(adapter, config, job, completedUnitsByJob = /* @__PURE_
|
|
|
11623
11588
|
}
|
|
11624
11589
|
async function handleJobInner(adapter, config, job, completedUnitsByJob, signal, unitCursorsByJob = /* @__PURE__ */ new Map()) {
|
|
11625
11590
|
const { session, inferenceClient, generator } = config;
|
|
11626
|
-
const { jobId } = job;
|
|
11627
|
-
if (!isJobType(job.type)) {
|
|
11628
|
-
adapter.failJob(jobId, `Unrecognized job type: ${job.type}`);
|
|
11629
|
-
return;
|
|
11630
|
-
}
|
|
11631
|
-
const jobType = job.type;
|
|
11632
|
-
const resourceId$1 = resourceId(job.resourceId);
|
|
11591
|
+
const { jobId, type: jobType, resourceId } = job;
|
|
11633
11592
|
const annotationId = referenceIdOf(job);
|
|
11634
11593
|
const attempt = job.retryCount + 1;
|
|
11635
11594
|
const lifecycleBase = {
|
|
11636
|
-
resourceId
|
|
11595
|
+
resourceId,
|
|
11637
11596
|
jobId,
|
|
11638
11597
|
jobType,
|
|
11639
11598
|
attempt,
|
|
@@ -11652,22 +11611,22 @@ async function handleJobInner(adapter, config, job, completedUnitsByJob, signal,
|
|
|
11652
11611
|
}
|
|
11653
11612
|
let ready = null;
|
|
11654
11613
|
if (jobType !== "generation") {
|
|
11655
|
-
const descriptor = await session.client.browse.resource(resourceId
|
|
11614
|
+
const descriptor = await session.client.browse.resource(resourceId).fresh();
|
|
11656
11615
|
const mediaType = getPrimaryMediaType(descriptor);
|
|
11657
11616
|
const source = await withSpan(
|
|
11658
11617
|
"detection:prepare",
|
|
11659
|
-
() => prepareDetection(mediaType ?? "", config.contentReads, resourceId
|
|
11660
|
-
{ attrs: { "resource.id": resourceId
|
|
11618
|
+
() => prepareDetection(mediaType ?? "", config.contentReads, resourceId, generator, (rid) => session.client.browse.resourceAnchoredText(rid)),
|
|
11619
|
+
{ attrs: { "resource.id": resourceId, "media.type": mediaType ?? "unknown" } }
|
|
11661
11620
|
);
|
|
11662
11621
|
if ("declined" in source) {
|
|
11663
11622
|
if (source.declined === "not-yet") {
|
|
11664
|
-
throw new Error(`Anchored text not yet derived for resource ${resourceId
|
|
11623
|
+
throw new Error(`Anchored text not yet derived for resource ${resourceId} \u2014 Smelter has not settled; retrying`);
|
|
11665
11624
|
}
|
|
11666
11625
|
if (source.declined === "no-extractor") {
|
|
11667
|
-
throw new DeterministicJobError(`Cannot run ${jobType} on resource ${resourceId
|
|
11626
|
+
throw new DeterministicJobError(`Cannot run ${jobType} on resource ${resourceId}: media type '${mediaType ?? "unknown"}' has no extractable text to analyze`);
|
|
11668
11627
|
}
|
|
11669
11628
|
if (source.declined === "no-map" || source.declined === "unknown") {
|
|
11670
|
-
throw new DeterministicJobError(`Cannot run ${jobType} on resource ${resourceId
|
|
11629
|
+
throw new DeterministicJobError(`Cannot run ${jobType} on resource ${resourceId}: anchored-text consult returned '${source.declined}'`);
|
|
11671
11630
|
}
|
|
11672
11631
|
await emitEvent(session, "job:complete", {
|
|
11673
11632
|
...terminalBase(),
|
|
@@ -11698,7 +11657,7 @@ async function handleJobInner(adapter, config, job, completedUnitsByJob, signal,
|
|
|
11698
11657
|
};
|
|
11699
11658
|
const unitCursors = /* @__PURE__ */ new Map();
|
|
11700
11659
|
const commitChunk = async (annotations, checkpoint) => {
|
|
11701
|
-
record(await commitAnnotations(session,
|
|
11660
|
+
record(await commitAnnotations(session, resourceId, annotations, jobId));
|
|
11702
11661
|
unitCursors.set(checkpoint.unit, checkpoint.cursor);
|
|
11703
11662
|
unitCursorsByJob.set(job.jobId, Object.fromEntries(unitCursors));
|
|
11704
11663
|
await emitEvent(session, "job:checkpoint", {
|
|
@@ -11859,7 +11818,7 @@ async function handleJobInner(adapter, config, job, completedUnitsByJob, signal,
|
|
|
11859
11818
|
file: Buffer.from(genResult.content),
|
|
11860
11819
|
format: genResult.format,
|
|
11861
11820
|
storageUri,
|
|
11862
|
-
sourceResourceId: resourceId
|
|
11821
|
+
sourceResourceId: resourceId,
|
|
11863
11822
|
...genReferenceId ? { sourceAnnotationId: genReferenceId } : {},
|
|
11864
11823
|
...genParams.prompt ? { generationPrompt: genParams.prompt } : {},
|
|
11865
11824
|
...genParams.language ? { language: genParams.language } : {},
|
|
@@ -11873,12 +11832,12 @@ async function handleJobInner(adapter, config, job, completedUnitsByJob, signal,
|
|
|
11873
11832
|
const { annotation: provenanceRef } = assembleAnnotation(
|
|
11874
11833
|
{
|
|
11875
11834
|
motivation: "linking",
|
|
11876
|
-
target: { source:
|
|
11877
|
-
body: { type: "SpecificResource", source:
|
|
11835
|
+
target: { source: resourceId },
|
|
11836
|
+
body: { type: "SpecificResource", source: newResourceId, purpose: "linking" }
|
|
11878
11837
|
},
|
|
11879
11838
|
generator
|
|
11880
11839
|
);
|
|
11881
|
-
record(await commitAnnotations(session,
|
|
11840
|
+
record(await commitAnnotations(session, resourceId, [provenanceRef], jobId));
|
|
11882
11841
|
}
|
|
11883
11842
|
const citationRefs = [];
|
|
11884
11843
|
if (genResult.format === "application/pdf" && genResult.citations.length > 0) {
|
|
@@ -11903,7 +11862,7 @@ async function handleJobInner(adapter, config, job, completedUnitsByJob, signal,
|
|
|
11903
11862
|
}
|
|
11904
11863
|
const citationRef = buildPdfAnnotation(
|
|
11905
11864
|
layer,
|
|
11906
|
-
|
|
11865
|
+
newResourceId,
|
|
11907
11866
|
generator,
|
|
11908
11867
|
"linking",
|
|
11909
11868
|
{ exact: layer.text.slice(span.start, span.end), start: span.start, end: span.end },
|
|
@@ -11918,7 +11877,7 @@ async function handleJobInner(adapter, config, job, completedUnitsByJob, signal,
|
|
|
11918
11877
|
{
|
|
11919
11878
|
motivation: "linking",
|
|
11920
11879
|
target: {
|
|
11921
|
-
source:
|
|
11880
|
+
source: newResourceId,
|
|
11922
11881
|
selector: [
|
|
11923
11882
|
{ type: "TextPositionSelector", start: citation.start, end: citation.end },
|
|
11924
11883
|
{ type: "TextQuoteSelector", exact: citation.exact }
|
|
@@ -11931,10 +11890,10 @@ async function handleJobInner(adapter, config, job, completedUnitsByJob, signal,
|
|
|
11931
11890
|
citationRefs.push(citationRef);
|
|
11932
11891
|
}
|
|
11933
11892
|
}
|
|
11934
|
-
record(await commitAnnotations(session,
|
|
11893
|
+
record(await commitAnnotations(session, newResourceId, citationRefs, jobId));
|
|
11935
11894
|
await emitEvent(session, "job:complete", {
|
|
11936
11895
|
...terminalBase(),
|
|
11937
|
-
result: { kind: "generation", resourceId: newResourceId, resourceName: genResult.title, truncated: genResult.
|
|
11896
|
+
result: { kind: "generation", resourceId: newResourceId, resourceName: genResult.title, truncated: genResult.truncated }
|
|
11938
11897
|
});
|
|
11939
11898
|
adapter.completeJob();
|
|
11940
11899
|
} else {
|