@semiont/jobs 0.5.12 → 0.5.14
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 +33 -1
- package/dist/index.js +48 -7
- package/dist/index.js.map +1 -1
- package/dist/worker-main.js +153 -20
- package/dist/worker-main.js.map +1 -1
- package/package.json +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -691,5 +691,37 @@ declare function generateResourceFromTopic(topic: string, entityTypes: string[],
|
|
|
691
691
|
content: string;
|
|
692
692
|
}>;
|
|
693
693
|
|
|
694
|
-
|
|
694
|
+
/**
|
|
695
|
+
* Worker Runtime — the importable half of the worker host.
|
|
696
|
+
*
|
|
697
|
+
* `worker-main.ts` is a process entrypoint (config at module scope,
|
|
698
|
+
* `main()` at import) and therefore untestable by construction; everything
|
|
699
|
+
* a unit test needs to reach lives here instead, fully parameterized — no
|
|
700
|
+
* module-scope env reads, no side effects at import.
|
|
701
|
+
*
|
|
702
|
+
* The load-bearing contract this module owns (and the reason it was
|
|
703
|
+
* extracted): a worker's stamped identity is the DID the
|
|
704
|
+
* `/api/tokens/agent` exchange MINTED for it, carried verbatim — never
|
|
705
|
+
* re-derived from the URL the worker happens to dial. One logical agent
|
|
706
|
+
* previously got two DIDs that way (.plans/bugs/agent-did-host-skew.md).
|
|
707
|
+
*/
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Stall watchdog (WORKER-LIVENESS.md P3) — the fail-fast line behind the
|
|
711
|
+
* inference timeout. There is no poll loop to heartbeat; the honest
|
|
712
|
+
* stall signal in this push-driven architecture is *processing without
|
|
713
|
+
* activity*: an agent holding a claimed job whose `lastActivityAt`
|
|
714
|
+
* (claim / progress / finish) has stopped advancing is wedged — the
|
|
715
|
+
* adapter ignores every announcement while `isProcessing`, so a wedged
|
|
716
|
+
* agent never recovers on its own. Silent hang → loud crash → whatever
|
|
717
|
+
* restart policy the deployment chose.
|
|
718
|
+
*
|
|
719
|
+
* Thresholds are fixed by design (no env knobs) and deliberately
|
|
720
|
+
* layered: inference timeout (10 min, P2) fires first; this watchdog
|
|
721
|
+
* (15 min) catches the failure modes nobody predicted; the backend's
|
|
722
|
+
* dead-worker janitor (30 min) re-queues the job regardless.
|
|
723
|
+
*/
|
|
724
|
+
declare const STALL_THRESHOLD_MS: number;
|
|
725
|
+
|
|
726
|
+
export { AnnotationDetection, FsJobQueue, STALL_THRESHOLD_MS, generateResourceFromTopic, isCancelledJob, isCompleteJob, isFailedJob, isPendingJob, isRunningJob, processAssessmentJob, processCommentJob, processGenerationJob, processHighlightJob, processReferenceJob, processTagJob };
|
|
695
727
|
export type { AnyJob, AssessmentDetectionJob, AssessmentDetectionParams, AssessmentDetectionProgress, AssessmentDetectionResult, CancelledJob, CommentDetectionJob, CommentDetectionParams, CommentDetectionProgress, CommentDetectionResult, CompleteJob, DetectionJob, DetectionParams, DetectionProgress, DetectionResult, FailedJob, GenerationJob, GenerationParams, GenerationResult, HighlightDetectionJob, HighlightDetectionParams, HighlightDetectionProgress, HighlightDetectionResult, JobMetadata, JobQueryFilters, JobQueue, JobStatus, JobType, OnProgress, PendingJob, ProcessorResult, RunningJob, TagDetectionJob, TagDetectionParams, TagDetectionProgress, TagDetectionResult, YieldProgress };
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,10 @@ import { promises } from 'fs';
|
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { jobId, deriveViews, reconcileSelector, isObject, isString, getLocaleEnglishName, didToAgent, isArray } from '@semiont/core';
|
|
4
4
|
import { generateAnnotationId } from '@semiont/event-sourcing';
|
|
5
|
+
import '@semiont/content';
|
|
6
|
+
import '@semiont/observability';
|
|
7
|
+
import '@semiont/sdk';
|
|
8
|
+
import '@semiont/http-transport';
|
|
5
9
|
|
|
6
10
|
// src/fs-job-queue.ts
|
|
7
11
|
var REANNOUNCE_INTERVAL_MS = 3e4;
|
|
@@ -419,6 +423,41 @@ function isFailedJob(job) {
|
|
|
419
423
|
function isCancelledJob(job) {
|
|
420
424
|
return job.status === "cancelled";
|
|
421
425
|
}
|
|
426
|
+
|
|
427
|
+
// src/workers/inference-call.ts
|
|
428
|
+
var INFERENCE_TIMEOUT_MS = 10 * 6e4;
|
|
429
|
+
async function withTimeout(work, label) {
|
|
430
|
+
let timer;
|
|
431
|
+
const timedOut = new Promise((_, reject) => {
|
|
432
|
+
timer = setTimeout(() => {
|
|
433
|
+
reject(new Error(
|
|
434
|
+
`Inference call timed out after ${INFERENCE_TIMEOUT_MS / 6e4} minutes (${label}) \u2014 failing the job to keep the claim loop live`
|
|
435
|
+
));
|
|
436
|
+
}, INFERENCE_TIMEOUT_MS);
|
|
437
|
+
timer.unref?.();
|
|
438
|
+
});
|
|
439
|
+
try {
|
|
440
|
+
return await Promise.race([work, timedOut]);
|
|
441
|
+
} catch (err) {
|
|
442
|
+
work.catch(() => {
|
|
443
|
+
});
|
|
444
|
+
throw err;
|
|
445
|
+
} finally {
|
|
446
|
+
clearTimeout(timer);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
function boundedGenerate(client, prompt, maxTokens, temperature, options) {
|
|
450
|
+
return withTimeout(
|
|
451
|
+
client.generateText(prompt, maxTokens, temperature, options),
|
|
452
|
+
`${client.type}:${client.modelId}`
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
function boundedGenerateWithMetadata(client, prompt, maxTokens, temperature, options) {
|
|
456
|
+
return withTimeout(
|
|
457
|
+
client.generateTextWithMetadata(prompt, maxTokens, temperature, options),
|
|
458
|
+
`${client.type}:${client.modelId}`
|
|
459
|
+
);
|
|
460
|
+
}
|
|
422
461
|
function languageName(tag) {
|
|
423
462
|
return getLocaleEnglishName(tag) || tag;
|
|
424
463
|
}
|
|
@@ -900,7 +939,7 @@ var AnnotationDetection = class {
|
|
|
900
939
|
*/
|
|
901
940
|
static async detectComments(content, client, instructions, tone, density, language, sourceLanguage) {
|
|
902
941
|
const prompt = MotivationPrompts.buildCommentPrompt(content, instructions, tone, density, language, sourceLanguage);
|
|
903
|
-
const response = await client
|
|
942
|
+
const response = await boundedGenerateWithMetadata(client, prompt, 3e3, 0.4, { format: "json" });
|
|
904
943
|
assertNotTruncated(response, "comment");
|
|
905
944
|
return MotivationParsers.parseComments(response.text, content);
|
|
906
945
|
}
|
|
@@ -913,7 +952,7 @@ var AnnotationDetection = class {
|
|
|
913
952
|
*/
|
|
914
953
|
static async detectHighlights(content, client, instructions, density, sourceLanguage) {
|
|
915
954
|
const prompt = MotivationPrompts.buildHighlightPrompt(content, instructions, density, sourceLanguage);
|
|
916
|
-
const response = await client
|
|
955
|
+
const response = await boundedGenerateWithMetadata(client, prompt, 2e3, 0.3, { format: "json" });
|
|
917
956
|
assertNotTruncated(response, "highlight");
|
|
918
957
|
return MotivationParsers.parseHighlights(response.text, content);
|
|
919
958
|
}
|
|
@@ -926,7 +965,7 @@ var AnnotationDetection = class {
|
|
|
926
965
|
*/
|
|
927
966
|
static async detectAssessments(content, client, instructions, tone, density, language, sourceLanguage) {
|
|
928
967
|
const prompt = MotivationPrompts.buildAssessmentPrompt(content, instructions, tone, density, language, sourceLanguage);
|
|
929
|
-
const response = await client
|
|
968
|
+
const response = await boundedGenerateWithMetadata(client, prompt, 3e3, 0.3, { format: "json" });
|
|
930
969
|
assertNotTruncated(response, "assessment");
|
|
931
970
|
return MotivationParsers.parseAssessments(response.text, content);
|
|
932
971
|
}
|
|
@@ -957,7 +996,7 @@ var AnnotationDetection = class {
|
|
|
957
996
|
categoryInfo.examples,
|
|
958
997
|
sourceLanguage
|
|
959
998
|
);
|
|
960
|
-
const response = await client
|
|
999
|
+
const response = await boundedGenerateWithMetadata(client, prompt, 4e3, 0.2, { format: "json" });
|
|
961
1000
|
assertNotTruncated(response, "tag");
|
|
962
1001
|
const parsedTags = MotivationParsers.parseTags(response.text);
|
|
963
1002
|
return MotivationParsers.validateTagOffsets(parsedTags, content, category);
|
|
@@ -1013,7 +1052,8 @@ If no entities are found, respond with an empty array [].
|
|
|
1013
1052
|
Example output:
|
|
1014
1053
|
[{"exact":"Alice","entityType":"Person","prefix":"","suffix":" went to"},{"exact":"Paris","entityType":"Location","prefix":"went to ","suffix":" yesterday"}]`;
|
|
1015
1054
|
logger.debug("Sending entity extraction request", { entityTypes: entityTypesDescription });
|
|
1016
|
-
const response = await
|
|
1055
|
+
const response = await boundedGenerateWithMetadata(
|
|
1056
|
+
client,
|
|
1017
1057
|
prompt,
|
|
1018
1058
|
4e3,
|
|
1019
1059
|
// Increased to handle many entities without truncation
|
|
@@ -1263,7 +1303,7 @@ ${formatRequirements}`;
|
|
|
1263
1303
|
temperature: finalTemperature,
|
|
1264
1304
|
maxTokens: finalMaxTokens
|
|
1265
1305
|
});
|
|
1266
|
-
const response = await client
|
|
1306
|
+
const response = await boundedGenerate(client, prompt, finalMaxTokens, finalTemperature);
|
|
1267
1307
|
logger.debug("Got response from inference", { responseLength: response.length });
|
|
1268
1308
|
const result = parseResponse(response);
|
|
1269
1309
|
logger.debug("Parsed response", {
|
|
@@ -1661,7 +1701,8 @@ async function processGenerationJob(inferenceClient, params, onProgress, logger)
|
|
|
1661
1701
|
}
|
|
1662
1702
|
};
|
|
1663
1703
|
}
|
|
1704
|
+
var STALL_THRESHOLD_MS = 15 * 6e4;
|
|
1664
1705
|
|
|
1665
|
-
export { AnnotationDetection, FsJobQueue, generateResourceFromTopic, isCancelledJob, isCompleteJob, isFailedJob, isPendingJob, isRunningJob, processAssessmentJob, processCommentJob, processGenerationJob, processHighlightJob, processReferenceJob, processTagJob };
|
|
1706
|
+
export { AnnotationDetection, FsJobQueue, STALL_THRESHOLD_MS, generateResourceFromTopic, isCancelledJob, isCompleteJob, isFailedJob, isPendingJob, isRunningJob, processAssessmentJob, processCommentJob, processGenerationJob, processHighlightJob, processReferenceJob, processTagJob };
|
|
1666
1707
|
//# sourceMappingURL=index.js.map
|
|
1667
1708
|
//# sourceMappingURL=index.js.map
|