@semiont/jobs 0.6.8 → 0.6.10

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.js CHANGED
@@ -1,4 +1,4 @@
1
- import { JOB_TYPES, replyChannelsFor, deriveViews, GENERATABLE_MEDIA_TYPES, estimateTokens, isObject, isString, reconcileSelector, getLocaleEnglishName, busRequest, BusRequestError, isArray, isNumber, cutChunk, chunkText } from '@semiont/core';
1
+ import { replyChannelsFor, deriveViews, GENERATABLE_MEDIA_TYPES, estimateTokens, isObject, isString, reconcileSelector, getLocaleEnglishName, isResourceId, busRequest, BusRequestError, cutChunk, chunkText } from '@semiont/core';
2
2
  import { withSpan, recordAnchorOutcome, recordDetectionCall } from '@semiont/observability';
3
3
  import { StructuredReadError } from '@semiont/inference';
4
4
  import { execFileSync } from 'child_process';
@@ -3764,9 +3764,9 @@ var require_mapOneOrManyArgs = __commonJS({
3764
3764
  Object.defineProperty(exports, "__esModule", { value: true });
3765
3765
  exports.mapOneOrManyArgs = void 0;
3766
3766
  var map_1 = require_map();
3767
- var isArray2 = Array.isArray;
3767
+ var isArray = Array.isArray;
3768
3768
  function callOrApply(fn, args) {
3769
- return isArray2(args) ? fn.apply(void 0, __spreadArray([], __read(args))) : fn(args);
3769
+ return isArray(args) ? fn.apply(void 0, __spreadArray([], __read(args))) : fn(args);
3770
3770
  }
3771
3771
  function mapOneOrManyArgs(fn) {
3772
3772
  return map_1.map(function(args) {
@@ -3911,14 +3911,14 @@ var require_argsArgArrayOrObject = __commonJS({
3911
3911
  "../../node_modules/rxjs/dist/cjs/internal/util/argsArgArrayOrObject.js"(exports) {
3912
3912
  Object.defineProperty(exports, "__esModule", { value: true });
3913
3913
  exports.argsArgArrayOrObject = void 0;
3914
- var isArray2 = Array.isArray;
3914
+ var isArray = Array.isArray;
3915
3915
  var getPrototypeOf = Object.getPrototypeOf;
3916
3916
  var objectProto = Object.prototype;
3917
3917
  var getKeys = Object.keys;
3918
3918
  function argsArgArrayOrObject(args) {
3919
3919
  if (args.length === 1) {
3920
3920
  var first_1 = args[0];
3921
- if (isArray2(first_1)) {
3921
+ if (isArray(first_1)) {
3922
3922
  return { args: first_1, keys: null };
3923
3923
  }
3924
3924
  if (isPOJO(first_1)) {
@@ -4666,9 +4666,9 @@ var require_argsOrArgArray = __commonJS({
4666
4666
  "../../node_modules/rxjs/dist/cjs/internal/util/argsOrArgArray.js"(exports) {
4667
4667
  Object.defineProperty(exports, "__esModule", { value: true });
4668
4668
  exports.argsOrArgArray = void 0;
4669
- var isArray2 = Array.isArray;
4669
+ var isArray = Array.isArray;
4670
4670
  function argsOrArgArray(args) {
4671
- return args.length === 1 && isArray2(args[0]) ? args[0] : args;
4671
+ return args.length === 1 && isArray(args[0]) ? args[0] : args;
4672
4672
  }
4673
4673
  exports.argsOrArgArray = argsOrArgArray;
4674
4674
  }
@@ -9203,7 +9203,8 @@ var require_cjs = __commonJS({
9203
9203
  } });
9204
9204
  }
9205
9205
  });
9206
- new Set(JOB_TYPES);
9206
+
9207
+ // src/types.ts
9207
9208
  function isPendingJob(job) {
9208
9209
  return job.status === "pending";
9209
9210
  }
@@ -9759,7 +9760,8 @@ Example format:
9759
9760
  /**
9760
9761
  * Build a prompt for detecting structural tags
9761
9762
  *
9762
- * @param content - The full text content to analyze (NOT truncated for structural analysis)
9763
+ * @param content - The text content to analyze — a chunk sized by the
9764
+ * caller from derived provider limits; NEVER re-truncated here
9763
9765
  * @param category - The specific category to detect
9764
9766
  * @param schemaName - Human-readable schema name
9765
9767
  * @param schemaDescription - Schema description
@@ -10187,7 +10189,7 @@ ${piece}
10187
10189
  }
10188
10190
  if (items.length * YIELD_COLLAPSE_BAND < counted) {
10189
10191
  throw new YieldCollapseError(
10190
- `Extraction found ${items.length} entities where a count call reports ~${counted} mentions (band \xD7${YIELD_COLLAPSE_BAND}) on a ${piece.length}-char chunk \u2014 silent yield collapse (F7): deterministic \u2014 a same-size retry returns the identical under-report.`,
10192
+ `Extraction found ${items.length} entities where a count call reports ~${counted} mentions (band \xD7${YIELD_COLLAPSE_BAND}) on a ${piece.length}-char chunk \u2014 silent yield collapse: deterministic \u2014 a same-size retry returns the identical under-report.`,
10191
10193
  [...items],
10192
10194
  { found: items.length, counted, pieceChars: piece.length }
10193
10195
  );
@@ -10562,8 +10564,6 @@ function compileTypst(source) {
10562
10564
  rmSync(dir, { recursive: true, force: true });
10563
10565
  }
10564
10566
  }
10565
-
10566
- // src/workers/generation/citation-resolver.ts
10567
10567
  var CITATION_TOKEN = /\[\[([^\s[\]/]+)(?:\/([^\s[\]/]+))?\]\]/g;
10568
10568
  function collectContextResourceIds(context) {
10569
10569
  const ids = /* @__PURE__ */ new Set();
@@ -10589,7 +10589,7 @@ function resolveCitationTokens(content, validResourceIds, logger) {
10589
10589
  const annotationId = match[2];
10590
10590
  clean += content.slice(last, match.index).replace(/[ \t]+$/, "");
10591
10591
  last = match.index + token.length;
10592
- if (!validResourceIds.has(citedResourceId)) {
10592
+ if (!isResourceId(citedResourceId) || !validResourceIds.has(citedResourceId)) {
10593
10593
  logger.warn("Citation token references an id absent from the provided context \u2014 dropped", {
10594
10594
  resourceId: citedResourceId
10595
10595
  });
@@ -10738,9 +10738,8 @@ async function processCommentJob(content, inferenceClient, params, buildAnnotati
10738
10738
  found += comments.length;
10739
10739
  const fresh = dedupe(comments.map(
10740
10740
  (c) => (
10741
- // Match the pre-#651 CommentAnnotationWorker: include format and
10742
- // language on the body TextualBody. Optional in the schema, but
10743
- // consumers that do language-aware rendering rely on them.
10741
+ // Format and language go on the body TextualBody: optional in the
10742
+ // schema, but consumers that do language-aware rendering rely on them.
10744
10743
  buildAnnotation("commenting", c, [
10745
10744
  { type: "TextualBody", value: c.comment, purpose: "commenting", format: "text/plain", language: bodyLanguage }
10746
10745
  ])
@@ -10781,8 +10780,7 @@ async function processAssessmentJob(content, inferenceClient, params, buildAnnot
10781
10780
  const fresh = dedupe(assessments.map(
10782
10781
  (a) => (
10783
10782
  // Single-object body with purpose aligned to motivation, matching the
10784
- // pre-#651 AssessmentAnnotationWorker's shape and the majority of
10785
- // persisted assessments. Do not switch to an array or to
10783
+ // majority of persisted assessments. Do not switch to an array or to
10786
10784
  // purpose='describing' — that loses the "this is an assessment, not
10787
10785
  // a description" signal and breaks existing readers that access
10788
10786
  // `body.value` directly on the object.
@@ -10850,11 +10848,11 @@ async function processReferenceJob(content, inferenceClient, params, buildAnnota
10850
10848
  params.includeDescriptiveReferences ?? false,
10851
10849
  logger,
10852
10850
  params.sourceLanguage,
10853
- // Liveness heartbeat (DETECTION-HEARTBEAT): fires at chunk boundaries and
10854
- // every ~15 s while a call is in flight, so a long single-chunk call is
10855
- // not silent. It repeats the current position rather than inventing an
10856
- // advance — the stall watchdog, janitor and client timeout need a signal,
10857
- // not a monotone.
10851
+ // Liveness heartbeat: fires at chunk boundaries and every ~15 s while a
10852
+ // call is in flight, so a long single-chunk call is not silent. It
10853
+ // repeats the current position rather than inventing an advance — the
10854
+ // stall watchdog, janitor and client timeout need a signal, not a
10855
+ // monotone.
10858
10856
  () => emitTypeProgress(entityTypeName),
10859
10857
  (verdict) => {
10860
10858
  underReported = {
@@ -11011,7 +11009,7 @@ async function processGenerationJob(inferenceClient, params, onProgress, logger)
11011
11009
  `Unsupported outputMediaType for generation: ${outputMediaType}. Generation produces ${GENERATABLE_MEDIA_TYPES.join(" or ")}.`
11012
11010
  );
11013
11011
  }
11014
- const title = params.title ?? "Untitled";
11012
+ const title = params.title;
11015
11013
  const entityTypes = (params.entityTypes ?? []).map(String);
11016
11014
  if (outputMediaType === "application/pdf") {
11017
11015
  onProgress(5, { code: "generating-resource" });
@@ -11091,12 +11089,7 @@ async function processGenerationJob(inferenceClient, params, onProgress, logger)
11091
11089
  title,
11092
11090
  format: outputMediaType,
11093
11091
  citations: citations2,
11094
- result: {
11095
- kind: "generation",
11096
- resourceId: "",
11097
- resourceName: title,
11098
- truncated: generated2.truncated
11099
- }
11092
+ truncated: generated2.truncated
11100
11093
  };
11101
11094
  }
11102
11095
  onProgress(5, { code: "generating-resource" });
@@ -11132,30 +11125,12 @@ async function processGenerationJob(inferenceClient, params, onProgress, logger)
11132
11125
  title,
11133
11126
  format: outputMediaType,
11134
11127
  citations,
11135
- result: {
11136
- kind: "generation",
11137
- resourceId: "",
11138
- resourceName: title,
11139
- truncated: generated.truncated
11140
- }
11128
+ truncated: generated.truncated
11141
11129
  };
11142
11130
  }
11143
11131
 
11144
11132
  // src/job-claim-adapter.ts
11145
11133
  var import_rxjs = __toESM(require_cjs());
11146
- function readUnitCursors(raw, completedUnits) {
11147
- if (!isObject(raw)) return {};
11148
- const done = new Set(completedUnits);
11149
- const cursors = {};
11150
- for (const [unit, value] of Object.entries(raw)) {
11151
- if (done.has(unit) || !isObject(value)) continue;
11152
- const { next, size, found, emitted } = value;
11153
- if (!isNumber(next) || !isNumber(size) || next < 0 || size < 1) continue;
11154
- if (!isNumber(found) || !isNumber(emitted) || found < 0 || emitted < 0) continue;
11155
- cursors[unit] = { next, size, found, emitted };
11156
- }
11157
- return cursors;
11158
- }
11159
11134
  function createJobClaimAdapter(options) {
11160
11135
  const { bus, jobTypes } = options;
11161
11136
  const activeJob$ = new import_rxjs.BehaviorSubject(null);
@@ -11174,9 +11149,9 @@ function createJobClaimAdapter(options) {
11174
11149
  let activeSince = null;
11175
11150
  const iso = (t) => t === null ? null : new Date(t).toISOString();
11176
11151
  const claimNext = async () => {
11177
- let record;
11152
+ let claimed;
11178
11153
  try {
11179
- record = await busRequest(bus, "job:claim", { types: jobTypes }, 1e4);
11154
+ claimed = await busRequest(bus, "job:claim", { types: jobTypes }, 1e4);
11180
11155
  } catch (error) {
11181
11156
  if (error instanceof BusRequestError) {
11182
11157
  if (error.code === "bus.none-pending") return { declined: true };
@@ -11184,25 +11159,19 @@ function createJobClaimAdapter(options) {
11184
11159
  }
11185
11160
  return { refused: { code: null, message: error instanceof Error ? error.message : String(error) } };
11186
11161
  }
11187
- if (!isString(record.metadata?.id) || !isString(record.metadata?.type)) {
11188
- return { refused: { code: null, message: "claimed record carries no job id or type" } };
11189
- }
11190
- const completedUnits = isArray(record.metadata?.completedUnits) ? record.metadata.completedUnits.filter(isString) : [];
11191
- const unitCursors = readUnitCursors(record.metadata?.unitCursors, completedUnits);
11192
- const params = record.params ?? {};
11162
+ const { metadata, params } = claimed;
11193
11163
  return {
11194
11164
  job: {
11195
- jobId: record.metadata.id,
11196
- type: record.metadata.type,
11197
- resourceId: isString(params.resourceId) ? params.resourceId : "",
11198
- userId: record.metadata?.userId ?? "",
11165
+ jobId: metadata.id,
11166
+ type: metadata.type,
11167
+ resourceId: params.resourceId,
11199
11168
  params,
11200
- completedUnits,
11201
- unitCursors,
11202
- // Absent or malformed metadata reads as "no budget left" — a worker
11203
- // that cannot see the budget must not claim a retry is coming.
11204
- retryCount: isNumber(record.metadata?.retryCount) ? record.metadata.retryCount : 0,
11205
- maxRetries: isNumber(record.metadata?.maxRetries) ? record.metadata.maxRetries : 0
11169
+ // Both appear on the record once an attempt has checkpointed, and a
11170
+ // finished unit has no cursor: the dispatcher drops it at the merge.
11171
+ completedUnits: metadata.completedUnits ?? [],
11172
+ unitCursors: metadata.unitCursors ?? {},
11173
+ retryCount: metadata.retryCount,
11174
+ maxRetries: metadata.maxRetries
11206
11175
  }
11207
11176
  };
11208
11177
  };
@@ -11319,26 +11288,25 @@ var WORKER_AWAITED_OPERATIONS = [
11319
11288
  "job:claim",
11320
11289
  "browse:resource-requested",
11321
11290
  // Canonical geometry for a geometry-bearing detection: the consult behind
11322
- // `ConsultAnchoredText` (SMELTER-OWNS-OCR P2). Its omission broke every
11323
- // PDF detection job at the transport probe
11324
- // (.plans/WORKER-ANCHORED-TEXT-CHANNEL.md); the census below now fails the
11291
+ // `ConsultAnchoredText`, answered by the Smelter. Without it every PDF
11292
+ // detection job fails at the transport probe; the census below fails the
11325
11293
  // BUILD when this list and the declared awaits drift.
11326
11294
  "browse:anchored-text-requested",
11327
- // Durability acknowledgement for a unit's annotations (JOB-RESTART-SAFETY
11328
- // P6). The worker AWAITS this one — a unit may not advance until its
11329
- // annotations are in the event log — so its replies must be in the narrow
11330
- // channel set or every commit fails fast with `bus.unsubscribed`.
11295
+ // Durability acknowledgement for a unit's annotations. The worker AWAITS
11296
+ // this one — a unit may not advance until its annotations are in the event
11297
+ // log — so its replies must be in the narrow channel set or every commit
11298
+ // fails fast with `bus.unsubscribed`.
11331
11299
  "mark:commit",
11332
- // The durability probe for a commit whose acknowledgement never routed
11333
- // (COMMIT-ACK-FALSE-FAILURE F1). SINGULAR by design: the annotation LIST
11334
- // channel is the multi-MB fan-out this narrowing exists to keep out, and a
11335
- // rare error path is no reason to let it back in.
11300
+ // The durability probe for a commit whose acknowledgement never routed.
11301
+ // SINGULAR by design: the annotation LIST channel is the multi-MB fan-out
11302
+ // this narrowing exists to keep out, and a rare error path is no reason to
11303
+ // let it in.
11336
11304
  "browse:annotation-requested"
11337
11305
  ];
11338
11306
  var WORKER_CONSUMED_BROADCASTS = [
11339
11307
  // The queue announcement the claim adapter races for.
11340
11308
  "job:queued",
11341
- // Cooperative cancellation of the ACTIVE job (JOB-RESTART-SAFETY P4).
11309
+ // Cooperative cancellation of the ACTIVE job: it stops at a unit boundary.
11342
11310
  "job:cancel-requested"
11343
11311
  ];
11344
11312
  var WORKER_CHANNELS = [