@hotmeshio/long-tail 0.2.2 → 0.2.3

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.
@@ -148,7 +148,8 @@ class LTCronRegistry {
148
148
  callback: async () => {
149
149
  try {
150
150
  const client = new hotmesh_1.Durable.Client({ connection });
151
- const workflowId = `${workflowType}-cron-${hotmesh_1.Durable.guid()}`;
151
+ const { guid } = hotmesh_1.Virtual.getContext();
152
+ const workflowId = `${workflowType}-cron-${guid}`;
152
153
  logger_1.loggerRegistry.info(`[lt-cron] invoking ${workflowType} (${workflowId})`);
153
154
  await client.workflow.start({
154
155
  args: [defaultEnvelope],
@@ -302,27 +303,8 @@ class LTCronRegistry {
302
303
  const topic = `lt.cron.agent.${agent.id}.${idx}`;
303
304
  const cronId = `lt-cron-agent-${agent.id}-${idx}`;
304
305
  const executeAs = schedule.execute_as || agent.user_id || undefined;
305
- let principal;
306
- if (executeAs) {
307
- try {
308
- principal = await (0, principal_1.resolvePrincipal)(executeAs);
309
- }
310
- catch { /* use system */ }
311
- }
312
- if (!principal) {
313
- principal = this.systemPrincipal ?? undefined;
314
- }
315
- const envelope = {
316
- data: schedule.envelope ?? {},
317
- metadata: { source: 'agent-cron', agentId: agent.id, agentName: agent.name, certified: true },
318
- lt: {
319
- userId: principal?.id ?? 'lt-system',
320
- principal,
321
- scopes: ['workflow:invoke'],
322
- },
323
- };
324
306
  const isPipeline = schedule.reaction_type === 'pipeline' && schedule.pipeline_id;
325
- // Resolve the actual task queue from workflow config (durable only)
307
+ // Resolve task queue at arm time (static — doesn't change between ticks)
326
308
  let taskQueue;
327
309
  if (!isPipeline) {
328
310
  const wfConfig = await configService.getWorkflowConfig(schedule.workflow_type);
@@ -334,6 +316,27 @@ class LTCronRegistry {
334
316
  connection,
335
317
  callback: async () => {
336
318
  try {
319
+ // Resolve principal at fire time so users seeded after startup are found
320
+ let principal;
321
+ if (executeAs) {
322
+ try {
323
+ principal = await (0, principal_1.resolvePrincipal)(executeAs);
324
+ }
325
+ catch { /* use system */ }
326
+ }
327
+ if (!principal) {
328
+ principal = this.systemPrincipal ?? undefined;
329
+ }
330
+ logger_1.loggerRegistry.info(`[lt-cron] agent ${agent.name} principal: ${principal?.id ?? 'NONE'} (executeAs=${executeAs ?? 'unset'})`);
331
+ const envelope = {
332
+ data: schedule.envelope ?? {},
333
+ metadata: { source: 'agent-cron', agentId: agent.id, agentName: agent.name, certified: true },
334
+ lt: {
335
+ userId: principal?.id ?? 'lt-system',
336
+ principal,
337
+ scopes: ['workflow:invoke'],
338
+ },
339
+ };
337
340
  if (isPipeline) {
338
341
  const { invokeYamlWorkflow } = await Promise.resolve().then(() => __importStar(require('../yaml-workflow/invoke')));
339
342
  const { getYamlWorkflow } = await Promise.resolve().then(() => __importStar(require('../yaml-workflow/db')));
@@ -348,7 +351,8 @@ class LTCronRegistry {
348
351
  }
349
352
  else {
350
353
  const client = new hotmesh_1.Durable.Client({ connection });
351
- const workflowId = `agent-cron-${agent.id}-${idx}-${hotmesh_1.Durable.guid()}`;
354
+ const { guid } = hotmesh_1.Virtual.getContext();
355
+ const workflowId = `agent-cron-${agent.id}-${idx}-${guid}`;
352
356
  logger_1.loggerRegistry.info(`[lt-cron] agent invoking ${schedule.workflow_type} on ${taskQueue} (${workflowId})`);
353
357
  await client.workflow.start({
354
358
  args: [envelope],
@@ -362,7 +366,13 @@ class LTCronRegistry {
362
366
  }
363
367
  }
364
368
  catch (err) {
365
- logger_1.loggerRegistry.error(`[lt-cron] agent ${agent.name}/${targetLabel} failed: ${err?.message}`);
369
+ const msg = err?.message ?? '';
370
+ if (msg.includes('Duplicate job')) {
371
+ // Expected — deterministic ID dedup when cron fires multiple consumers
372
+ }
373
+ else {
374
+ logger_1.loggerRegistry.error(`[lt-cron] agent ${agent.name}/${targetLabel} failed: ${msg}`);
375
+ }
366
376
  }
367
377
  },
368
378
  args: [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hotmeshio/long-tail",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Long Tail Workflows — Durable AI workflows with human-in-the-loop escalation. Powered by PostgreSQL.",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -70,7 +70,7 @@
70
70
  "@anthropic-ai/sdk": "^0.92.0",
71
71
  "@aws-sdk/client-s3": "^3.1017.0",
72
72
  "@aws-sdk/s3-request-presigner": "^3.1045.0",
73
- "@hotmeshio/hotmesh": "^0.16.0",
73
+ "@hotmeshio/hotmesh": "^0.16.1",
74
74
  "@modelcontextprotocol/sdk": "^1.27.1",
75
75
  "@opentelemetry/exporter-trace-otlp-proto": "^0.215.0",
76
76
  "@opentelemetry/resources": "^2.5.1",