@exulu/backend 1.66.0 → 1.68.0
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/chunk-VPSLTGZF.js +10267 -0
- package/dist/{convert-exulu-tools-to-ai-sdk-tools-ZFIN7A5V.js → convert-exulu-tools-to-ai-sdk-tools-CHQF36XW.js} +1 -2
- package/dist/index.cjs +23930 -22308
- package/dist/index.d.cts +401 -100
- package/dist/index.d.ts +401 -100
- package/dist/index.js +15215 -4233
- package/ee/agentic-retrieval/v3/agent-loop.ts +4 -4
- package/ee/agentic-retrieval/v3/index.ts +20 -6
- package/ee/python/documents/processing/doc_processor.ts +79 -34
- package/ee/python/requirements.txt +8 -1
- package/ee/python/setup.sh +0 -49
- package/ee/queues/decorator.ts +36 -0
- package/ee/queues/prune-job-results.ts +55 -0
- package/ee/schemas.ts +19 -0
- package/ee/workers.ts +59 -32
- package/package.json +1 -1
- package/dist/chunk-KQDNL5WU.js +0 -19399
- package/ee/agentic-retrieval/v4/agent-loop.ts +0 -208
- package/ee/agentic-retrieval/v4/context-sampler.ts +0 -79
- package/ee/agentic-retrieval/v4/index.ts +0 -690
- package/ee/agentic-retrieval/v4/types.ts +0 -58
- package/ee/python/.hermes/.env.example +0 -8
- package/ee/python/.hermes/README.md +0 -44
- package/ee/python/.hermes/SOUL.md.example +0 -8
- package/ee/python/.hermes/config.yaml.example +0 -55
package/ee/workers.ts
CHANGED
|
@@ -7,12 +7,12 @@ import { ExuluStorage } from "@SRC/exulu/storage.ts";
|
|
|
7
7
|
import type { ExuluAgent } from "@EXULU_TYPES/models/agent.ts";
|
|
8
8
|
import type { ExuluQueueConfig } from "@EXULU_TYPES/queue-config.ts";
|
|
9
9
|
import { getTableName, type ExuluContext } from "@SRC/exulu/context.ts";
|
|
10
|
-
import type { ExuluReranker } from "@SRC/exulu/reranker.ts";
|
|
11
10
|
import type { ExuluEval } from "@SRC/exulu/evals.ts";
|
|
12
11
|
import type { ExuluTool } from "@SRC/exulu/tool.ts";
|
|
13
12
|
import { resolveModel } from "@SRC/exulu/resolve-model.ts";
|
|
14
13
|
import { postgresClient } from "@SRC/postgres/client";
|
|
15
14
|
import type { BullMqJobData } from "@EE/queues/decorator.ts";
|
|
15
|
+
import { maybePruneJobResults } from "@EE/queues/prune-job-results.ts";
|
|
16
16
|
import { type Tracer } from "@opentelemetry/api";
|
|
17
17
|
import { v4 as uuidv4 } from "uuid";
|
|
18
18
|
import { type UIMessage } from "ai";
|
|
@@ -114,7 +114,6 @@ export const createWorkers = async (
|
|
|
114
114
|
queues: ExuluQueueConfig[],
|
|
115
115
|
config: ExuluConfig,
|
|
116
116
|
contexts: ExuluContext[],
|
|
117
|
-
rerankers: ExuluReranker[],
|
|
118
117
|
evals: ExuluEval[],
|
|
119
118
|
tools: ExuluTool[],
|
|
120
119
|
tracer?: Tracer,
|
|
@@ -275,13 +274,7 @@ export const createWorkers = async (
|
|
|
275
274
|
|
|
276
275
|
const label = `embedder-${bullmqJob.name}`;
|
|
277
276
|
|
|
278
|
-
await db
|
|
279
|
-
job_id: bullmqJob.id,
|
|
280
|
-
label: label,
|
|
281
|
-
state: await bullmqJob.getState(),
|
|
282
|
-
result: null,
|
|
283
|
-
metadata: {},
|
|
284
|
-
});
|
|
277
|
+
await upsertJobStart(db, bullmqJob, label, "embedder");
|
|
285
278
|
|
|
286
279
|
const context = contexts.find((context) => context.id === data.context);
|
|
287
280
|
|
|
@@ -289,14 +282,8 @@ export const createWorkers = async (
|
|
|
289
282
|
throw new Error(`Context ${data.context} not found in the registry.`);
|
|
290
283
|
}
|
|
291
284
|
|
|
292
|
-
if (!
|
|
293
|
-
throw new Error(`No embedder
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
const embedder = contexts.find((context) => context.embedder?.id === data.embedder);
|
|
297
|
-
|
|
298
|
-
if (!embedder) {
|
|
299
|
-
throw new Error(`Embedder ${data.embedder} not found in the registry.`);
|
|
285
|
+
if (!context.embedder) {
|
|
286
|
+
throw new Error(`No embedder configured for context ${data.context}.`);
|
|
300
287
|
}
|
|
301
288
|
|
|
302
289
|
const result = await context.createAndUpsertEmbeddings(
|
|
@@ -304,7 +291,7 @@ export const createWorkers = async (
|
|
|
304
291
|
config,
|
|
305
292
|
data.user,
|
|
306
293
|
{
|
|
307
|
-
label: embedder.
|
|
294
|
+
label: context.embedder.model,
|
|
308
295
|
trigger: data.trigger,
|
|
309
296
|
},
|
|
310
297
|
data.role,
|
|
@@ -331,13 +318,7 @@ export const createWorkers = async (
|
|
|
331
318
|
|
|
332
319
|
const label = `processor-${bullmqJob.name}`;
|
|
333
320
|
|
|
334
|
-
await db
|
|
335
|
-
job_id: bullmqJob.id,
|
|
336
|
-
label: label,
|
|
337
|
-
state: await bullmqJob.getState(),
|
|
338
|
-
result: null,
|
|
339
|
-
metadata: {},
|
|
340
|
-
});
|
|
321
|
+
await upsertJobStart(db, bullmqJob, label, "processor");
|
|
341
322
|
|
|
342
323
|
const context = contexts.find((context) => context.id === data.context);
|
|
343
324
|
|
|
@@ -502,6 +483,7 @@ export const createWorkers = async (
|
|
|
502
483
|
agent,
|
|
503
484
|
provider,
|
|
504
485
|
user,
|
|
486
|
+
workflow,
|
|
505
487
|
messages: inputMessages,
|
|
506
488
|
} = await validateWorkflowPayload(data, providers);
|
|
507
489
|
|
|
@@ -530,11 +512,12 @@ export const createWorkers = async (
|
|
|
530
512
|
provider,
|
|
531
513
|
inputMessages,
|
|
532
514
|
contexts,
|
|
533
|
-
rerankers,
|
|
534
515
|
user,
|
|
535
516
|
tools,
|
|
536
517
|
config,
|
|
537
518
|
variables: data.inputs,
|
|
519
|
+
// Tag LLM spend to this routine (cron + ad-hoc share this path).
|
|
520
|
+
routine: { id: workflow.id, name: workflow.name },
|
|
538
521
|
});
|
|
539
522
|
resolve(messages);
|
|
540
523
|
break;
|
|
@@ -631,7 +614,6 @@ export const createWorkers = async (
|
|
|
631
614
|
provider,
|
|
632
615
|
inputMessages,
|
|
633
616
|
contexts,
|
|
634
|
-
rerankers,
|
|
635
617
|
user,
|
|
636
618
|
tools,
|
|
637
619
|
config,
|
|
@@ -1021,6 +1003,9 @@ export const createWorkers = async (
|
|
|
1021
1003
|
result: returnvalue.result != null ? JSON.stringify(returnvalue.result) : null,
|
|
1022
1004
|
metadata: returnvalue.metadata != null ? JSON.stringify(returnvalue.metadata) : null,
|
|
1023
1005
|
});
|
|
1006
|
+
|
|
1007
|
+
// Cap the table as rows become terminal (every Nth, idempotent).
|
|
1008
|
+
void maybePruneJobResults(db);
|
|
1024
1009
|
},
|
|
1025
1010
|
);
|
|
1026
1011
|
|
|
@@ -1034,6 +1019,9 @@ export const createWorkers = async (
|
|
|
1034
1019
|
state: JOB_STATUS_ENUM.failed,
|
|
1035
1020
|
error,
|
|
1036
1021
|
});
|
|
1022
|
+
|
|
1023
|
+
// Cap the table as rows become terminal (every Nth, idempotent).
|
|
1024
|
+
void maybePruneJobResults(db);
|
|
1037
1025
|
return;
|
|
1038
1026
|
}
|
|
1039
1027
|
console.error(
|
|
@@ -1326,22 +1314,29 @@ export const processUiMessagesFlow = async ({
|
|
|
1326
1314
|
provider,
|
|
1327
1315
|
inputMessages,
|
|
1328
1316
|
contexts,
|
|
1329
|
-
rerankers,
|
|
1330
1317
|
user,
|
|
1331
1318
|
tools,
|
|
1332
1319
|
config,
|
|
1333
1320
|
variables,
|
|
1321
|
+
routine,
|
|
1334
1322
|
}: {
|
|
1335
1323
|
providers: ExuluProvider[];
|
|
1336
1324
|
agent: ExuluAgent;
|
|
1337
1325
|
provider: ExuluProvider;
|
|
1338
1326
|
inputMessages: UIMessage[];
|
|
1339
1327
|
contexts: ExuluContext[];
|
|
1340
|
-
rerankers: ExuluReranker[];
|
|
1341
1328
|
user: User;
|
|
1342
1329
|
tools: ExuluTool[];
|
|
1343
1330
|
config: ExuluConfig;
|
|
1344
1331
|
variables?: Record<string, any>;
|
|
1332
|
+
/**
|
|
1333
|
+
* Set when this flow is invoked from a workflow_template run (one-shot via
|
|
1334
|
+
* runWorkflow or cron via upsertWorkflowSchedule). Forwarded to resolveModel
|
|
1335
|
+
* so buildTags() emits routine_id_/routine_name_ alongside user/agent tags
|
|
1336
|
+
* for /analytics + /admin/budgets attribution. /chat and /openai-gateway
|
|
1337
|
+
* callers leave this undefined — they have no routine context.
|
|
1338
|
+
*/
|
|
1339
|
+
routine?: { id: string; name: string };
|
|
1345
1340
|
}): Promise<{
|
|
1346
1341
|
messages: UIMessage[];
|
|
1347
1342
|
metadata: {
|
|
@@ -1369,7 +1364,6 @@ export const processUiMessagesFlow = async ({
|
|
|
1369
1364
|
agent,
|
|
1370
1365
|
tools,
|
|
1371
1366
|
contexts,
|
|
1372
|
-
rerankers,
|
|
1373
1367
|
disabledTools,
|
|
1374
1368
|
providers,
|
|
1375
1369
|
user,
|
|
@@ -1390,7 +1384,8 @@ export const processUiMessagesFlow = async ({
|
|
|
1390
1384
|
modelId: agent.model,
|
|
1391
1385
|
user,
|
|
1392
1386
|
providers,
|
|
1393
|
-
agent: agent
|
|
1387
|
+
agent: agent,
|
|
1388
|
+
routine,
|
|
1394
1389
|
});
|
|
1395
1390
|
const providerapikey = resolved.apiKey;
|
|
1396
1391
|
const resolvedLanguageModel = resolved.languageModel;
|
|
@@ -1487,7 +1482,6 @@ export const processUiMessagesFlow = async ({
|
|
|
1487
1482
|
try {
|
|
1488
1483
|
const result = await provider.generateStream({
|
|
1489
1484
|
contexts,
|
|
1490
|
-
rerankers,
|
|
1491
1485
|
agent: agent,
|
|
1492
1486
|
user,
|
|
1493
1487
|
approvedTools: tools.map((tool) => "tool-" + sanitizeToolName(tool.name)),
|
|
@@ -1632,3 +1626,36 @@ function getAverage(arr: number[]): number {
|
|
|
1632
1626
|
if (arr.length === 0) return 0; // Handle empty array
|
|
1633
1627
|
return arr.reduce((a, b) => a + b, 0) / arr.length;
|
|
1634
1628
|
}
|
|
1629
|
+
|
|
1630
|
+
// KB-7: at worker pickup, advance the enqueue-time job_results row (state
|
|
1631
|
+
// "waiting", written by the queue decorator) to the live state instead of
|
|
1632
|
+
// inserting a duplicate. Falls back to an insert for jobs enqueued before
|
|
1633
|
+
// this change. Used by the processor + embedder handlers; the completed/
|
|
1634
|
+
// failed worker events then drive the same row to its terminal state.
|
|
1635
|
+
async function upsertJobStart(
|
|
1636
|
+
db: any,
|
|
1637
|
+
bullmqJob: { id?: string; data?: any; getState: () => Promise<string> },
|
|
1638
|
+
label: string,
|
|
1639
|
+
fallbackType: string,
|
|
1640
|
+
): Promise<void> {
|
|
1641
|
+
const state = await bullmqJob.getState();
|
|
1642
|
+
const rawItem = bullmqJob.data?.item;
|
|
1643
|
+
const itemId =
|
|
1644
|
+
rawItem == null ? null : typeof rawItem === "object" ? (rawItem.id ?? null) : rawItem;
|
|
1645
|
+
const updated = await db
|
|
1646
|
+
.from("job_results")
|
|
1647
|
+
.where({ job_id: bullmqJob.id })
|
|
1648
|
+
.update({ label, state });
|
|
1649
|
+
if (!updated) {
|
|
1650
|
+
await db.from("job_results").insert({
|
|
1651
|
+
job_id: bullmqJob.id,
|
|
1652
|
+
label,
|
|
1653
|
+
state,
|
|
1654
|
+
result: null,
|
|
1655
|
+
metadata: {},
|
|
1656
|
+
type: bullmqJob.data?.type ?? fallbackType,
|
|
1657
|
+
item: itemId == null ? null : String(itemId),
|
|
1658
|
+
context: bullmqJob.data?.context ? String(bullmqJob.data.context) : null,
|
|
1659
|
+
});
|
|
1660
|
+
}
|
|
1661
|
+
}
|