@exaudeus/workrail 3.24.3 → 3.25.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.
Files changed (43) hide show
  1. package/dist/cli/commands/index.d.ts +1 -0
  2. package/dist/cli/commands/index.js +3 -1
  3. package/dist/cli/commands/version.d.ts +6 -0
  4. package/dist/cli/commands/version.js +14 -0
  5. package/dist/cli.js +90 -0
  6. package/dist/console/assets/index-8dh0Psu-.css +1 -0
  7. package/dist/console/assets/{index-TMfptYpQ.js → index-HhtarvD5.js} +10 -10
  8. package/dist/console/index.html +2 -2
  9. package/dist/daemon/pi-mono-loader.d.ts +5 -0
  10. package/dist/daemon/pi-mono-loader.js +65 -0
  11. package/dist/daemon/workflow-runner.d.ts +41 -0
  12. package/dist/daemon/workflow-runner.js +573 -0
  13. package/dist/infrastructure/session/HttpServer.js +2 -2
  14. package/dist/manifest.json +112 -32
  15. package/dist/mcp/handlers/v2-execution/start.d.ts +2 -1
  16. package/dist/mcp/handlers/v2-execution/start.js +4 -3
  17. package/dist/mcp/server.js +1 -1
  18. package/dist/mcp/transports/http-entry.js +1 -1
  19. package/dist/trigger/index.d.ts +5 -0
  20. package/dist/trigger/index.js +8 -0
  21. package/dist/trigger/trigger-listener.d.ts +30 -0
  22. package/dist/trigger/trigger-listener.js +166 -0
  23. package/dist/trigger/trigger-router.d.ts +32 -0
  24. package/dist/trigger/trigger-router.js +185 -0
  25. package/dist/trigger/trigger-store.d.ts +31 -0
  26. package/dist/trigger/trigger-store.js +457 -0
  27. package/dist/trigger/types.d.ts +46 -0
  28. package/dist/trigger/types.js +6 -0
  29. package/dist/v2/infra/in-memory/daemon-registry/index.d.ts +14 -0
  30. package/dist/v2/infra/in-memory/daemon-registry/index.js +32 -0
  31. package/dist/v2/infra/in-memory/keyed-async-queue/index.d.ts +5 -0
  32. package/dist/v2/infra/in-memory/keyed-async-queue/index.js +32 -0
  33. package/dist/v2/usecases/console-routes.d.ts +3 -1
  34. package/dist/v2/usecases/console-routes.js +102 -1
  35. package/dist/v2/usecases/console-service.d.ts +2 -0
  36. package/dist/v2/usecases/console-service.js +18 -2
  37. package/dist/v2/usecases/console-types.d.ts +2 -0
  38. package/package.json +5 -3
  39. package/workflows/coding-task-workflow-agentic.lean.v2.json +1 -1
  40. package/workflows/workflow-for-workflows.json +4 -2
  41. package/workflows/workflow-for-workflows.v2.json +4 -2
  42. package/dist/console/assets/index-BXRk3te_.css +0 -1
  43. package/workflows/rich-object-contribution.json +0 -258
@@ -238,8 +238,8 @@
238
238
  "bytes": 31
239
239
  },
240
240
  "cli.js": {
241
- "sha256": "4fa91d141cb398a7ba46ea2dadbf47bb2fba3cd30425137e740ae4f4dea6c353",
242
- "bytes": 8027
241
+ "sha256": "aaaa221e1e23720c0c62f3ac2a17308fb30c3355bfc752f277171605ab8dd91c",
242
+ "bytes": 11866
243
243
  },
244
244
  "cli/commands/cleanup.d.ts": {
245
245
  "sha256": "efe1f9e2ecd58e92007ed38b9581a3852c2babe4b3f2a97237dccd878eebe7ec",
@@ -250,12 +250,12 @@
250
250
  "bytes": 745
251
251
  },
252
252
  "cli/commands/index.d.ts": {
253
- "sha256": "d9060f00f6f9431c2dae86e1b9cce72b332a8207a4e697e0188f2528db682e37",
254
- "bytes": 856
253
+ "sha256": "a5045789481f435d99e8e0eda80f37d9190a787ae50817a2b1dd45c500706869",
254
+ "bytes": 935
255
255
  },
256
256
  "cli/commands/index.js": {
257
- "sha256": "a6786e4f60ed6729a14b84f69df4afbf6cff3f09d7a03bc8738e1b2fa7550a82",
258
- "bytes": 2436
257
+ "sha256": "db2f4d050324decbb425a3b5917d647b991544d6d971a29ca9657f8750ea70d5",
258
+ "bytes": 2656
259
259
  },
260
260
  "cli/commands/init.d.ts": {
261
261
  "sha256": "b5f8b88a072c68509dab3938ba1d6b4a949ad32f8fc55e91c5039b8c77301c1b",
@@ -305,6 +305,14 @@
305
305
  "sha256": "abfe2dede282853df7242b52e52f96364e692b6e65707ca0db581668708c9b09",
306
306
  "bytes": 3481
307
307
  },
308
+ "cli/commands/version.d.ts": {
309
+ "sha256": "b1dfb758b202ea230bc35688794a08edad78001eec0e7088a01d1b6b921bb34b",
310
+ "bytes": 267
311
+ },
312
+ "cli/commands/version.js": {
313
+ "sha256": "bd6ca78870fdafe5ce36b41404c49ad15b60092f117c9f74cb8156f2bed0445c",
314
+ "bytes": 538
315
+ },
308
316
  "cli/interpret-result.d.ts": {
309
317
  "sha256": "255f04350df9c8cf8d5e65ed2fc11d41fa60a7b5ccc818e7728b1c081340a66a",
310
318
  "bytes": 315
@@ -369,16 +377,16 @@
369
377
  "sha256": "5fe866e54f796975dec5d8ba9983aefd86074db212d3fccd64eed04bc9f0b3da",
370
378
  "bytes": 8011
371
379
  },
372
- "console/assets/index-BXRk3te_.css": {
373
- "sha256": "2151b10aedd5da99f5bac5cdb54c4cb73894b9069eab0fb859db50b9aa71fba2",
374
- "bytes": 59906
380
+ "console/assets/index-8dh0Psu-.css": {
381
+ "sha256": "cf9d09641f1c31fffe6c7835b30bbbad52572befec1acab7fb9a0c188431af36",
382
+ "bytes": 60355
375
383
  },
376
- "console/assets/index-TMfptYpQ.js": {
377
- "sha256": "475c71c4cca93f8ed30139569638b9ec272b43eb44feccb4ce08c6f7e2064dc7",
378
- "bytes": 744551
384
+ "console/assets/index-HhtarvD5.js": {
385
+ "sha256": "08f261e8ee93433485c04dfceb497517787ffa0c9e871415a7a0aca5d05fe731",
386
+ "bytes": 754653
379
387
  },
380
388
  "console/index.html": {
381
- "sha256": "1ff870763f5df29998d56597a3b138e07e23b8fb054c93f6ce9f7f5ae4a0c9a5",
389
+ "sha256": "c9d211c6ed52bc75fb22ae55d4e9bb349f22dcde4a03911603749fb0a68facdf",
382
390
  "bytes": 417
383
391
  },
384
392
  "core/error-handler.d.ts": {
@@ -389,6 +397,22 @@
389
397
  "sha256": "a3c7ee47d37f111561e2b73f7487670bb4dc894d45931a0745c26fe5acd8c759",
390
398
  "bytes": 3493
391
399
  },
400
+ "daemon/pi-mono-loader.d.ts": {
401
+ "sha256": "e04d7244df5eb05522e7da115376b543cdd8a7a31a9deab511718b0ffb6b31f0",
402
+ "bytes": 331
403
+ },
404
+ "daemon/pi-mono-loader.js": {
405
+ "sha256": "d15e69b30ab83280471be3b8cd478aaf15b38b8545e47de3e2ceb793def5ba0d",
406
+ "bytes": 2635
407
+ },
408
+ "daemon/workflow-runner.d.ts": {
409
+ "sha256": "e33759a1e9063d178f2c0a1775b4da316bbbaa94a5ce3aa38aa45d0997bfb8de",
410
+ "bytes": 2101
411
+ },
412
+ "daemon/workflow-runner.js": {
413
+ "sha256": "f44cd08bbed6cb9e3596fcf4216d3020dc4ece29625e79ce0d2f54586018910c",
414
+ "bytes": 24092
415
+ },
392
416
  "di/container.d.ts": {
393
417
  "sha256": "003bb7fb7478d627524b9b1e76bd0a963a243794a687ff233b96dc0e33a06d9f",
394
418
  "bytes": 620
@@ -546,8 +570,8 @@
546
570
  "bytes": 2025
547
571
  },
548
572
  "infrastructure/session/HttpServer.js": {
549
- "sha256": "5d526849ef6e97e5341df73fb9b9789a4bfa7e132f2751b9892f3cbfe09aa2c9",
550
- "bytes": 31215
573
+ "sha256": "cb3c733c5dfd4e998e0170d60e1689390454afdeb9c8a5838fd9af3a9da2fa56",
574
+ "bytes": 31241
551
575
  },
552
576
  "infrastructure/session/SessionDataNormalizer.d.ts": {
553
577
  "sha256": "c89bb5e00d7d01fb4aa6d0095602541de53c425c6b99b67fa8367eb29cb63e9e",
@@ -918,12 +942,12 @@
918
942
  "bytes": 11397
919
943
  },
920
944
  "mcp/handlers/v2-execution/start.d.ts": {
921
- "sha256": "2deb05345e125667576ede3bb20756a1b22ec86f18028d242b5d9b54dd25afaf",
922
- "bytes": 3405
945
+ "sha256": "3d93d6119b89d6cabf8bebbaafd24d8de53d84dd671440d221dda5a238ba4fc4",
946
+ "bytes": 3519
923
947
  },
924
948
  "mcp/handlers/v2-execution/start.js": {
925
- "sha256": "68e95c6414807f6e069961b176f7ddc220c1fe248433b8d6d2a929f102532fb4",
926
- "bytes": 21109
949
+ "sha256": "f57771c4baa31204fc683615802a02c4c9cf65e8727426210fc656d173e9fe51",
950
+ "bytes": 21208
927
951
  },
928
952
  "mcp/handlers/v2-execution/workflow-object-cache.d.ts": {
929
953
  "sha256": "7e58a2a020fd8443821dbe4e6a2702a9882c517f032a340c1b393cdebf4af907",
@@ -1034,8 +1058,8 @@
1034
1058
  "bytes": 960
1035
1059
  },
1036
1060
  "mcp/server.js": {
1037
- "sha256": "a54d39ce8d7282abe16d140abbe1011e67cd3f9d9353f40727c44c1c212a90c2",
1038
- "bytes": 16152
1061
+ "sha256": "b60d150f98355033ef172a58e7c2b12f01848f0bbb4a2b633276791ffce96637",
1062
+ "bytes": 16178
1039
1063
  },
1040
1064
  "mcp/step-content-envelope.d.ts": {
1041
1065
  "sha256": "19bd63c4d4de1d5d93393d346625d28ffd1bebdc320d4ba4e694cb740ec97d3b",
@@ -1098,7 +1122,7 @@
1098
1122
  "bytes": 70
1099
1123
  },
1100
1124
  "mcp/transports/http-entry.js": {
1101
- "sha256": "fdebcd58e111f3051081003599e8608fa1becf20abf97a666a957f8048c95334",
1125
+ "sha256": "29de54000abc8c0f5aae334c1866bf4ac4198ba29e8ce5a3f0e61a7f0128eb40",
1102
1126
  "bytes": 3314
1103
1127
  },
1104
1128
  "mcp/transports/http-listener.d.ts": {
@@ -1389,6 +1413,46 @@
1389
1413
  "sha256": "d43aa81f5bc89faa359e0f97c814ba25155591ff078fbb9bfd40f8c7c9683230",
1390
1414
  "bytes": 77
1391
1415
  },
1416
+ "trigger/index.d.ts": {
1417
+ "sha256": "ac0df6f84ff1ca493f28870b4303e5d68c3bfb2e8109678a10c1cfe11c28c802",
1418
+ "bytes": 471
1419
+ },
1420
+ "trigger/index.js": {
1421
+ "sha256": "c4bfc4c4e9845fb5570badbdfbf133919b71aa513f1ad8fdbe51682450b03359",
1422
+ "bytes": 749
1423
+ },
1424
+ "trigger/trigger-listener.d.ts": {
1425
+ "sha256": "dc0f1d359ef4f6052c360ba2f6464388e526c6b566a0a627517c9a39ae160b21",
1426
+ "bytes": 1137
1427
+ },
1428
+ "trigger/trigger-listener.js": {
1429
+ "sha256": "92579deef666a588d19167e96b881410dd1cb7c791c3682c149f7bd040001043",
1430
+ "bytes": 7034
1431
+ },
1432
+ "trigger/trigger-router.d.ts": {
1433
+ "sha256": "bb7d7c369bc4c3c7018fd7a272b04522937c6aad575aa3198f3002cf69edea89",
1434
+ "bytes": 1304
1435
+ },
1436
+ "trigger/trigger-router.js": {
1437
+ "sha256": "f277e81e4512617dce597105ec34bab5ce0c809d877eaa772eb5c2df3b766689",
1438
+ "bytes": 7457
1439
+ },
1440
+ "trigger/trigger-store.d.ts": {
1441
+ "sha256": "7ce8f2fe7cc80b1b15568dabd3e508acd9ee4a2fbf4bcb2810f44f5a6927f266",
1442
+ "bytes": 1232
1443
+ },
1444
+ "trigger/trigger-store.js": {
1445
+ "sha256": "a35fd740f08804b6057f946d507cdc8d7c3f7d8aaf7e21f12a9940680e6297e0",
1446
+ "bytes": 18505
1447
+ },
1448
+ "trigger/types.d.ts": {
1449
+ "sha256": "b087d72c41e3292882fee49bc3a0048e7e790e4113f609b27f3ca498f8773a98",
1450
+ "bytes": 1433
1451
+ },
1452
+ "trigger/types.js": {
1453
+ "sha256": "c2f56c08d47a76344a5acce16fdfec723da9302232480dcf200a462ad7859f4f",
1454
+ "bytes": 162
1455
+ },
1392
1456
  "types/server.d.ts": {
1393
1457
  "sha256": "2a6e466b41f7263563cddddd3aaffcd786925dfd878bde3871d5681167eac5d8",
1394
1458
  "bytes": 97
@@ -2157,6 +2221,22 @@
2157
2221
  "sha256": "15a8f8b7dac5ab4449f389c75ce7c13a163f639ade481c3890a7f527d23f500d",
2158
2222
  "bytes": 3441
2159
2223
  },
2224
+ "v2/infra/in-memory/daemon-registry/index.d.ts": {
2225
+ "sha256": "874c4ce17fa901640737fce7cdb70eb288d1ab3620c1d9615cdddb5afd27c208",
2226
+ "bytes": 521
2227
+ },
2228
+ "v2/infra/in-memory/daemon-registry/index.js": {
2229
+ "sha256": "f79b1593176dc042afa8fc621698f529be478084891bb1c45b9b76fae3d8c761",
2230
+ "bytes": 910
2231
+ },
2232
+ "v2/infra/in-memory/keyed-async-queue/index.d.ts": {
2233
+ "sha256": "1a5c59ec29f35532b34579ea3d03817b7cda369807a0a0e48a15a30ee72d13c4",
2234
+ "bytes": 167
2235
+ },
2236
+ "v2/infra/in-memory/keyed-async-queue/index.js": {
2237
+ "sha256": "831885209d746693488c7331db137edd5c9a43a012ef3d87dfcea850ebf97426",
2238
+ "bytes": 863
2239
+ },
2160
2240
  "v2/infra/in-memory/managed-source-store/index.d.ts": {
2161
2241
  "sha256": "fe06e50f66f9b542704884e0a4dd491e0380270ee41c52feb1217d327c37604e",
2162
2242
  "bytes": 544
@@ -2662,24 +2742,24 @@
2662
2742
  "bytes": 4795
2663
2743
  },
2664
2744
  "v2/usecases/console-routes.d.ts": {
2665
- "sha256": "1afd41269475fecd4a27ac1c5faccf1e369ec8bd8c9a9c36d38ed92c79e4ec51",
2666
- "bytes": 508
2745
+ "sha256": "41cfffc165d2f98327b78ca86c92d69269cc399f6239ee394377af538ace4df1",
2746
+ "bytes": 697
2667
2747
  },
2668
2748
  "v2/usecases/console-routes.js": {
2669
- "sha256": "315a10a46cacd8bf279ecdc72b2cfac912f6d6ab5f606419d16fd734c9406718",
2670
- "bytes": 15503
2749
+ "sha256": "33426b2538cc35f1380531f2be4a6b8078349c8ec3e5473c39b4af5e8557ec39",
2750
+ "bytes": 20254
2671
2751
  },
2672
2752
  "v2/usecases/console-service.d.ts": {
2673
- "sha256": "489a44091dc1b15ff938a60f9cf3ac28363614b9f0446286f0914157528c7eb3",
2674
- "bytes": 1572
2753
+ "sha256": "fc8fe65427fa9f4f3535344b385b36f66ca06b7e3bfaea708931817a3edcad2b",
2754
+ "bytes": 1701
2675
2755
  },
2676
2756
  "v2/usecases/console-service.js": {
2677
- "sha256": "99f25ac6595cddccb6941c99e9773b075c665eed8b820303efd41a1da1d95e05",
2678
- "bytes": 30332
2757
+ "sha256": "bb394fbad8dd703896aa1593f87487d742a090016e4debe9c8527b984ccd6a1d",
2758
+ "bytes": 31112
2679
2759
  },
2680
2760
  "v2/usecases/console-types.d.ts": {
2681
- "sha256": "9f1060c1689eb1fa6e23e6fbba00ad406c1956e196110c8eab7f95e8ceae81c9",
2682
- "bytes": 7386
2761
+ "sha256": "a7b7ecd30ef7532f6b71aa1280c1bc150225d0558b89a19858a9b760ff834d8a",
2762
+ "bytes": 7452
2683
2763
  },
2684
2764
  "v2/usecases/console-types.js": {
2685
2765
  "sha256": "d43aa81f5bc89faa359e0f97c814ba25155591ff078fbb9bfd40f8c7c9683230",
@@ -45,6 +45,7 @@ export declare function buildInitialEvents(args: {
45
45
  readonly mintEventId: () => string;
46
46
  };
47
47
  readonly goal: string;
48
+ readonly extraContext?: Readonly<Record<string, string>>;
48
49
  }): readonly DomainEventV1[];
49
50
  export declare function mintStartTokens(args: {
50
51
  readonly sessionId: SessionId;
@@ -59,4 +60,4 @@ export declare function mintStartTokens(args: {
59
60
  readonly continueToken: string;
60
61
  readonly checkpointToken: string;
61
62
  }, StartWorkflowError>;
62
- export declare function executeStartWorkflow(input: import('../../v2/tools.js').V2StartWorkflowInput, ctx: V2ToolContext): RA<StartWorkflowResult, StartWorkflowError>;
63
+ export declare function executeStartWorkflow(input: import('../../v2/tools.js').V2StartWorkflowInput, ctx: V2ToolContext, internalContext?: Readonly<Record<string, string>>): RA<StartWorkflowResult, StartWorkflowError>;
@@ -109,7 +109,7 @@ function loadAndPinWorkflow(args) {
109
109
  });
110
110
  }
111
111
  function buildInitialEvents(args) {
112
- const { sessionId, runId, nodeId, workflowId, workflowHash, workflowSourceKind, workflowSourceRef, snapshotRef, observations, idFactory, goal, } = args;
112
+ const { sessionId, runId, nodeId, workflowId, workflowHash, workflowSourceKind, workflowSourceRef, snapshotRef, observations, idFactory, goal, extraContext, } = args;
113
113
  const evtSessionCreated = idFactory.mintEventId();
114
114
  const evtRunStarted = idFactory.mintEventId();
115
115
  const evtNodeCreated = idFactory.mintEventId();
@@ -191,7 +191,7 @@ function buildInitialEvents(args) {
191
191
  scope: { runId: String(runId) },
192
192
  data: {
193
193
  contextId,
194
- context: { goal },
194
+ context: { ...extraContext, goal },
195
195
  source: 'initial',
196
196
  },
197
197
  });
@@ -229,7 +229,7 @@ function mintStartTokens(args) {
229
229
  cause: failure,
230
230
  }));
231
231
  }
232
- function executeStartWorkflow(input, ctx) {
232
+ function executeStartWorkflow(input, ctx, internalContext) {
233
233
  const { gate, sessionStore, snapshotStore, pinnedStore, crypto, tokenCodecPorts, idFactory, validationPipelineDeps, tokenAliasStore, entropy } = ctx.v2;
234
234
  const shouldUseRequestReader = ctx.featureFlags != null && (0, request_workflow_reader_js_1.hasRequestWorkspaceSignal)({
235
235
  workspacePath: input.workspacePath,
@@ -313,6 +313,7 @@ function executeStartWorkflow(input, ctx) {
313
313
  observations,
314
314
  idFactory,
315
315
  goal: input.goal,
316
+ extraContext: internalContext,
316
317
  });
317
318
  const emptyTruth = { manifest: [], events: [] };
318
319
  return gate.withHealthySessionLock(sessionId, (lock) => sessionStore.append(lock, {
@@ -188,7 +188,7 @@ async function composeServer() {
188
188
  snapshotStore: ctx.v2.snapshotStore,
189
189
  pinnedWorkflowStore: ctx.v2.pinnedStore,
190
190
  });
191
- ctx.httpServer.mountRoutes((app) => mountConsoleRoutes(app, consoleService, ctx.workflowService, timingRingBuffer, toolCallsPerfFile ?? undefined, serverVersion));
191
+ ctx.httpServer.mountRoutes((app) => mountConsoleRoutes(app, consoleService, ctx.workflowService, timingRingBuffer, toolCallsPerfFile ?? undefined, serverVersion, ctx.v2 ? ctx : undefined));
192
192
  console.error('[Console] v2 Console API routes mounted at /api/v2/');
193
193
  }
194
194
  ctx.httpServer?.finalize();
@@ -56,10 +56,10 @@ async function startHttpServer(port) {
56
56
  listener.app.post('/mcp', (req, res) => transport.handleRequest(req, res, req.body));
57
57
  listener.app.get('/mcp', (req, res) => transport.handleRequest(req, res));
58
58
  listener.app.delete('/mcp', (req, res) => transport.handleRequest(req, res));
59
+ await server.connect(transport);
59
60
  listener.app.get('/workrail-health', (_req, res) => {
60
61
  res.json({ service: 'workrail' });
61
62
  });
62
- await server.connect(transport);
63
63
  const boundPort = listener.getBoundPort();
64
64
  console.error('[Transport] WorkRail MCP Server running on HTTP');
65
65
  console.error(`[Transport] MCP endpoint: http://localhost:${boundPort}/mcp`);
@@ -0,0 +1,5 @@
1
+ export { startTriggerListener } from './trigger-listener.js';
2
+ export type { TriggerListenerHandle, TriggerListenerError, StartTriggerListenerOptions } from './trigger-listener.js';
3
+ export { loadTriggerConfig, loadTriggerConfigFromFile } from './trigger-store.js';
4
+ export type { TriggerStoreError } from './trigger-store.js';
5
+ export type { TriggerId, TriggerDefinition, TriggerConfig, TriggerSource, WebhookEvent, ContextMapping, ContextMappingEntry, } from './types.js';
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadTriggerConfigFromFile = exports.loadTriggerConfig = exports.startTriggerListener = void 0;
4
+ var trigger_listener_js_1 = require("./trigger-listener.js");
5
+ Object.defineProperty(exports, "startTriggerListener", { enumerable: true, get: function () { return trigger_listener_js_1.startTriggerListener; } });
6
+ var trigger_store_js_1 = require("./trigger-store.js");
7
+ Object.defineProperty(exports, "loadTriggerConfig", { enumerable: true, get: function () { return trigger_store_js_1.loadTriggerConfig; } });
8
+ Object.defineProperty(exports, "loadTriggerConfigFromFile", { enumerable: true, get: function () { return trigger_store_js_1.loadTriggerConfigFromFile; } });
@@ -0,0 +1,30 @@
1
+ import 'reflect-metadata';
2
+ import express from 'express';
3
+ import type { V2ToolContext } from '../mcp/types.js';
4
+ import type { TriggerStoreError } from './trigger-store.js';
5
+ import { TriggerRouter, type RunWorkflowFn } from './trigger-router.js';
6
+ export type TriggerListenerError = TriggerStoreError | {
7
+ readonly kind: 'port_conflict';
8
+ readonly port: number;
9
+ } | {
10
+ readonly kind: 'feature_disabled';
11
+ } | {
12
+ readonly kind: 'missing_api_key';
13
+ };
14
+ export interface TriggerListenerHandle {
15
+ readonly port: number;
16
+ readonly router: TriggerRouter;
17
+ stop(): Promise<void>;
18
+ }
19
+ export interface StartTriggerListenerOptions {
20
+ readonly workspacePath: string;
21
+ readonly apiKey?: string;
22
+ readonly port?: number;
23
+ readonly env?: Record<string, string | undefined>;
24
+ readonly runWorkflowFn?: RunWorkflowFn;
25
+ }
26
+ export declare function createTriggerApp(router: TriggerRouter): express.Application;
27
+ export declare function startTriggerListener(ctx: V2ToolContext, options: StartTriggerListenerOptions): Promise<TriggerListenerHandle | null | {
28
+ readonly _kind: 'err';
29
+ readonly error: TriggerListenerError;
30
+ }>;
@@ -0,0 +1,166 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.createTriggerApp = createTriggerApp;
40
+ exports.startTriggerListener = startTriggerListener;
41
+ require("reflect-metadata");
42
+ const express_1 = __importDefault(require("express"));
43
+ const http = __importStar(require("node:http"));
44
+ const trigger_store_js_1 = require("./trigger-store.js");
45
+ const trigger_router_js_1 = require("./trigger-router.js");
46
+ const workflow_runner_js_1 = require("../daemon/workflow-runner.js");
47
+ const types_js_1 = require("./types.js");
48
+ const DEFAULT_TRIGGER_PORT = 3200;
49
+ function createTriggerApp(router) {
50
+ const app = (0, express_1.default)();
51
+ app.use('/webhook', express_1.default.raw({ type: 'application/json', limit: '1mb' }));
52
+ app.get('/health', (_req, res) => {
53
+ res.status(200).json({ status: 'ok' });
54
+ });
55
+ app.post('/webhook/:triggerId', (req, res) => {
56
+ const triggerId = (0, types_js_1.asTriggerId)(req.params['triggerId'] ?? '');
57
+ if (!triggerId) {
58
+ res.status(400).json({ error: 'Missing triggerId' });
59
+ return;
60
+ }
61
+ const rawBody = Buffer.isBuffer(req.body) ? req.body : Buffer.from('');
62
+ let payload;
63
+ try {
64
+ const bodyStr = rawBody.toString('utf8');
65
+ if (bodyStr) {
66
+ payload = JSON.parse(bodyStr);
67
+ if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) {
68
+ res.status(400).json({ error: 'Payload must be a JSON object' });
69
+ return;
70
+ }
71
+ }
72
+ else {
73
+ payload = {};
74
+ }
75
+ }
76
+ catch {
77
+ res.status(400).json({ error: 'Invalid JSON body' });
78
+ return;
79
+ }
80
+ const signature = req.headers['x-workrail-signature'];
81
+ const event = {
82
+ triggerId,
83
+ rawBody,
84
+ payload,
85
+ ...(signature !== undefined ? { signature } : {}),
86
+ };
87
+ const result = router.route(event);
88
+ if (result._tag === 'error') {
89
+ switch (result.error.kind) {
90
+ case 'not_found':
91
+ res.status(404).json({ error: `Unknown trigger: ${result.error.triggerId}` });
92
+ return;
93
+ case 'hmac_invalid':
94
+ res.status(401).json({ error: 'Invalid signature' });
95
+ return;
96
+ case 'payload_error':
97
+ res.status(400).json({ error: result.error.message });
98
+ return;
99
+ }
100
+ }
101
+ res.status(202).json({ status: 'accepted', triggerId });
102
+ });
103
+ return app;
104
+ }
105
+ async function startTriggerListener(ctx, options) {
106
+ const env = options.env ?? process.env;
107
+ if (env['WORKRAIL_TRIGGERS_ENABLED'] !== 'true') {
108
+ return null;
109
+ }
110
+ const apiKey = options.apiKey ?? env['ANTHROPIC_API_KEY'];
111
+ if (!apiKey) {
112
+ return { _kind: 'err', error: { kind: 'missing_api_key' } };
113
+ }
114
+ const configResult = await (0, trigger_store_js_1.loadTriggerConfigFromFile)(options.workspacePath, env);
115
+ let triggerIndex;
116
+ if (configResult.kind === 'err') {
117
+ if (configResult.error.kind === 'file_not_found') {
118
+ console.warn(`[TriggerListener] triggers.yml not found at ${options.workspacePath}. ` +
119
+ `Listener will start with 0 triggers. ` +
120
+ `Create triggers.yml in that directory to configure triggers.`);
121
+ triggerIndex = new Map();
122
+ }
123
+ else {
124
+ return { _kind: 'err', error: configResult.error };
125
+ }
126
+ }
127
+ else {
128
+ const indexResult = (0, trigger_store_js_1.buildTriggerIndex)(configResult.value);
129
+ if (indexResult.kind === 'err') {
130
+ return { _kind: 'err', error: indexResult.error };
131
+ }
132
+ triggerIndex = indexResult.value;
133
+ console.log(`[TriggerListener] Loaded ${configResult.value.triggers.length} trigger(s) from triggers.yml`);
134
+ }
135
+ const runWorkflowFn = options.runWorkflowFn ?? workflow_runner_js_1.runWorkflow;
136
+ const router = new trigger_router_js_1.TriggerRouter(triggerIndex, ctx, apiKey, runWorkflowFn);
137
+ const app = createTriggerApp(router);
138
+ await (0, workflow_runner_js_1.runStartupRecovery)().catch((err) => {
139
+ console.warn('[TriggerListener] Startup recovery encountered an unexpected error:', err instanceof Error ? err.message : String(err));
140
+ });
141
+ const portEnv = env['WORKRAIL_TRIGGER_PORT'];
142
+ const port = options.port ?? (portEnv ? parseInt(portEnv, 10) : DEFAULT_TRIGGER_PORT);
143
+ return new Promise((resolve) => {
144
+ const server = http.createServer(app);
145
+ server.on('error', (error) => {
146
+ if (error.code === 'EADDRINUSE') {
147
+ resolve({ _kind: 'err', error: { kind: 'port_conflict', port } });
148
+ }
149
+ else {
150
+ resolve({ _kind: 'err', error: { kind: 'io_error', message: error.message } });
151
+ }
152
+ });
153
+ server.listen(port, '127.0.0.1', () => {
154
+ const addr = server.address();
155
+ const actualPort = (addr && typeof addr === 'object') ? addr.port : port;
156
+ console.log(`[TriggerListener] Webhook server listening on port ${actualPort}`);
157
+ resolve({
158
+ port: actualPort,
159
+ router,
160
+ stop: () => new Promise((res, rej) => {
161
+ server.close((e) => (e ? rej(e) : res()));
162
+ }),
163
+ });
164
+ });
165
+ });
166
+ }
@@ -0,0 +1,32 @@
1
+ import type { WorkflowTrigger, WorkflowRunResult } from '../daemon/workflow-runner.js';
2
+ import type { V2ToolContext } from '../mcp/types.js';
3
+ import type { TriggerDefinition, WebhookEvent } from './types.js';
4
+ export type RouteError = {
5
+ readonly kind: 'not_found';
6
+ readonly triggerId: string;
7
+ } | {
8
+ readonly kind: 'hmac_invalid';
9
+ } | {
10
+ readonly kind: 'payload_error';
11
+ readonly message: string;
12
+ };
13
+ export type RouteResult = {
14
+ readonly _tag: 'enqueued';
15
+ readonly triggerId: string;
16
+ } | {
17
+ readonly _tag: 'error';
18
+ readonly error: RouteError;
19
+ };
20
+ export type RunWorkflowFn = (trigger: WorkflowTrigger, ctx: V2ToolContext, apiKey: string) => Promise<WorkflowRunResult>;
21
+ export declare function interpolateGoalTemplate(template: string, staticGoal: string, payload: Readonly<Record<string, unknown>>): string;
22
+ export declare class TriggerRouter {
23
+ private readonly index;
24
+ private readonly ctx;
25
+ private readonly apiKey;
26
+ private readonly runWorkflowFn;
27
+ private readonly queue;
28
+ constructor(index: ReadonlyMap<string, TriggerDefinition>, ctx: V2ToolContext, apiKey: string, runWorkflowFn: RunWorkflowFn);
29
+ route(event: WebhookEvent): RouteResult;
30
+ dispatch(workflowTrigger: WorkflowTrigger): string;
31
+ listTriggers(): readonly TriggerDefinition[];
32
+ }