@semiont/jobs 0.5.27 → 0.5.29
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 +4 -2
- package/dist/index.d.ts +15 -3
- package/dist/index.js +39 -24
- package/dist/index.js.map +1 -1
- package/dist/worker-main.js +101 -50
- package/dist/worker-main.js.map +1 -1
- package/package.json +12 -12
package/dist/worker-main.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { createTomlConfigLoader, didToAgent, baseUrl, STARTUP_FETCH_RETRY, retryWithBackoff, isTransientFetchError, busRequest, resourceId, getPrimaryMediaType, isGenerationJobParams, assembleAnnotation, findClaimSpan, textExtractionOf, reconcileSelector, GENERATABLE_MEDIA_TYPES, locate, createFragmentSelector, getLocaleEnglishName, estimateTokens, chunkText, isObject, isString, deriveViews } from '@semiont/core';
|
|
2
|
-
import {
|
|
1
|
+
import { createTomlConfigLoader, didToAgent, baseUrl, STARTUP_FETCH_RETRY, retryWithBackoff, isTransientFetchError, busRequest, resourceId, getPrimaryMediaType, isGenerationJobParams, capabilitiesOf, assembleAnnotation, findClaimSpan, textExtractionOf, reconcileSelector, GENERATABLE_MEDIA_TYPES, locate, createFragmentSelector, getLocaleEnglishName, estimateTokens, chunkText, isObject, isString, deriveViews } from '@semiont/core';
|
|
2
|
+
import { archivistContentReads, extractPdfTextLayer, EXTRACTORS, calculateChecksum, withinByteBudget, MAX_PDF_BYTES } from '@semiont/content';
|
|
3
3
|
import { withSpan, SpanKind, recordJobOutcome } from '@semiont/observability';
|
|
4
4
|
import { execFileSync } from 'child_process';
|
|
5
5
|
import { existsSync, readFileSync, mkdtempSync, writeFileSync, rmSync } from 'fs';
|
|
6
6
|
import { homedir, hostname, tmpdir } from 'os';
|
|
7
7
|
import { join } from 'path';
|
|
8
8
|
import { generateAnnotationId } from '@semiont/event-sourcing';
|
|
9
|
-
import { InMemorySessionStorage, setStoredSession,
|
|
9
|
+
import { InMemorySessionStorage, setStoredSession, kbGatewayUrl, SemiontClient, SemiontSession } from '@semiont/sdk';
|
|
10
10
|
import { HttpTransport, HttpContentTransport } from '@semiont/http-transport';
|
|
11
11
|
import { createInferenceClient } from '@semiont/inference';
|
|
12
12
|
import { createServer } from 'http';
|
|
@@ -9390,9 +9390,9 @@ async function withTimeout(work, label, onHeartbeat) {
|
|
|
9390
9390
|
if (heartbeat) clearInterval(heartbeat);
|
|
9391
9391
|
}
|
|
9392
9392
|
}
|
|
9393
|
-
function
|
|
9393
|
+
function boundedGenerateWithMetadata(client, prompt, maxTokens, temperature, onHeartbeat) {
|
|
9394
9394
|
return spanned(client, "text", maxTokens, () => withTimeout(
|
|
9395
|
-
client.
|
|
9395
|
+
client.generateTextWithMetadata(prompt, maxTokens, temperature),
|
|
9396
9396
|
`${client.type}:${client.modelId}`,
|
|
9397
9397
|
onHeartbeat
|
|
9398
9398
|
));
|
|
@@ -10175,6 +10175,7 @@ var SEMANTIC_MATCH_CHARS = 240;
|
|
|
10175
10175
|
function idLabel(resourceId, annotationId) {
|
|
10176
10176
|
return `[${resourceId}${annotationId ? `/${annotationId}` : ""}]`;
|
|
10177
10177
|
}
|
|
10178
|
+
var DEFAULT_MAX_TOKENS = 500;
|
|
10178
10179
|
async function generateResourceFromTopic(topic, entityTypes, client, logger2, userPrompt, locale, context, temperature, maxTokens, sourceLanguage, outputMediaType = "text/markdown", task = "resource", structure, cite = false, repair) {
|
|
10179
10180
|
logger2.debug("Generating resource from topic", {
|
|
10180
10181
|
topicPreview: topic.substring(0, 100),
|
|
@@ -10190,7 +10191,7 @@ async function generateResourceFromTopic(topic, entityTypes, client, logger2, us
|
|
|
10190
10191
|
structure
|
|
10191
10192
|
});
|
|
10192
10193
|
const finalTemperature = temperature ?? 0.7;
|
|
10193
|
-
const finalMaxTokens = maxTokens ??
|
|
10194
|
+
const finalMaxTokens = maxTokens ?? DEFAULT_MAX_TOKENS;
|
|
10194
10195
|
const languageInstruction = locale && locale !== "en" ? `
|
|
10195
10196
|
|
|
10196
10197
|
IMPORTANT: Write the entire resource in ${getLanguageName(locale)}.` : "";
|
|
@@ -10217,6 +10218,9 @@ The source resource and embedded context are in ${getLanguageName(sourceLanguage
|
|
|
10217
10218
|
parts.push(`- ${label}: ${bodyItem.value}`);
|
|
10218
10219
|
}
|
|
10219
10220
|
}
|
|
10221
|
+
if (focus.userHint) {
|
|
10222
|
+
parts.push(`- User hint (steers what to generate): ${focus.userHint}`);
|
|
10223
|
+
}
|
|
10220
10224
|
annotationSection = `
|
|
10221
10225
|
|
|
10222
10226
|
Annotation context:
|
|
@@ -10375,16 +10379,16 @@ ${formatRequirements}`;
|
|
|
10375
10379
|
temperature: finalTemperature,
|
|
10376
10380
|
maxTokens: finalMaxTokens
|
|
10377
10381
|
});
|
|
10378
|
-
const response = await
|
|
10379
|
-
logger2.debug("Got response from inference", { responseLength: response.length });
|
|
10380
|
-
const result = parseResponse(response);
|
|
10382
|
+
const response = await boundedGenerateWithMetadata(client, prompt, finalMaxTokens, finalTemperature);
|
|
10383
|
+
logger2.debug("Got response from inference", { responseLength: response.text.length, stopReason: response.stopReason });
|
|
10384
|
+
const result = parseResponse(response.text);
|
|
10381
10385
|
logger2.debug("Parsed response", {
|
|
10382
10386
|
hasTitle: !!result.title,
|
|
10383
10387
|
titleLength: result.title?.length,
|
|
10384
10388
|
hasContent: !!result.content,
|
|
10385
10389
|
contentLength: result.content?.length
|
|
10386
10390
|
});
|
|
10387
|
-
return result;
|
|
10391
|
+
return { ...result, truncated: response.stopReason === "max_tokens" };
|
|
10388
10392
|
}
|
|
10389
10393
|
var PINNED_CREATION_TIMESTAMP = 17e8;
|
|
10390
10394
|
var MAX_COMPILE_REPAIRS = 2;
|
|
@@ -10616,7 +10620,7 @@ async function processHighlightJob(content, inferenceClient, params, buildAnnota
|
|
|
10616
10620
|
onProgress(100, { code: "complete-created", count: annotations.length, kind: "highlight" }, echo);
|
|
10617
10621
|
return {
|
|
10618
10622
|
annotations,
|
|
10619
|
-
result: { highlightsFound: highlights.length, highlightsCreated: annotations.length }
|
|
10623
|
+
result: { kind: "highlight-annotation", highlightsFound: highlights.length, highlightsCreated: annotations.length }
|
|
10620
10624
|
};
|
|
10621
10625
|
}
|
|
10622
10626
|
function detectionEcho(p) {
|
|
@@ -10656,7 +10660,7 @@ async function processCommentJob(content, inferenceClient, params, buildAnnotati
|
|
|
10656
10660
|
onProgress(100, { code: "complete-created", count: annotations.length, kind: "comment" }, echo);
|
|
10657
10661
|
return {
|
|
10658
10662
|
annotations,
|
|
10659
|
-
result: { commentsFound: comments.length, commentsCreated: annotations.length }
|
|
10663
|
+
result: { kind: "comment-annotation", commentsFound: comments.length, commentsCreated: annotations.length }
|
|
10660
10664
|
};
|
|
10661
10665
|
}
|
|
10662
10666
|
async function processAssessmentJob(content, inferenceClient, params, buildAnnotation, onProgress) {
|
|
@@ -10696,7 +10700,7 @@ async function processAssessmentJob(content, inferenceClient, params, buildAnnot
|
|
|
10696
10700
|
onProgress(100, { code: "complete-created", count: annotations.length, kind: "assessment" }, echo);
|
|
10697
10701
|
return {
|
|
10698
10702
|
annotations,
|
|
10699
|
-
result: { assessmentsFound: assessments.length, assessmentsCreated: annotations.length }
|
|
10703
|
+
result: { kind: "assessment-annotation", assessmentsFound: assessments.length, assessmentsCreated: annotations.length }
|
|
10700
10704
|
};
|
|
10701
10705
|
}
|
|
10702
10706
|
async function processReferenceJob(content, inferenceClient, params, buildAnnotation, onProgress, logger2) {
|
|
@@ -10786,7 +10790,7 @@ async function processReferenceJob(content, inferenceClient, params, buildAnnota
|
|
|
10786
10790
|
onProgress(100, { code: "complete-created", count: annotations.length, kind: "reference" }, { requestParams });
|
|
10787
10791
|
return {
|
|
10788
10792
|
annotations,
|
|
10789
|
-
result: { totalFound, totalEmitted: annotations.length, errors }
|
|
10793
|
+
result: { kind: "reference-annotation", totalFound, totalEmitted: annotations.length, errors }
|
|
10790
10794
|
};
|
|
10791
10795
|
}
|
|
10792
10796
|
async function processTagJob(content, inferenceClient, params, buildAnnotation, onProgress) {
|
|
@@ -10843,7 +10847,7 @@ async function processTagJob(content, inferenceClient, params, buildAnnotation,
|
|
|
10843
10847
|
onProgress(100, { code: "complete-created", count: annotations.length, kind: "tag" });
|
|
10844
10848
|
return {
|
|
10845
10849
|
annotations,
|
|
10846
|
-
result: { tagsFound: tags.length, tagsCreated: annotations.length, byCategory }
|
|
10850
|
+
result: { kind: "tag-annotation", tagsFound: tags.length, tagsCreated: annotations.length, byCategory }
|
|
10847
10851
|
};
|
|
10848
10852
|
}
|
|
10849
10853
|
function assertWithinOutputBudget(byteLength) {
|
|
@@ -10890,7 +10894,17 @@ async function processGenerationJob(inferenceClient, params, onProgress, logger2
|
|
|
10890
10894
|
}
|
|
10891
10895
|
let compiled = compileTypst(source);
|
|
10892
10896
|
let repairs = 0;
|
|
10893
|
-
while ("error" in compiled
|
|
10897
|
+
while ("error" in compiled) {
|
|
10898
|
+
if (generated2.truncated) {
|
|
10899
|
+
throw new Error(
|
|
10900
|
+
`Generation stopped at the maxTokens ceiling (${params.maxTokens ?? DEFAULT_MAX_TOKENS} tokens) and the cut-off Typst source does not compile \u2014 repair cannot help; raise maxTokens. Compile error: ${compiled.error}`
|
|
10901
|
+
);
|
|
10902
|
+
}
|
|
10903
|
+
if (repairs >= MAX_COMPILE_REPAIRS) {
|
|
10904
|
+
throw new Error(
|
|
10905
|
+
`Typst compilation failed after ${MAX_COMPILE_REPAIRS} repair attempts: ${compiled.error}`
|
|
10906
|
+
);
|
|
10907
|
+
}
|
|
10894
10908
|
repairs++;
|
|
10895
10909
|
logger2.warn("Typst compile failed \u2014 feeding the error back for repair", {
|
|
10896
10910
|
attempt: repairs,
|
|
@@ -10922,21 +10936,19 @@ async function processGenerationJob(inferenceClient, params, onProgress, logger2
|
|
|
10922
10936
|
}
|
|
10923
10937
|
compiled = compileTypst(source);
|
|
10924
10938
|
}
|
|
10925
|
-
if ("error" in compiled) {
|
|
10926
|
-
throw new Error(
|
|
10927
|
-
`Typst compilation failed after ${MAX_COMPILE_REPAIRS} repair attempts: ${compiled.error}`
|
|
10928
|
-
);
|
|
10929
|
-
}
|
|
10930
10939
|
assertWithinOutputBudget(compiled.pdf.byteLength);
|
|
10931
10940
|
onProgress(95, { code: "creating-resource" });
|
|
10941
|
+
onProgress(100, { code: "complete-generated", truncated: generated2.truncated });
|
|
10932
10942
|
return {
|
|
10933
10943
|
content: compiled.pdf,
|
|
10934
|
-
title
|
|
10944
|
+
title,
|
|
10935
10945
|
format: outputMediaType,
|
|
10936
10946
|
citations: citations2,
|
|
10937
10947
|
result: {
|
|
10948
|
+
kind: "generation",
|
|
10938
10949
|
resourceId: "",
|
|
10939
|
-
resourceName:
|
|
10950
|
+
resourceName: title,
|
|
10951
|
+
truncated: generated2.truncated
|
|
10940
10952
|
}
|
|
10941
10953
|
};
|
|
10942
10954
|
}
|
|
@@ -10967,29 +10979,32 @@ async function processGenerationJob(inferenceClient, params, onProgress, logger2
|
|
|
10967
10979
|
onProgress(95, { code: "creating-resource" });
|
|
10968
10980
|
const artifact = new TextEncoder().encode(content);
|
|
10969
10981
|
assertWithinOutputBudget(artifact.byteLength);
|
|
10982
|
+
onProgress(100, { code: "complete-generated", truncated: generated.truncated });
|
|
10970
10983
|
return {
|
|
10971
10984
|
content: artifact,
|
|
10972
|
-
title
|
|
10985
|
+
title,
|
|
10973
10986
|
format: outputMediaType,
|
|
10974
10987
|
citations,
|
|
10975
10988
|
result: {
|
|
10989
|
+
kind: "generation",
|
|
10976
10990
|
resourceId: "",
|
|
10977
|
-
resourceName:
|
|
10991
|
+
resourceName: title,
|
|
10992
|
+
truncated: generated.truncated
|
|
10978
10993
|
}
|
|
10979
10994
|
};
|
|
10980
10995
|
}
|
|
10981
10996
|
|
|
10982
10997
|
// src/workers/detection/prepare-detection.ts
|
|
10983
|
-
async function prepareDetection(mediaType,
|
|
10998
|
+
async function prepareDetection(mediaType, content, resourceId, userId, generator, store) {
|
|
10984
10999
|
const extractor = EXTRACTORS[textExtractionOf(mediaType)];
|
|
10985
11000
|
if (!extractor) return { declined: "no-extractor" };
|
|
10986
|
-
const { data } = await
|
|
11001
|
+
const { data } = await content.getBinary(resourceId);
|
|
10987
11002
|
const bytes = Buffer.from(data);
|
|
10988
11003
|
const extracted = await extractor.extract(bytes, mediaType, {
|
|
10989
11004
|
key: calculateChecksum(bytes),
|
|
10990
11005
|
store
|
|
10991
11006
|
});
|
|
10992
|
-
if ("declined"
|
|
11007
|
+
if (extracted.kind === "declined") return extracted;
|
|
10993
11008
|
if (!extracted.text.trim()) return { declined: "empty" };
|
|
10994
11009
|
const items = extracted.items;
|
|
10995
11010
|
if (items && items.length > 0) {
|
|
@@ -11099,7 +11114,7 @@ async function handleJobInner(adapter, config, job) {
|
|
|
11099
11114
|
const mediaType = getPrimaryMediaType(descriptor);
|
|
11100
11115
|
const source = await withSpan(
|
|
11101
11116
|
"detection:prepare",
|
|
11102
|
-
() => prepareDetection(mediaType ?? "",
|
|
11117
|
+
() => prepareDetection(mediaType ?? "", config.contentReads, resourceId$1, userId, generator, config.anchoredTextStore),
|
|
11103
11118
|
{ attrs: { "resource.id": resourceId$1, "media.type": mediaType ?? "unknown" } }
|
|
11104
11119
|
);
|
|
11105
11120
|
if ("declined" in source) {
|
|
@@ -11109,6 +11124,7 @@ async function handleJobInner(adapter, config, job) {
|
|
|
11109
11124
|
await emitEvent(session, "job:complete", {
|
|
11110
11125
|
...lifecycleBase,
|
|
11111
11126
|
result: {
|
|
11127
|
+
kind: "declined",
|
|
11112
11128
|
declined: true,
|
|
11113
11129
|
reason: source.declined
|
|
11114
11130
|
}
|
|
@@ -11227,7 +11243,16 @@ async function handleJobInner(adapter, config, job) {
|
|
|
11227
11243
|
);
|
|
11228
11244
|
const genParams = job.params;
|
|
11229
11245
|
const genReferenceId = referenceIdOf(job);
|
|
11230
|
-
const storageUri =
|
|
11246
|
+
const storageUri = job.params.storageUri;
|
|
11247
|
+
const expectedExtension = capabilitiesOf(genResult.format)?.extension;
|
|
11248
|
+
if (expectedExtension && !storageUri.toLowerCase().endsWith(expectedExtension)) {
|
|
11249
|
+
config.logger.warn("Storage URI extension does not match the generated format \u2014 writing it as requested", {
|
|
11250
|
+
jobId,
|
|
11251
|
+
storageUri,
|
|
11252
|
+
format: genResult.format,
|
|
11253
|
+
expectedExtension
|
|
11254
|
+
});
|
|
11255
|
+
}
|
|
11231
11256
|
const { resourceId: newResourceId } = await session.client.yield.resource({
|
|
11232
11257
|
name: genResult.title,
|
|
11233
11258
|
file: Buffer.from(genResult.content),
|
|
@@ -11304,7 +11329,7 @@ async function handleJobInner(adapter, config, job) {
|
|
|
11304
11329
|
}
|
|
11305
11330
|
await emitEvent(session, "job:complete", {
|
|
11306
11331
|
...lifecycleBase,
|
|
11307
|
-
result: { resourceId: newResourceId, resourceName: genResult.title }
|
|
11332
|
+
result: { kind: "generation", resourceId: newResourceId, resourceName: genResult.title, truncated: genResult.result.truncated }
|
|
11308
11333
|
});
|
|
11309
11334
|
adapter.completeJob();
|
|
11310
11335
|
} else {
|
|
@@ -11312,6 +11337,29 @@ async function handleJobInner(adapter, config, job) {
|
|
|
11312
11337
|
}
|
|
11313
11338
|
}
|
|
11314
11339
|
|
|
11340
|
+
// src/anchored-text-over-bus.ts
|
|
11341
|
+
function anchoredTextOverBus(client, logger2) {
|
|
11342
|
+
return {
|
|
11343
|
+
async read(key) {
|
|
11344
|
+
try {
|
|
11345
|
+
return await client.browse.anchoredTextByChecksum(key);
|
|
11346
|
+
} catch (error) {
|
|
11347
|
+
logger2?.debug("Anchored-text consult failed \u2014 treating as miss", {
|
|
11348
|
+
key,
|
|
11349
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
11350
|
+
});
|
|
11351
|
+
return null;
|
|
11352
|
+
}
|
|
11353
|
+
},
|
|
11354
|
+
async write(key) {
|
|
11355
|
+
logger2?.debug("Anchored-text write skipped \u2014 the Smelter is the sole writer", { key });
|
|
11356
|
+
},
|
|
11357
|
+
async list() {
|
|
11358
|
+
return [];
|
|
11359
|
+
}
|
|
11360
|
+
};
|
|
11361
|
+
}
|
|
11362
|
+
|
|
11315
11363
|
// src/worker-runtime.ts
|
|
11316
11364
|
var import_rxjs2 = __toESM(require_cjs());
|
|
11317
11365
|
function buildHealthPayload(workers) {
|
|
@@ -11351,7 +11399,7 @@ function startStallWatchdog(opts) {
|
|
|
11351
11399
|
timer.unref?.();
|
|
11352
11400
|
return { dispose: () => clearInterval(timer) };
|
|
11353
11401
|
}
|
|
11354
|
-
function
|
|
11402
|
+
function parseGatewayUrl(url) {
|
|
11355
11403
|
const parsed = new URL(url);
|
|
11356
11404
|
const protocol = parsed.protocol.replace(":", "") === "https" ? "https" : "http";
|
|
11357
11405
|
const host = parsed.hostname;
|
|
@@ -11359,13 +11407,13 @@ function parseBackendUrl(url) {
|
|
|
11359
11407
|
return { protocol, host, port };
|
|
11360
11408
|
}
|
|
11361
11409
|
async function authenticateAgent(opts) {
|
|
11362
|
-
const {
|
|
11410
|
+
const { gatewayBaseUrl: gatewayBaseUrl2, workerSecret: workerSecret2, provider, model, logger: logger2, retry = STARTUP_FETCH_RETRY } = opts;
|
|
11363
11411
|
if (!workerSecret2) {
|
|
11364
11412
|
throw new Error("SEMIONT_WORKER_SECRET is required to authenticate worker agents");
|
|
11365
11413
|
}
|
|
11366
11414
|
return retryWithBackoff(
|
|
11367
11415
|
async () => {
|
|
11368
|
-
const response = await fetch(`${
|
|
11416
|
+
const response = await fetch(`${gatewayBaseUrl2}/api/tokens/agent`, {
|
|
11369
11417
|
method: "POST",
|
|
11370
11418
|
headers: { "Content-Type": "application/json" },
|
|
11371
11419
|
body: JSON.stringify({ secret: workerSecret2, provider, model })
|
|
@@ -11378,7 +11426,7 @@ async function authenticateAgent(opts) {
|
|
|
11378
11426
|
isTransientFetchError,
|
|
11379
11427
|
retry,
|
|
11380
11428
|
({ attempt, attempts, delayMs, error }) => {
|
|
11381
|
-
logger2?.warn("
|
|
11429
|
+
logger2?.warn("Gateway unreachable, retrying agent authentication", {
|
|
11382
11430
|
agent: `${provider}:${model}`,
|
|
11383
11431
|
attempt,
|
|
11384
11432
|
attempts,
|
|
@@ -11389,11 +11437,11 @@ async function authenticateAgent(opts) {
|
|
|
11389
11437
|
);
|
|
11390
11438
|
}
|
|
11391
11439
|
async function startAgentWorker(opts) {
|
|
11392
|
-
const { group,
|
|
11440
|
+
const { group, gatewayBaseUrl: gatewayBaseUrl2, workerSecret: workerSecret2, contentReads: contentReads2, logger: logger2 } = opts;
|
|
11393
11441
|
const { inference } = group;
|
|
11394
|
-
const { protocol, host, port } =
|
|
11442
|
+
const { protocol, host, port } = parseGatewayUrl(gatewayBaseUrl2);
|
|
11395
11443
|
const { token: initialToken, did } = await authenticateAgent({
|
|
11396
|
-
|
|
11444
|
+
gatewayBaseUrl: gatewayBaseUrl2,
|
|
11397
11445
|
workerSecret: workerSecret2,
|
|
11398
11446
|
provider: inference.type,
|
|
11399
11447
|
model: inference.model,
|
|
@@ -11413,7 +11461,7 @@ async function startAgentWorker(opts) {
|
|
|
11413
11461
|
const token$ = new import_rxjs2.BehaviorSubject(null);
|
|
11414
11462
|
let session;
|
|
11415
11463
|
const transport = new HttpTransport({
|
|
11416
|
-
baseUrl: baseUrl(
|
|
11464
|
+
baseUrl: baseUrl(kbGatewayUrl(endpoint)),
|
|
11417
11465
|
token$,
|
|
11418
11466
|
tokenRefresher: () => session.refresh().then((t) => t ?? null)
|
|
11419
11467
|
});
|
|
@@ -11427,7 +11475,7 @@ async function startAgentWorker(opts) {
|
|
|
11427
11475
|
refresh: async () => {
|
|
11428
11476
|
try {
|
|
11429
11477
|
const { token } = await authenticateAgent({
|
|
11430
|
-
|
|
11478
|
+
gatewayBaseUrl: gatewayBaseUrl2,
|
|
11431
11479
|
workerSecret: workerSecret2,
|
|
11432
11480
|
provider: inference.type,
|
|
11433
11481
|
model: inference.model,
|
|
@@ -11452,10 +11500,12 @@ async function startAgentWorker(opts) {
|
|
|
11452
11500
|
jobTypes: group.jobTypes,
|
|
11453
11501
|
inferenceClient: group.client,
|
|
11454
11502
|
generator,
|
|
11455
|
-
// The extraction seam's cache, over
|
|
11456
|
-
// (
|
|
11457
|
-
//
|
|
11458
|
-
|
|
11503
|
+
// The extraction seam's cache, consulted over the bus and never written
|
|
11504
|
+
// (ANCHORED-TEXT-TO-SMELTER D2): the Smelter owns this store, the
|
|
11505
|
+
// Archivist answers the checksum-addressed read, and a worker that
|
|
11506
|
+
// misses extracts locally and discards.
|
|
11507
|
+
anchoredTextStore: anchoredTextOverBus(client, logger2),
|
|
11508
|
+
contentReads: contentReads2,
|
|
11459
11509
|
logger: logger2
|
|
11460
11510
|
});
|
|
11461
11511
|
logger2.info("Agent ready", {
|
|
@@ -11511,12 +11561,13 @@ function resolveWorker(jobType) {
|
|
|
11511
11561
|
`No inference config for worker '${jobType}' and no workers.default in ~/.semiontconfig.`
|
|
11512
11562
|
);
|
|
11513
11563
|
}
|
|
11514
|
-
var
|
|
11515
|
-
if (!
|
|
11516
|
-
throw new Error("services.
|
|
11564
|
+
var gatewayPublicURL = envConfig.services?.gateway?.publicURL;
|
|
11565
|
+
if (!gatewayPublicURL) {
|
|
11566
|
+
throw new Error("services.gateway.publicURL is required in ~/.semiontconfig");
|
|
11517
11567
|
}
|
|
11518
|
-
var
|
|
11568
|
+
var gatewayBaseUrl = gatewayPublicURL;
|
|
11519
11569
|
var workerSecret = process.env.SEMIONT_WORKER_SECRET ?? "";
|
|
11570
|
+
var contentReads = archivistContentReads(envConfig);
|
|
11520
11571
|
var healthPort = 9090;
|
|
11521
11572
|
var logger = createProcessLogger("worker");
|
|
11522
11573
|
function clientKey(w) {
|
|
@@ -11550,7 +11601,7 @@ async function main() {
|
|
|
11550
11601
|
const { initObservabilityNode } = await import('@semiont/observability/node');
|
|
11551
11602
|
initObservabilityNode({ serviceName: "semiont-worker" });
|
|
11552
11603
|
logger.info("Starting agents", {
|
|
11553
|
-
baseUrl:
|
|
11604
|
+
baseUrl: gatewayBaseUrl,
|
|
11554
11605
|
agents: Array.from(groups.values()).map((g) => ({
|
|
11555
11606
|
provider: g.inference.type,
|
|
11556
11607
|
model: g.inference.model,
|
|
@@ -11559,7 +11610,7 @@ async function main() {
|
|
|
11559
11610
|
});
|
|
11560
11611
|
const workers = await Promise.all(
|
|
11561
11612
|
Array.from(groups.values()).map(
|
|
11562
|
-
(group) => startAgentWorker({ group,
|
|
11613
|
+
(group) => startAgentWorker({ group, gatewayBaseUrl, workerSecret, contentReads, logger })
|
|
11563
11614
|
)
|
|
11564
11615
|
);
|
|
11565
11616
|
const health = createServer((req, res) => {
|