@semiont/jobs 0.5.25 → 0.5.26
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 +1 -0
- package/dist/index.js +87 -77
- package/dist/index.js.map +1 -1
- package/dist/worker-main.js +93 -83
- 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 { createTomlConfigLoader, didToAgent, baseUrl, STARTUP_FETCH_RETRY, retryWithBackoff, isTransientFetchError, busRequest, resourceId, getPrimaryMediaType, assembleAnnotation, findClaimSpan, textExtractionOf, reconcileSelector, GENERATABLE_MEDIA_TYPES, locate, createFragmentSelector, getLocaleEnglishName, estimateTokens, chunkText,
|
|
1
|
+
import { createTomlConfigLoader, didToAgent, baseUrl, STARTUP_FETCH_RETRY, retryWithBackoff, isTransientFetchError, busRequest, resourceId, getPrimaryMediaType, assembleAnnotation, findClaimSpan, textExtractionOf, reconcileSelector, GENERATABLE_MEDIA_TYPES, locate, createFragmentSelector, getLocaleEnglishName, estimateTokens, chunkText, isObject, isString, deriveViews } from '@semiont/core';
|
|
2
2
|
import { anchoredTextStoreOverTransport, deriveStorageUri, extractPdfTextLayer, EXTRACTORS, calculateChecksum, withinByteBudget, MAX_PDF_BYTES } from '@semiont/content';
|
|
3
3
|
import { execFileSync } from 'child_process';
|
|
4
4
|
import { existsSync, readFileSync, mkdtempSync, writeFileSync, rmSync } from 'fs';
|
|
@@ -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
|
}
|
|
@@ -9371,15 +9371,15 @@ async function withTimeout(work, label) {
|
|
|
9371
9371
|
clearTimeout(timer);
|
|
9372
9372
|
}
|
|
9373
9373
|
}
|
|
9374
|
-
function boundedGenerate(client, prompt, maxTokens, temperature
|
|
9374
|
+
function boundedGenerate(client, prompt, maxTokens, temperature) {
|
|
9375
9375
|
return withTimeout(
|
|
9376
|
-
client.generateText(prompt, maxTokens, temperature
|
|
9376
|
+
client.generateText(prompt, maxTokens, temperature),
|
|
9377
9377
|
`${client.type}:${client.modelId}`
|
|
9378
9378
|
);
|
|
9379
9379
|
}
|
|
9380
|
-
function
|
|
9380
|
+
function boundedGenerateStructured(client, prompt, maxTokens, temperature, elementSchema) {
|
|
9381
9381
|
return withTimeout(
|
|
9382
|
-
client.
|
|
9382
|
+
client.generateStructured(prompt, maxTokens, temperature, elementSchema),
|
|
9383
9383
|
`${client.type}:${client.modelId}`
|
|
9384
9384
|
);
|
|
9385
9385
|
}
|
|
@@ -9713,32 +9713,57 @@ Example format:
|
|
|
9713
9713
|
return prompt;
|
|
9714
9714
|
}
|
|
9715
9715
|
};
|
|
9716
|
-
|
|
9717
|
-
|
|
9718
|
-
|
|
9719
|
-
|
|
9720
|
-
|
|
9721
|
-
|
|
9722
|
-
|
|
9723
|
-
|
|
9724
|
-
|
|
9725
|
-
|
|
9726
|
-
|
|
9727
|
-
|
|
9728
|
-
|
|
9729
|
-
|
|
9730
|
-
}
|
|
9716
|
+
var COMMENT_ELEMENT_SCHEMA = {
|
|
9717
|
+
type: "object",
|
|
9718
|
+
properties: {
|
|
9719
|
+
exact: { type: "string" },
|
|
9720
|
+
prefix: { type: "string" },
|
|
9721
|
+
suffix: { type: "string" },
|
|
9722
|
+
comment: { type: "string" }
|
|
9723
|
+
},
|
|
9724
|
+
required: ["exact", "comment"],
|
|
9725
|
+
additionalProperties: false
|
|
9726
|
+
};
|
|
9727
|
+
var HIGHLIGHT_ELEMENT_SCHEMA = {
|
|
9728
|
+
type: "object",
|
|
9729
|
+
properties: {
|
|
9730
|
+
exact: { type: "string" },
|
|
9731
|
+
prefix: { type: "string" },
|
|
9732
|
+
suffix: { type: "string" }
|
|
9733
|
+
},
|
|
9734
|
+
required: ["exact"],
|
|
9735
|
+
additionalProperties: false
|
|
9736
|
+
};
|
|
9737
|
+
var ASSESSMENT_ELEMENT_SCHEMA = {
|
|
9738
|
+
type: "object",
|
|
9739
|
+
properties: {
|
|
9740
|
+
exact: { type: "string" },
|
|
9741
|
+
prefix: { type: "string" },
|
|
9742
|
+
suffix: { type: "string" },
|
|
9743
|
+
assessment: { type: "string" }
|
|
9744
|
+
},
|
|
9745
|
+
required: ["exact", "assessment"],
|
|
9746
|
+
additionalProperties: false
|
|
9747
|
+
};
|
|
9748
|
+
var TAG_ELEMENT_SCHEMA = {
|
|
9749
|
+
type: "object",
|
|
9750
|
+
properties: {
|
|
9751
|
+
exact: { type: "string" },
|
|
9752
|
+
prefix: { type: "string" },
|
|
9753
|
+
suffix: { type: "string" }
|
|
9754
|
+
},
|
|
9755
|
+
required: ["exact"],
|
|
9756
|
+
additionalProperties: false
|
|
9757
|
+
};
|
|
9731
9758
|
var MotivationParsers = class {
|
|
9732
9759
|
/**
|
|
9733
|
-
*
|
|
9760
|
+
* Validate and reconcile structured comment elements.
|
|
9734
9761
|
*
|
|
9735
|
-
* @param
|
|
9762
|
+
* @param parsed - Already-parsed elements from the structured surface
|
|
9736
9763
|
* @param content - Original content to validate offsets against
|
|
9737
9764
|
* @returns Array of validated comment matches
|
|
9738
|
-
* @throws if the response is not a parseable JSON array
|
|
9739
9765
|
*/
|
|
9740
|
-
static parseComments(
|
|
9741
|
-
const parsed = parseJsonArray(response, "comment");
|
|
9766
|
+
static parseComments(parsed, content) {
|
|
9742
9767
|
const valid = parsed.filter(
|
|
9743
9768
|
(c) => isObject(c) && isString(c.exact) && isString(c.comment) && c.comment.trim().length > 0
|
|
9744
9769
|
);
|
|
@@ -9767,15 +9792,13 @@ var MotivationParsers = class {
|
|
|
9767
9792
|
return validatedComments;
|
|
9768
9793
|
}
|
|
9769
9794
|
/**
|
|
9770
|
-
*
|
|
9795
|
+
* Validate and reconcile structured highlight elements.
|
|
9771
9796
|
*
|
|
9772
|
-
* @param
|
|
9797
|
+
* @param parsed - Already-parsed elements from the structured surface
|
|
9773
9798
|
* @param content - Original content to validate offsets against
|
|
9774
9799
|
* @returns Array of validated highlight matches
|
|
9775
|
-
* @throws if the response is not a parseable JSON array
|
|
9776
9800
|
*/
|
|
9777
|
-
static parseHighlights(
|
|
9778
|
-
const parsed = parseJsonArray(response, "highlight");
|
|
9801
|
+
static parseHighlights(parsed, content) {
|
|
9779
9802
|
const highlights = parsed.filter(
|
|
9780
9803
|
(h) => isObject(h) && isString(h.exact)
|
|
9781
9804
|
);
|
|
@@ -9802,15 +9825,13 @@ var MotivationParsers = class {
|
|
|
9802
9825
|
return validatedHighlights;
|
|
9803
9826
|
}
|
|
9804
9827
|
/**
|
|
9805
|
-
*
|
|
9828
|
+
* Validate and reconcile structured assessment elements.
|
|
9806
9829
|
*
|
|
9807
|
-
* @param
|
|
9830
|
+
* @param parsed - Already-parsed elements from the structured surface
|
|
9808
9831
|
* @param content - Original content to validate offsets against
|
|
9809
9832
|
* @returns Array of validated assessment matches
|
|
9810
|
-
* @throws if the response is not a parseable JSON array
|
|
9811
9833
|
*/
|
|
9812
|
-
static parseAssessments(
|
|
9813
|
-
const parsed = parseJsonArray(response, "assessment");
|
|
9834
|
+
static parseAssessments(parsed, content) {
|
|
9814
9835
|
const assessments = parsed.filter(
|
|
9815
9836
|
(a) => isObject(a) && isString(a.exact) && isString(a.assessment)
|
|
9816
9837
|
);
|
|
@@ -9838,14 +9859,13 @@ var MotivationParsers = class {
|
|
|
9838
9859
|
return validatedAssessments;
|
|
9839
9860
|
}
|
|
9840
9861
|
/**
|
|
9841
|
-
*
|
|
9862
|
+
* Validate structured tag elements into raw, pre-reconciliation tag inputs.
|
|
9842
9863
|
* Reconciliation happens in `validateTagOffsets`, which adds `start`/`end`
|
|
9843
9864
|
* by anchoring `exact` against the source content.
|
|
9844
9865
|
*
|
|
9845
|
-
* @
|
|
9866
|
+
* @param parsed - Already-parsed elements from the structured surface
|
|
9846
9867
|
*/
|
|
9847
|
-
static parseTags(
|
|
9848
|
-
const parsed = parseJsonArray(response, "tag");
|
|
9868
|
+
static parseTags(parsed) {
|
|
9849
9869
|
const valid = parsed.filter(
|
|
9850
9870
|
(t) => isObject(t) && isString(t.exact) && t.exact.trim().length > 0
|
|
9851
9871
|
);
|
|
@@ -9892,22 +9912,22 @@ function assertNotTruncated(response, motivation, chunk, totalChunks, outputBudg
|
|
|
9892
9912
|
throw new Error(`${motivation} detection response truncated (max_tokens) on chunk ${chunk}/${totalChunks} despite the derived output budget of ${outputBudget} tokens \u2014 failing the job rather than under-reporting annotations.`);
|
|
9893
9913
|
}
|
|
9894
9914
|
}
|
|
9895
|
-
async function detectInChunks(client, content, buildPrompt, temperature, motivation, parse, onChunk) {
|
|
9915
|
+
async function detectInChunks(client, content, buildPrompt, temperature, motivation, elementSchema, parse, onChunk) {
|
|
9896
9916
|
const limits = await client.limits();
|
|
9897
9917
|
const scaffoldTokens = estimateTokens(buildPrompt(""));
|
|
9898
9918
|
const { chunking, outputBudget } = deriveDetectionBudget(limits, scaffoldTokens);
|
|
9899
9919
|
const chunks = chunkText(content, chunking);
|
|
9900
9920
|
const collected = [];
|
|
9901
9921
|
for (let i = 0; i < chunks.length; i++) {
|
|
9902
|
-
const response = await
|
|
9922
|
+
const response = await boundedGenerateStructured(
|
|
9903
9923
|
client,
|
|
9904
9924
|
buildPrompt(chunks[i]),
|
|
9905
9925
|
outputBudget,
|
|
9906
9926
|
temperature,
|
|
9907
|
-
|
|
9927
|
+
elementSchema
|
|
9908
9928
|
);
|
|
9909
9929
|
assertNotTruncated(response, motivation, i + 1, chunks.length, outputBudget);
|
|
9910
|
-
collected.push(...parse(response.
|
|
9930
|
+
collected.push(...parse(response.items));
|
|
9911
9931
|
if (i < chunks.length - 1) {
|
|
9912
9932
|
onChunk?.(i + 1, chunks.length);
|
|
9913
9933
|
}
|
|
@@ -9930,7 +9950,8 @@ var AnnotationDetection = class {
|
|
|
9930
9950
|
(chunk) => MotivationPrompts.buildCommentPrompt(chunk, instructions, tone, density, language, sourceLanguage),
|
|
9931
9951
|
0.4,
|
|
9932
9952
|
"comment",
|
|
9933
|
-
|
|
9953
|
+
COMMENT_ELEMENT_SCHEMA,
|
|
9954
|
+
(items) => MotivationParsers.parseComments(items, content),
|
|
9934
9955
|
onChunk
|
|
9935
9956
|
);
|
|
9936
9957
|
}
|
|
@@ -9948,7 +9969,8 @@ var AnnotationDetection = class {
|
|
|
9948
9969
|
(chunk) => MotivationPrompts.buildHighlightPrompt(chunk, instructions, density, sourceLanguage),
|
|
9949
9970
|
0.3,
|
|
9950
9971
|
"highlight",
|
|
9951
|
-
|
|
9972
|
+
HIGHLIGHT_ELEMENT_SCHEMA,
|
|
9973
|
+
(items) => MotivationParsers.parseHighlights(items, content),
|
|
9952
9974
|
onChunk
|
|
9953
9975
|
);
|
|
9954
9976
|
}
|
|
@@ -9966,7 +9988,8 @@ var AnnotationDetection = class {
|
|
|
9966
9988
|
(chunk) => MotivationPrompts.buildAssessmentPrompt(chunk, instructions, tone, density, language, sourceLanguage),
|
|
9967
9989
|
0.3,
|
|
9968
9990
|
"assessment",
|
|
9969
|
-
|
|
9991
|
+
ASSESSMENT_ELEMENT_SCHEMA,
|
|
9992
|
+
(items) => MotivationParsers.parseAssessments(items, content),
|
|
9970
9993
|
onChunk
|
|
9971
9994
|
);
|
|
9972
9995
|
}
|
|
@@ -10002,12 +10025,24 @@ var AnnotationDetection = class {
|
|
|
10002
10025
|
),
|
|
10003
10026
|
0.2,
|
|
10004
10027
|
"tag",
|
|
10005
|
-
|
|
10028
|
+
TAG_ELEMENT_SCHEMA,
|
|
10029
|
+
(items) => MotivationParsers.parseTags(items),
|
|
10006
10030
|
onChunk
|
|
10007
10031
|
);
|
|
10008
10032
|
return MotivationParsers.validateTagOffsets(parsedTags, content, category);
|
|
10009
10033
|
}
|
|
10010
10034
|
};
|
|
10035
|
+
var ENTITY_ELEMENT_SCHEMA = {
|
|
10036
|
+
type: "object",
|
|
10037
|
+
properties: {
|
|
10038
|
+
exact: { type: "string" },
|
|
10039
|
+
entityType: { type: "string" },
|
|
10040
|
+
prefix: { type: "string" },
|
|
10041
|
+
suffix: { type: "string" }
|
|
10042
|
+
},
|
|
10043
|
+
required: ["exact", "entityType"],
|
|
10044
|
+
additionalProperties: false
|
|
10045
|
+
};
|
|
10011
10046
|
async function extractEntities(exact, entityTypes, client, includeDescriptiveReferences, logger2, sourceLanguage, onChunk) {
|
|
10012
10047
|
const entityTypesDescription = entityTypes.map((et) => {
|
|
10013
10048
|
if (typeof et === "string") {
|
|
@@ -10069,50 +10104,25 @@ Example output:
|
|
|
10069
10104
|
});
|
|
10070
10105
|
const collected = [];
|
|
10071
10106
|
for (let i = 0; i < chunks.length; i++) {
|
|
10072
|
-
const response = await
|
|
10107
|
+
const response = await boundedGenerateStructured(
|
|
10073
10108
|
client,
|
|
10074
10109
|
buildPrompt(chunks[i]),
|
|
10075
10110
|
outputBudget,
|
|
10076
10111
|
0.3,
|
|
10077
10112
|
// Lower temperature for more consistent extraction
|
|
10078
|
-
|
|
10079
|
-
// periodically emit malformed JSON (truncated brackets, mid-token
|
|
10080
|
-
// breaks at higher token counts) which silently parse-fails into
|
|
10081
|
-
// [] downstream. The prompt's schema (which keys, what types) still
|
|
10082
|
-
// governs *what* the JSON contains; `format: 'json'` governs that
|
|
10083
|
-
// it's syntactically valid.
|
|
10084
|
-
{ format: "json" }
|
|
10113
|
+
ENTITY_ELEMENT_SCHEMA
|
|
10085
10114
|
);
|
|
10086
10115
|
logger2.debug("Got entity extraction response", {
|
|
10087
10116
|
chunk: i + 1,
|
|
10088
10117
|
chunks: chunks.length,
|
|
10089
|
-
|
|
10118
|
+
items: response.items.length
|
|
10090
10119
|
});
|
|
10091
10120
|
if (response.stopReason === "max_tokens") {
|
|
10092
10121
|
const errorMsg = `Entity extraction response truncated (max_tokens) on chunk ${i + 1}/${chunks.length} despite the derived output budget of ${outputBudget} tokens \u2014 failing the job rather than dropping annotations.`;
|
|
10093
|
-
logger2.error(errorMsg, {
|
|
10122
|
+
logger2.error(errorMsg, { items: response.items.length });
|
|
10094
10123
|
throw new Error(errorMsg);
|
|
10095
10124
|
}
|
|
10096
|
-
|
|
10097
|
-
try {
|
|
10098
|
-
entities = JSON.parse(response.text.trim());
|
|
10099
|
-
} catch (error) {
|
|
10100
|
-
logger2.error("Failed to parse entity extraction response", {
|
|
10101
|
-
error: error instanceof Error ? error.message : String(error),
|
|
10102
|
-
response: response.text.slice(0, 500)
|
|
10103
|
-
});
|
|
10104
|
-
throw new Error("Failed to parse entity extraction response", {
|
|
10105
|
-
cause: error instanceof Error ? error : new Error(String(error))
|
|
10106
|
-
});
|
|
10107
|
-
}
|
|
10108
|
-
if (!isArray(entities)) {
|
|
10109
|
-
logger2.error("Failed to parse entity extraction response: expected a JSON array", {
|
|
10110
|
-
response: response.text.slice(0, 500)
|
|
10111
|
-
});
|
|
10112
|
-
throw new Error("Failed to parse entity extraction response: expected a JSON array");
|
|
10113
|
-
}
|
|
10114
|
-
logger2.debug("Parsed entities from AI response", { chunk: i + 1, count: entities.length });
|
|
10115
|
-
for (const e of entities) {
|
|
10125
|
+
for (const e of response.items) {
|
|
10116
10126
|
if (isObject(e) && isString(e.exact) && isString(e.entityType)) {
|
|
10117
10127
|
collected.push({
|
|
10118
10128
|
exact: e.exact,
|