@relayfx/sdk 0.0.48 → 0.0.49

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 (34) hide show
  1. package/dist/ai.js +2050 -576
  2. package/dist/index.js +2879 -859
  3. package/dist/migrations/20260709214238_faithful_black_widow/migration.sql +53 -0
  4. package/dist/migrations/20260709214238_faithful_black_widow/snapshot.json +5426 -0
  5. package/dist/migrations/20260709220016_fearless_aaron_stack/migration.sql +2 -0
  6. package/dist/migrations/20260709220016_fearless_aaron_stack/snapshot.json +5426 -0
  7. package/dist/migrations/mysql/0002_durable_tool_placement.sql +75 -0
  8. package/dist/migrations/pg/20260709214238_faithful_black_widow/migration.sql +53 -0
  9. package/dist/migrations/pg/20260709214238_faithful_black_widow/snapshot.json +5426 -0
  10. package/dist/migrations/pg/20260709220016_fearless_aaron_stack/migration.sql +2 -0
  11. package/dist/migrations/pg/20260709220016_fearless_aaron_stack/snapshot.json +5426 -0
  12. package/dist/migrations/sqlite/0002_durable_tool_placement.sql +71 -0
  13. package/dist/types/relay/client.d.ts +27 -6
  14. package/dist/types/relay/index.d.ts +1 -0
  15. package/dist/types/relay/operation.d.ts +525 -53
  16. package/dist/types/relay/tool-worker.d.ts +19 -0
  17. package/dist/types/runtime/address/address-resolution-service.d.ts +69 -54
  18. package/dist/types/runtime/agent/relay-compaction.d.ts +1 -0
  19. package/dist/types/runtime/cluster/execution-entity.d.ts +10 -477
  20. package/dist/types/runtime/execution/event-log-service.d.ts +6 -0
  21. package/dist/types/runtime/index.d.ts +1 -0
  22. package/dist/types/runtime/runner/runner-runtime-service.d.ts +18 -15
  23. package/dist/types/runtime/tool/tool-runtime-service.d.ts +17 -1
  24. package/dist/types/runtime/tool/tool-transition-coordinator.d.ts +13 -0
  25. package/dist/types/runtime/workflow/execution-workflow.d.ts +146 -114
  26. package/dist/types/schema/agent-schema.d.ts +431 -320
  27. package/dist/types/schema/execution-schema.d.ts +69 -53
  28. package/dist/types/schema/ids-schema.d.ts +4 -0
  29. package/dist/types/schema/tool-schema.d.ts +29 -0
  30. package/dist/types/store-sql/envelope/envelope-repository.d.ts +6 -0
  31. package/dist/types/store-sql/execution/execution-event-repository.d.ts +6 -0
  32. package/dist/types/store-sql/schema/relay-schema.d.ts +386 -7
  33. package/dist/types/store-sql/tool/tool-call-repository.d.ts +160 -1
  34. package/package.json +3 -3
package/dist/ai.js CHANGED
@@ -62,6 +62,7 @@ __export(exports_ids_schema, {
62
62
  WorkspaceLeaseId: () => WorkspaceLeaseId,
63
63
  WaitId: () => WaitId,
64
64
  ToolCallId: () => ToolCallId,
65
+ ToolAttemptId: () => ToolAttemptId,
65
66
  TenantId: () => TenantId,
66
67
  SystemTenantId: () => SystemTenantId,
67
68
  SnapshotRef: () => SnapshotRef,
@@ -104,6 +105,7 @@ var WorkspaceSnapshotId = id("Relay.WorkspaceSnapshotId");
104
105
  var WorkspaceRef = id("Relay.WorkspaceRef");
105
106
  var SnapshotRef = id("Relay.SnapshotRef");
106
107
  var ToolCallId = id("Relay.ToolCallId");
108
+ var ToolAttemptId = id("Relay.ToolAttemptId");
107
109
  var WaitId = id("Relay.WaitId");
108
110
  var ScheduleId = id("Relay.ScheduleId");
109
111
  var EventId = id("Relay.EventId");
@@ -170,9 +172,12 @@ var RouteList = Schema3.Struct({
170
172
  // ../schema/src/agent-schema.ts
171
173
  var exports_agent_schema = {};
172
174
  __export(exports_agent_schema, {
175
+ maxTurnPolicySnapshotNodes: () => maxTurnPolicySnapshotNodes,
176
+ maxTurnPolicySnapshotDepth: () => maxTurnPolicySnapshotDepth,
173
177
  define: () => define,
174
178
  defaultMaxWaitTurns: () => defaultMaxWaitTurns,
175
179
  defaultMaxToolTurns: () => defaultMaxToolTurns,
180
+ TurnPolicySnapshot: () => TurnPolicySnapshot,
176
181
  ToolInputSchemaDigests: () => ToolInputSchemaDigests,
177
182
  RegisterDefinitionPayload: () => RegisterDefinitionPayload,
178
183
  PermissionRuleset: () => PermissionRuleset,
@@ -195,12 +200,19 @@ import { Schema as Schema5 } from "effect";
195
200
  // ../schema/src/tool-schema.ts
196
201
  var exports_tool_schema = {};
197
202
  __export(exports_tool_schema, {
203
+ resultSchema: () => resultSchema,
198
204
  parametersSchema: () => parametersSchema,
205
+ WorkerId: () => WorkerId,
199
206
  RuntimeRequirement: () => RuntimeRequirement,
200
207
  Result: () => Result,
208
+ PlacementKey: () => PlacementKey,
209
+ Placement: () => Placement,
201
210
  Permission: () => Permission,
211
+ ExternalOutcome: () => ExternalOutcome,
202
212
  Definition: () => Definition,
203
- Call: () => Call
213
+ CallState: () => CallState,
214
+ Call: () => Call,
215
+ AttemptState: () => AttemptState
204
216
  });
205
217
  import { JsonSchema, Schema as Schema4, SchemaRepresentation } from "effect";
206
218
  var Permission = Schema4.Struct({
@@ -214,6 +226,38 @@ var RuntimeRequirement = Schema4.Union([
214
226
  mode: Schema4.Literals(["read", "write", "exec"])
215
227
  })
216
228
  ]).annotate({ identifier: "Relay.Tool.RuntimeRequirement" });
229
+ var PlacementKey = NonEmptyString.check(Schema4.isMaxLength(191)).annotate({
230
+ identifier: "Relay.Tool.PlacementKey"
231
+ });
232
+ var WorkerId = NonEmptyString.check(Schema4.isMaxLength(191)).annotate({
233
+ identifier: "Relay.Tool.WorkerId"
234
+ });
235
+ var Placement = Schema4.Union([
236
+ Schema4.Struct({ kind: Schema4.Literal("local") }),
237
+ Schema4.Struct({ kind: Schema4.Literal("client") }),
238
+ Schema4.Struct({ kind: Schema4.Literal("remote"), queue: PlacementKey }),
239
+ Schema4.Struct({ kind: Schema4.Literal("mcp"), server_id: PlacementKey })
240
+ ]).annotate({ identifier: "Relay.Tool.Placement" });
241
+ var ExternalOutcome = Schema4.Union([
242
+ Schema4.Struct({ kind: Schema4.Literal("success"), output: JsonValue }),
243
+ Schema4.Struct({ kind: Schema4.Literal("failure"), message: Schema4.String })
244
+ ]).annotate({ identifier: "Relay.Tool.ExternalOutcome" });
245
+ var CallState = Schema4.Literals([
246
+ "requested",
247
+ "waiting",
248
+ "running",
249
+ "submitted",
250
+ "completed",
251
+ "failed"
252
+ ]).annotate({ identifier: "Relay.Tool.CallState" });
253
+ var AttemptState = Schema4.Literals([
254
+ "running",
255
+ "completed",
256
+ "failed",
257
+ "released",
258
+ "expired",
259
+ "abandoned"
260
+ ]).annotate({ identifier: "Relay.Tool.AttemptState" });
217
261
  var Definition = Schema4.Struct({
218
262
  name: NonEmptyString,
219
263
  description: Schema4.String,
@@ -274,6 +318,19 @@ var parametersSchema = (inputSchema) => {
274
318
  return Schema4.Unknown;
275
319
  }
276
320
  };
321
+ var resultSchema = (outputSchema) => {
322
+ if (outputSchema === true || isJsonObject(outputSchema) && Object.keys(outputSchema).length === 0) {
323
+ return Schema4.Unknown;
324
+ }
325
+ if (outputSchema === false)
326
+ return Schema4.Never;
327
+ try {
328
+ const schema = SchemaRepresentation.toSchema(SchemaRepresentation.fromJsonSchemaDocument(JsonSchema.fromSchemaDraft2020_12(outputSchema)));
329
+ return schema.ast._tag === "Unknown" ? Schema4.Never : schema;
330
+ } catch {
331
+ return Schema4.Never;
332
+ }
333
+ };
277
334
 
278
335
  // ../schema/src/agent-schema.ts
279
336
  var DefinitionRevision = Schema5.Int.check(Schema5.isGreaterThanOrEqualTo(1)).annotate({
@@ -318,9 +375,56 @@ var PermissionRuleset = Schema5.Struct({
318
375
  var ToolInputSchemaDigests = Schema5.Record(Schema5.String, Schema5.String).annotate({
319
376
  identifier: "Relay.Agent.ToolInputSchemaDigests"
320
377
  });
378
+ var RecursTurnPolicySnapshot = Schema5.Struct({
379
+ kind: Schema5.Literals(["recurs"]),
380
+ count: Schema5.Int.check(Schema5.isGreaterThanOrEqualTo(0))
381
+ });
382
+ var UntilToolCallTurnPolicySnapshot = Schema5.Struct({
383
+ kind: Schema5.Literals(["until-tool-call"]),
384
+ name: NonEmptyString
385
+ });
386
+ var maxTurnPolicySnapshotDepth = 16;
387
+ var maxTurnPolicySnapshotNodes = 64;
388
+ var turnPolicySnapshotNodeCount = Schema5.makeFilter((input) => {
389
+ let nodes = 0;
390
+ const pending = [input];
391
+ while (pending.length > 0) {
392
+ const snapshot = pending.pop();
393
+ if (snapshot === undefined)
394
+ continue;
395
+ nodes += 1;
396
+ if (nodes > maxTurnPolicySnapshotNodes) {
397
+ return `turn policy snapshot node count exceeds ${maxTurnPolicySnapshotNodes}`;
398
+ }
399
+ if (snapshot.kind === "both")
400
+ pending.push(snapshot.second, snapshot.first);
401
+ }
402
+ return;
403
+ });
404
+ var turnPolicySnapshotLeaf = Schema5.Union([RecursTurnPolicySnapshot, UntilToolCallTurnPolicySnapshot]);
405
+ var makeTurnPolicySnapshotTree = () => {
406
+ let tree = turnPolicySnapshotLeaf;
407
+ for (let depth = 2;depth <= maxTurnPolicySnapshotDepth; depth += 1) {
408
+ const child = tree;
409
+ tree = Schema5.Union([
410
+ RecursTurnPolicySnapshot,
411
+ UntilToolCallTurnPolicySnapshot,
412
+ Schema5.Struct({
413
+ kind: Schema5.Literals(["both"]),
414
+ first: child,
415
+ second: child
416
+ })
417
+ ]);
418
+ if (depth < maxTurnPolicySnapshotDepth) {
419
+ tree = tree.annotate({ identifier: `Relay.Agent.TurnPolicySnapshot.Depth${depth}` });
420
+ }
421
+ }
422
+ return tree;
423
+ };
424
+ var TurnPolicySnapshot = makeTurnPolicySnapshotTree().check(turnPolicySnapshotNodeCount).annotate({ identifier: "Relay.Agent.TurnPolicySnapshot" });
321
425
  var defaultMaxToolTurns = 8;
322
426
  var defaultMaxWaitTurns = 8;
323
- var Definition2 = Schema5.Struct({
427
+ var DefinitionSchema = Schema5.Struct({
324
428
  name: NonEmptyString,
325
429
  instructions: Schema5.optionalKey(Schema5.String),
326
430
  model: ModelSelection,
@@ -328,6 +432,7 @@ var Definition2 = Schema5.Struct({
328
432
  permissions: Schema5.Array(Permission),
329
433
  skill_definition_ids: Schema5.optionalKey(Schema5.Array(SkillDefinitionId)),
330
434
  permission_rules: Schema5.optionalKey(PermissionRuleset),
435
+ turn_policy: Schema5.optionalKey(TurnPolicySnapshot),
331
436
  max_tool_turns: Schema5.optionalKey(Schema5.Int.check(Schema5.isGreaterThanOrEqualTo(1))),
332
437
  max_wait_turns: Schema5.optionalKey(Schema5.Int.check(Schema5.isGreaterThanOrEqualTo(0))),
333
438
  token_budget: Schema5.optionalKey(Schema5.Int.check(Schema5.isGreaterThanOrEqualTo(1))),
@@ -336,6 +441,7 @@ var Definition2 = Schema5.Struct({
336
441
  output_schema_ref: Schema5.optionalKey(Schema5.String),
337
442
  metadata: Schema5.optionalKey(Metadata)
338
443
  }).annotate({ identifier: "Relay.Agent.Definition" });
444
+ var Definition2 = DefinitionSchema;
339
445
  var define = (input) => ({
340
446
  id: input.id,
341
447
  definition: {
@@ -346,6 +452,7 @@ var define = (input) => ({
346
452
  permissions: input.permissions,
347
453
  ...input.skill_definition_ids === undefined ? {} : { skill_definition_ids: input.skill_definition_ids },
348
454
  ...input.permission_rules === undefined ? {} : { permission_rules: input.permission_rules },
455
+ ...input.turn_policy === undefined ? {} : { turn_policy: input.turn_policy },
349
456
  ...input.max_tool_turns === undefined ? {} : { max_tool_turns: input.max_tool_turns },
350
457
  ...input.max_wait_turns === undefined ? {} : { max_wait_turns: input.max_wait_turns },
351
458
  ...input.token_budget === undefined ? {} : { token_budget: input.token_budget },
@@ -1469,8 +1576,9 @@ __export(exports_child_execution_repository, {
1469
1576
  ChildExecutionRepositoryError: () => ChildExecutionRepositoryError,
1470
1577
  ChildExecutionNotFound: () => ChildExecutionNotFound
1471
1578
  });
1472
- import { Context as Context6, Effect as Effect6, Layer as Layer6, Schema as Schema16 } from "effect";
1579
+ import { Context as Context6, Effect as Effect6, Layer as Layer6, Predicate, Schema as Schema16 } from "effect";
1473
1580
  import { SqlClient as SqlClient5 } from "effect/unstable/sql/SqlClient";
1581
+ import { isSqlError } from "effect/unstable/sql/SqlError";
1474
1582
  class ChildExecutionRepositoryError extends Schema16.TaggedErrorClass()("ChildExecutionRepositoryError", {
1475
1583
  message: Schema16.String
1476
1584
  }) {
@@ -1508,6 +1616,16 @@ var toRecord3 = (row) => ({
1508
1616
  updatedAt: fromDbTimestamp(row.updated_at)
1509
1617
  });
1510
1618
  var toRepositoryError4 = (error) => new ChildExecutionRepositoryError({ message: String(error) });
1619
+ var isDuplicateConstraint = (error) => {
1620
+ if (!isSqlError(error))
1621
+ return false;
1622
+ if (error.reason._tag === "UniqueViolation")
1623
+ return true;
1624
+ if (error.reason._tag !== "ConstraintError")
1625
+ return false;
1626
+ const cause = error.reason.cause;
1627
+ return Predicate.hasProperty(cause, "code") && (cause.code === "SQLITE_CONSTRAINT_PRIMARYKEY" || cause.code === 1555) || Predicate.hasProperty(cause, "errno") && cause.errno === 1555;
1628
+ };
1511
1629
  var decodeRow4 = (row) => Schema16.decodeUnknownEffect(ChildExecutionRow)(row).pipe(Effect6.mapError(toRepositoryError4));
1512
1630
  var layer6 = Layer6.effect(Service6, Effect6.gen(function* () {
1513
1631
  const sql2 = yield* SqlClient5;
@@ -1561,10 +1679,7 @@ var layer6 = Layer6.effect(Service6, Effect6.gen(function* () {
1561
1679
  });
1562
1680
  const create = Effect6.fn("ChildExecutionRepository.create")(function* (input) {
1563
1681
  const tenantId = yield* current();
1564
- const existing = yield* selectByKey(tenantId, input.id).pipe(Effect6.mapError(toRepositoryError4));
1565
- if (existing[0] !== undefined)
1566
- return yield* Effect6.fail(new DuplicateChildExecution({ id: input.id }));
1567
- const rows = yield* insertChildExecution(tenantId, input).pipe(Effect6.mapError(toRepositoryError4));
1682
+ const rows = yield* insertChildExecution(tenantId, input).pipe(Effect6.mapError((error) => isDuplicateConstraint(error) ? new DuplicateChildExecution({ id: input.id }) : toRepositoryError4(error)));
1568
1683
  const row = rows[0];
1569
1684
  if (row === undefined) {
1570
1685
  return yield* Effect6.fail(new ChildExecutionRepositoryError({ message: "Child execution insert returned no row" }));
@@ -1582,7 +1697,7 @@ var layer6 = Layer6.effect(Service6, Effect6.gen(function* () {
1582
1697
  SELECT ${columns}
1583
1698
  FROM relay_child_executions
1584
1699
  WHERE tenant_id = ${tenantId} AND execution_id = ${executionId}
1585
- ORDER BY created_at ASC
1700
+ ORDER BY created_at ASC, id ASC
1586
1701
  `.pipe(Effect6.mapError(toRepositoryError4));
1587
1702
  const decoded = yield* Effect6.forEach(rows, decodeRow4);
1588
1703
  return decoded.map(toRecord3);
@@ -1619,7 +1734,7 @@ var memoryLayer4 = Layer6.sync(Service6, () => {
1619
1734
  return yield* Effect6.sync(() => records.get(id2));
1620
1735
  }),
1621
1736
  listByExecution: Effect6.fn("ChildExecutionRepository.memory.listByExecution")(function* (executionId) {
1622
- return yield* Effect6.sync(() => [...records.values()].filter((record) => record.executionId === executionId).toSorted((left, right) => left.createdAt - right.createdAt));
1737
+ return yield* Effect6.sync(() => [...records.values()].filter((record) => record.executionId === executionId).toSorted((left, right) => left.createdAt - right.createdAt || left.id.localeCompare(right.id)));
1623
1738
  }),
1624
1739
  updateStatus: Effect6.fn("ChildExecutionRepository.memory.updateStatus")(function* (input) {
1625
1740
  const existing = records.get(input.id);
@@ -1885,6 +2000,7 @@ __export(exports_envelope_repository, {
1885
2000
  releaseReady: () => releaseReady,
1886
2001
  memoryLayer: () => memoryLayer7,
1887
2002
  listWaits: () => listWaits,
2003
+ listAllWaits: () => listAllWaits,
1888
2004
  layer: () => layer9,
1889
2005
  getWait: () => getWait,
1890
2006
  getEnvelope: () => getEnvelope,
@@ -2150,6 +2266,25 @@ var layer9 = Layer9.effect(Service9, Effect9.gen(function* () {
2150
2266
  }
2151
2267
  return records;
2152
2268
  });
2269
+ const listAllWaits = Effect9.fn("EnvelopeRepository.listAllWaits")(function* (input) {
2270
+ const tenantId = yield* current();
2271
+ const conditions = [
2272
+ sql2`tenant_id = ${tenantId}`,
2273
+ ...input.executionId === undefined ? [] : [sql2`execution_id = ${input.executionId}`],
2274
+ ...input.state === undefined ? [] : [sql2`state = ${input.state}`]
2275
+ ];
2276
+ const rows = yield* sql2`
2277
+ SELECT ${waitColumns}
2278
+ FROM relay_waits
2279
+ WHERE ${sql2.and(conditions)}
2280
+ ORDER BY created_at DESC, id DESC
2281
+ `.pipe(Effect9.mapError(toRepositoryError6));
2282
+ const records = [];
2283
+ for (const row of rows) {
2284
+ records.push(toWaitRecord(yield* decodeWaitRow(row)));
2285
+ }
2286
+ return records;
2287
+ });
2153
2288
  const claimablePredicate = (input) => sql2.or([
2154
2289
  sql2.and([sql2`state = 'ready'`, sql2`available_at <= ${ts(input.now)}`]),
2155
2290
  sql2.and([sql2`state = 'claimed'`, sql2`claim_expires_at IS NOT NULL`, sql2`claim_expires_at <= ${ts(input.now)}`])
@@ -2370,6 +2505,7 @@ var layer9 = Layer9.effect(Service9, Effect9.gen(function* () {
2370
2505
  getWait,
2371
2506
  createWait,
2372
2507
  listWaits,
2508
+ listAllWaits,
2373
2509
  claimReady,
2374
2510
  releaseReady,
2375
2511
  ackReady,
@@ -2454,6 +2590,9 @@ var memoryLayer7 = Layer9.sync(Service9, () => {
2454
2590
  listWaits: Effect9.fn("EnvelopeRepository.memory.listWaits")(function* (input) {
2455
2591
  return yield* Effect9.sync(() => [...waits.values()].filter((record2) => (input.executionId === undefined || record2.executionId === input.executionId) && (input.state === undefined || record2.state === input.state)).toSorted(compareWaitsDesc).slice(0, listWaitsLimit(input)));
2456
2592
  }),
2593
+ listAllWaits: Effect9.fn("EnvelopeRepository.memory.listAllWaits")(function* (input) {
2594
+ return yield* Effect9.sync(() => [...waits.values()].filter((record2) => (input.executionId === undefined || record2.executionId === input.executionId) && (input.state === undefined || record2.state === input.state)).toSorted(compareWaitsDesc));
2595
+ }),
2457
2596
  claimReady: Effect9.fn("EnvelopeRepository.memory.claimReady")(function* (input) {
2458
2597
  const candidate = [...readyRows.values()].filter((row) => row.routeType === input.routeType && (input.routeKey === undefined || row.routeKey === input.routeKey) && (row.state === "ready" && row.availableAt <= input.now || row.state === "claimed" && row.claimExpiresAt !== undefined && row.claimExpiresAt <= input.now)).toSorted((a, b) => a.availableAt - b.availableAt || a.createdAt - b.createdAt)[0];
2459
2598
  if (candidate === undefined)
@@ -2543,6 +2682,10 @@ var listWaits = Effect9.fn("EnvelopeRepository.listWaits.call")(function* (input
2543
2682
  const repository = yield* Service9;
2544
2683
  return yield* repository.listWaits(input);
2545
2684
  });
2685
+ var listAllWaits = Effect9.fn("EnvelopeRepository.listAllWaits.call")(function* (input) {
2686
+ const repository = yield* Service9;
2687
+ return yield* repository.listAllWaits(input);
2688
+ });
2546
2689
  var claimReady = Effect9.fn("EnvelopeRepository.claimReady.call")(function* (input) {
2547
2690
  const repository = yield* Service9;
2548
2691
  return yield* repository.claimReady(input);
@@ -2577,6 +2720,7 @@ __export(exports_execution_event_repository, {
2577
2720
  layer: () => layer10,
2578
2721
  findFirstByTypeAfterSequence: () => findFirstByTypeAfterSequence,
2579
2722
  findBySequenceOrCursor: () => findBySequenceOrCursor,
2723
+ findBySequence: () => findBySequence,
2580
2724
  findByCursor: () => findByCursor,
2581
2725
  executionEventsChannel: () => executionEventsChannel,
2582
2726
  appendedSignals: () => appendedSignals,
@@ -2865,6 +3009,17 @@ var layer10 = Layer11.effect(Service11, Effect11.gen(function* () {
2865
3009
  const row = rows[0];
2866
3010
  return row === undefined ? Option2.none() : Option2.some(toEvent(yield* decodeRow6(row)));
2867
3011
  });
3012
+ const findBySequence = Effect11.fn("ExecutionEventRepository.findBySequence")(function* (input) {
3013
+ const tenantId = yield* current();
3014
+ const rows = yield* sql2`
3015
+ SELECT ${columns}
3016
+ FROM relay_execution_events
3017
+ WHERE tenant_id = ${tenantId} AND execution_id = ${input.executionId} AND sequence = ${input.sequence}
3018
+ LIMIT 1
3019
+ `.pipe(Effect11.mapError(toRepositoryError7));
3020
+ const row = rows[0];
3021
+ return row === undefined ? Option2.none() : Option2.some(toEvent(yield* decodeRow6(row)));
3022
+ });
2868
3023
  const findFirstByTypeAfterSequence = Effect11.fn("ExecutionEventRepository.findFirstByTypeAfterSequence")(function* (input) {
2869
3024
  const tenantId = yield* current();
2870
3025
  const rows = yield* sql2`
@@ -2942,6 +3097,7 @@ var layer10 = Layer11.effect(Service11, Effect11.gen(function* () {
2942
3097
  list: list4,
2943
3098
  findBySequenceOrCursor,
2944
3099
  findByCursor,
3100
+ findBySequence,
2945
3101
  findFirstByTypeAfterSequence,
2946
3102
  maxSequence,
2947
3103
  sumUsage,
@@ -2981,6 +3137,11 @@ var memoryLayer8 = Layer11.sync(Service11, () => {
2981
3137
  const event = executionEvents.find((item) => item.cursor === input.cursor);
2982
3138
  return Effect11.succeed(event === undefined ? Option2.none() : Option2.some(event));
2983
3139
  }),
3140
+ findBySequence: Effect11.fn("ExecutionEventRepository.memory.findBySequence")((input) => {
3141
+ const executionEvents = events.get(input.executionId) ?? [];
3142
+ const event = executionEvents.find((item) => item.sequence === input.sequence);
3143
+ return Effect11.succeed(event === undefined ? Option2.none() : Option2.some(event));
3144
+ }),
2984
3145
  findFirstByTypeAfterSequence: Effect11.fn("ExecutionEventRepository.memory.findFirstByTypeAfterSequence")((input) => {
2985
3146
  const executionEvents = events.get(input.executionId) ?? [];
2986
3147
  const event = executionEvents.find((item) => item.type === input.type && item.sequence > input.afterSequence);
@@ -3019,6 +3180,10 @@ var findByCursor = Effect11.fn("ExecutionEventRepository.findByCursor.call")(fun
3019
3180
  const repository = yield* Service11;
3020
3181
  return yield* repository.findByCursor(input);
3021
3182
  });
3183
+ var findBySequence = Effect11.fn("ExecutionEventRepository.findBySequence.call")(function* (input) {
3184
+ const repository = yield* Service11;
3185
+ return yield* repository.findBySequence(input);
3186
+ });
3022
3187
  var findFirstByTypeAfterSequence = Effect11.fn("ExecutionEventRepository.findFirstByTypeAfterSequence.call")(function* (input) {
3023
3188
  const repository = yield* Service11;
3024
3189
  return yield* repository.findFirstByTypeAfterSequence(input);
@@ -3980,6 +4145,7 @@ __export(exports_relay_schema, {
3980
4145
  relayWaits: () => relayWaits,
3981
4146
  relayToolResults: () => relayToolResults,
3982
4147
  relayToolCalls: () => relayToolCalls,
4148
+ relayToolAttempts: () => relayToolAttempts,
3983
4149
  relaySteeringMessages: () => relaySteeringMessages,
3984
4150
  relaySteeringDrains: () => relaySteeringDrains,
3985
4151
  relaySkillDefinitions: () => relaySkillDefinitions,
@@ -4380,11 +4546,44 @@ var relayToolCalls = pgTable("relay_tool_calls", {
4380
4546
  executionId: text2("execution_id").$type().notNull(),
4381
4547
  name: text2("name").notNull(),
4382
4548
  inputJson: jsonb("input_json").notNull(),
4549
+ definitionJson: jsonb("definition_json").$type(),
4550
+ placementKind: text2("placement_kind").$type().notNull().default("local"),
4551
+ placementKey: text2("placement_key"),
4552
+ state: text2("state").$type().notNull().default("requested"),
4553
+ waitId: text2("wait_id").$type(),
4554
+ idempotencyKey: text2("idempotency_key").notNull(),
4555
+ availableAt: timestamp("available_at", { withTimezone: true }).notNull().defaultNow(),
4556
+ activeAttemptId: text2("active_attempt_id").$type(),
4557
+ claimOwner: text2("claim_owner"),
4558
+ claimedAt: timestamp("claimed_at", { withTimezone: true }),
4559
+ claimExpiresAt: timestamp("claim_expires_at", { withTimezone: true }),
4560
+ externalOutcomeJson: jsonb("external_outcome_json").$type(),
4561
+ externalOutcomeAt: timestamp("external_outcome_at", { withTimezone: true }),
4383
4562
  metadataJson: jsonb("metadata_json").$type().notNull().default({}),
4384
- createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
4563
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
4564
+ updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
4385
4565
  }, (table) => [
4386
4566
  primaryKey({ columns: [table.tenantId, table.id], name: "pk_relay_tool_calls" }),
4387
- index("idx_relay_tool_calls_execution").on(table.tenantId, table.executionId, table.createdAt)
4567
+ index("idx_relay_tool_calls_execution").on(table.tenantId, table.executionId, table.createdAt),
4568
+ index("idx_relay_tool_calls_remote_claim").on(table.tenantId, table.placementKind, table.placementKey, table.state, table.availableAt, table.createdAt, table.id),
4569
+ index("idx_relay_tool_calls_stale_claim").on(table.tenantId, table.state, table.claimExpiresAt),
4570
+ index("idx_relay_tool_calls_client_pending").on(table.tenantId, table.placementKind, table.state, table.createdAt, table.id)
4571
+ ]);
4572
+ var relayToolAttempts = pgTable("relay_tool_attempts", {
4573
+ tenantId: tenantId(),
4574
+ id: text2("id").$type().notNull(),
4575
+ toolCallId: text2("tool_call_id").$type().notNull(),
4576
+ attemptNumber: integer("attempt_number").notNull(),
4577
+ state: text2("state").$type().notNull(),
4578
+ workerId: text2("worker_id"),
4579
+ claimExpiresAt: timestamp("claim_expires_at", { withTimezone: true }),
4580
+ error: text2("error"),
4581
+ createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
4582
+ completedAt: timestamp("completed_at", { withTimezone: true })
4583
+ }, (table) => [
4584
+ primaryKey({ columns: [table.tenantId, table.toolCallId, table.id], name: "pk_relay_tool_attempts" }),
4585
+ uniqueIndex("uq_relay_tool_attempts_number").on(table.tenantId, table.toolCallId, table.attemptNumber),
4586
+ index("idx_relay_tool_attempts_call").on(table.tenantId, table.toolCallId, table.attemptNumber)
4388
4587
  ]);
4389
4588
  var relayToolResults = pgTable("relay_tool_results", {
4390
4589
  tenantId: tenantId(),
@@ -6344,18 +6543,33 @@ var drainUnconsumed = Effect20.fn("SteeringRepository.drainUnconsumed.call")(fun
6344
6543
  // ../store-sql/src/tool/tool-call-repository.ts
6345
6544
  var exports_tool_call_repository = {};
6346
6545
  __export(exports_tool_call_repository, {
6546
+ toolCallIdempotencyKey: () => toolCallIdempotencyKey,
6347
6547
  testLayer: () => testLayer18,
6548
+ releaseRemote: () => releaseRemote,
6348
6549
  recordResult: () => recordResult,
6349
6550
  recordCall: () => recordCall,
6551
+ prepareExternalWait: () => prepareExternalWait,
6350
6552
  memoryLayer: () => memoryLayer18,
6351
6553
  listCalls: () => listCalls,
6554
+ listAttempts: () => listAttempts,
6352
6555
  layer: () => layer20,
6353
6556
  getResult: () => getResult,
6354
6557
  getCall: () => getCall,
6558
+ failOpenForExecution: () => failOpenForExecution,
6559
+ ensureCall: () => ensureCall,
6560
+ claimRemote: () => claimRemote,
6561
+ beginAttempt: () => beginAttempt,
6562
+ acceptRemoteOutcome: () => acceptRemoteOutcome,
6563
+ acceptClientOutcome: () => acceptClientOutcome,
6355
6564
  ToolResultRow: () => ToolResultRow,
6565
+ ToolOutcomeConflict: () => ToolOutcomeConflict,
6566
+ ToolClaimRejected: () => ToolClaimRejected,
6567
+ ToolCallTransitionRejected: () => ToolCallTransitionRejected,
6356
6568
  ToolCallRow: () => ToolCallRow,
6357
6569
  ToolCallRepositoryError: () => ToolCallRepositoryError,
6358
6570
  ToolCallNotFound: () => ToolCallNotFound,
6571
+ ToolCallConflict: () => ToolCallConflict,
6572
+ ToolAttemptRow: () => ToolAttemptRow,
6359
6573
  Service: () => Service21,
6360
6574
  DuplicateToolResult: () => DuplicateToolResult,
6361
6575
  DuplicateToolCall: () => DuplicateToolCall
@@ -6382,6 +6596,30 @@ class DuplicateToolResult extends Schema30.TaggedErrorClass()("DuplicateToolResu
6382
6596
  }) {
6383
6597
  }
6384
6598
 
6599
+ class ToolCallConflict extends Schema30.TaggedErrorClass()("ToolCallConflict", {
6600
+ id: exports_ids_schema.ToolCallId
6601
+ }) {
6602
+ }
6603
+
6604
+ class ToolCallTransitionRejected extends Schema30.TaggedErrorClass()("ToolCallTransitionRejected", {
6605
+ id: exports_ids_schema.ToolCallId,
6606
+ message: Schema30.String
6607
+ }) {
6608
+ }
6609
+
6610
+ class ToolOutcomeConflict extends Schema30.TaggedErrorClass()("ToolOutcomeConflict", {
6611
+ id: exports_ids_schema.ToolCallId
6612
+ }) {
6613
+ }
6614
+
6615
+ class ToolClaimRejected extends Schema30.TaggedErrorClass()("ToolClaimRejected", {
6616
+ message: Schema30.String
6617
+ }) {
6618
+ }
6619
+ var lengthPrefixed = (value) => `${[...value].length}:${value}`;
6620
+ var toolCallIdempotencyKey = (tenantId2, executionId, callId) => `tool:${lengthPrefixed(tenantId2)}:${lengthPrefixed(executionId)}:${lengthPrefixed(callId)}`;
6621
+ var toolAttemptId = (attemptNumber) => exports_ids_schema.ToolAttemptId.make(`tool-attempt:${attemptNumber}`);
6622
+
6385
6623
  class Service21 extends Context21.Service()("@relayfx/store-sql/ToolCallRepository") {
6386
6624
  }
6387
6625
  var ToolCallRow = Schema30.Struct({
@@ -6389,9 +6627,34 @@ var ToolCallRow = Schema30.Struct({
6389
6627
  execution_id: Schema30.String,
6390
6628
  name: Schema30.String,
6391
6629
  input_json: Schema30.Unknown,
6630
+ definition_json: Schema30.NullishOr(Schema30.Unknown),
6631
+ placement_kind: Schema30.String,
6632
+ placement_key: Schema30.NullishOr(Schema30.String),
6633
+ state: Schema30.String,
6634
+ wait_id: Schema30.NullishOr(Schema30.String),
6635
+ idempotency_key: Schema30.String,
6636
+ available_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number]),
6637
+ active_attempt_id: Schema30.NullishOr(Schema30.String),
6638
+ claim_owner: Schema30.NullishOr(Schema30.String),
6639
+ claimed_at: Schema30.NullishOr(Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])),
6640
+ claim_expires_at: Schema30.NullishOr(Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])),
6641
+ external_outcome_json: Schema30.NullishOr(Schema30.Unknown),
6642
+ external_outcome_at: Schema30.NullishOr(Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])),
6392
6643
  metadata_json: Schema30.Unknown,
6393
- created_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])
6644
+ created_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number]),
6645
+ updated_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])
6394
6646
  }).annotate({ identifier: "Relay.ToolCall.Row" });
6647
+ var ToolAttemptRow = Schema30.Struct({
6648
+ id: Schema30.String,
6649
+ tool_call_id: Schema30.String,
6650
+ attempt_number: Schema30.Union([Schema30.Number, Schema30.String, Schema30.BigInt]),
6651
+ state: Schema30.String,
6652
+ worker_id: Schema30.NullishOr(Schema30.String),
6653
+ claim_expires_at: Schema30.NullishOr(Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])),
6654
+ error: Schema30.NullishOr(Schema30.String),
6655
+ created_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number]),
6656
+ completed_at: Schema30.NullishOr(Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number]))
6657
+ }).annotate({ identifier: "Relay.ToolAttempt.Row" });
6395
6658
  var ToolResultRow = Schema30.Struct({
6396
6659
  tool_call_id: Schema30.String,
6397
6660
  output_json: Schema30.Unknown,
@@ -6400,15 +6663,46 @@ var ToolResultRow = Schema30.Struct({
6400
6663
  created_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])
6401
6664
  }).annotate({ identifier: "Relay.ToolResult.Row" });
6402
6665
  var metadata8 = (input) => input ?? {};
6403
- var toCallRecord = (row) => ({
6404
- executionId: exports_ids_schema.ExecutionId.make(row.execution_id),
6405
- call: {
6406
- id: exports_ids_schema.ToolCallId.make(row.id),
6407
- name: row.name,
6408
- input: decodeJson(row.input_json),
6409
- metadata: decodeJson(row.metadata_json)
6410
- },
6411
- createdAt: fromDbTimestamp(row.created_at)
6666
+ var normalizeCall = (call) => ({ ...call, metadata: metadata8(call.metadata) });
6667
+ var sameCallIdentity = (left, right) => exports_shared_schema.canonicalString(normalizeCall(left)) === exports_shared_schema.canonicalString(normalizeCall(right));
6668
+ var placementFromRow = (row) => Schema30.decodeUnknownSync(exports_tool_schema.Placement)(row.placement_kind === "remote" ? { kind: "remote", queue: row.placement_key } : row.placement_kind === "mcp" ? { kind: "mcp", server_id: row.placement_key } : { kind: row.placement_kind });
6669
+ var toCallRecord = (row) => {
6670
+ const definition = row.definition_json === null || row.definition_json === undefined ? undefined : Schema30.decodeUnknownSync(exports_tool_schema.Definition)(decodeJson(row.definition_json));
6671
+ const outcome = row.external_outcome_json === null || row.external_outcome_json === undefined ? undefined : Schema30.decodeUnknownSync(exports_tool_schema.ExternalOutcome)(decodeJson(row.external_outcome_json));
6672
+ return {
6673
+ executionId: exports_ids_schema.ExecutionId.make(row.execution_id),
6674
+ call: normalizeCall({
6675
+ id: exports_ids_schema.ToolCallId.make(row.id),
6676
+ name: row.name,
6677
+ input: decodeJson(row.input_json),
6678
+ metadata: decodeJson(row.metadata_json)
6679
+ }),
6680
+ ...definition === undefined ? {} : { definition },
6681
+ placement: placementFromRow(row),
6682
+ state: Schema30.decodeUnknownSync(exports_tool_schema.CallState)(row.state),
6683
+ ...row.wait_id === null || row.wait_id === undefined ? {} : { waitId: exports_ids_schema.WaitId.make(row.wait_id) },
6684
+ idempotencyKey: row.idempotency_key,
6685
+ availableAt: fromDbTimestamp(row.available_at),
6686
+ ...row.active_attempt_id === null || row.active_attempt_id === undefined ? {} : { activeAttemptId: exports_ids_schema.ToolAttemptId.make(row.active_attempt_id) },
6687
+ ...row.claim_owner === null || row.claim_owner === undefined ? {} : { claimOwner: row.claim_owner },
6688
+ ...row.claimed_at === null || row.claimed_at === undefined ? {} : { claimedAt: fromDbTimestamp(row.claimed_at) },
6689
+ ...row.claim_expires_at === null || row.claim_expires_at === undefined ? {} : { claimExpiresAt: fromDbTimestamp(row.claim_expires_at) },
6690
+ ...outcome === undefined ? {} : { externalOutcome: outcome },
6691
+ ...row.external_outcome_at === null || row.external_outcome_at === undefined ? {} : { externalOutcomeAt: fromDbTimestamp(row.external_outcome_at) },
6692
+ createdAt: fromDbTimestamp(row.created_at),
6693
+ updatedAt: fromDbTimestamp(row.updated_at)
6694
+ };
6695
+ };
6696
+ var toAttemptRecord = (row) => ({
6697
+ id: exports_ids_schema.ToolAttemptId.make(row.id),
6698
+ callId: exports_ids_schema.ToolCallId.make(row.tool_call_id),
6699
+ attemptNumber: Number(row.attempt_number),
6700
+ state: Schema30.decodeUnknownSync(exports_tool_schema.AttemptState)(row.state),
6701
+ ...row.worker_id === null || row.worker_id === undefined ? {} : { workerId: row.worker_id },
6702
+ ...row.claim_expires_at === null || row.claim_expires_at === undefined ? {} : { claimExpiresAt: fromDbTimestamp(row.claim_expires_at) },
6703
+ ...row.error === null || row.error === undefined ? {} : { error: row.error },
6704
+ createdAt: fromDbTimestamp(row.created_at),
6705
+ ...row.completed_at === null || row.completed_at === undefined ? {} : { completedAt: fromDbTimestamp(row.completed_at) }
6412
6706
  });
6413
6707
  var toResultRecord = (row) => ({
6414
6708
  result: {
@@ -6422,9 +6716,44 @@ var toResultRecord = (row) => ({
6422
6716
  var toRepositoryError17 = (error) => new ToolCallRepositoryError({ message: String(error) });
6423
6717
  var decodeCallRow = (row) => Schema30.decodeUnknownEffect(ToolCallRow)(row).pipe(Effect21.mapError(toRepositoryError17));
6424
6718
  var decodeResultRow = (row) => Schema30.decodeUnknownEffect(ToolResultRow)(row).pipe(Effect21.mapError(toRepositoryError17));
6719
+ var decodeAttemptRow = (row) => Schema30.decodeUnknownEffect(ToolAttemptRow)(row).pipe(Effect21.mapError(toRepositoryError17));
6425
6720
  var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6426
6721
  const sql3 = yield* SqlClient20;
6427
- const callColumns = sql3.literal(["id", "execution_id", "name", "input_json", "metadata_json", "created_at"].join(", "));
6722
+ const ts = (millis) => timestampParam(sql3, millis);
6723
+ const repositoryTransaction = (effect) => sql3.withTransaction(effect).pipe(Effect21.catchTag("SqlError", (error) => Effect21.fail(toRepositoryError17(error))));
6724
+ const callColumns = sql3.literal([
6725
+ "id",
6726
+ "execution_id",
6727
+ "name",
6728
+ "input_json",
6729
+ "definition_json",
6730
+ "placement_kind",
6731
+ "placement_key",
6732
+ "state",
6733
+ "wait_id",
6734
+ "idempotency_key",
6735
+ "available_at",
6736
+ "active_attempt_id",
6737
+ "claim_owner",
6738
+ "claimed_at",
6739
+ "claim_expires_at",
6740
+ "external_outcome_json",
6741
+ "external_outcome_at",
6742
+ "metadata_json",
6743
+ "created_at",
6744
+ "updated_at"
6745
+ ].join(", "));
6746
+ const attemptColumns = sql3.literal([
6747
+ "id",
6748
+ "tool_call_id",
6749
+ "attempt_number",
6750
+ "state",
6751
+ "worker_id",
6752
+ "claim_expires_at",
6753
+ "error",
6754
+ "created_at",
6755
+ "completed_at"
6756
+ ].join(", "));
6428
6757
  const resultColumns = sql3.literal(["tool_call_id", "output_json", "error", "metadata_json", "created_at"].join(", "));
6429
6758
  const selectCallByKey = (tenantId2, id2) => sql3`
6430
6759
  SELECT ${callColumns}
@@ -6436,8 +6765,8 @@ var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6436
6765
  FROM relay_tool_results
6437
6766
  WHERE tenant_id = ${tenantId2} AND tool_call_id = ${callId}
6438
6767
  `;
6439
- const insertCallStatement = (tenantId2, input) => sql3`
6440
- INSERT INTO relay_tool_calls (
6768
+ const insertCallBody = (tenantId2, input, definition, placement = { kind: "local" }) => sql3`
6769
+ (
6441
6770
  tenant_id, ${callColumns}
6442
6771
  )
6443
6772
  VALUES (
@@ -6446,17 +6775,43 @@ var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6446
6775
  ${input.executionId},
6447
6776
  ${input.call.name},
6448
6777
  ${encodeJson(input.call.input)},
6778
+ ${definition === undefined ? null : encodeJson(definition)},
6779
+ ${placement.kind},
6780
+ ${placement.kind === "remote" ? placement.queue : placement.kind === "mcp" ? placement.server_id : null},
6781
+ 'requested',
6782
+ ${null},
6783
+ ${toolCallIdempotencyKey(tenantId2, input.executionId, input.call.id)},
6784
+ ${ts(input.createdAt)},
6785
+ ${null},
6786
+ ${null},
6787
+ ${null},
6788
+ ${null},
6789
+ ${null},
6790
+ ${null},
6449
6791
  ${encodeJson(metadata8(input.call.metadata))},
6450
- ${timestampParam(sql3, input.createdAt)}
6792
+ ${ts(input.createdAt)},
6793
+ ${ts(input.createdAt)}
6451
6794
  )
6452
6795
  `;
6796
+ const insertCallStatement = (tenantId2, input, definition, placement) => sql3`
6797
+ INSERT INTO relay_tool_calls ${insertCallBody(tenantId2, input, definition, placement)}
6798
+ `;
6799
+ const insertCallIgnore = sql3.onDialectOrElse({
6800
+ mysql: () => (tenantId2, input, definition, placement) => sql3`
6801
+ INSERT IGNORE INTO relay_tool_calls ${insertCallBody(tenantId2, input, definition, placement)}
6802
+ `,
6803
+ orElse: () => (tenantId2, input, definition, placement) => sql3`
6804
+ INSERT INTO relay_tool_calls ${insertCallBody(tenantId2, input, definition, placement)}
6805
+ ON CONFLICT (tenant_id, id) DO NOTHING
6806
+ `
6807
+ });
6453
6808
  const insertCall = sql3.onDialectOrElse({
6454
- mysql: () => (tenantId2, input) => sql3.withTransaction(Effect21.gen(function* () {
6455
- yield* insertCallStatement(tenantId2, input);
6809
+ mysql: () => (tenantId2, input, definition, placement) => sql3.withTransaction(Effect21.gen(function* () {
6810
+ yield* insertCallStatement(tenantId2, input, definition, placement);
6456
6811
  return yield* selectCallByKey(tenantId2, input.call.id);
6457
6812
  })),
6458
- orElse: () => (tenantId2, input) => sql3`
6459
- ${insertCallStatement(tenantId2, input)}
6813
+ orElse: () => (tenantId2, input, definition, placement) => sql3`
6814
+ ${insertCallStatement(tenantId2, input, definition, placement)}
6460
6815
  RETURNING ${callColumns}
6461
6816
  `
6462
6817
  });
@@ -6473,16 +6828,404 @@ var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6473
6828
  ${timestampParam(sql3, input.createdAt)}
6474
6829
  )
6475
6830
  `;
6476
- const insertResult = sql3.onDialectOrElse({
6477
- mysql: () => (tenantId2, input) => sql3.withTransaction(Effect21.gen(function* () {
6478
- yield* insertResultStatement(tenantId2, input);
6479
- return yield* selectResultByKey(tenantId2, input.result.call_id);
6480
- })),
6831
+ const selectAttempts = (tenantId2, callId) => sql3`
6832
+ SELECT ${attemptColumns}
6833
+ FROM relay_tool_attempts
6834
+ WHERE tenant_id = ${tenantId2} AND tool_call_id = ${callId}
6835
+ ORDER BY attempt_number ASC
6836
+ `;
6837
+ const lockedCallRows = sql3.onDialectOrElse({
6838
+ pg: () => (tenantId2, callId) => sql3`
6839
+ ${selectCallByKey(tenantId2, callId)}
6840
+ FOR UPDATE
6841
+ `,
6842
+ mysql: () => (tenantId2, callId) => sql3`
6843
+ ${selectCallByKey(tenantId2, callId)}
6844
+ FOR UPDATE
6845
+ `,
6846
+ orElse: () => selectCallByKey
6847
+ });
6848
+ const decodeCall = Effect21.fn("ToolCallRepository.decodeCall")(function* (row) {
6849
+ const decoded = yield* decodeCallRow(row);
6850
+ return yield* Effect21.try({ try: () => toCallRecord(decoded), catch: toRepositoryError17 });
6851
+ });
6852
+ const decodeAttempt = Effect21.fn("ToolCallRepository.decodeAttempt")(function* (row) {
6853
+ const decoded = yield* decodeAttemptRow(row);
6854
+ return yield* Effect21.try({ try: () => toAttemptRecord(decoded), catch: toRepositoryError17 });
6855
+ });
6856
+ const readLockedCall = Effect21.fn("ToolCallRepository.readLockedCall")(function* (tenantId2, callId) {
6857
+ const rows = yield* lockedCallRows(tenantId2, callId).pipe(Effect21.mapError(toRepositoryError17));
6858
+ if (rows[0] === undefined)
6859
+ return yield* Effect21.fail(new ToolCallNotFound({ id: callId }));
6860
+ return yield* decodeCall(rows[0]);
6861
+ });
6862
+ const readAttempts = Effect21.fn("ToolCallRepository.readAttempts")(function* (tenantId2, callId) {
6863
+ const rows = yield* selectAttempts(tenantId2, callId).pipe(Effect21.mapError(toRepositoryError17));
6864
+ return yield* Effect21.forEach(rows, decodeAttempt);
6865
+ });
6866
+ const nextAttemptNumber = Effect21.fn("ToolCallRepository.nextAttemptNumber")(function* (tenantId2, callId) {
6867
+ const rows = yield* sql3`
6868
+ SELECT COALESCE(MAX(attempt_number), 0) AS max_attempt
6869
+ FROM relay_tool_attempts
6870
+ WHERE tenant_id = ${tenantId2} AND tool_call_id = ${callId}
6871
+ `.pipe(Effect21.mapError(toRepositoryError17));
6872
+ const max = Number(rows[0]?.max_attempt ?? 0);
6873
+ return max + 1;
6874
+ });
6875
+ const insertAttemptNumber = Effect21.fn("ToolCallRepository.insertAttemptNumber")(function* (tenantId2, callId, attemptNumber, createdAt, workerId, claimExpiresAt) {
6876
+ const attemptId = toolAttemptId(attemptNumber);
6877
+ yield* sql3`
6878
+ INSERT INTO relay_tool_attempts (
6879
+ tenant_id, id, tool_call_id, attempt_number, state, worker_id, claim_expires_at,
6880
+ error, created_at, completed_at
6881
+ )
6882
+ VALUES (
6883
+ ${tenantId2}, ${attemptId}, ${callId}, ${attemptNumber}, 'running', ${workerId ?? null},
6884
+ ${claimExpiresAt === undefined ? null : ts(claimExpiresAt)}, ${null}, ${ts(createdAt)}, ${null}
6885
+ )
6886
+ `.pipe(Effect21.mapError(toRepositoryError17));
6887
+ return {
6888
+ id: attemptId,
6889
+ callId,
6890
+ attemptNumber,
6891
+ state: "running",
6892
+ ...workerId === undefined ? {} : { workerId },
6893
+ ...claimExpiresAt === undefined ? {} : { claimExpiresAt },
6894
+ createdAt
6895
+ };
6896
+ });
6897
+ const insertAttempt = Effect21.fn("ToolCallRepository.insertAttempt")(function* (tenantId2, callId, createdAt, workerId, claimExpiresAt) {
6898
+ const attemptNumber = yield* nextAttemptNumber(tenantId2, callId);
6899
+ return yield* insertAttemptNumber(tenantId2, callId, attemptNumber, createdAt, workerId, claimExpiresAt);
6900
+ });
6901
+ const loadAttempt = Effect21.fn("ToolCallRepository.loadAttempt")(function* (tenantId2, callId, attemptId) {
6902
+ const rows = yield* sql3`
6903
+ SELECT ${attemptColumns}
6904
+ FROM relay_tool_attempts
6905
+ WHERE tenant_id = ${tenantId2} AND tool_call_id = ${callId} AND id = ${attemptId}
6906
+ `.pipe(Effect21.mapError(toRepositoryError17));
6907
+ return rows[0] === undefined ? undefined : yield* decodeAttempt(rows[0]);
6908
+ });
6909
+ const completeAttempt = Effect21.fn("ToolCallRepository.completeAttempt")(function* (tenantId2, callId, attemptId, state, completedAt, error) {
6910
+ yield* sql3`
6911
+ UPDATE relay_tool_attempts
6912
+ SET state = ${state}, error = ${error ?? null}, completed_at = ${ts(completedAt)}
6913
+ WHERE tenant_id = ${tenantId2} AND tool_call_id = ${callId} AND id = ${attemptId} AND state = 'running'
6914
+ `.pipe(Effect21.mapError(toRepositoryError17));
6915
+ const attempt = yield* loadAttempt(tenantId2, callId, attemptId);
6916
+ if (attempt === undefined) {
6917
+ return yield* Effect21.fail(new ToolCallRepositoryError({ message: `Tool attempt not found: ${attemptId}` }));
6918
+ }
6919
+ return attempt;
6920
+ });
6921
+ const ensureCall = Effect21.fn("ToolCallRepository.ensureCall")(function* (input) {
6922
+ const tenantId2 = yield* current();
6923
+ return yield* repositoryTransaction(Effect21.gen(function* () {
6924
+ yield* insertCallIgnore(tenantId2, input, input.definition, input.placement).pipe(Effect21.mapError(toRepositoryError17));
6925
+ const existing = yield* readLockedCall(tenantId2, input.call.id);
6926
+ if (existing.executionId !== input.executionId || !sameCallIdentity(existing.call, input.call) || exports_shared_schema.canonicalString(existing.definition) !== exports_shared_schema.canonicalString(input.definition) || exports_shared_schema.canonicalString(existing.placement) !== exports_shared_schema.canonicalString(input.placement)) {
6927
+ return yield* Effect21.fail(new ToolCallConflict({ id: input.call.id }));
6928
+ }
6929
+ if (existing.definition === undefined) {
6930
+ return yield* Effect21.fail(new ToolCallRepositoryError({ message: "Tool call insert returned no row" }));
6931
+ }
6932
+ return existing;
6933
+ }));
6934
+ });
6935
+ const prepareExternalWait = Effect21.fn("ToolCallRepository.prepareExternalWait")(function* (input) {
6936
+ const tenantId2 = yield* current();
6937
+ return yield* repositoryTransaction(Effect21.gen(function* () {
6938
+ const call = yield* readLockedCall(tenantId2, input.callId);
6939
+ if (call.placement.kind !== "client" && call.placement.kind !== "remote") {
6940
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: "Tool placement is not external" }));
6941
+ }
6942
+ if (call.state === "waiting" && call.waitId === input.waitId)
6943
+ return call;
6944
+ if (call.state !== "requested") {
6945
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: `Call is ${call.state}` }));
6946
+ }
6947
+ yield* sql3`
6948
+ UPDATE relay_tool_calls
6949
+ SET state = 'waiting', wait_id = ${input.waitId}, available_at = ${ts(input.availableAt)},
6950
+ updated_at = ${ts(input.updatedAt)}
6951
+ WHERE tenant_id = ${tenantId2} AND id = ${input.callId} AND state = 'requested'
6952
+ `.pipe(Effect21.mapError(toRepositoryError17));
6953
+ return yield* readLockedCall(tenantId2, input.callId);
6954
+ }));
6955
+ });
6956
+ const beginAttempt = Effect21.fn("ToolCallRepository.beginAttempt")(function* (input) {
6957
+ const tenantId2 = yield* current();
6958
+ return yield* repositoryTransaction(Effect21.gen(function* () {
6959
+ const call = yield* readLockedCall(tenantId2, input.callId);
6960
+ if (call.placement.kind !== "local" && call.placement.kind !== "mcp") {
6961
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: "Tool placement is not immediate" }));
6962
+ }
6963
+ if (call.state === "completed" || call.state === "failed") {
6964
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: `Call is ${call.state}` }));
6965
+ }
6966
+ if (call.activeAttemptId !== undefined) {
6967
+ yield* completeAttempt(tenantId2, input.callId, call.activeAttemptId, "abandoned", input.startedAt);
6968
+ }
6969
+ const attempt = yield* insertAttempt(tenantId2, input.callId, input.startedAt);
6970
+ yield* sql3`
6971
+ UPDATE relay_tool_calls
6972
+ SET state = 'running', active_attempt_id = ${attempt.id}, updated_at = ${ts(input.startedAt)}
6973
+ WHERE tenant_id = ${tenantId2} AND id = ${input.callId}
6974
+ `.pipe(Effect21.mapError(toRepositoryError17));
6975
+ return attempt;
6976
+ }));
6977
+ });
6978
+ const acceptClientOutcome = Effect21.fn("ToolCallRepository.acceptClientOutcome")(function* (input) {
6979
+ const tenantId2 = yield* current();
6980
+ return yield* repositoryTransaction(Effect21.gen(function* () {
6981
+ const call = yield* readLockedCall(tenantId2, input.callId);
6982
+ if (call.executionId !== input.executionId || call.placement.kind !== "client") {
6983
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: "Client outcome does not match the call" }));
6984
+ }
6985
+ if (call.externalOutcome !== undefined) {
6986
+ if (exports_shared_schema.canonicalString(call.externalOutcome) !== exports_shared_schema.canonicalString(input.outcome)) {
6987
+ return yield* Effect21.fail(new ToolOutcomeConflict({ id: input.callId }));
6988
+ }
6989
+ if (call.activeAttemptId === undefined) {
6990
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: "Accepted attempt is missing" }));
6991
+ }
6992
+ const attempt2 = yield* loadAttempt(tenantId2, input.callId, call.activeAttemptId);
6993
+ if (attempt2 === undefined) {
6994
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: "Accepted attempt is missing" }));
6995
+ }
6996
+ return { call, attempt: attempt2, duplicate: true };
6997
+ }
6998
+ if (call.state !== "waiting") {
6999
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: `Call is ${call.state}` }));
7000
+ }
7001
+ const running = yield* insertAttempt(tenantId2, input.callId, input.submittedAt);
7002
+ const attempt = yield* completeAttempt(tenantId2, input.callId, running.id, input.outcome.kind === "success" ? "completed" : "failed", input.submittedAt, input.outcome.kind === "failure" ? input.outcome.message : undefined);
7003
+ yield* sql3`
7004
+ UPDATE relay_tool_calls
7005
+ SET state = 'submitted', active_attempt_id = ${attempt.id},
7006
+ external_outcome_json = ${encodeJson(input.outcome)},
7007
+ external_outcome_at = ${ts(input.submittedAt)}, updated_at = ${ts(input.submittedAt)}
7008
+ WHERE tenant_id = ${tenantId2} AND id = ${input.callId}
7009
+ `.pipe(Effect21.mapError(toRepositoryError17));
7010
+ const updated = yield* readLockedCall(tenantId2, input.callId);
7011
+ return { call: updated, attempt, duplicate: false };
7012
+ }));
7013
+ });
7014
+ const claimCandidate = (tenantId2, input) => sql3`
7015
+ SELECT id
7016
+ FROM relay_tool_calls
7017
+ WHERE tenant_id = ${tenantId2} AND placement_kind = 'remote' AND placement_key = ${input.queue}
7018
+ AND state = 'waiting' AND available_at <= ${ts(input.now)}
7019
+ ORDER BY available_at ASC, created_at ASC, id ASC
7020
+ LIMIT 1
7021
+ `;
7022
+ const selectClaimCandidate = sql3.onDialectOrElse({
7023
+ pg: () => (tenantId2, input) => sql3`
7024
+ ${claimCandidate(tenantId2, input)}
7025
+ FOR UPDATE SKIP LOCKED
7026
+ `,
7027
+ mysql: () => (tenantId2, input) => sql3`
7028
+ ${claimCandidate(tenantId2, input)}
7029
+ FOR UPDATE SKIP LOCKED
7030
+ `,
7031
+ orElse: () => claimCandidate
7032
+ });
7033
+ const claimCall = sql3.onDialectOrElse({
7034
+ mysql: () => (tenantId2, callId, attemptId, input) => sql3`
7035
+ UPDATE relay_tool_calls
7036
+ SET state = 'running', active_attempt_id = ${attemptId}, claim_owner = ${input.workerId},
7037
+ claimed_at = ${ts(input.now)}, claim_expires_at = ${ts(input.claimExpiresAt)},
7038
+ updated_at = ${ts(input.now)}
7039
+ WHERE tenant_id = ${tenantId2} AND id = ${callId} AND state = 'waiting'
7040
+ AND available_at <= ${ts(input.now)}
7041
+ `.pipe(Effect21.as([{ id: callId }])),
7042
+ orElse: () => (tenantId2, callId, attemptId, input) => sql3`
7043
+ UPDATE relay_tool_calls
7044
+ SET state = 'running', active_attempt_id = ${attemptId}, claim_owner = ${input.workerId},
7045
+ claimed_at = ${ts(input.now)}, claim_expires_at = ${ts(input.claimExpiresAt)},
7046
+ updated_at = ${ts(input.now)}
7047
+ WHERE tenant_id = ${tenantId2} AND id = ${callId} AND state = 'waiting'
7048
+ AND available_at <= ${ts(input.now)}
7049
+ RETURNING id
7050
+ `
7051
+ });
7052
+ const claimRemote = Effect21.fn("ToolCallRepository.claimRemote")(function* (input) {
7053
+ if (input.claimExpiresAt <= input.now) {
7054
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Claim expiry must be after now" }));
7055
+ }
7056
+ const tenantId2 = yield* current();
7057
+ return yield* repositoryTransaction(Effect21.gen(function* () {
7058
+ const expired = yield* sql3`
7059
+ SELECT id, active_attempt_id
7060
+ FROM relay_tool_calls
7061
+ WHERE tenant_id = ${tenantId2} AND placement_kind = 'remote' AND placement_key = ${input.queue}
7062
+ AND state = 'running' AND claim_expires_at IS NOT NULL AND claim_expires_at <= ${ts(input.now)}
7063
+ `.pipe(Effect21.mapError(toRepositoryError17));
7064
+ for (const row of expired) {
7065
+ if (row.active_attempt_id !== null && row.active_attempt_id !== undefined) {
7066
+ yield* completeAttempt(tenantId2, exports_ids_schema.ToolCallId.make(row.id), exports_ids_schema.ToolAttemptId.make(row.active_attempt_id), "expired", input.now);
7067
+ }
7068
+ yield* sql3`
7069
+ UPDATE relay_tool_calls
7070
+ SET state = 'waiting', active_attempt_id = NULL, claim_owner = NULL, claimed_at = NULL,
7071
+ claim_expires_at = NULL, updated_at = ${ts(input.now)}
7072
+ WHERE tenant_id = ${tenantId2} AND id = ${row.id} AND state = 'running'
7073
+ `.pipe(Effect21.mapError(toRepositoryError17));
7074
+ }
7075
+ const candidates = yield* selectClaimCandidate(tenantId2, input).pipe(Effect21.mapError(toRepositoryError17));
7076
+ const candidate = candidates[0];
7077
+ if (candidate?.id === undefined)
7078
+ return;
7079
+ const callId = exports_ids_schema.ToolCallId.make(candidate.id);
7080
+ const call = yield* readLockedCall(tenantId2, callId);
7081
+ if (call.definition === undefined || call.placement.kind !== "remote") {
7082
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: callId, message: "Remote call definition snapshot is missing" }));
7083
+ }
7084
+ const attemptNumber = yield* nextAttemptNumber(tenantId2, callId);
7085
+ const attemptId = toolAttemptId(attemptNumber);
7086
+ const claimed = yield* claimCall(tenantId2, callId, attemptId, input).pipe(Effect21.mapError(toRepositoryError17));
7087
+ if (claimed[0] === undefined)
7088
+ return;
7089
+ const attempt = yield* insertAttemptNumber(tenantId2, callId, attemptNumber, input.now, input.workerId, input.claimExpiresAt);
7090
+ const updated = yield* readLockedCall(tenantId2, callId);
7091
+ if (updated.definition === undefined || updated.placement.kind !== "remote") {
7092
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: callId, message: "Remote call definition snapshot is missing" }));
7093
+ }
7094
+ return {
7095
+ call: { ...updated, definition: updated.definition },
7096
+ attempt,
7097
+ queue: updated.placement.queue,
7098
+ workerId: input.workerId,
7099
+ claimExpiresAt: input.claimExpiresAt,
7100
+ idempotencyKey: updated.idempotencyKey
7101
+ };
7102
+ }));
7103
+ });
7104
+ const releaseRemote = Effect21.fn("ToolCallRepository.releaseRemote")(function* (input) {
7105
+ const tenantId2 = yield* current();
7106
+ return yield* repositoryTransaction(Effect21.gen(function* () {
7107
+ const call = yield* readLockedCall(tenantId2, input.callId);
7108
+ if (call.placement.kind !== "remote" || call.state !== "running" || call.activeAttemptId !== input.attemptId || call.claimOwner !== input.workerId || call.claimExpiresAt === undefined || call.claimExpiresAt <= input.releasedAt) {
7109
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote claim is not active" }));
7110
+ }
7111
+ yield* completeAttempt(tenantId2, input.callId, input.attemptId, "released", input.releasedAt, input.error);
7112
+ yield* sql3`
7113
+ UPDATE relay_tool_calls
7114
+ SET state = 'waiting', available_at = ${ts(input.nextAvailableAt)}, active_attempt_id = NULL,
7115
+ claim_owner = NULL, claimed_at = NULL, claim_expires_at = NULL,
7116
+ updated_at = ${ts(input.releasedAt)}
7117
+ WHERE tenant_id = ${tenantId2} AND id = ${input.callId}
7118
+ `.pipe(Effect21.mapError(toRepositoryError17));
7119
+ return yield* readLockedCall(tenantId2, input.callId);
7120
+ }));
7121
+ });
7122
+ const acceptRemoteOutcome = Effect21.fn("ToolCallRepository.acceptRemoteOutcome")(function* (input) {
7123
+ const tenantId2 = yield* current();
7124
+ return yield* repositoryTransaction(Effect21.gen(function* () {
7125
+ const call = yield* readLockedCall(tenantId2, input.callId);
7126
+ if (call.externalOutcome !== undefined) {
7127
+ if (exports_shared_schema.canonicalString(call.externalOutcome) !== exports_shared_schema.canonicalString(input.outcome)) {
7128
+ return yield* Effect21.fail(new ToolOutcomeConflict({ id: input.callId }));
7129
+ }
7130
+ if (call.activeAttemptId !== input.attemptId) {
7131
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote attempt was not accepted" }));
7132
+ }
7133
+ const attempt2 = yield* loadAttempt(tenantId2, input.callId, input.attemptId);
7134
+ if (attempt2 === undefined || attempt2.callId !== input.callId || attempt2.workerId !== input.workerId) {
7135
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote attempt was not accepted" }));
7136
+ }
7137
+ return { call, attempt: attempt2, duplicate: true };
7138
+ }
7139
+ if (call.placement.kind !== "remote" || call.state !== "running" || call.activeAttemptId !== input.attemptId || call.claimOwner !== input.workerId || call.claimExpiresAt === undefined || call.claimExpiresAt <= input.submittedAt) {
7140
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote claim is not active" }));
7141
+ }
7142
+ const attempt = yield* completeAttempt(tenantId2, input.callId, input.attemptId, input.outcome.kind === "success" ? "completed" : "failed", input.submittedAt, input.outcome.kind === "failure" ? input.outcome.message : undefined);
7143
+ yield* sql3`
7144
+ UPDATE relay_tool_calls
7145
+ SET state = 'submitted', external_outcome_json = ${encodeJson(input.outcome)},
7146
+ external_outcome_at = ${ts(input.submittedAt)}, claim_owner = NULL, claimed_at = NULL,
7147
+ claim_expires_at = NULL, updated_at = ${ts(input.submittedAt)}
7148
+ WHERE tenant_id = ${tenantId2} AND id = ${input.callId}
7149
+ `.pipe(Effect21.mapError(toRepositoryError17));
7150
+ const updated = yield* readLockedCall(tenantId2, input.callId);
7151
+ return { call: updated, attempt, duplicate: false };
7152
+ }));
7153
+ });
7154
+ const listAttempts = Effect21.fn("ToolCallRepository.listAttempts")(function* (callId) {
7155
+ const tenantId2 = yield* current();
7156
+ return yield* readAttempts(tenantId2, callId);
7157
+ });
7158
+ const selectOpenCalls = sql3.onDialectOrElse({
7159
+ pg: () => (tenantId2, input) => sql3`
7160
+ SELECT ${callColumns}
7161
+ FROM relay_tool_calls
7162
+ WHERE tenant_id = ${tenantId2} AND execution_id = ${input.executionId}
7163
+ AND state NOT IN ('submitted', 'completed', 'failed')
7164
+ ORDER BY created_at ASC, id ASC
7165
+ FOR UPDATE
7166
+ `,
7167
+ mysql: () => (tenantId2, input) => sql3`
7168
+ SELECT ${callColumns}
7169
+ FROM relay_tool_calls
7170
+ WHERE tenant_id = ${tenantId2} AND execution_id = ${input.executionId}
7171
+ AND state NOT IN ('submitted', 'completed', 'failed')
7172
+ ORDER BY created_at ASC, id ASC
7173
+ FOR UPDATE
7174
+ `,
6481
7175
  orElse: () => (tenantId2, input) => sql3`
6482
- ${insertResultStatement(tenantId2, input)}
6483
- RETURNING ${resultColumns}
7176
+ SELECT ${callColumns}
7177
+ FROM relay_tool_calls
7178
+ WHERE tenant_id = ${tenantId2} AND execution_id = ${input.executionId}
7179
+ AND state NOT IN ('submitted', 'completed', 'failed')
7180
+ ORDER BY created_at ASC, id ASC
6484
7181
  `
6485
7182
  });
7183
+ const failCall = sql3.onDialectOrElse({
7184
+ mysql: () => (tenantId2, callId, failedAt) => sql3`
7185
+ UPDATE relay_tool_calls
7186
+ SET state = 'failed', claim_owner = NULL, claimed_at = NULL, claim_expires_at = NULL,
7187
+ updated_at = ${ts(failedAt)}
7188
+ WHERE tenant_id = ${tenantId2} AND id = ${callId} AND state NOT IN ('submitted', 'completed', 'failed')
7189
+ `.pipe(Effect21.as([{ id: callId }])),
7190
+ orElse: () => (tenantId2, callId, failedAt) => sql3`
7191
+ UPDATE relay_tool_calls
7192
+ SET state = 'failed', claim_owner = NULL, claimed_at = NULL, claim_expires_at = NULL,
7193
+ updated_at = ${ts(failedAt)}
7194
+ WHERE tenant_id = ${tenantId2} AND id = ${callId} AND state NOT IN ('submitted', 'completed', 'failed')
7195
+ RETURNING id
7196
+ `
7197
+ });
7198
+ const failOpenForExecution = Effect21.fn("ToolCallRepository.failOpenForExecution")(function* (input) {
7199
+ const tenantId2 = yield* current();
7200
+ return yield* repositoryTransaction(Effect21.gen(function* () {
7201
+ const rows = yield* selectOpenCalls(tenantId2, input).pipe(Effect21.mapError(toRepositoryError17));
7202
+ const open = yield* Effect21.forEach(rows, decodeCall);
7203
+ const selected = input.callIds === undefined ? undefined : new Set(input.callIds);
7204
+ const failed = [];
7205
+ for (const call of open) {
7206
+ if (selected !== undefined && !selected.has(call.call.id))
7207
+ continue;
7208
+ const transitioned = yield* failCall(tenantId2, call.call.id, input.failedAt).pipe(Effect21.mapError(toRepositoryError17));
7209
+ if (transitioned[0] === undefined)
7210
+ continue;
7211
+ if (call.activeAttemptId !== undefined) {
7212
+ const attempt = yield* loadAttempt(tenantId2, call.call.id, call.activeAttemptId);
7213
+ if (attempt?.state === "running") {
7214
+ yield* completeAttempt(tenantId2, call.call.id, call.activeAttemptId, "failed", input.failedAt, input.message);
7215
+ }
7216
+ }
7217
+ const existingResult = yield* selectResultByKey(tenantId2, call.call.id).pipe(Effect21.mapError(toRepositoryError17));
7218
+ if (existingResult[0] === undefined) {
7219
+ yield* insertResultStatement(tenantId2, {
7220
+ result: { call_id: call.call.id, output: null, error: input.message },
7221
+ createdAt: input.failedAt
7222
+ }).pipe(Effect21.mapError(toRepositoryError17));
7223
+ }
7224
+ failed.push(yield* readLockedCall(tenantId2, call.call.id));
7225
+ }
7226
+ return failed;
7227
+ }));
7228
+ });
6486
7229
  const recordCall = Effect21.fn("ToolCallRepository.recordCall")(function* (input) {
6487
7230
  const tenantId2 = yield* current();
6488
7231
  const existing = yield* selectCallByKey(tenantId2, input.call.id).pipe(Effect21.mapError(toRepositoryError17));
@@ -6493,12 +7236,12 @@ var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6493
7236
  if (row === undefined) {
6494
7237
  return yield* Effect21.fail(new ToolCallRepositoryError({ message: "Tool call insert returned no row" }));
6495
7238
  }
6496
- return toCallRecord(yield* decodeCallRow(row));
7239
+ return yield* decodeCall(row);
6497
7240
  });
6498
7241
  const getCall = Effect21.fn("ToolCallRepository.getCall")(function* (id2) {
6499
7242
  const tenantId2 = yield* current();
6500
7243
  const rows = yield* selectCallByKey(tenantId2, id2).pipe(Effect21.mapError(toRepositoryError17));
6501
- return rows[0] === undefined ? undefined : toCallRecord(yield* decodeCallRow(rows[0]));
7244
+ return rows[0] === undefined ? undefined : yield* decodeCall(rows[0]);
6502
7245
  });
6503
7246
  const listCalls = Effect21.fn("ToolCallRepository.listCalls")(function* (executionId) {
6504
7247
  const tenantId2 = yield* current();
@@ -6506,71 +7249,428 @@ var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6506
7249
  SELECT ${callColumns}
6507
7250
  FROM relay_tool_calls
6508
7251
  WHERE tenant_id = ${tenantId2} AND execution_id = ${executionId}
6509
- ORDER BY created_at ASC
7252
+ ORDER BY created_at ASC, id ASC
6510
7253
  `.pipe(Effect21.mapError(toRepositoryError17));
6511
- const decoded = yield* Effect21.forEach(rows, decodeCallRow);
6512
- return decoded.map(toCallRecord);
7254
+ return yield* Effect21.forEach(rows, decodeCall);
6513
7255
  });
6514
7256
  const recordResult = Effect21.fn("ToolCallRepository.recordResult")(function* (input) {
6515
7257
  const tenantId2 = yield* current();
6516
- const callRows = yield* selectCallByKey(tenantId2, input.result.call_id).pipe(Effect21.mapError(toRepositoryError17));
6517
- if (callRows[0] === undefined)
6518
- return yield* Effect21.fail(new ToolCallNotFound({ id: input.result.call_id }));
6519
- const existing = yield* selectResultByKey(tenantId2, input.result.call_id).pipe(Effect21.mapError(toRepositoryError17));
6520
- if (existing[0] !== undefined) {
6521
- return yield* Effect21.fail(new DuplicateToolResult({ call_id: input.result.call_id }));
6522
- }
6523
- const rows = yield* insertResult(tenantId2, input).pipe(Effect21.mapError(toRepositoryError17));
6524
- const row = rows[0];
6525
- if (row === undefined) {
6526
- return yield* Effect21.fail(new ToolCallRepositoryError({ message: "Tool result insert returned no row" }));
6527
- }
6528
- return toResultRecord(yield* decodeResultRow(row));
7258
+ return yield* repositoryTransaction(Effect21.gen(function* () {
7259
+ const call = yield* readLockedCall(tenantId2, input.result.call_id);
7260
+ const existing = yield* selectResultByKey(tenantId2, input.result.call_id).pipe(Effect21.mapError(toRepositoryError17));
7261
+ if (existing[0] !== undefined) {
7262
+ return yield* Effect21.fail(new DuplicateToolResult({ call_id: input.result.call_id }));
7263
+ }
7264
+ yield* insertResultStatement(tenantId2, input).pipe(Effect21.mapError(toRepositoryError17));
7265
+ if (call.activeAttemptId !== undefined) {
7266
+ const attempt = yield* loadAttempt(tenantId2, input.result.call_id, call.activeAttemptId);
7267
+ if (attempt?.state === "running") {
7268
+ yield* completeAttempt(tenantId2, input.result.call_id, call.activeAttemptId, input.result.error === undefined ? "completed" : "failed", input.createdAt, input.result.error);
7269
+ }
7270
+ }
7271
+ yield* sql3`
7272
+ UPDATE relay_tool_calls
7273
+ SET state = ${input.result.error === undefined ? "completed" : "failed"},
7274
+ claim_owner = NULL, claimed_at = NULL, claim_expires_at = NULL,
7275
+ updated_at = ${ts(input.createdAt)}
7276
+ WHERE tenant_id = ${tenantId2} AND id = ${input.result.call_id}
7277
+ `.pipe(Effect21.mapError(toRepositoryError17));
7278
+ const rows = yield* selectResultByKey(tenantId2, input.result.call_id).pipe(Effect21.mapError(toRepositoryError17));
7279
+ if (rows[0] === undefined) {
7280
+ return yield* Effect21.fail(new ToolCallRepositoryError({ message: "Tool result insert returned no row" }));
7281
+ }
7282
+ return toResultRecord(yield* decodeResultRow(rows[0]));
7283
+ }));
6529
7284
  });
6530
7285
  const getResult = Effect21.fn("ToolCallRepository.getResult")(function* (callId) {
6531
7286
  const tenantId2 = yield* current();
6532
7287
  const rows = yield* selectResultByKey(tenantId2, callId).pipe(Effect21.mapError(toRepositoryError17));
6533
7288
  return rows[0] === undefined ? undefined : toResultRecord(yield* decodeResultRow(rows[0]));
6534
7289
  });
6535
- return Service21.of({ recordCall, getCall, listCalls, recordResult, getResult });
7290
+ return Service21.of({
7291
+ ensureCall,
7292
+ recordCall,
7293
+ getCall,
7294
+ listCalls,
7295
+ recordResult,
7296
+ getResult,
7297
+ prepareExternalWait,
7298
+ beginAttempt,
7299
+ acceptClientOutcome,
7300
+ claimRemote,
7301
+ releaseRemote,
7302
+ acceptRemoteOutcome,
7303
+ listAttempts,
7304
+ failOpenForExecution
7305
+ });
6536
7306
  }));
6537
7307
  var memoryLayer18 = Layer21.sync(Service21, () => {
6538
7308
  const calls = new Map;
7309
+ const callTenants = new Map;
6539
7310
  const results = new Map;
7311
+ const attempts = new Map;
7312
+ const key2 = (tenantId2, callId) => exports_shared_schema.canonicalString([tenantId2, callId]);
7313
+ const same = (left, right) => exports_shared_schema.canonicalString(left) === exports_shared_schema.canonicalString(right);
7314
+ const callRecord = (tenantId2, input, definition, placement = { kind: "local" }) => ({
7315
+ executionId: input.executionId,
7316
+ call: normalizeCall(input.call),
7317
+ ...definition === undefined ? {} : { definition },
7318
+ placement,
7319
+ state: "requested",
7320
+ idempotencyKey: toolCallIdempotencyKey(tenantId2, input.executionId, input.call.id),
7321
+ availableAt: input.createdAt,
7322
+ createdAt: input.createdAt,
7323
+ updatedAt: input.createdAt
7324
+ });
7325
+ const attemptsFor = (tenantId2, callId) => attempts.get(key2(tenantId2, callId)) ?? [];
7326
+ const replaceAttempt = (tenantId2, attempt) => {
7327
+ const callAttempts = attemptsFor(tenantId2, attempt.callId);
7328
+ attempts.set(key2(tenantId2, attempt.callId), callAttempts.map((existing) => existing.id === attempt.id ? attempt : existing));
7329
+ };
7330
+ const appendAttempt = (tenantId2, callId, createdAt, options = {}) => {
7331
+ const callAttempts = attemptsFor(tenantId2, callId);
7332
+ const attemptNumber = callAttempts.length + 1;
7333
+ const attempt = {
7334
+ id: toolAttemptId(attemptNumber),
7335
+ callId,
7336
+ attemptNumber,
7337
+ state: "running",
7338
+ ...options.workerId === undefined ? {} : { workerId: options.workerId },
7339
+ ...options.claimExpiresAt === undefined ? {} : { claimExpiresAt: options.claimExpiresAt },
7340
+ createdAt
7341
+ };
7342
+ attempts.set(key2(tenantId2, callId), [...callAttempts, attempt]);
7343
+ return attempt;
7344
+ };
7345
+ const requireCall = (tenantId2, callId) => {
7346
+ const record2 = calls.get(key2(tenantId2, callId));
7347
+ return record2 === undefined ? Effect21.fail(new ToolCallNotFound({ id: callId })) : Effect21.succeed(record2);
7348
+ };
7349
+ const transitionRejected = (id2, message) => Effect21.fail(new ToolCallTransitionRejected({ id: id2, message }));
6540
7350
  return Service21.of({
7351
+ ensureCall: Effect21.fn("ToolCallRepository.memory.ensureCall")(function* (input) {
7352
+ const tenantId2 = yield* current();
7353
+ const storageKey = key2(tenantId2, input.call.id);
7354
+ const existing = calls.get(storageKey);
7355
+ if (existing !== undefined) {
7356
+ if (existing.executionId !== input.executionId || !sameCallIdentity(existing.call, input.call) || !same(existing.definition, input.definition) || !same(existing.placement, input.placement)) {
7357
+ return yield* Effect21.fail(new ToolCallConflict({ id: input.call.id }));
7358
+ }
7359
+ return existing;
7360
+ }
7361
+ const record2 = callRecord(tenantId2, input, input.definition, input.placement);
7362
+ calls.set(storageKey, record2);
7363
+ callTenants.set(storageKey, tenantId2);
7364
+ return record2;
7365
+ }),
6541
7366
  recordCall: Effect21.fn("ToolCallRepository.memory.recordCall")(function* (input) {
6542
- if (calls.has(input.call.id))
7367
+ const tenantId2 = yield* current();
7368
+ const storageKey = key2(tenantId2, input.call.id);
7369
+ if (calls.has(storageKey))
6543
7370
  return yield* Effect21.fail(new DuplicateToolCall({ id: input.call.id }));
6544
- const record2 = {
6545
- executionId: input.executionId,
6546
- call: input.call,
6547
- createdAt: input.createdAt
6548
- };
6549
- yield* Effect21.sync(() => calls.set(input.call.id, record2));
7371
+ const record2 = callRecord(tenantId2, input);
7372
+ calls.set(storageKey, record2);
7373
+ callTenants.set(storageKey, tenantId2);
6550
7374
  return record2;
6551
7375
  }),
6552
- getCall: Effect21.fn("ToolCallRepository.memory.getCall")(function* (id2) {
6553
- return yield* Effect21.sync(() => calls.get(id2));
7376
+ getCall: Effect21.fn("ToolCallRepository.memory.getCall")(function* (id2) {
7377
+ const tenantId2 = yield* current();
7378
+ return calls.get(key2(tenantId2, id2));
7379
+ }),
7380
+ listCalls: Effect21.fn("ToolCallRepository.memory.listCalls")(function* (executionId) {
7381
+ const tenantId2 = yield* current();
7382
+ return [...calls.entries()].filter(([storageKey, record2]) => callTenants.get(storageKey) === tenantId2 && record2.executionId === executionId).map(([, record2]) => record2).toSorted((a, b) => a.createdAt - b.createdAt || a.call.id.localeCompare(b.call.id));
7383
+ }),
7384
+ recordResult: Effect21.fn("ToolCallRepository.memory.recordResult")(function* (input) {
7385
+ const tenantId2 = yield* current();
7386
+ const storageKey = key2(tenantId2, input.result.call_id);
7387
+ const call = calls.get(storageKey);
7388
+ if (call === undefined)
7389
+ return yield* Effect21.fail(new ToolCallNotFound({ id: input.result.call_id }));
7390
+ if (results.has(storageKey)) {
7391
+ return yield* Effect21.fail(new DuplicateToolResult({ call_id: input.result.call_id }));
7392
+ }
7393
+ if (call.activeAttemptId !== undefined) {
7394
+ const active = attemptsFor(tenantId2, input.result.call_id).find((attempt) => attempt.id === call.activeAttemptId);
7395
+ if (active?.state === "running") {
7396
+ replaceAttempt(tenantId2, {
7397
+ ...active,
7398
+ state: input.result.error === undefined ? "completed" : "failed",
7399
+ ...input.result.error === undefined ? {} : { error: input.result.error },
7400
+ completedAt: input.createdAt
7401
+ });
7402
+ }
7403
+ }
7404
+ const record2 = { result: input.result, createdAt: input.createdAt };
7405
+ results.set(storageKey, record2);
7406
+ calls.set(storageKey, {
7407
+ ...call,
7408
+ state: input.result.error === undefined ? "completed" : "failed",
7409
+ updatedAt: input.createdAt
7410
+ });
7411
+ return record2;
7412
+ }),
7413
+ getResult: Effect21.fn("ToolCallRepository.memory.getResult")(function* (callId) {
7414
+ const tenantId2 = yield* current();
7415
+ return results.get(key2(tenantId2, callId));
7416
+ }),
7417
+ prepareExternalWait: Effect21.fn("ToolCallRepository.memory.prepareExternalWait")(function* (input) {
7418
+ const tenantId2 = yield* current();
7419
+ const call = yield* requireCall(tenantId2, input.callId);
7420
+ if (call.placement.kind !== "client" && call.placement.kind !== "remote") {
7421
+ return yield* transitionRejected(input.callId, "Tool placement is not external");
7422
+ }
7423
+ if (call.state === "waiting" && call.waitId === input.waitId)
7424
+ return call;
7425
+ if (call.state !== "requested")
7426
+ return yield* transitionRejected(input.callId, `Call is ${call.state}`);
7427
+ const updated = {
7428
+ ...call,
7429
+ state: "waiting",
7430
+ waitId: input.waitId,
7431
+ availableAt: input.availableAt,
7432
+ updatedAt: input.updatedAt
7433
+ };
7434
+ calls.set(key2(tenantId2, input.callId), updated);
7435
+ return updated;
7436
+ }),
7437
+ beginAttempt: Effect21.fn("ToolCallRepository.memory.beginAttempt")(function* (input) {
7438
+ const tenantId2 = yield* current();
7439
+ const call = yield* requireCall(tenantId2, input.callId);
7440
+ if (call.placement.kind !== "local" && call.placement.kind !== "mcp") {
7441
+ return yield* transitionRejected(input.callId, "Tool placement is not immediate");
7442
+ }
7443
+ if (call.state === "completed" || call.state === "failed") {
7444
+ return yield* transitionRejected(input.callId, `Call is ${call.state}`);
7445
+ }
7446
+ if (call.activeAttemptId !== undefined) {
7447
+ const active = attemptsFor(tenantId2, input.callId).find((attempt2) => attempt2.id === call.activeAttemptId);
7448
+ if (active?.state === "running") {
7449
+ replaceAttempt(tenantId2, { ...active, state: "abandoned", completedAt: input.startedAt });
7450
+ }
7451
+ }
7452
+ const attempt = appendAttempt(tenantId2, input.callId, input.startedAt);
7453
+ calls.set(key2(tenantId2, input.callId), {
7454
+ ...call,
7455
+ state: "running",
7456
+ activeAttemptId: attempt.id,
7457
+ updatedAt: input.startedAt
7458
+ });
7459
+ return attempt;
7460
+ }),
7461
+ acceptClientOutcome: Effect21.fn("ToolCallRepository.memory.acceptClientOutcome")(function* (input) {
7462
+ const tenantId2 = yield* current();
7463
+ const call = yield* requireCall(tenantId2, input.callId);
7464
+ if (call.executionId !== input.executionId || call.placement.kind !== "client") {
7465
+ return yield* transitionRejected(input.callId, "Client outcome does not match the call");
7466
+ }
7467
+ if (call.externalOutcome !== undefined) {
7468
+ if (!same(call.externalOutcome, input.outcome)) {
7469
+ return yield* Effect21.fail(new ToolOutcomeConflict({ id: input.callId }));
7470
+ }
7471
+ const attempt2 = attemptsFor(tenantId2, input.callId).find((item) => item.id === call.activeAttemptId);
7472
+ if (attempt2 === undefined)
7473
+ return yield* transitionRejected(input.callId, "Accepted attempt is missing");
7474
+ return { call, attempt: attempt2, duplicate: true };
7475
+ }
7476
+ if (call.state !== "waiting")
7477
+ return yield* transitionRejected(input.callId, `Call is ${call.state}`);
7478
+ const running = appendAttempt(tenantId2, input.callId, input.submittedAt);
7479
+ const attempt = {
7480
+ ...running,
7481
+ state: input.outcome.kind === "success" ? "completed" : "failed",
7482
+ ...input.outcome.kind === "failure" ? { error: input.outcome.message } : {},
7483
+ completedAt: input.submittedAt
7484
+ };
7485
+ replaceAttempt(tenantId2, attempt);
7486
+ const updated = {
7487
+ ...call,
7488
+ state: "submitted",
7489
+ activeAttemptId: attempt.id,
7490
+ externalOutcome: input.outcome,
7491
+ externalOutcomeAt: input.submittedAt,
7492
+ updatedAt: input.submittedAt
7493
+ };
7494
+ calls.set(key2(tenantId2, input.callId), updated);
7495
+ return { call: updated, attempt, duplicate: false };
7496
+ }),
7497
+ claimRemote: Effect21.fn("ToolCallRepository.memory.claimRemote")(function* (input) {
7498
+ const tenantId2 = yield* current();
7499
+ if (input.claimExpiresAt <= input.now) {
7500
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Claim expiry must be after now" }));
7501
+ }
7502
+ for (const [storageKey, call] of calls) {
7503
+ if (callTenants.get(storageKey) !== tenantId2 || call.placement.kind !== "remote" || call.state !== "running" || call.claimExpiresAt === undefined || call.claimExpiresAt > input.now) {
7504
+ continue;
7505
+ }
7506
+ const active = attemptsFor(tenantId2, call.call.id).find((attempt2) => attempt2.id === call.activeAttemptId);
7507
+ if (active?.state === "running") {
7508
+ replaceAttempt(tenantId2, { ...active, state: "expired", completedAt: input.now });
7509
+ }
7510
+ calls.set(storageKey, {
7511
+ ...call,
7512
+ state: "waiting",
7513
+ activeAttemptId: undefined,
7514
+ claimOwner: undefined,
7515
+ claimedAt: undefined,
7516
+ claimExpiresAt: undefined,
7517
+ updatedAt: input.now
7518
+ });
7519
+ }
7520
+ const candidate = [...calls.entries()].filter(([storageKey, call]) => callTenants.get(storageKey) === tenantId2 && call.placement.kind === "remote" && call.placement.queue === input.queue && call.state === "waiting" && call.availableAt <= input.now).map(([, call]) => call).toSorted((left, right) => left.availableAt - right.availableAt || left.createdAt - right.createdAt || left.call.id.localeCompare(right.call.id))[0];
7521
+ if (candidate === undefined)
7522
+ return;
7523
+ if (candidate.definition === undefined) {
7524
+ return yield* transitionRejected(candidate.call.id, "Remote call definition snapshot is missing");
7525
+ }
7526
+ const attempt = appendAttempt(tenantId2, candidate.call.id, input.now, {
7527
+ workerId: input.workerId,
7528
+ claimExpiresAt: input.claimExpiresAt
7529
+ });
7530
+ const updated = {
7531
+ ...candidate,
7532
+ definition: candidate.definition,
7533
+ state: "running",
7534
+ activeAttemptId: attempt.id,
7535
+ claimOwner: input.workerId,
7536
+ claimedAt: input.now,
7537
+ claimExpiresAt: input.claimExpiresAt,
7538
+ updatedAt: input.now
7539
+ };
7540
+ calls.set(key2(tenantId2, candidate.call.id), updated);
7541
+ return {
7542
+ call: updated,
7543
+ attempt,
7544
+ queue: input.queue,
7545
+ workerId: input.workerId,
7546
+ claimExpiresAt: input.claimExpiresAt,
7547
+ idempotencyKey: updated.idempotencyKey
7548
+ };
7549
+ }),
7550
+ releaseRemote: Effect21.fn("ToolCallRepository.memory.releaseRemote")(function* (input) {
7551
+ const tenantId2 = yield* current();
7552
+ const call = yield* requireCall(tenantId2, input.callId);
7553
+ const valid = call.placement.kind === "remote" && call.state === "running" && call.activeAttemptId === input.attemptId && call.claimOwner === input.workerId && call.claimExpiresAt !== undefined && call.claimExpiresAt > input.releasedAt;
7554
+ if (!valid)
7555
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote claim is not active" }));
7556
+ const attempt = attemptsFor(tenantId2, input.callId).find((item) => item.id === input.attemptId);
7557
+ if (attempt === undefined)
7558
+ return yield* transitionRejected(input.callId, "Remote attempt is missing");
7559
+ replaceAttempt(tenantId2, {
7560
+ ...attempt,
7561
+ state: "released",
7562
+ ...input.error === undefined ? {} : { error: input.error },
7563
+ completedAt: input.releasedAt
7564
+ });
7565
+ const updated = {
7566
+ ...call,
7567
+ state: "waiting",
7568
+ availableAt: input.nextAvailableAt,
7569
+ activeAttemptId: undefined,
7570
+ claimOwner: undefined,
7571
+ claimedAt: undefined,
7572
+ claimExpiresAt: undefined,
7573
+ updatedAt: input.releasedAt
7574
+ };
7575
+ calls.set(key2(tenantId2, input.callId), updated);
7576
+ return updated;
7577
+ }),
7578
+ acceptRemoteOutcome: Effect21.fn("ToolCallRepository.memory.acceptRemoteOutcome")(function* (input) {
7579
+ const tenantId2 = yield* current();
7580
+ const call = yield* requireCall(tenantId2, input.callId);
7581
+ if (call.externalOutcome !== undefined) {
7582
+ if (!same(call.externalOutcome, input.outcome)) {
7583
+ return yield* Effect21.fail(new ToolOutcomeConflict({ id: input.callId }));
7584
+ }
7585
+ if (call.activeAttemptId !== input.attemptId) {
7586
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote attempt was not accepted" }));
7587
+ }
7588
+ const attempt2 = attemptsFor(tenantId2, input.callId).find((item) => item.id === input.attemptId);
7589
+ if (attempt2 === undefined || attempt2.callId !== input.callId || attempt2.workerId !== input.workerId) {
7590
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote attempt was not accepted" }));
7591
+ }
7592
+ return { call, attempt: attempt2, duplicate: true };
7593
+ }
7594
+ const valid = call.placement.kind === "remote" && call.state === "running" && call.activeAttemptId === input.attemptId && call.claimOwner === input.workerId && call.claimExpiresAt !== undefined && call.claimExpiresAt > input.submittedAt;
7595
+ if (!valid)
7596
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote claim is not active" }));
7597
+ const running = attemptsFor(tenantId2, input.callId).find((item) => item.id === input.attemptId);
7598
+ if (running === undefined)
7599
+ return yield* transitionRejected(input.callId, "Remote attempt is missing");
7600
+ const attempt = {
7601
+ ...running,
7602
+ state: input.outcome.kind === "success" ? "completed" : "failed",
7603
+ ...input.outcome.kind === "failure" ? { error: input.outcome.message } : {},
7604
+ completedAt: input.submittedAt
7605
+ };
7606
+ replaceAttempt(tenantId2, attempt);
7607
+ const updated = {
7608
+ ...call,
7609
+ state: "submitted",
7610
+ externalOutcome: input.outcome,
7611
+ externalOutcomeAt: input.submittedAt,
7612
+ claimOwner: undefined,
7613
+ claimedAt: undefined,
7614
+ claimExpiresAt: undefined,
7615
+ updatedAt: input.submittedAt
7616
+ };
7617
+ calls.set(key2(tenantId2, input.callId), updated);
7618
+ return { call: updated, attempt, duplicate: false };
6554
7619
  }),
6555
- listCalls: Effect21.fn("ToolCallRepository.memory.listCalls")(function* (executionId) {
6556
- return yield* Effect21.sync(() => [...calls.values()].filter((record2) => record2.executionId === executionId).toSorted((a, b) => a.createdAt - b.createdAt));
7620
+ listAttempts: Effect21.fn("ToolCallRepository.memory.listAttempts")(function* (callId) {
7621
+ const tenantId2 = yield* current();
7622
+ return attemptsFor(tenantId2, callId);
6557
7623
  }),
6558
- recordResult: Effect21.fn("ToolCallRepository.memory.recordResult")(function* (input) {
6559
- if (!calls.has(input.result.call_id))
6560
- return yield* Effect21.fail(new ToolCallNotFound({ id: input.result.call_id }));
6561
- if (results.has(input.result.call_id)) {
6562
- return yield* Effect21.fail(new DuplicateToolResult({ call_id: input.result.call_id }));
7624
+ failOpenForExecution: Effect21.fn("ToolCallRepository.memory.failOpenForExecution")(function* (input) {
7625
+ const tenantId2 = yield* current();
7626
+ const failed = [];
7627
+ for (const [storageKey, call] of calls) {
7628
+ if (callTenants.get(storageKey) !== tenantId2 || call.executionId !== input.executionId || input.callIds !== undefined && !input.callIds.includes(call.call.id) || call.state === "submitted" || call.state === "completed" || call.state === "failed") {
7629
+ continue;
7630
+ }
7631
+ if (call.activeAttemptId !== undefined) {
7632
+ const active = attemptsFor(tenantId2, call.call.id).find((attempt) => attempt.id === call.activeAttemptId);
7633
+ if (active?.state === "running") {
7634
+ replaceAttempt(tenantId2, {
7635
+ ...active,
7636
+ state: "failed",
7637
+ error: input.message,
7638
+ completedAt: input.failedAt
7639
+ });
7640
+ }
7641
+ }
7642
+ const updated = {
7643
+ ...call,
7644
+ state: "failed",
7645
+ claimOwner: undefined,
7646
+ claimedAt: undefined,
7647
+ claimExpiresAt: undefined,
7648
+ updatedAt: input.failedAt
7649
+ };
7650
+ calls.set(storageKey, updated);
7651
+ results.set(storageKey, {
7652
+ result: { call_id: call.call.id, output: null, error: input.message },
7653
+ createdAt: input.failedAt
7654
+ });
7655
+ failed.push(updated);
6563
7656
  }
6564
- const record2 = { result: input.result, createdAt: input.createdAt };
6565
- yield* Effect21.sync(() => results.set(input.result.call_id, record2));
6566
- return record2;
6567
- }),
6568
- getResult: Effect21.fn("ToolCallRepository.memory.getResult")(function* (callId) {
6569
- return yield* Effect21.sync(() => results.get(callId));
7657
+ return failed.toSorted((left, right) => left.createdAt - right.createdAt || left.call.id.localeCompare(right.call.id));
6570
7658
  })
6571
7659
  });
6572
7660
  });
6573
- var testLayer18 = (implementation) => Layer21.succeed(Service21, Service21.of(implementation));
7661
+ var unsupportedTestOperation = (operation) => Effect21.fail(new ToolCallRepositoryError({ message: `ToolCallRepository.testLayer does not implement ${operation}` }));
7662
+ var testLayer18 = (implementation) => Layer21.succeed(Service21, Service21.of({
7663
+ ensureCall: () => unsupportedTestOperation("ensureCall"),
7664
+ prepareExternalWait: () => unsupportedTestOperation("prepareExternalWait"),
7665
+ beginAttempt: () => unsupportedTestOperation("beginAttempt"),
7666
+ acceptClientOutcome: () => unsupportedTestOperation("acceptClientOutcome"),
7667
+ claimRemote: () => unsupportedTestOperation("claimRemote"),
7668
+ releaseRemote: () => unsupportedTestOperation("releaseRemote"),
7669
+ acceptRemoteOutcome: () => unsupportedTestOperation("acceptRemoteOutcome"),
7670
+ listAttempts: () => unsupportedTestOperation("listAttempts"),
7671
+ failOpenForExecution: () => unsupportedTestOperation("failOpenForExecution"),
7672
+ ...implementation
7673
+ }));
6574
7674
  var recordCall = Effect21.fn("ToolCallRepository.recordCall.call")(function* (input) {
6575
7675
  const repository = yield* Service21;
6576
7676
  return yield* repository.recordCall(input);
@@ -6591,6 +7691,42 @@ var getResult = Effect21.fn("ToolCallRepository.getResult.call")(function* (call
6591
7691
  const repository = yield* Service21;
6592
7692
  return yield* repository.getResult(callId);
6593
7693
  });
7694
+ var ensureCall = Effect21.fn("ToolCallRepository.ensureCall.call")(function* (input) {
7695
+ const repository = yield* Service21;
7696
+ return yield* repository.ensureCall(input);
7697
+ });
7698
+ var prepareExternalWait = Effect21.fn("ToolCallRepository.prepareExternalWait.call")(function* (input) {
7699
+ const repository = yield* Service21;
7700
+ return yield* repository.prepareExternalWait(input);
7701
+ });
7702
+ var beginAttempt = Effect21.fn("ToolCallRepository.beginAttempt.call")(function* (input) {
7703
+ const repository = yield* Service21;
7704
+ return yield* repository.beginAttempt(input);
7705
+ });
7706
+ var acceptClientOutcome = Effect21.fn("ToolCallRepository.acceptClientOutcome.call")(function* (input) {
7707
+ const repository = yield* Service21;
7708
+ return yield* repository.acceptClientOutcome(input);
7709
+ });
7710
+ var claimRemote = Effect21.fn("ToolCallRepository.claimRemote.call")(function* (input) {
7711
+ const repository = yield* Service21;
7712
+ return yield* repository.claimRemote(input);
7713
+ });
7714
+ var releaseRemote = Effect21.fn("ToolCallRepository.releaseRemote.call")(function* (input) {
7715
+ const repository = yield* Service21;
7716
+ return yield* repository.releaseRemote(input);
7717
+ });
7718
+ var acceptRemoteOutcome = Effect21.fn("ToolCallRepository.acceptRemoteOutcome.call")(function* (input) {
7719
+ const repository = yield* Service21;
7720
+ return yield* repository.acceptRemoteOutcome(input);
7721
+ });
7722
+ var listAttempts = Effect21.fn("ToolCallRepository.listAttempts.call")(function* (callId) {
7723
+ const repository = yield* Service21;
7724
+ return yield* repository.listAttempts(callId);
7725
+ });
7726
+ var failOpenForExecution = Effect21.fn("ToolCallRepository.failOpenForExecution.call")(function* (input) {
7727
+ const repository = yield* Service21;
7728
+ return yield* repository.failOpenForExecution(input);
7729
+ });
6594
7730
  // ../store-sql/src/workspace/workspace-lease-repository.ts
6595
7731
  var exports_workspace_lease_repository = {};
6596
7732
  __export(exports_workspace_lease_repository, {
@@ -7285,6 +8421,7 @@ __export(exports_tool_runtime_service, {
7285
8421
  tool: () => tool,
7286
8422
  testLayer: () => testLayer23,
7287
8423
  run: () => run,
8424
+ remoteTool: () => remoteTool,
7288
8425
  registeredTools: () => registeredTools,
7289
8426
  register: () => register2,
7290
8427
  memoryLayerFromToolkit: () => memoryLayerFromToolkit,
@@ -7293,6 +8430,7 @@ __export(exports_tool_runtime_service, {
7293
8430
  layer: () => layer23,
7294
8431
  dynamicTool: () => dynamicTool,
7295
8432
  definitions: () => definitions,
8433
+ clientTool: () => clientTool,
7296
8434
  ToolRuntimeError: () => ToolRuntimeError,
7297
8435
  ToolPermissionDenied: () => ToolPermissionDenied,
7298
8436
  ToolNotRegistered: () => ToolNotRegistered,
@@ -7317,6 +8455,7 @@ __export(exports_event_log_service, {
7317
8455
  layerFromRepository: () => layerFromRepository2,
7318
8456
  findFirstByTypeAfterSequence: () => findFirstByTypeAfterSequence2,
7319
8457
  findBySequenceOrCursor: () => findBySequenceOrCursor2,
8458
+ findBySequence: () => findBySequence2,
7320
8459
  findByCursor: () => findByCursor2,
7321
8460
  appendIdempotentTo: () => appendIdempotentTo,
7322
8461
  appendIdempotent: () => appendIdempotent,
@@ -7472,6 +8611,7 @@ var layerFromRepository2 = Layer24.effect(Service24, Effect26.gen(function* () {
7472
8611
  stream: (input) => Stream3.unwrap(loadReplay(input).pipe(Effect26.map(({ history, sequence }) => Stream3.fromIterable(history).pipe(Stream3.concat(liveTail(repository, pubsub, input, history.at(-1)?.sequence ?? sequence, pollInterval).pipe(Stream3.takeUntil(isTerminal))))))),
7473
8612
  findBySequenceOrCursor: Effect26.fn("EventLog.repository.findBySequenceOrCursor")((input) => repository.findBySequenceOrCursor(input).pipe(Effect26.mapError(mapRepositoryFindError))),
7474
8613
  findByCursor: Effect26.fn("EventLog.repository.findByCursor")((input) => repository.findByCursor(input).pipe(Effect26.mapError(mapRepositoryFindError))),
8614
+ findBySequence: Effect26.fn("EventLog.repository.findBySequence")((input) => repository.findBySequence(input).pipe(Effect26.mapError(mapRepositoryFindError))),
7475
8615
  findFirstByTypeAfterSequence: Effect26.fn("EventLog.repository.findFirstByTypeAfterSequence")((input) => repository.findFirstByTypeAfterSequence(input).pipe(Effect26.mapError(mapRepositoryFindError))),
7476
8616
  maxSequence: Effect26.fn("EventLog.repository.maxSequence")((executionId) => repository.maxSequence(executionId).pipe(Effect26.mapError(mapRepositoryFindError))),
7477
8617
  sumUsage: Effect26.fn("EventLog.repository.sumUsage")((executionId) => repository.sumUsage(executionId).pipe(Effect26.mapError(mapRepositoryFindError)))
@@ -7531,6 +8671,11 @@ var memoryLayer21 = Layer24.effect(Service24, Effect26.gen(function* () {
7531
8671
  const event = executionEvents.find((item) => item.cursor === input.cursor);
7532
8672
  return event === undefined ? Option4.none() : Option4.some(event);
7533
8673
  }),
8674
+ findBySequence: Effect26.fn("EventLog.memory.findBySequence")(function* (input) {
8675
+ const executionEvents = yield* allEvents(input.executionId);
8676
+ const event = executionEvents.find((item) => item.sequence === input.sequence);
8677
+ return event === undefined ? Option4.none() : Option4.some(event);
8678
+ }),
7534
8679
  findFirstByTypeAfterSequence: Effect26.fn("EventLog.memory.findFirstByTypeAfterSequence")(function* (input) {
7535
8680
  const executionEvents = yield* allEvents(input.executionId);
7536
8681
  const event = executionEvents.find((item) => item.type === input.type && item.sequence > input.afterSequence);
@@ -7575,6 +8720,10 @@ var findByCursor2 = Effect26.fn("EventLog.findByCursor.call")(function* (input)
7575
8720
  const service = yield* Service24;
7576
8721
  return yield* service.findByCursor(input);
7577
8722
  });
8723
+ var findBySequence2 = Effect26.fn("EventLog.findBySequence.call")(function* (input) {
8724
+ const service = yield* Service24;
8725
+ return yield* service.findBySequence(input);
8726
+ });
7578
8727
  var findFirstByTypeAfterSequence2 = Effect26.fn("EventLog.findFirstByTypeAfterSequence.call")(function* (input) {
7579
8728
  const service = yield* Service24;
7580
8729
  return yield* service.findFirstByTypeAfterSequence(input);
@@ -7890,6 +9039,11 @@ var requestedEvent = (input) => ({
7890
9039
  },
7891
9040
  created_at: input.createdAt
7892
9041
  });
9042
+ var sameToolEventPayload = (left, right) => left.id === right.id && left.execution_id === right.execution_id && left.child_execution_id === right.child_execution_id && left.type === right.type && left.cursor === right.cursor && left.created_at === right.created_at && exports_shared_schema.canonicalString(left.data ?? {}) === exports_shared_schema.canonicalString(right.data ?? {});
9043
+ var ensureToolEvent = (eventLog, event) => eventLog.findByCursor({ executionId: event.execution_id, cursor: event.cursor }).pipe(Effect28.mapError(mapEventLogError2), Effect28.flatMap(Option6.match({
9044
+ onNone: () => appendIdempotentTo(eventLog, event).pipe(Effect28.mapError(mapEventLogError2), Effect28.asVoid),
9045
+ onSome: (existing) => sameToolEventPayload(existing, event) ? Effect28.void : Effect28.fail(new ToolRuntimeError({ message: "EventLogError" }))
9046
+ })));
7893
9047
  var resultEvent = (input, result) => ({
7894
9048
  id: exports_ids_schema.EventId.make(`event:${input.call.id}:tool-result`),
7895
9049
  execution_id: input.executionId,
@@ -7941,13 +9095,17 @@ var runHandledToolkitTool = (toolkit, name, input) => toolkit.handle(name, input
7941
9095
  onNone: () => Effect28.fail("Tool handler did not produce a final result"),
7942
9096
  onSome: (result) => result.isFailure ? Effect28.fail(result.result) : Effect28.succeed(jsonValue(result.encodedResult))
7943
9097
  })));
7944
- var finalToolResult = (tool, input) => Effect28.gen(function* () {
9098
+ var finalToolResult = (tool, input, idempotencyKey) => Effect28.gen(function* () {
9099
+ if (tool.run === undefined) {
9100
+ return yield* Effect28.fail(new ToolRuntimeError({ message: `Tool ${tool.definition.name} has no local handler` }));
9101
+ }
7945
9102
  const context = {
7946
9103
  executionId: input.executionId,
7947
9104
  call: input.call,
7948
9105
  permissions: input.permissions,
7949
9106
  eventSequence: input.eventSequence,
7950
- createdAt: input.createdAt
9107
+ createdAt: input.createdAt,
9108
+ idempotencyKey
7951
9109
  };
7952
9110
  const callInfo = ToolCallInfo.of(context);
7953
9111
  const output = yield* tool.run(input.call.input, context).pipe(Effect28.provideService(ToolCallInfo, callInfo), Effect28.mapError((error) => preserveToolError(input.call.name, error)));
@@ -8021,11 +9179,17 @@ var resolveApproval = (waits, eventLog, input) => Effect28.gen(function* () {
8021
9179
  return { _tag: "approved" };
8022
9180
  return { _tag: "denied", reason: deniedReason(existing.state) };
8023
9181
  });
8024
- var recordRequested = (repository, eventLog, input) => repository.getCall(input.call.id).pipe(Effect28.mapError(mapRepositoryError4), Effect28.flatMap((existing) => {
8025
- if (existing !== undefined)
8026
- return Effect28.void;
8027
- return repository.recordCall({ executionId: input.executionId, call: input.call, createdAt: input.createdAt }).pipe(Effect28.mapError(mapRepositoryError4), Effect28.flatMap(() => appendIdempotentTo(eventLog, requestedEvent(input)).pipe(Effect28.mapError(mapEventLogError2))), Effect28.asVoid);
8028
- }));
9182
+ var recordRequested = (repository, eventLog, input, tool) => repository.ensureCall({
9183
+ executionId: input.executionId,
9184
+ call: input.call,
9185
+ definition: tool.definition,
9186
+ placement: tool.placement ?? { kind: "local" },
9187
+ createdAt: input.createdAt
9188
+ }).pipe(Effect28.mapError(mapRepositoryError4), Effect28.tap((call) => ensureToolEvent(eventLog, requestedEvent({ ...input, createdAt: call.createdAt }))));
9189
+ var repairResultEvent = (eventLog, input, record2) => {
9190
+ const event = resultEvent({ ...input, createdAt: record2.createdAt - 1 }, record2.result);
9191
+ return ensureToolEvent(eventLog, event);
9192
+ };
8029
9193
  var recordReceived = (repository, eventLog, input, result) => repository.recordResult({ result, createdAt: input.createdAt + 1 }).pipe(Effect28.catchTag("DuplicateToolResult", () => repository.getResult(result.call_id).pipe(Effect28.mapError(mapRepositoryError4), Effect28.flatMap((existing) => existing === undefined ? Effect28.fail(new ToolRuntimeError({ message: "DuplicateToolResult" })) : Effect28.succeed(existing)))), Effect28.mapError(preserveRecordResultError), Effect28.flatMap((record2) => appendIdempotentTo(eventLog, resultEvent(input, record2.result)).pipe(Effect28.mapError(mapEventLogError2), Effect28.as(record2.result))));
8030
9194
  var nonEmptyName = (name) => Schema35.decodeUnknownSync(exports_shared_schema.NonEmptyString)(name);
8031
9195
  var needsApprovalFromEffectTool = (tool) => tool.needsApproval === undefined ? undefined : typeof tool.needsApproval === "boolean" ? tool.needsApproval : true;
@@ -8046,6 +9210,7 @@ var registeredToolFromToolkit = (toolkit, modelTool, options = {}) => {
8046
9210
  return {
8047
9211
  definition: definitionFromEffectTool(modelTool, { ...toolOptions, needsApproval }),
8048
9212
  tool: modelTool,
9213
+ ...toolOptions.placement === undefined ? {} : { placement: toolOptions.placement },
8049
9214
  ...toolOptions.requiredPermissions === undefined ? {} : { requiredPermissions: toolOptions.requiredPermissions },
8050
9215
  validateInput: (input) => Schema35.decodeUnknownEffect(parametersSchemaFromEffectTool(modelTool))(input).pipe(Effect28.mapError((error) => new ToolInputInvalid({ tool_name: modelTool.name, message: error.message })), Effect28.asVoid),
8051
9216
  run: (input) => runHandledToolkitTool(toolkit, modelTool.name, input)
@@ -8064,6 +9229,7 @@ var tool = (name, options) => {
8064
9229
  return {
8065
9230
  definition,
8066
9231
  tool: effectTool,
9232
+ ...options.placement === undefined ? {} : { placement: options.placement },
8067
9233
  ...options.requiredPermissions === undefined ? {} : { requiredPermissions: options.requiredPermissions },
8068
9234
  validateInput: (input) => Schema35.decodeUnknownEffect(options.input)(input).pipe(Effect28.mapError((error) => new ToolInputInvalid({ tool_name: name, message: error.message })), Effect28.asVoid),
8069
9235
  run: (input, context) => Schema35.decodeUnknownEffect(options.input)(input).pipe(Effect28.flatMap((decoded) => options.run(decoded, context)), Effect28.flatMap(Schema35.encodeUnknownEffect(options.output)), Effect28.map(jsonValue))
@@ -8089,10 +9255,78 @@ var dynamicTool = (name, options) => {
8089
9255
  ...options.metadata === undefined ? {} : { metadata: options.metadata }
8090
9256
  },
8091
9257
  tool: modelTool,
9258
+ ...options.placement === undefined ? {} : { placement: options.placement },
8092
9259
  ...options.requiredPermissions === undefined ? {} : { requiredPermissions: options.requiredPermissions },
8093
9260
  run: options.run
8094
9261
  };
8095
9262
  };
9263
+ var placedTool = (modelTool, placement, options = {}) => ({
9264
+ definition: definitionFromEffectTool(modelTool, options),
9265
+ tool: modelTool,
9266
+ placement,
9267
+ ...options.requiredPermissions === undefined ? {} : { requiredPermissions: options.requiredPermissions },
9268
+ validateInput: (input) => Schema35.decodeUnknownEffect(parametersSchemaFromEffectTool(modelTool))(input).pipe(Effect28.mapError((error) => new ToolInputInvalid({ tool_name: modelTool.name, message: error.message })), Effect28.asVoid)
9269
+ });
9270
+ var clientTool = (modelTool, options = {}) => placedTool(modelTool, { kind: "client" }, options);
9271
+ var remoteTool = (modelTool, options) => placedTool(modelTool, { kind: "remote", queue: options.queue }, options);
9272
+ var placementWaitId = (input) => exports_ids_schema.WaitId.make(`wait:tool:${input.call.id}`);
9273
+ var placementFailureResult = (input, message) => ({
9274
+ call_id: input.call.id,
9275
+ output: null,
9276
+ error: message
9277
+ });
9278
+ var externalOutcomeResult = (call, input) => {
9279
+ if (call.definition === undefined) {
9280
+ return Effect28.fail(new ToolRuntimeError({ message: "Tool call definition snapshot is missing" }));
9281
+ }
9282
+ if (call.externalOutcome === undefined) {
9283
+ return Effect28.fail(new ToolRuntimeError({ message: "Resolved tool wait has no mirrored external outcome" }));
9284
+ }
9285
+ if (call.externalOutcome.kind === "failure") {
9286
+ return Effect28.succeed(placementFailureResult(input, call.externalOutcome.message));
9287
+ }
9288
+ const placement = call.placement.kind;
9289
+ return Schema35.decodeUnknownEffect(exports_tool_schema.resultSchema(call.definition.output_schema))(call.externalOutcome.output).pipe(Effect28.map((output) => ({ call_id: input.call.id, output: jsonValue(output) })), Effect28.catch((error) => Effect28.succeed(placementFailureResult(input, `invalid ${placement} result: ${error.message}`))));
9290
+ };
9291
+ var runExternalTool = (repository, waits, call, input) => Effect28.gen(function* () {
9292
+ const waitId = placementWaitId(input);
9293
+ let wait = yield* waits.get(waitId).pipe(Effect28.mapError(mapWaitServiceError));
9294
+ if (wait === undefined) {
9295
+ wait = yield* waits.createDetached({
9296
+ waitId,
9297
+ executionId: input.executionId,
9298
+ mode: "event",
9299
+ correlationKey: input.call.id,
9300
+ metadata: {
9301
+ kind: "tool-placement",
9302
+ tool_call_id: input.call.id,
9303
+ tool_name: input.call.name,
9304
+ placement: call.placement
9305
+ },
9306
+ eventSequence: input.eventSequence + 1,
9307
+ createdAt: input.createdAt
9308
+ }).pipe(Effect28.mapError(mapWaitServiceError));
9309
+ }
9310
+ const waitingCall = call.state === "requested" ? yield* repository.prepareExternalWait({
9311
+ callId: input.call.id,
9312
+ waitId,
9313
+ availableAt: input.createdAt,
9314
+ updatedAt: input.createdAt
9315
+ }).pipe(Effect28.mapError(mapRepositoryError4)) : call;
9316
+ if (wait.state === "open")
9317
+ return yield* waitRequested(input, waitId);
9318
+ if (wait.state === "timed_out")
9319
+ return placementFailureResult(input, "Tool execution timed out");
9320
+ if (wait.state === "cancelled")
9321
+ return placementFailureResult(input, "Tool execution cancelled");
9322
+ const repairedCall = waitingCall.externalOutcome === undefined && waitingCall.placement.kind === "client" ? yield* Schema35.decodeUnknownEffect(exports_tool_schema.ExternalOutcome)(wait.metadata.external_outcome).pipe(Effect28.mapError((error) => new ToolRuntimeError({ message: error.message })), Effect28.flatMap((outcome) => repository.acceptClientOutcome({
9323
+ executionId: input.executionId,
9324
+ callId: input.call.id,
9325
+ outcome,
9326
+ submittedAt: wait.resolvedAt ?? input.createdAt
9327
+ }).pipe(Effect28.mapError(mapRepositoryError4), Effect28.map((accepted2) => accepted2.call)))) : waitingCall;
9328
+ return yield* externalOutcomeResult(repairedCall, input);
9329
+ });
8096
9330
  var makeService = (initialTools) => Effect28.gen(function* () {
8097
9331
  const repository = yield* exports_tool_call_repository.Service;
8098
9332
  const eventLog = yield* Service24;
@@ -8109,13 +9343,15 @@ var makeService = (initialTools) => Effect28.gen(function* () {
8109
9343
  if (registeredTool === undefined) {
8110
9344
  return yield* Effect28.fail(new ToolNotRegistered({ tool_name: input.call.name }));
8111
9345
  }
8112
- const existingResult = yield* repository.getResult(input.call.id).pipe(Effect28.mapError(mapRepositoryError4));
8113
- if (existingResult !== undefined)
8114
- return existingResult.result;
8115
9346
  return yield* Effect28.gen(function* () {
8116
9347
  yield* ensureAllowed(registeredTool, input);
8117
9348
  yield* validateInput(registeredTool, input);
8118
- yield* recordRequested(repository, eventLog, input);
9349
+ const call = yield* recordRequested(repository, eventLog, input, registeredTool);
9350
+ const existingResult = yield* repository.getResult(input.call.id).pipe(Effect28.mapError(mapRepositoryError4));
9351
+ if (existingResult !== undefined) {
9352
+ yield* repairResultEvent(eventLog, input, existingResult);
9353
+ return existingResult.result;
9354
+ }
8119
9355
  let effectiveInput = input;
8120
9356
  if (registeredTool.definition.needs_approval === true) {
8121
9357
  const bypass = yield* hasPermissionApprovalBypass(waits, input);
@@ -8133,7 +9369,7 @@ var makeService = (initialTools) => Effect28.gen(function* () {
8133
9369
  }
8134
9370
  }
8135
9371
  }
8136
- const rawResult = yield* finalToolResult(registeredTool, effectiveInput);
9372
+ const rawResult = call.placement.kind === "client" || call.placement.kind === "remote" ? yield* runExternalTool(repository, waits, call, effectiveInput) : yield* repository.beginAttempt({ callId: input.call.id, startedAt: effectiveInput.createdAt }).pipe(Effect28.mapError(mapRepositoryError4), Effect28.flatMap(() => finalToolResult(registeredTool, effectiveInput, call.idempotencyKey)), Effect28.catchTag("ToolExecutionFailed", (error) => Effect28.succeed(placementFailureResult(input, error.message))));
8137
9373
  const result = input.transformResult === undefined || rawResult.error !== undefined ? rawResult : yield* input.transformResult(rawResult);
8138
9374
  const received = yield* recordReceived(repository, eventLog, effectiveInput, result);
8139
9375
  yield* recordToolCall(input.call.name, result.error === undefined ? "success" : "failure");
@@ -8213,12 +9449,53 @@ var firstDuplicate = (values) => {
8213
9449
  };
8214
9450
  var missingFrom = (values, allowed) => values.find((value) => !HashSet4.has(allowed, value));
8215
9451
  var transferToolName = (name) => `transfer_to_${name.trim().toLowerCase().replaceAll(/[^a-z0-9]+/g, "_").replaceAll(/^_+|_+$/g, "")}`;
9452
+ var validateTurnPolicySnapshot = Effect29.fn("AgentRegistry.validateTurnPolicySnapshot")(function* (snapshot) {
9453
+ if (snapshot === undefined)
9454
+ return;
9455
+ const decoded = yield* Schema36.decodeUnknownEffect(exports_agent_schema.TurnPolicySnapshot)(snapshot).pipe(Effect29.mapError(() => new AgentDefinitionInvalid({ message: "definition.turn_policy must be a valid turn policy snapshot" })));
9456
+ let nodes = 0;
9457
+ const pending = [
9458
+ { snapshot: decoded, depth: 1 }
9459
+ ];
9460
+ while (pending.length > 0) {
9461
+ const current2 = pending.pop();
9462
+ if (current2 === undefined)
9463
+ continue;
9464
+ nodes += 1;
9465
+ if (current2.depth > exports_agent_schema.maxTurnPolicySnapshotDepth) {
9466
+ return yield* Effect29.fail(new AgentDefinitionInvalid({
9467
+ message: `definition.turn_policy depth exceeds ${exports_agent_schema.maxTurnPolicySnapshotDepth}`
9468
+ }));
9469
+ }
9470
+ if (nodes > exports_agent_schema.maxTurnPolicySnapshotNodes) {
9471
+ return yield* Effect29.fail(new AgentDefinitionInvalid({
9472
+ message: `definition.turn_policy node count exceeds ${exports_agent_schema.maxTurnPolicySnapshotNodes}`
9473
+ }));
9474
+ }
9475
+ switch (current2.snapshot.kind) {
9476
+ case "recurs":
9477
+ if (!Number.isInteger(current2.snapshot.count) || current2.snapshot.count < 0) {
9478
+ return yield* Effect29.fail(new AgentDefinitionInvalid({
9479
+ message: "definition.turn_policy recurs count must be a non-negative integer"
9480
+ }));
9481
+ }
9482
+ break;
9483
+ case "until-tool-call":
9484
+ yield* requireText(current2.snapshot.name, "definition.turn_policy until-tool-call name");
9485
+ break;
9486
+ case "both":
9487
+ pending.push({ snapshot: current2.snapshot.second, depth: current2.depth + 1 }, { snapshot: current2.snapshot.first, depth: current2.depth + 1 });
9488
+ break;
9489
+ }
9490
+ }
9491
+ });
8216
9492
  var validateDefinition = Effect29.fn("AgentRegistry.validateDefinition")(function* (definition) {
8217
9493
  yield* requireText(definition.name, "definition.name");
8218
9494
  yield* requireOptionalText(definition.instructions, "definition.instructions");
8219
9495
  yield* requireText(definition.model.provider, "definition.model.provider");
8220
9496
  yield* requireText(definition.model.model, "definition.model.model");
8221
9497
  yield* requireOptionalText(definition.output_schema_ref, "definition.output_schema_ref");
9498
+ yield* validateTurnPolicySnapshot(definition.turn_policy);
8222
9499
  for (const toolName of definition.tool_names) {
8223
9500
  yield* requireText(toolName, "definition.tool_names[]");
8224
9501
  }
@@ -8420,7 +9697,7 @@ __export(exports_agent_loop_service, {
8420
9697
  testLayer: () => testLayer46,
8421
9698
  run: () => run3,
8422
9699
  mapBoundaryError: () => mapBoundaryError,
8423
- layer: () => layer44,
9700
+ layer: () => layer45,
8424
9701
  Service: () => Service41,
8425
9702
  STRUCTURED_TURN_PROMPT: () => STRUCTURED_TURN_PROMPT,
8426
9703
  AgentLoopWaitRequested: () => AgentLoopWaitRequested,
@@ -8428,7 +9705,7 @@ __export(exports_agent_loop_service, {
8428
9705
  AgentLoopBudgetExceeded: () => AgentLoopBudgetExceeded
8429
9706
  });
8430
9707
 
8431
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/agent.ts
9708
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/agent.ts
8432
9709
  var exports_agent = {};
8433
9710
  __export(exports_agent, {
8434
9711
  streamObject: () => streamObject,
@@ -8439,9 +9716,9 @@ __export(exports_agent, {
8439
9716
  defaultObjectPrompt: () => defaultObjectPrompt
8440
9717
  });
8441
9718
  import { Cause as Cause3, Effect as Effect46, Fiber, Option as Option16, Queue as Queue2, Ref as Ref11, Schema as Schema48, Stream as Stream7 } from "effect";
8442
- import { Chat, LanguageModel as LanguageModel4, Prompt as Prompt4, Response as Response3, Telemetry, Tokenizer as Tokenizer2, Tool as Tool4, Toolkit as Toolkit3 } from "effect/unstable/ai";
9719
+ import { Chat, LanguageModel as LanguageModel4, Prompt as Prompt4, Response as Response3, Telemetry, Tokenizer as Tokenizer2, Tool as Tool3, Toolkit as Toolkit3 } from "effect/unstable/ai";
8443
9720
 
8444
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/agent-event.ts
9721
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/agent-event.ts
8445
9722
  var exports_agent_event = {};
8446
9723
  __export(exports_agent_event, {
8447
9724
  addUsage: () => addUsage,
@@ -8498,7 +9775,7 @@ class AgentSuspended extends Schema38.TaggedErrorClass()("@batonfx/core/AgentSus
8498
9775
  }) {
8499
9776
  }
8500
9777
 
8501
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/approvals.ts
9778
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/approvals.ts
8502
9779
  var exports_approvals = {};
8503
9780
  __export(exports_approvals, {
8504
9781
  testLayer: () => testLayer26,
@@ -8514,25 +9791,30 @@ var autoApprove = Layer29.succeed(Approvals, Approvals.of({ check: () => Effect3
8514
9791
  var denyAll = Layer29.succeed(Approvals, Approvals.of({ check: () => Effect31.succeed({ _tag: "Denied" }) }));
8515
9792
  var testLayer26 = (implementation) => Layer29.succeed(Approvals, Approvals.of(implementation));
8516
9793
 
8517
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/compaction.ts
9794
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/compaction.ts
8518
9795
  var exports_compaction = {};
8519
9796
  __export(exports_compaction, {
8520
9797
  truncate: () => truncate,
9798
+ toolOutputBound: () => toolOutputBound,
8521
9799
  testLayer: () => testLayer29,
9800
+ structuredSummary: () => structuredSummary,
9801
+ strategy: () => strategy,
8522
9802
  make: () => make2,
8523
9803
  layer: () => layer26,
9804
+ keepRecent: () => keepRecent,
8524
9805
  isContextOverflow: () => isContextOverflow,
8525
9806
  defaultStrategy: () => defaultStrategy,
8526
9807
  SUMMARY_TEMPLATE: () => SUMMARY_TEMPLATE,
8527
9808
  DEFAULT_RESERVE_TOKENS: () => DEFAULT_RESERVE_TOKENS,
8528
9809
  DEFAULT_KEEP_RECENT_TOKENS: () => DEFAULT_KEEP_RECENT_TOKENS,
8529
9810
  CompactionError: () => CompactionError,
8530
- Compaction: () => Compaction
9811
+ Compaction: () => Compaction,
9812
+ AgentSummary: () => AgentSummary
8531
9813
  });
8532
9814
  import { Context as Context32, Effect as Effect34, Layer as Layer32, Option as Option10, Schema as Schema41 } from "effect";
8533
9815
  import { LanguageModel, Prompt as Prompt3, Tokenizer, Toolkit as Toolkit2 } from "effect/unstable/ai";
8534
9816
 
8535
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/session.ts
9817
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/session.ts
8536
9818
  var exports_session = {};
8537
9819
  __export(exports_session, {
8538
9820
  testLayer: () => testLayer27,
@@ -8705,7 +9987,7 @@ var memoryLayer24 = Layer30.effect(SessionStore, Ref7.make(initialState).pipe(Ef
8705
9987
  }))));
8706
9988
  var testLayer27 = (implementation) => Layer30.succeed(SessionStore, SessionStore.of(implementation));
8707
9989
 
8708
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/tool-output.ts
9990
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/tool-output.ts
8709
9991
  var exports_tool_output = {};
8710
9992
  __export(exports_tool_output, {
8711
9993
  testLayer: () => testLayer28,
@@ -8765,7 +10047,7 @@ var bound = (result, options) => Effect33.gen(function* () {
8765
10047
  return { _tag: "Success", result: output, encodedResult: output };
8766
10048
  });
8767
10049
 
8768
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/compaction.ts
10050
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/compaction.ts
8769
10051
  var DEFAULT_RESERVE_TOKENS = 16384;
8770
10052
  var DEFAULT_KEEP_RECENT_TOKENS = 20000;
8771
10053
  var SUMMARY_TEMPLATE = `Summarize the conversation so another agent can continue seamlessly.
@@ -8783,6 +10065,13 @@ Use Markdown with these sections:
8783
10065
  ## Critical Context
8784
10066
 
8785
10067
  Do not mention that context was compacted.`;
10068
+ var AgentSummary = Schema41.Struct({
10069
+ goal: Schema41.String,
10070
+ facts: Schema41.Array(Schema41.String),
10071
+ decisions: Schema41.Array(Schema41.String),
10072
+ openQuestions: Schema41.Array(Schema41.String),
10073
+ toolFindings: Schema41.Array(Schema41.String)
10074
+ });
8786
10075
 
8787
10076
  class CompactionError extends Schema41.TaggedErrorClass()("@batonfx/core/CompactionError", {
8788
10077
  message: Schema41.String,
@@ -8796,6 +10085,27 @@ var serialized2 = (value) => {
8796
10085
  const json = JSON.stringify(value);
8797
10086
  return json === undefined ? String(value) : json;
8798
10087
  };
10088
+ var safeNonNegativeInteger = (name, value) => {
10089
+ if (!Number.isSafeInteger(value) || value < 0)
10090
+ throw new TypeError(`${name} must be a non-negative safe integer`);
10091
+ return value;
10092
+ };
10093
+ var markdownList = (items) => items.length === 0 ? "- None" : items.map((item) => `- ${item}`).join(`
10094
+ `);
10095
+ var renderAgentSummary = (summary) => [
10096
+ `## Goal
10097
+ ${summary.goal}`,
10098
+ `## Facts
10099
+ ${markdownList(summary.facts)}`,
10100
+ `## Decisions
10101
+ ${markdownList(summary.decisions)}`,
10102
+ `## Open Questions
10103
+ ${markdownList(summary.openQuestions)}`,
10104
+ `## Tool Findings
10105
+ ${markdownList(summary.toolFindings)}`
10106
+ ].join(`
10107
+
10108
+ `);
8799
10109
  var APPROX_CHARS_PER_TOKEN = 4;
8800
10110
  var estimateTokens = (text3) => Math.ceil(text3.length / APPROX_CHARS_PER_TOKEN);
8801
10111
  var estimateEntryTokens = (entry) => estimateTokens(serialized2(entry));
@@ -8856,7 +10166,7 @@ var summaryPrompt = (template, prompt) => Prompt3.make(`${template}
8856
10166
  Conversation to summarize:
8857
10167
  ${serialized2(prompt.content)}`);
8858
10168
  var systemMessages = (entries) => entries.flatMap((entry) => entry._tag === "Message" && entry.message.role === "system" ? [entry.message] : []);
8859
- var compactedHistory = (summary, head, recent) => Prompt3.concat(Prompt3.fromMessages([...systemMessages(head), checkpointMessage2(summary)]), buildContext(recent));
10169
+ var compactedHistory = (summary, head, recent) => Prompt3.concat(Prompt3.fromMessages([...systemMessages(head), checkpointMessage2(summary)]), recent);
8860
10170
  var normalizeUsage = (usage, options) => ({
8861
10171
  contextTokens: Number.isFinite(usage.contextTokens) ? usage.contextTokens : 0,
8862
10172
  contextWindow: Number.isFinite(usage.contextWindow) ? usage.contextWindow : options.contextWindow ?? Number.POSITIVE_INFINITY,
@@ -8900,38 +10210,77 @@ var defaultStrategy = (options = {}) => ({
8900
10210
  return options.summaryModel === undefined ? effect : effect.pipe(Effect34.provide(options.summaryModel));
8901
10211
  }
8902
10212
  });
8903
- var make2 = (strategy, options = {}) => ({
10213
+ var strategy = (parts, base = defaultStrategy()) => parts.reduce((current2, part) => ({
10214
+ shouldCompact: part.shouldCompact ?? current2.shouldCompact,
10215
+ cut: part.cut ?? current2.cut,
10216
+ summarize: part.summarize ?? current2.summarize,
10217
+ ...part.toolOutputMaxBytes !== undefined ? { toolOutputMaxBytes: part.toolOutputMaxBytes } : current2.toolOutputMaxBytes === undefined ? {} : { toolOutputMaxBytes: current2.toolOutputMaxBytes },
10218
+ ...part.keepRecentTokens !== undefined ? { keepRecentTokens: part.keepRecentTokens } : current2.keepRecentTokens === undefined ? {} : { keepRecentTokens: current2.keepRecentTokens }
10219
+ }), base);
10220
+ var toolOutputBound = (options) => ({
10221
+ toolOutputMaxBytes: safeNonNegativeInteger("ToolOutputBoundOptions.maxBytes", options.maxBytes)
10222
+ });
10223
+ var keepRecent = (options) => ({
10224
+ keepRecentTokens: safeNonNegativeInteger("KeepRecentOptions.tokens", options.tokens)
10225
+ });
10226
+ var structuredSummary = (options = {}) => ({
10227
+ summarize: (plan2, request) => {
10228
+ const effect = Effect34.gen(function* () {
10229
+ const head = buildContext(plan2.head);
10230
+ const [compactedHead] = request.toolOutputMaxBytes === undefined ? [head, false] : yield* microcompactPrompt(head, request.toolOutputMaxBytes);
10231
+ const prompt = summaryPrompt(options.summaryPrompt ?? SUMMARY_TEMPLATE, compactedHead);
10232
+ const model = yield* LanguageModel.LanguageModel;
10233
+ return yield* model.generateObject({
10234
+ prompt,
10235
+ schema: AgentSummary,
10236
+ objectName: options.objectName ?? "AgentSummary",
10237
+ toolChoice: "none"
10238
+ }).pipe(Effect34.map((response) => renderAgentSummary(response.value)), Effect34.mapError((error) => new CompactionError({ message: String(error), cause: error })));
10239
+ });
10240
+ return options.summaryModel === undefined ? effect : effect.pipe(Effect34.provide(options.summaryModel));
10241
+ }
10242
+ });
10243
+ var make2 = (compactionStrategy, options = {}) => ({
8904
10244
  maybeCompact: (input) => Effect34.gen(function* () {
8905
10245
  const usage = normalizeUsage(input.usage, options);
8906
- const shouldCompact = input.overflow || strategy.shouldCompact(usage);
10246
+ const shouldCompact = input.overflow || compactionStrategy.shouldCompact(usage);
8907
10247
  if (!shouldCompact)
8908
10248
  return Option10.none();
8909
10249
  let history = input.history;
8910
10250
  let prompt = input.prompt;
8911
10251
  let changed = false;
8912
- if (input.toolOutputMaxBytes !== undefined) {
8913
- const [compactedHistoryPrompt, historyChanged] = yield* microcompactPrompt(history, input.toolOutputMaxBytes);
8914
- const [compactedPrompt, promptChanged] = yield* microcompactPrompt(prompt, input.toolOutputMaxBytes);
10252
+ const toolOutputMaxBytes = input.toolOutputMaxBytes ?? compactionStrategy.toolOutputMaxBytes;
10253
+ if (toolOutputMaxBytes !== undefined) {
10254
+ const [compactedHistoryPrompt, historyChanged] = yield* microcompactPrompt(history, toolOutputMaxBytes);
10255
+ const [compactedPrompt, promptChanged] = yield* microcompactPrompt(prompt, toolOutputMaxBytes);
8915
10256
  history = compactedHistoryPrompt;
8916
10257
  prompt = compactedPrompt;
8917
10258
  changed = historyChanged || promptChanged;
8918
10259
  if (changed && fits(history, prompt, usage))
8919
10260
  return Option10.some(makeMicrocompact(history, prompt));
8920
10261
  }
8921
- const plan2 = strategy.cut(input.path ?? [], options.keepRecentTokens ?? DEFAULT_KEEP_RECENT_TOKENS);
10262
+ const plan2 = compactionStrategy.cut(input.path ?? [], compactionStrategy.keepRecentTokens ?? options.keepRecentTokens ?? DEFAULT_KEEP_RECENT_TOKENS);
8922
10263
  if (Option10.isNone(plan2))
8923
10264
  return changed ? Option10.some(makeMicrocompact(history, prompt)) : Option10.none();
8924
- const summary = yield* strategy.summarize(plan2.value, { ...input, history, prompt, usage });
10265
+ const summary = yield* compactionStrategy.summarize(plan2.value, {
10266
+ ...input,
10267
+ history,
10268
+ prompt,
10269
+ usage,
10270
+ ...toolOutputMaxBytes === undefined ? {} : { toolOutputMaxBytes }
10271
+ });
10272
+ const recent = buildContext(plan2.value.recent);
10273
+ const [compactedRecent] = toolOutputMaxBytes === undefined ? [recent, false] : yield* microcompactPrompt(recent, toolOutputMaxBytes);
8925
10274
  return Option10.some({
8926
10275
  _tag: "Summarize",
8927
- history: compactedHistory(summary, plan2.value.head, plan2.value.recent),
10276
+ history: compactedHistory(summary, plan2.value.head, compactedRecent),
8928
10277
  prompt,
8929
10278
  summary,
8930
10279
  firstKeptEntryId: plan2.value.firstKeptEntryId
8931
10280
  });
8932
10281
  })
8933
10282
  });
8934
- var layer26 = (options = {}, strategy = defaultStrategy(options)) => Layer32.succeed(Compaction, Compaction.of(make2(strategy, options)));
10283
+ var layer26 = (options = {}, providedStrategy = options.strategy ?? defaultStrategy(options)) => Layer32.succeed(Compaction, Compaction.of(make2(providedStrategy, options)));
8935
10284
  var truncate = (maxTokens) => ({
8936
10285
  maybeCompact: (input) => Effect34.gen(function* () {
8937
10286
  const usage = input.usage;
@@ -8948,7 +10297,7 @@ var truncate = (maxTokens) => ({
8948
10297
  var testLayer29 = (implementation) => Layer32.succeed(Compaction, Compaction.of(implementation));
8949
10298
  var isContextOverflow = (error) => /context|token|prompt/i.test(error instanceof Error ? `${error.name}: ${error.message}` : String(error)) && /overflow|exceed|exceeded|maximum|too large|too long|length/i.test(error instanceof Error ? `${error.name}: ${error.message}` : String(error));
8950
10299
 
8951
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/instructions.ts
10300
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/instructions.ts
8952
10301
  var exports_instructions = {};
8953
10302
  __export(exports_instructions, {
8954
10303
  testLayer: () => testLayer30,
@@ -8997,7 +10346,7 @@ var renderUpdate = (epoch, context) => Effect35.gen(function* () {
8997
10346
  var layer27 = (sources) => Layer33.succeed(Instructions, Instructions.of({ sources: [...sources] }));
8998
10347
  var testLayer30 = (implementation) => Layer33.succeed(Instructions, Instructions.of(implementation));
8999
10348
 
9000
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/memory.ts
10349
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/memory.ts
9001
10350
  var exports_memory = {};
9002
10351
  __export(exports_memory, {
9003
10352
  testLayer: () => testLayer31,
@@ -9028,7 +10377,7 @@ var merge = (first, second) => ({
9028
10377
  var noopLayer = Layer34.succeed(Memory, Memory.of(noop));
9029
10378
  var testLayer31 = (implementation) => Layer34.succeed(Memory, Memory.of(implementation));
9030
10379
 
9031
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/model-middleware.ts
10380
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/model-middleware.ts
9032
10381
  var exports_model_middleware = {};
9033
10382
  __export(exports_model_middleware, {
9034
10383
  layer: () => layer28,
@@ -9042,7 +10391,7 @@ class ModelMiddleware extends Context35.Service()("@batonfx/core/ModelMiddleware
9042
10391
  var identityLayer = Layer35.succeed(ModelMiddleware, []);
9043
10392
  var layer28 = (middleware) => Layer35.succeed(ModelMiddleware, middleware);
9044
10393
 
9045
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/model-registry.ts
10394
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/model-registry.ts
9046
10395
  var exports_model_registry = {};
9047
10396
  __export(exports_model_registry, {
9048
10397
  testLayer: () => testLayer32,
@@ -9131,7 +10480,7 @@ var provide = (selection, effect) => Effect38.gen(function* () {
9131
10480
  return yield* service.provide(selection, effect);
9132
10481
  });
9133
10482
 
9134
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/model-resilience.ts
10483
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/model-resilience.ts
9135
10484
  var exports_model_resilience = {};
9136
10485
  __export(exports_model_resilience, {
9137
10486
  testLayer: () => testLayer33,
@@ -9177,7 +10526,7 @@ var apply = (model, resilience) => ({
9177
10526
  }).pipe(Stream5.retry(retryStreamSchedule(resilience)))
9178
10527
  });
9179
10528
 
9180
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/permissions.ts
10529
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/permissions.ts
9181
10530
  var exports_permissions = {};
9182
10531
  __export(exports_permissions, {
9183
10532
  testLayer: () => testLayer34,
@@ -9307,12 +10656,14 @@ var ruleStoreMemory = (initialRules = []) => Layer38.effect(RuleStore, Ref10.mak
9307
10656
  var ruleStoreTestLayer = (implementation) => Layer38.succeed(RuleStore, RuleStore.of(implementation));
9308
10657
  var testLayer34 = (implementation) => Layer38.succeed(Permissions, Permissions.of(implementation));
9309
10658
 
9310
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/skill-source.ts
10659
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/skill-source.ts
9311
10660
  var exports_skill_source = {};
9312
10661
  __export(exports_skill_source, {
9313
10662
  testLayer: () => testLayer35,
9314
10663
  selectListings: () => selectListings,
10664
+ merge: () => merge2,
9315
10665
  makeListing: () => makeListing,
10666
+ layer: () => layer31,
9316
10667
  fromSkills: () => fromSkills,
9317
10668
  empty: () => empty,
9318
10669
  SkillSourceError: () => SkillSourceError,
@@ -9327,7 +10678,7 @@ class SkillSourceError extends Schema45.TaggedErrorClass()("@batonfx/core/SkillS
9327
10678
  cause: Schema45.optionalKey(Schema45.Defect())
9328
10679
  }) {
9329
10680
  }
9330
- var DESCRIPTION_CAP = 1536;
10681
+ var DESCRIPTION_CAP = 1024;
9331
10682
 
9332
10683
  class SkillSource extends Context39.Service()("@batonfx/core/SkillSource") {
9333
10684
  }
@@ -9342,6 +10693,25 @@ var fromSkills = (skills) => {
9342
10693
  };
9343
10694
  var empty = fromSkills([]);
9344
10695
  var testLayer35 = (implementation) => Layer39.succeed(SkillSource, SkillSource.of(implementation));
10696
+ var merge2 = (sources) => ({
10697
+ all: Effect41.forEach(sources, (source) => source.all).pipe(Effect41.map((groups) => {
10698
+ const byName = new Map;
10699
+ for (const skills of groups) {
10700
+ for (const skill of skills)
10701
+ byName.set(skill.frontmatter.name, skill);
10702
+ }
10703
+ return [...byName.values()];
10704
+ })),
10705
+ get: (name) => Effect41.gen(function* () {
10706
+ for (const source of sources.toReversed()) {
10707
+ const found = yield* source.get(name);
10708
+ if (found !== undefined)
10709
+ return found;
10710
+ }
10711
+ return;
10712
+ })
10713
+ });
10714
+ var layer31 = (sources) => Layer39.effect(SkillSource, Effect41.forEach(sources, (source) => source).pipe(Effect41.map((built) => SkillSource.of(merge2(built)))));
9345
10715
  var estimatedTokens = (listing) => Math.ceil(listing.length / 4);
9346
10716
  var usageRank = (skill, recentlyUsed) => {
9347
10717
  const index2 = recentlyUsed.indexOf(skill.frontmatter.name);
@@ -9365,11 +10735,11 @@ var selectListings = (skills, budgetTokens, recentlyUsed) => {
9365
10735
  return selected;
9366
10736
  };
9367
10737
 
9368
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/steering.ts
10738
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/steering.ts
9369
10739
  var exports_steering = {};
9370
10740
  __export(exports_steering, {
9371
10741
  testLayer: () => testLayer36,
9372
- layer: () => layer31,
10742
+ layer: () => layer32,
9373
10743
  SteeringQueueFull: () => SteeringQueueFull,
9374
10744
  Steering: () => Steering
9375
10745
  });
@@ -9388,8 +10758,8 @@ var resolvePolicy = (policy, mode) => ({
9388
10758
  ...policy?.capacity === undefined ? {} : { capacity: policy.capacity },
9389
10759
  onFull: policy?.onFull ?? "fail"
9390
10760
  });
9391
- var queueStrategy = (strategy) => {
9392
- switch (strategy) {
10761
+ var queueStrategy = (strategy2) => {
10762
+ switch (strategy2) {
9393
10763
  case "drop-oldest":
9394
10764
  return "sliding";
9395
10765
  case "drop-newest":
@@ -9410,7 +10780,7 @@ var drainOne = (queue) => Effect42.sync(() => {
9410
10780
  return taken === undefined || !Exit.isSuccess(taken) ? [] : [taken.value];
9411
10781
  });
9412
10782
  var drain = (queue, mode) => mode === "all" ? Queue.clear(queue) : drainOne(queue);
9413
- var layer31 = (options = {}) => Layer40.effect(Steering, Effect42.gen(function* () {
10783
+ var layer32 = (options = {}) => Layer40.effect(Steering, Effect42.gen(function* () {
9414
10784
  const steeringQueue = yield* makeQueue("steering", resolvePolicy(options.steering, "all"));
9415
10785
  const followUpQueue = yield* makeQueue("followUp", resolvePolicy(options.followUp, "one-at-a-time"));
9416
10786
  return Steering.of({
@@ -9422,7 +10792,7 @@ var layer31 = (options = {}) => Layer40.effect(Steering, Effect42.gen(function*
9422
10792
  }));
9423
10793
  var testLayer36 = (implementation) => Layer40.succeed(Steering, Steering.of(implementation));
9424
10794
 
9425
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/tool-context.ts
10795
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/tool-context.ts
9426
10796
  var exports_tool_context = {};
9427
10797
  __export(exports_tool_context, {
9428
10798
  testLayer: () => testLayer37,
@@ -9440,7 +10810,7 @@ var layerDefault = Layer41.sync(ToolContext, () => ToolContext.of({
9440
10810
  }));
9441
10811
  var testLayer37 = (implementation) => Layer41.succeed(ToolContext, ToolContext.of(implementation));
9442
10812
 
9443
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/tool-executor.ts
10813
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/tool-executor.ts
9444
10814
  var exports_tool_executor = {};
9445
10815
  __export(exports_tool_executor, {
9446
10816
  testLayer: () => testLayer38,
@@ -9566,7 +10936,7 @@ function router(routes) {
9566
10936
  }
9567
10937
  var testLayer38 = (implementation) => Layer42.succeed(ToolExecutor, ToolExecutor.of(implementation));
9568
10938
 
9569
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/turn-policy.ts
10939
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/turn-policy.ts
9570
10940
  var exports_turn_policy = {};
9571
10941
  __export(exports_turn_policy, {
9572
10942
  untilToolCall: () => untilToolCall,
@@ -9585,8 +10955,14 @@ var decision = {
9585
10955
  stop: { _tag: "Stop" }
9586
10956
  };
9587
10957
  var make4 = (decide) => ({ decide });
9588
- var recurs = (n) => make4((info) => Effect45.succeed(info.turn < n + 1 ? decision.continue() : decision.stop));
9589
- var untilToolCall = (name) => make4((info) => Effect45.succeed(info.pendingToolResults.some((result) => result.name === name) ? decision.stop : decision.continue()));
10958
+ var recurs = (n) => ({
10959
+ decide: (info) => Effect45.succeed(info.turn < n + 1 ? decision.continue() : decision.stop),
10960
+ ...Number.isFinite(n) ? { snapshot: { _tag: "Recurs", count: n } } : {}
10961
+ });
10962
+ var untilToolCall = (name) => ({
10963
+ decide: (info) => Effect45.succeed(info.pendingToolResults.some((result) => result.name === name) ? decision.stop : decision.continue()),
10964
+ snapshot: { _tag: "UntilToolCall", name }
10965
+ });
9590
10966
  var mergeOverrides = (first, second) => {
9591
10967
  if (first === undefined)
9592
10968
  return second;
@@ -9594,18 +10970,21 @@ var mergeOverrides = (first, second) => {
9594
10970
  return first;
9595
10971
  return { ...first, ...second };
9596
10972
  };
9597
- var both = (first, second) => make4((info) => Effect45.gen(function* () {
9598
- const left = yield* first.decide(info);
9599
- if (left._tag === "Stop")
9600
- return decision.stop;
9601
- const right = yield* second.decide(info);
9602
- if (right._tag === "Stop")
9603
- return decision.stop;
9604
- return decision.continue(mergeOverrides(left.overrides, right.overrides));
9605
- }));
10973
+ var both = (first, second) => ({
10974
+ decide: (info) => Effect45.gen(function* () {
10975
+ const left = yield* first.decide(info);
10976
+ if (left._tag === "Stop")
10977
+ return decision.stop;
10978
+ const right = yield* second.decide(info);
10979
+ if (right._tag === "Stop")
10980
+ return decision.stop;
10981
+ return decision.continue(mergeOverrides(left.overrides, right.overrides));
10982
+ }),
10983
+ ...first.snapshot === undefined || second.snapshot === undefined ? {} : { snapshot: { _tag: "Both", first: first.snapshot, second: second.snapshot } }
10984
+ });
9606
10985
  var defaultPolicy = recurs(8);
9607
10986
 
9608
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/agent.ts
10987
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/agent.ts
9609
10988
  function make5(nameOrOptions, options = {}) {
9610
10989
  const resolved = typeof nameOrOptions === "string" ? { ...options, name: nameOrOptions } : nameOrOptions;
9611
10990
  return {
@@ -9628,7 +11007,7 @@ var steeringDrainedEvent = (turn, queue, messages) => ({
9628
11007
  var skillListingBudgetTokens = 2048;
9629
11008
  var activateSkillToolName = "activate_skill";
9630
11009
  var activateSkillParameters = Schema48.Struct({ name: Schema48.String });
9631
- var activateSkillTool = Tool4.make(activateSkillToolName, {
11010
+ var activateSkillTool = Tool3.make(activateSkillToolName, {
9632
11011
  description: "Load the full body for one listed Baton skill by name before applying that skill.",
9633
11012
  parameters: activateSkillParameters,
9634
11013
  success: Schema48.Struct({
@@ -10302,13 +11681,13 @@ var generateObject = (agent, options) => Stream7.runFold(streamObject(agent, opt
10302
11681
  })
10303
11682
  })
10304
11683
  })));
10305
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/agent-tool.ts
11684
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/agent-tool.ts
10306
11685
  var exports_agent_tool = {};
10307
11686
  __export(exports_agent_tool, {
10308
11687
  asTool: () => asTool
10309
11688
  });
10310
11689
  import { Cause as Cause4, Effect as Effect47, Schema as Schema49 } from "effect";
10311
- import { Tool as Tool5, Toolkit as Toolkit4 } from "effect/unstable/ai";
11690
+ import { Tool as Tool4, Toolkit as Toolkit4 } from "effect/unstable/ai";
10312
11691
  var defaultParameters = Schema49.Struct({ prompt: Schema49.String });
10313
11692
  var errorMessage2 = (error) => {
10314
11693
  if (error instanceof AgentSuspended) {
@@ -10338,7 +11717,7 @@ var asTool = (agent, options = {}) => {
10338
11717
  const success2 = options.success ?? Schema49.String;
10339
11718
  const toPrompt = options.toPrompt ?? ((params) => params.prompt);
10340
11719
  const fromResult = options.fromResult ?? ((result) => result.text);
10341
- const tool2 = Tool5.make(name, {
11720
+ const tool2 = Tool4.make(name, {
10342
11721
  ...options.description === undefined ? {} : { description: options.description },
10343
11722
  parameters,
10344
11723
  success: success2,
@@ -10357,7 +11736,7 @@ var asTool = (agent, options = {}) => {
10357
11736
  });
10358
11737
  return lazyHandled(toolkit, name, handler);
10359
11738
  };
10360
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/guardrail.ts
11739
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/guardrail.ts
10361
11740
  var exports_guardrail = {};
10362
11741
  __export(exports_guardrail, {
10363
11742
  validateInput: () => validateInput2,
@@ -10437,7 +11816,7 @@ var redactOutput = (options) => ({
10437
11816
  var filterOutput = (keep) => ({
10438
11817
  transformPart: (part, context) => Effect48.succeed(part.type === "tool-call" || keep(part, context) ? Option17.some(part) : Option17.none())
10439
11818
  });
10440
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/handoff.ts
11819
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/handoff.ts
10441
11820
  var exports_handoff = {};
10442
11821
  __export(exports_handoff, {
10443
11822
  transferTool: () => transferTool,
@@ -10501,7 +11880,7 @@ var supervisor = (options) => {
10501
11880
  };
10502
11881
  };
10503
11882
 
10504
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/index.ts
11883
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/index.ts
10505
11884
  import {
10506
11885
  AiError as AiError3,
10507
11886
  Chat as Chat2,
@@ -10514,7 +11893,7 @@ import {
10514
11893
  ResponseIdTracker,
10515
11894
  Telemetry as Telemetry2,
10516
11895
  Tokenizer as Tokenizer3,
10517
- Tool as Tool7,
11896
+ Tool as Tool6,
10518
11897
  Toolkit as Toolkit6
10519
11898
  } from "effect/unstable/ai";
10520
11899
 
@@ -10530,7 +11909,7 @@ __export(exports_child_run_service, {
10530
11909
  spawnDynamic: () => spawnDynamic,
10531
11910
  resolveForDispatch: () => resolveForDispatch,
10532
11911
  memoryLayer: () => memoryLayer26,
10533
- layer: () => layer32,
11912
+ layer: () => layer33,
10534
11913
  childDefinition: () => childDefinition,
10535
11914
  StaticChildRunPresetNotFound: () => StaticChildRunPresetNotFound,
10536
11915
  Service: () => Service31,
@@ -10755,7 +12134,7 @@ var persistChild = Effect51.fn("ChildRunService.persistChild")(function* (reposi
10755
12134
  yield* eventLog.append(spawnedEvent(input, kind, context, presetName, workspaceRef)).pipe(Effect51.mapError(mapEventLogError3));
10756
12135
  return acceptedOutput(input);
10757
12136
  });
10758
- var layer32 = Layer45.effect(Service31, Effect51.gen(function* () {
12137
+ var layer33 = Layer45.effect(Service31, Effect51.gen(function* () {
10759
12138
  const repository = yield* exports_child_execution_repository.Service;
10760
12139
  const eventLog = yield* Service24;
10761
12140
  return Service31.of({
@@ -10789,7 +12168,7 @@ var layer32 = Layer45.effect(Service31, Effect51.gen(function* () {
10789
12168
  })
10790
12169
  });
10791
12170
  }));
10792
- var memoryLayer26 = layer32.pipe(Layer45.provide(exports_child_execution_repository.memoryLayer), Layer45.provide(memoryLayer21));
12171
+ var memoryLayer26 = layer33.pipe(Layer45.provide(exports_child_execution_repository.memoryLayer), Layer45.provide(memoryLayer21));
10793
12172
  var testLayer39 = (implementation) => Layer45.succeed(Service31, Service31.of(implementation));
10794
12173
  var agentContextFromSchema = (input) => ({
10795
12174
  toolNames: input.tool_names,
@@ -10831,6 +12210,10 @@ var childDefinition = (parentDefinition, context) => context.model === undefined
10831
12210
  tool_names: [...context.toolNames],
10832
12211
  permissions: parentDefinition.permissions.filter((permission) => context.permissions.includes(permission.name)),
10833
12212
  child_run_presets: {},
12213
+ ...parentDefinition.turn_policy === undefined ? {} : { turn_policy: parentDefinition.turn_policy },
12214
+ ...parentDefinition.max_tool_turns === undefined ? {} : { max_tool_turns: parentDefinition.max_tool_turns },
12215
+ ...parentDefinition.max_wait_turns === undefined ? {} : { max_wait_turns: parentDefinition.max_wait_turns },
12216
+ ...parentDefinition.token_budget === undefined ? {} : { token_budget: parentDefinition.token_budget },
10834
12217
  ...context.instructions === undefined ? {} : { instructions: context.instructions },
10835
12218
  ...context.outputSchemaRef === undefined ? {} : { output_schema_ref: context.outputSchemaRef }
10836
12219
  });
@@ -11094,14 +12477,14 @@ var resolveDefault = (registrations2, options) => {
11094
12477
  }
11095
12478
  return registrations2.length === 1 ? registrations2[0] : undefined;
11096
12479
  };
11097
- var registrationFromLayer2 = (input) => Model3.make(input.provider, input.model, input.layer).captureRequirements.pipe(Effect53.map((layer33) => toRegistration({
12480
+ var registrationFromLayer2 = (input) => Model3.make(input.provider, input.model, input.layer).captureRequirements.pipe(Effect53.map((layer34) => toRegistration({
11098
12481
  provider: input.provider,
11099
12482
  model: input.model,
11100
12483
  ...input.registrationKey === undefined ? {} : { registrationKey: input.registrationKey },
11101
- layer: layer33,
12484
+ layer: layer34,
11102
12485
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
11103
12486
  })));
11104
- var layer33 = (initialRegistrations = [], options) => Layer46.effect(Service32, Effect53.gen(function* () {
12487
+ var layer34 = (initialRegistrations = [], options) => Layer46.effect(Service32, Effect53.gen(function* () {
11105
12488
  const registry = yield* Ref13.make([...initialRegistrations]);
11106
12489
  const register5 = Effect53.fn("EmbeddingModelService.register")(function* (input) {
11107
12490
  const registration = toRegistration(input);
@@ -11130,8 +12513,8 @@ var layer33 = (initialRegistrations = [], options) => Layer46.effect(Service32,
11130
12513
  };
11131
12514
  return Service32.of({ register: register5, registrations: registrations2, provide: provide2, provideDefault, provideForAgent });
11132
12515
  }));
11133
- var layerFromRegistrationEffects2 = (registrations2, options) => Layer46.unwrap(Effect53.all(registrations2).pipe(Effect53.map((items) => layer33(items, options))));
11134
- var memoryLayer27 = layer33;
12516
+ var layerFromRegistrationEffects2 = (registrations2, options) => Layer46.unwrap(Effect53.all(registrations2).pipe(Effect53.map((items) => layer34(items, options))));
12517
+ var memoryLayer27 = layer34;
11135
12518
  var words = (input) => input.toLowerCase().match(/[a-z0-9]+/g) ?? [];
11136
12519
  var hashWord = (word) => {
11137
12520
  let hash = 2166136261;
@@ -11312,7 +12695,7 @@ var batonLayer = Layer47.effect(exports_memory.Memory, Effect54.gen(function* ()
11312
12695
  const service = yield* Service33;
11313
12696
  return exports_memory.Memory.of(service);
11314
12697
  }));
11315
- var layer34 = (options) => batonLayer.pipe(Layer47.provideMerge(serviceLayer(options)));
12698
+ var layer35 = (options) => batonLayer.pipe(Layer47.provideMerge(serviceLayer(options)));
11316
12699
  var recall = Effect54.fn("MemoryService.recall.call")(function* (input) {
11317
12700
  const service = yield* Service33;
11318
12701
  return yield* service.recall(input);
@@ -11337,7 +12720,7 @@ __export(exports_language_model_service, {
11337
12720
  provide: () => provide2,
11338
12721
  memoryLayer: () => memoryLayer28,
11339
12722
  layerFromRegistrationEffects: () => layerFromRegistrationEffects3,
11340
- layer: () => layer35,
12723
+ layer: () => layer36,
11341
12724
  Service: () => Service34,
11342
12725
  LanguageModelNotRegistered: () => LanguageModelNotRegistered2
11343
12726
  });
@@ -11352,7 +12735,7 @@ var toSelection = (selection) => ({
11352
12735
  class Service34 extends Context47.Service()("@relayfx/runtime/LanguageModelService") {
11353
12736
  }
11354
12737
  var registrationFromLayer3 = exports_model_registry.registrationFromLayer;
11355
- var layer35 = (initialRegistrations = [], options) => Layer48.effect(Service34, Effect55.gen(function* () {
12738
+ var layer36 = (initialRegistrations = [], options) => Layer48.effect(Service34, Effect55.gen(function* () {
11356
12739
  const registry = yield* exports_model_registry.Service;
11357
12740
  return Service34.of({
11358
12741
  register: (input) => registry.register(input),
@@ -11361,8 +12744,8 @@ var layer35 = (initialRegistrations = [], options) => Layer48.effect(Service34,
11361
12744
  provideForAgent: (agent, effect) => registry.provide(toSelection(agent.model), effect)
11362
12745
  });
11363
12746
  })).pipe(Layer48.provide(exports_model_registry.layer(initialRegistrations, options)));
11364
- var layerFromRegistrationEffects3 = (registrations3, options) => Layer48.unwrap(Effect55.all(registrations3).pipe(Effect55.map((items) => layer35(items, options))));
11365
- var memoryLayer28 = layer35;
12747
+ var layerFromRegistrationEffects3 = (registrations3, options) => Layer48.unwrap(Effect55.all(registrations3).pipe(Effect55.map((items) => layer36(items, options))));
12748
+ var memoryLayer28 = layer36;
11366
12749
  var testLayer40 = (implementation) => Layer48.succeed(Service34, Service34.of(implementation));
11367
12750
  var register6 = Effect55.fn("LanguageModelService.register.call")(function* (input) {
11368
12751
  const service = yield* Service34;
@@ -11387,7 +12770,7 @@ __export(exports_model_call_policy, {
11387
12770
  testLayer: () => testLayer41,
11388
12771
  noRetryLayer: () => noRetryLayer,
11389
12772
  make: () => make7,
11390
- layer: () => layer36,
12773
+ layer: () => layer37,
11391
12774
  defaultSchedule: () => defaultSchedule,
11392
12775
  defaultClassify: () => defaultClassify2,
11393
12776
  Service: () => Service35
@@ -11404,8 +12787,8 @@ var make7 = (input) => ({
11404
12787
  classify: input?.classify ?? defaultClassify2,
11405
12788
  retrySchedule: input?.retrySchedule ?? defaultSchedule
11406
12789
  });
11407
- var layer36 = (input) => Layer49.succeed(Service35, Service35.of(make7(input)));
11408
- var noRetryLayer = layer36({ retrySchedule: Schedule4.recurs(0) });
12790
+ var layer37 = (input) => Layer49.succeed(Service35, Service35.of(make7(input)));
12791
+ var noRetryLayer = layer37({ retrySchedule: Schedule4.recurs(0) });
11409
12792
  var testLayer41 = (implementation) => Layer49.succeed(Service35, Service35.of(implementation));
11410
12793
 
11411
12794
  // ../runtime/src/schema-registry/schema-registry-service.ts
@@ -11416,7 +12799,7 @@ __export(exports_schema_registry_service, {
11416
12799
  registrations: () => registrations4,
11417
12800
  register: () => register7,
11418
12801
  memoryLayer: () => memoryLayer29,
11419
- layer: () => layer37,
12802
+ layer: () => layer38,
11420
12803
  Service: () => Service36,
11421
12804
  SchemaRefNotRegistered: () => SchemaRefNotRegistered
11422
12805
  });
@@ -11433,7 +12816,7 @@ var upsertRegistration2 = (registry, registration) => {
11433
12816
  return [...registry, registration];
11434
12817
  return registry.map((item) => item.ref === registration.ref ? registration : item);
11435
12818
  };
11436
- var layer37 = (initialRegistrations = []) => Layer50.effect(Service36, Effect56.gen(function* () {
12819
+ var layer38 = (initialRegistrations = []) => Layer50.effect(Service36, Effect56.gen(function* () {
11437
12820
  const registry = yield* Ref14.make(initialRegistrations.reduce(upsertRegistration2, []));
11438
12821
  const register7 = Effect56.fn("SchemaRegistry.register")(function* (registration) {
11439
12822
  yield* Ref14.update(registry, (items) => upsertRegistration2(items, registration));
@@ -11449,7 +12832,7 @@ var layer37 = (initialRegistrations = []) => Layer50.effect(Service36, Effect56.
11449
12832
  });
11450
12833
  return Service36.of({ register: register7, registrations: registrations4, resolve: resolve4 });
11451
12834
  }));
11452
- var memoryLayer29 = layer37;
12835
+ var memoryLayer29 = layer38;
11453
12836
  var testLayer42 = (implementation) => Layer50.succeed(Service36, Service36.of(implementation));
11454
12837
  var register7 = Effect56.fn("SchemaRegistry.register.call")(function* (registration) {
11455
12838
  const service = yield* Service36;
@@ -11738,7 +13121,7 @@ var put3 = Effect58.fn("BlobStore.put.call")(function* (input) {
11738
13121
  var exports_prompt_assembler_service = {};
11739
13122
  __export(exports_prompt_assembler_service, {
11740
13123
  testLayer: () => testLayer45,
11741
- layer: () => layer38,
13124
+ layer: () => layer39,
11742
13125
  defaultLayerWithStores: () => defaultLayerWithStores,
11743
13126
  defaultLayer: () => defaultLayer,
11744
13127
  contentToPromptPart: () => contentToPromptPart,
@@ -11898,7 +13281,7 @@ var defaultLayerWithStores = Layer54.effect(Service40, Effect60.gen(function* ()
11898
13281
  return Service40.of(makeDefaultInterface(blobs, artifacts));
11899
13282
  }));
11900
13283
  var defaultLayer = defaultLayerWithStores.pipe(Layer54.provide(Layer54.mergeAll(passthroughLayer, passthroughLayer2)));
11901
- var layer38 = (implementation) => Layer54.succeed(Service40, Service40.of(implementation));
13284
+ var layer39 = (implementation) => Layer54.succeed(Service40, Service40.of(implementation));
11902
13285
  var testLayer45 = (implementation) => Layer54.succeed(Service40, Service40.of(implementation));
11903
13286
  var assemble = Effect60.fn("PromptAssembler.assemble.call")(function* (input) {
11904
13287
  const service = yield* Service40;
@@ -11906,7 +13289,7 @@ var assemble = Effect60.fn("PromptAssembler.assemble.call")(function* (input) {
11906
13289
  });
11907
13290
 
11908
13291
  // ../runtime/src/agent/relay-approvals.ts
11909
- var layer39 = exports_approvals.autoApprove;
13292
+ var layer40 = exports_approvals.autoApprove;
11910
13293
 
11911
13294
  // ../runtime/src/agent/relay-compaction.ts
11912
13295
  import { Clock as Clock5, Effect as Effect61, Layer as Layer55 } from "effect";
@@ -11918,11 +13301,10 @@ var defaultOptions = (options) => ({
11918
13301
  ...options?.reserveTokens === undefined ? {} : { reserveTokens: options.reserveTokens },
11919
13302
  ...options?.keepRecentTokens === undefined ? {} : { keepRecentTokens: options.keepRecentTokens }
11920
13303
  });
11921
- var strategy = (config) => {
11922
- const base = exports_compaction.defaultStrategy(defaultOptions(config.options));
13304
+ var strategy2 = (config) => {
13305
+ const base = config.strategy ?? exports_compaction.defaultStrategy(defaultOptions(config.options));
11923
13306
  return {
11924
- shouldCompact: base.shouldCompact,
11925
- cut: base.cut,
13307
+ ...base,
11926
13308
  summarize: (plan2, request) => {
11927
13309
  const id2 = checkpointId({
11928
13310
  executionId: config.executionId,
@@ -11952,7 +13334,7 @@ var strategy = (config) => {
11952
13334
  }
11953
13335
  };
11954
13336
  };
11955
- var make9 = (config) => exports_compaction.make(strategy(config), defaultOptions(config.options));
13337
+ var make9 = (config) => exports_compaction.make(strategy2(config), defaultOptions(config.options));
11956
13338
 
11957
13339
  // ../runtime/src/agent/relay-instructions.ts
11958
13340
  var layerFromEpoch = (epoch) => exports_instructions.layer(epoch.baseline.length === 0 ? [] : [exports_instructions.staticSource("relay:context-epoch", epoch.baseline)]);
@@ -12133,7 +13515,7 @@ var rememberRule = Effect62.fn("RelayPermissions.rememberRule")(function* (confi
12133
13515
  createdAt
12134
13516
  }).pipe(Effect62.mapError((error) => permissionError(error.message)));
12135
13517
  });
12136
- var layer40 = (config) => Layer56.mergeAll(Layer56.succeed(exports_permissions.Permissions, exports_permissions.Permissions.of({
13518
+ var layer41 = (config) => Layer56.mergeAll(Layer56.succeed(exports_permissions.Permissions, exports_permissions.Permissions.of({
12137
13519
  evaluate: (request) => evaluateDecision(config, request),
12138
13520
  await: (pending) => awaitAnswer(config, pending)
12139
13521
  })), Layer56.succeed(exports_permissions.RuleStore, exports_permissions.RuleStore.of({
@@ -12213,7 +13595,7 @@ var append4 = (config, kind, message) => Clock7.currentTimeMillis.pipe(Effect63.
12213
13595
  content: contentFromMessage(message),
12214
13596
  createdAt
12215
13597
  })), Effect63.asVoid);
12216
- var layer41 = (config) => Layer57.succeed(exports_steering.Steering, exports_steering.Steering.of({
13598
+ var layer42 = (config) => Layer57.succeed(exports_steering.Steering, exports_steering.Steering.of({
12217
13599
  steer: (message) => append4(config, "steering", message).pipe(Effect63.orDie),
12218
13600
  followUp: (message) => append4(config, "follow_up", message).pipe(Effect63.orDie),
12219
13601
  takeSteering: () => drain2(config, "steering", "all").pipe(Effect63.orDie),
@@ -12274,7 +13656,7 @@ var make10 = (config) => ({
12274
13656
  }))))));
12275
13657
  })
12276
13658
  });
12277
- var layer42 = (config) => Layer58.succeed(exports_tool_executor.ToolExecutor, exports_tool_executor.ToolExecutor.of(make10(config)));
13659
+ var layer43 = (config) => Layer58.succeed(exports_tool_executor.ToolExecutor, exports_tool_executor.ToolExecutor.of(make10(config)));
12278
13660
 
12279
13661
  // ../runtime/src/agent/relay-tool-output.ts
12280
13662
  import { Effect as Effect65, Layer as Layer59, Option as Option21 } from "effect";
@@ -12318,7 +13700,7 @@ var store = (blobStore, toolCallId, content) => {
12318
13700
  var make11 = (blobStore) => ({
12319
13701
  put: (toolCallId, content) => store(blobStore, toolCallId, content)
12320
13702
  });
12321
- var layer43 = Layer59.effect(exports_tool_output.ToolOutputStore, Service38.pipe(Effect65.map((blobStore) => exports_tool_output.ToolOutputStore.of(make11(blobStore)))));
13703
+ var layer44 = Layer59.effect(exports_tool_output.ToolOutputStore, Service38.pipe(Effect65.map((blobStore) => exports_tool_output.ToolOutputStore.of(make11(blobStore)))));
12322
13704
 
12323
13705
  // ../runtime/src/agent/sequence-allocator.ts
12324
13706
  import { Effect as Effect66, Ref as Ref17 } from "effect";
@@ -12353,6 +13735,20 @@ class Service41 extends Context54.Service()("@relayfx/runtime/AgentLoop") {
12353
13735
  }
12354
13736
  var jsonValue6 = (value) => Schema63.decodeUnknownSync(exports_shared_schema.JsonValue)(value);
12355
13737
  var toolNames = (agent) => HashSet6.fromIterable(agent.tool_names);
13738
+ var turnPolicyFromSnapshot = (snapshot2) => {
13739
+ switch (snapshot2.kind) {
13740
+ case "recurs":
13741
+ return exports_turn_policy.recurs(snapshot2.count);
13742
+ case "until-tool-call":
13743
+ return exports_turn_policy.untilToolCall(snapshot2.name);
13744
+ case "both":
13745
+ return exports_turn_policy.both(turnPolicyFromSnapshot(snapshot2.first), turnPolicyFromSnapshot(snapshot2.second));
13746
+ }
13747
+ };
13748
+ var turnPolicyFromDefinition = (agent) => {
13749
+ const cap = exports_turn_policy.recurs(agent.max_tool_turns ?? exports_agent_schema.defaultMaxToolTurns);
13750
+ return agent.turn_policy === undefined ? cap : exports_turn_policy.both(cap, turnPolicyFromSnapshot(agent.turn_policy));
13751
+ };
12356
13752
  var availableRegisteredTools = (agent, registered) => {
12357
13753
  const names = toolNames(agent);
12358
13754
  return registered.filter((tool2) => tool2.definition.name !== toolName && HashSet6.has(names, tool2.definition.name));
@@ -12666,7 +14062,7 @@ var compactionOptionsFromAgentMetadata = Effect67.fn("AgentLoop.compactionOption
12666
14062
  };
12667
14063
  });
12668
14064
  var effectiveCompactionOptions = (input) => input.compaction !== undefined ? Effect67.succeed(input.compaction ?? undefined) : compactionOptionsFromAgentMetadata(input);
12669
- var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
14065
+ var layer45 = Layer60.effect(Service41, Effect67.gen(function* () {
12670
14066
  const eventLog = yield* Service24;
12671
14067
  const languageModels = yield* Service34;
12672
14068
  const tools = yield* Service26;
@@ -12709,7 +14105,7 @@ var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
12709
14105
  const permissionsLayer = input.agent.permission_rules === undefined ? Layer60.empty : Option22.isNone(permissionRules) || Option22.isNone(waits) ? yield* Effect67.fail(new AgentLoopError({
12710
14106
  message: "Execution permission rules require PermissionRuleRepository and WaitService in context",
12711
14107
  next_event_sequence: input.eventSequence + 1
12712
- })) : layer40({
14108
+ })) : layer41({
12713
14109
  ruleset: input.agent.permission_rules,
12714
14110
  repository: permissionRules.value,
12715
14111
  waits: waits.value,
@@ -12724,7 +14120,7 @@ var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
12724
14120
  const steeringLayer = input.steeringEnabled !== true ? Layer60.empty : Option22.isNone(steeringRepository) ? yield* Effect67.fail(new AgentLoopError({
12725
14121
  message: "Execution steering requires SteeringRepository in context",
12726
14122
  next_event_sequence: input.eventSequence + 1
12727
- })) : layer41({
14123
+ })) : layer42({
12728
14124
  repository: steeringRepository.value,
12729
14125
  eventLog,
12730
14126
  allocator,
@@ -12764,7 +14160,7 @@ var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
12764
14160
  const agent = exports_agent.make({
12765
14161
  name: input.agent.name,
12766
14162
  toolkit,
12767
- policy: exports_turn_policy.recurs(input.agent.max_tool_turns ?? exports_agent_schema.defaultMaxToolTurns)
14163
+ policy: turnPolicyFromDefinition(input.agent)
12768
14164
  });
12769
14165
  if (toolOutputMaxBytes !== undefined && Option22.isNone(blobStore)) {
12770
14166
  return yield* Effect67.fail(new AgentLoopError({
@@ -12796,7 +14192,7 @@ var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
12796
14192
  ...toolOutputMaxBytes === undefined ? {} : { toolOutputMaxBytes },
12797
14193
  ...batonCompaction === undefined ? {} : { compaction: batonCompaction }
12798
14194
  };
12799
- const executorLayer = layer42({
14195
+ const executorLayer = layer43({
12800
14196
  toolRuntime: tools,
12801
14197
  eventLog,
12802
14198
  allocator,
@@ -12882,7 +14278,7 @@ var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
12882
14278
  const runFold = Effect67.gen(function* () {
12883
14279
  const base = yield* LanguageModel6.LanguageModel;
12884
14280
  const sessionStore = input.sessionId !== undefined && Option22.isSome(sessionRepository) ? yield* make8(input.sessionId, input.sessionEntryScope ?? input.executionId).pipe(Effect67.provideService(exports_session_repository.Service, sessionRepository.value)) : undefined;
12885
- const folded = exports_agent.stream(agent, batonOptions).pipe(Stream8.runFoldEffect(() => ({ text: "", transcript: undefined, turn: undefined, tokensUsed: seededTokens }), foldEvent), Effect67.provideService(LanguageModel6.LanguageModel, base), Effect67.provideService(exports_model_resilience.ModelResilience, policy), Effect67.provide(executorLayer), Effect67.provide(handlerLayer), Effect67.provide(layer39), Effect67.provide(exports_model_middleware.identityLayer), Effect67.provide(instructionsLayer), Effect67.provide(permissionsLayer), Effect67.provide(steeringLayer));
14281
+ const folded = exports_agent.stream(agent, batonOptions).pipe(Stream8.runFoldEffect(() => ({ text: "", transcript: undefined, turn: undefined, tokensUsed: seededTokens }), foldEvent), Effect67.provideService(LanguageModel6.LanguageModel, base), Effect67.provideService(exports_model_resilience.ModelResilience, policy), Effect67.provide(executorLayer), Effect67.provide(handlerLayer), Effect67.provide(layer40), Effect67.provide(exports_model_middleware.identityLayer), Effect67.provide(instructionsLayer), Effect67.provide(permissionsLayer), Effect67.provide(steeringLayer));
12886
14282
  const withToolOutput = toolOutputStore === undefined ? folded : folded.pipe(Effect67.provideService(exports_tool_output.ToolOutputStore, toolOutputStore));
12887
14283
  const withCompaction = compactionService === undefined ? withToolOutput : withToolOutput.pipe(Effect67.provideService(exports_compaction.Compaction, compactionService));
12888
14284
  const withSession = sessionStore === undefined ? withCompaction : withCompaction.pipe(Effect67.provideService(exports_session.SessionStore, sessionStore));
@@ -12919,11 +14315,12 @@ var run3 = Effect67.fn("AgentLoop.run.call")(function* (input) {
12919
14315
  // ../runtime/src/cluster/execution-entity.ts
12920
14316
  var exports_execution_entity = {};
12921
14317
  __export(exports_execution_entity, {
12922
- layer: () => layer49,
14318
+ layer: () => layer50,
12923
14319
  entity: () => entity,
12924
14320
  client: () => client2,
12925
14321
  Start: () => Start,
12926
14322
  SignalWait: () => SignalWait,
14323
+ Dispatch: () => Dispatch,
12927
14324
  Cancel: () => Cancel
12928
14325
  });
12929
14326
  import { ClusterSchema, Entity } from "effect/unstable/cluster";
@@ -12941,7 +14338,8 @@ __export(exports_execution_workflow, {
12941
14338
  sessionEntryScope: () => sessionEntryScope,
12942
14339
  resume: () => resume3,
12943
14340
  poll: () => poll,
12944
- layer: () => layer48,
14341
+ layer: () => layer49,
14342
+ dispatchRequest: () => dispatchRequest,
12945
14343
  cancelRequest: () => cancelRequest,
12946
14344
  activeWorkflowExecutionIdForExecution: () => activeWorkflowExecutionIdForExecution,
12947
14345
  WaitSnapshot: () => WaitSnapshot,
@@ -12959,7 +14357,7 @@ __export(exports_execution_workflow, {
12959
14357
  ActivityNameTemplates: () => ActivityNameTemplates
12960
14358
  });
12961
14359
  import { Activity, DurableDeferred, Workflow } from "effect/unstable/workflow";
12962
- import { Effect as Effect73, Exit as Exit2, Option as Option26, Schema as Schema69 } from "effect";
14360
+ import { Effect as Effect74, Exit as Exit2, Option as Option26, Schema as Schema69 } from "effect";
12963
14361
 
12964
14362
  // ../runtime/src/child/parent-notifier-service.ts
12965
14363
  import { Context as Context55, Effect as Effect68, Layer as Layer61, Option as Option23, Ref as Ref19, Schema as Schema64 } from "effect";
@@ -13058,7 +14456,7 @@ __export(exports_skill_registry_service, {
13058
14456
  listRevisions: () => listRevisions4,
13059
14457
  listPins: () => listPins2,
13060
14458
  list: () => list12,
13061
- layer: () => layer45,
14459
+ layer: () => layer46,
13062
14460
  getRevision: () => getRevision4,
13063
14461
  getPinned: () => getPinned2,
13064
14462
  get: () => get13,
@@ -13139,7 +14537,7 @@ var toBatonSkill = (pin) => {
13139
14537
  };
13140
14538
  };
13141
14539
  var sourceError = (error) => new exports_skill_source.SkillSourceError({ source: "relay.skill_registry", message: error.message });
13142
- var layer45 = Layer62.effect(Service43, Effect69.gen(function* () {
14540
+ var layer46 = Layer62.effect(Service43, Effect69.gen(function* () {
13143
14541
  const repository = yield* exports_skill_definition_repository.Service;
13144
14542
  return Service43.of({
13145
14543
  register: Effect69.fn("SkillRegistry.register")(function* (input) {
@@ -13237,7 +14635,7 @@ __export(exports_execution_service, {
13237
14635
  send: () => send,
13238
14636
  run: () => run4,
13239
14637
  memoryLayer: () => memoryLayer32,
13240
- layer: () => layer46,
14638
+ layer: () => layer47,
13241
14639
  cancel: () => cancel3,
13242
14640
  accept: () => accept,
13243
14641
  Service: () => Service44,
@@ -13268,7 +14666,7 @@ var toExecution = (record2) => ({
13268
14666
  });
13269
14667
  var mapRepositoryError9 = (error) => new ExecutionServiceError({ message: error._tag });
13270
14668
  var mapEventLogError4 = (error) => new ExecutionServiceError({ message: error._tag });
13271
- var mapChildRunError2 = (error) => new ExecutionServiceError({ message: error._tag });
14669
+ var mapChildRunError2 = (error) => new ExecutionServiceError({ message: error._tag === "ChildRunServiceError" ? error.message : error._tag });
13272
14670
  var childExecutionId2 = (input) => input.child_execution_id ?? exports_ids_schema.ChildExecutionId.make(`${input.execution_id}:child:${input.address_id}`);
13273
14671
  var hasCompleteAgentDefinitionPin2 = (input) => {
13274
14672
  const present = [input.agentId !== undefined, input.agentRevision !== undefined, input.agentSnapshot !== undefined];
@@ -13416,7 +14814,7 @@ var updateStatus2 = Effect70.fn("ExecutionService.updateStatus")(function* (repo
13416
14814
  }).pipe(Effect70.mapError(mapRepositoryError9));
13417
14815
  return toExecution(record2);
13418
14816
  });
13419
- var layer46 = Layer63.effect(Service44, Effect70.gen(function* () {
14817
+ var layer47 = Layer63.effect(Service44, Effect70.gen(function* () {
13420
14818
  const repository = yield* exports_execution_repository.Service;
13421
14819
  const eventLog = yield* Service24;
13422
14820
  const childRuns = yield* Service31;
@@ -13538,7 +14936,7 @@ var layer46 = Layer63.effect(Service44, Effect70.gen(function* () {
13538
14936
  stream: (input) => eventLog.stream(input).pipe(Stream9.take(input.limit ?? 1000), Stream9.mapError((error) => mapEventLogError4(error)))
13539
14937
  });
13540
14938
  }));
13541
- var memoryLayer32 = layer46.pipe(Layer63.provide(layer32), Layer63.provide(exports_execution_repository.memoryLayer), Layer63.provide(exports_session_repository.memoryLayer), Layer63.provide(exports_child_execution_repository.memoryLayer), Layer63.provide(memoryLayer21), Layer63.provide(ShardingConfig.layer({ runnerAddress: Option24.none() })));
14939
+ var memoryLayer32 = layer47.pipe(Layer63.provide(layer33), Layer63.provide(exports_execution_repository.memoryLayer), Layer63.provide(exports_session_repository.memoryLayer), Layer63.provide(exports_child_execution_repository.memoryLayer), Layer63.provide(memoryLayer21), Layer63.provide(ShardingConfig.layer({ runnerAddress: Option24.none() })));
13542
14940
  var testLayer48 = (implementation) => Layer63.succeed(Service44, Service44.of(implementation));
13543
14941
  var accept = Effect70.fn("ExecutionService.accept.call")(function* (input) {
13544
14942
  const service = yield* Service44;
@@ -13562,37 +14960,69 @@ var spawnChildRun = Effect70.fn("ExecutionService.spawnChildRun.call")(function*
13562
14960
  });
13563
14961
  var stream3 = (input) => Stream9.unwrap(Service44.pipe(Effect70.map((service) => service.stream(input))));
13564
14962
 
14963
+ // ../runtime/src/tool/tool-transition-coordinator.ts
14964
+ var exports_tool_transition_coordinator = {};
14965
+ __export(exports_tool_transition_coordinator, {
14966
+ sqlLayer: () => sqlLayer,
14967
+ memoryLayer: () => memoryLayer33,
14968
+ coordinate: () => coordinate,
14969
+ Service: () => Service45
14970
+ });
14971
+ import { Context as Context58, Effect as Effect71, Layer as Layer64, Semaphore as Semaphore4 } from "effect";
14972
+ import { SqlClient as SqlClient22 } from "effect/unstable/sql/SqlClient";
14973
+
14974
+ class Service45 extends Context58.Service()("@relayfx/runtime/ToolTransitionCoordinator") {
14975
+ }
14976
+ var make14 = Effect71.gen(function* () {
14977
+ const semaphore = yield* Semaphore4.make(1);
14978
+ return Service45.of({
14979
+ coordinate: (effect) => semaphore.withPermit(effect)
14980
+ });
14981
+ });
14982
+ var memoryLayer33 = Layer64.effect(Service45, make14);
14983
+ var sqlLayer = Layer64.effect(Service45, Effect71.gen(function* () {
14984
+ const sql3 = yield* SqlClient22;
14985
+ const semaphore = yield* Semaphore4.make(1);
14986
+ return Service45.of({
14987
+ coordinate: (effect) => semaphore.withPermit(sql3.withTransaction(effect))
14988
+ });
14989
+ }));
14990
+ var coordinate = Effect71.fn("ToolTransitionCoordinator.coordinate")(function* (effect) {
14991
+ const service = yield* Service45;
14992
+ return yield* service.coordinate(effect);
14993
+ });
14994
+
13565
14995
  // ../runtime/src/workspace/workspace-planner-service.ts
13566
- import { Context as Context59, Effect as Effect72, HashSet as HashSet7, Layer as Layer65, Option as Option25, Schema as Schema68 } from "effect";
14996
+ import { Context as Context60, Effect as Effect73, HashSet as HashSet7, Layer as Layer66, Option as Option25, Schema as Schema68 } from "effect";
13567
14997
 
13568
14998
  // ../runtime/src/workspace/workspace-runtime-service.ts
13569
- import { Context as Context58, Effect as Effect71, Layer as Layer64, Schema as Schema67 } from "effect";
14999
+ import { Context as Context59, Effect as Effect72, Layer as Layer65, Schema as Schema67 } from "effect";
13570
15000
 
13571
15001
  class WorkspaceRuntimeError extends Schema67.TaggedErrorClass()("WorkspaceRuntimeError", {
13572
15002
  message: Schema67.String
13573
15003
  }) {
13574
15004
  }
13575
15005
 
13576
- class Service45 extends Context58.Service()("@relayfx/runtime/WorkspaceRuntime") {
15006
+ class Service46 extends Context59.Service()("@relayfx/runtime/WorkspaceRuntime") {
13577
15007
  }
13578
15008
  var mapRuntimeError = (error) => new WorkspaceRuntimeError({
13579
15009
  message: error._tag === "WorkspaceNotFound" ? `Workspace not found: ${error.sandbox_ref}` : error.message
13580
15010
  });
13581
- var layerFromHandle = (handle) => Layer64.succeed(Service45, Service45.of({
13582
- readFile: Effect71.fn("WorkspaceRuntime.readFile")((path2) => handle.readFile(path2).pipe(Effect71.mapError(mapRuntimeError))),
13583
- writeFile: Effect71.fn("WorkspaceRuntime.writeFile")((path2, content) => handle.writeFile(path2, content).pipe(Effect71.mapError(mapRuntimeError))),
13584
- exec: Effect71.fn("WorkspaceRuntime.exec")((input) => handle.exec(input).pipe(Effect71.mapError((error) => new WorkspaceRuntimeError({ message: error.message }))))
15011
+ var layerFromHandle = (handle) => Layer65.succeed(Service46, Service46.of({
15012
+ readFile: Effect72.fn("WorkspaceRuntime.readFile")((path2) => handle.readFile(path2).pipe(Effect72.mapError(mapRuntimeError))),
15013
+ writeFile: Effect72.fn("WorkspaceRuntime.writeFile")((path2, content) => handle.writeFile(path2, content).pipe(Effect72.mapError(mapRuntimeError))),
15014
+ exec: Effect72.fn("WorkspaceRuntime.exec")((input) => handle.exec(input).pipe(Effect72.mapError((error) => new WorkspaceRuntimeError({ message: error.message }))))
13585
15015
  }));
13586
- var readFile = Effect71.fn("WorkspaceRuntime.readFile.call")(function* (path2) {
13587
- const service = yield* Service45;
15016
+ var readFile = Effect72.fn("WorkspaceRuntime.readFile.call")(function* (path2) {
15017
+ const service = yield* Service46;
13588
15018
  return yield* service.readFile(path2);
13589
15019
  });
13590
- var writeFile = Effect71.fn("WorkspaceRuntime.writeFile.call")(function* (path2, content) {
13591
- const service = yield* Service45;
15020
+ var writeFile = Effect72.fn("WorkspaceRuntime.writeFile.call")(function* (path2, content) {
15021
+ const service = yield* Service46;
13592
15022
  return yield* service.writeFile(path2, content);
13593
15023
  });
13594
- var exec = Effect71.fn("WorkspaceRuntime.exec.call")(function* (input) {
13595
- const service = yield* Service45;
15024
+ var exec = Effect72.fn("WorkspaceRuntime.exec.call")(function* (input) {
15025
+ const service = yield* Service46;
13596
15026
  return yield* service.exec(input);
13597
15027
  });
13598
15028
 
@@ -13612,7 +15042,7 @@ class WorkspacePlannerError extends Schema68.TaggedErrorClass()("WorkspacePlanne
13612
15042
  }) {
13613
15043
  }
13614
15044
 
13615
- class Service46 extends Context59.Service()("@relayfx/runtime/WorkspacePlanner") {
15045
+ class Service47 extends Context60.Service()("@relayfx/runtime/WorkspacePlanner") {
13616
15046
  }
13617
15047
  var selectedToolNames = (agent) => HashSet7.fromIterable(agent.tool_names);
13618
15048
  var selectedDefinitions = (input) => {
@@ -13624,11 +15054,11 @@ var needsWorkspace = (input) => selectedDefinitions(input).some(requiresWorkspac
13624
15054
  var leaseId = (executionId) => exports_ids_schema.WorkspaceLeaseId.make(`workspace-lease:${executionId}`);
13625
15055
  var mapRepositoryError10 = (error) => new WorkspacePlannerError({ message: error._tag });
13626
15056
  var mapEventLogError5 = (error) => new WorkspacePlannerError({ message: error._tag });
13627
- var providerOrMissing = (executionId) => Effect72.serviceOption(Service30).pipe(Effect72.flatMap((provider) => Option25.match(provider, {
13628
- onNone: () => Effect72.fail(new WorkspaceRuntimeMissing({ execution_id: executionId })),
13629
- onSome: Effect72.succeed
15057
+ var providerOrMissing = (executionId) => Effect73.serviceOption(Service30).pipe(Effect73.flatMap((provider) => Option25.match(provider, {
15058
+ onNone: () => Effect73.fail(new WorkspaceRuntimeMissing({ execution_id: executionId })),
15059
+ onSome: Effect73.succeed
13630
15060
  })));
13631
- var nextEventSequence3 = (eventLog, executionId) => eventLog.maxSequence(executionId).pipe(Effect72.map((max) => max === undefined ? 0 : max + 1), Effect72.catch(() => Effect72.succeed(0)));
15061
+ var nextEventSequence3 = (eventLog, executionId) => eventLog.maxSequence(executionId).pipe(Effect73.map((max) => max === undefined ? 0 : max + 1), Effect73.catch(() => Effect73.succeed(0)));
13632
15062
  var workspaceEvent = (type, lease, sequence, createdAt) => ({
13633
15063
  id: exports_ids_schema.EventId.make(`event:${lease.execution_id}:workspace:${type}:${sequence}`),
13634
15064
  execution_id: lease.execution_id,
@@ -13644,7 +15074,7 @@ var workspaceEvent = (type, lease, sequence, createdAt) => ({
13644
15074
  },
13645
15075
  created_at: createdAt
13646
15076
  });
13647
- var appendWorkspaceEvent = (eventLog, type, lease, sequence, createdAt) => appendIdempotentTo(eventLog, workspaceEvent(type, lease, sequence, createdAt)).pipe(Effect72.mapError(mapEventLogError5), Effect72.asVoid);
15077
+ var appendWorkspaceEvent = (eventLog, type, lease, sequence, createdAt) => appendIdempotentTo(eventLog, workspaceEvent(type, lease, sequence, createdAt)).pipe(Effect73.mapError(mapEventLogError5), Effect73.asVoid);
13648
15078
  var providerAcquireSpec = (input) => ({
13649
15079
  executionId: input.executionId,
13650
15080
  ...input.request === undefined ? {} : { request: input.request }
@@ -13661,50 +15091,50 @@ var planResult = (lease, handle) => ({
13661
15091
  runtimeLayer: layerFromHandle(handle)
13662
15092
  });
13663
15093
  var missingRef = (executionId) => new WorkspaceLeaseMissingRef({ execution_id: executionId });
13664
- var ensureFromExisting = Effect72.fn("WorkspacePlanner.ensureFromExisting")(function* (repository, eventLog, provider, lease, input) {
15094
+ var ensureFromExisting = Effect73.fn("WorkspacePlanner.ensureFromExisting")(function* (repository, eventLog, provider, lease, input) {
13665
15095
  if (lease.sandbox_ref === undefined) {
13666
15096
  const handle2 = yield* provider.acquire(providerAcquireSpec(input));
13667
- const running2 = yield* repository.markRunning({ executionId: input.executionId, sandboxRef: handle2.ref, updatedAt: input.now }).pipe(Effect72.mapError(mapRepositoryError10));
15097
+ const running2 = yield* repository.markRunning({ executionId: input.executionId, sandboxRef: handle2.ref, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13668
15098
  const sequence2 = yield* nextEventSequence3(eventLog, input.executionId);
13669
15099
  yield* appendWorkspaceEvent(eventLog, "workspace.lease.acquired", running2, sequence2, input.now);
13670
15100
  return planResult(running2, handle2);
13671
15101
  }
13672
15102
  const handle = yield* provider.resume(lease.sandbox_ref);
13673
- const running = yield* repository.markResumed({ executionId: input.executionId, sandboxRef: handle.ref, updatedAt: input.now }).pipe(Effect72.mapError(mapRepositoryError10));
15103
+ const running = yield* repository.markResumed({ executionId: input.executionId, sandboxRef: handle.ref, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13674
15104
  const sequence = yield* nextEventSequence3(eventLog, input.executionId);
13675
15105
  yield* appendWorkspaceEvent(eventLog, "workspace.resumed", running, sequence, input.now);
13676
15106
  return planResult(running, handle);
13677
15107
  });
13678
- var layer47 = Layer65.effect(Service46, Effect72.gen(function* () {
15108
+ var layer48 = Layer66.effect(Service47, Effect73.gen(function* () {
13679
15109
  const repository = yield* exports_workspace_lease_repository.Service;
13680
15110
  const eventLog = yield* Service24;
13681
- return Service46.of({
13682
- ensure: Effect72.fn("WorkspacePlanner.ensure")(function* (input) {
15111
+ return Service47.of({
15112
+ ensure: Effect73.fn("WorkspacePlanner.ensure")(function* (input) {
13683
15113
  if (!needsWorkspace(input))
13684
15114
  return;
13685
15115
  const provider = yield* providerOrMissing(input.executionId);
13686
- const existing = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15116
+ const existing = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13687
15117
  if (existing !== undefined && existing.status !== "released" && existing.status !== "failed") {
13688
15118
  return yield* ensureFromExisting(repository, eventLog, provider, existing, input);
13689
15119
  }
13690
- const planned = yield* repository.plan(planInput(input, provider)).pipe(Effect72.mapError(mapRepositoryError10));
15120
+ const planned = yield* repository.plan(planInput(input, provider)).pipe(Effect73.mapError(mapRepositoryError10));
13691
15121
  let sequence = yield* nextEventSequence3(eventLog, input.executionId);
13692
15122
  yield* appendWorkspaceEvent(eventLog, "workspace.lease.planned", planned, sequence, input.now);
13693
15123
  const handle = yield* provider.acquire(providerAcquireSpec(input));
13694
- const running = yield* repository.markRunning({ executionId: input.executionId, sandboxRef: handle.ref, updatedAt: input.now }).pipe(Effect72.mapError(mapRepositoryError10));
15124
+ const running = yield* repository.markRunning({ executionId: input.executionId, sandboxRef: handle.ref, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13695
15125
  sequence += 1;
13696
15126
  yield* appendWorkspaceEvent(eventLog, "workspace.lease.acquired", running, sequence, input.now);
13697
15127
  return planResult(running, handle);
13698
15128
  }),
13699
- suspend: Effect72.fn("WorkspacePlanner.suspend")(function* (input) {
13700
- const lease = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15129
+ suspend: Effect73.fn("WorkspacePlanner.suspend")(function* (input) {
15130
+ const lease = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13701
15131
  if (lease === undefined || lease.status === "released" || lease.status === "failed")
13702
15132
  return;
13703
15133
  if (lease.sandbox_ref === undefined)
13704
- return yield* Effect72.fail(missingRef(input.executionId));
15134
+ return yield* Effect73.fail(missingRef(input.executionId));
13705
15135
  const provider = yield* providerOrMissing(input.executionId);
13706
15136
  if (!provider.capabilities.can_suspend && !provider.capabilities.persistent_by_default) {
13707
- return yield* Effect72.fail(new WorkspaceCapabilityUnsupported({
15137
+ return yield* Effect73.fail(new WorkspaceCapabilityUnsupported({
13708
15138
  capability: "suspend",
13709
15139
  provider_key: provider.providerKey
13710
15140
  }));
@@ -13712,84 +15142,84 @@ var layer47 = Layer65.effect(Service46, Effect72.gen(function* () {
13712
15142
  if (provider.capabilities.can_suspend) {
13713
15143
  yield* provider.suspend(lease.sandbox_ref);
13714
15144
  }
13715
- const suspended2 = yield* repository.markSuspended({ executionId: input.executionId, updatedAt: input.now }).pipe(Effect72.mapError(mapRepositoryError10));
15145
+ const suspended2 = yield* repository.markSuspended({ executionId: input.executionId, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13716
15146
  const sequence = yield* nextEventSequence3(eventLog, input.executionId);
13717
15147
  yield* appendWorkspaceEvent(eventLog, "workspace.suspended", suspended2, sequence, input.now);
13718
15148
  return suspended2;
13719
15149
  }),
13720
- resume: Effect72.fn("WorkspacePlanner.resume")(function* (input) {
13721
- const lease = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15150
+ resume: Effect73.fn("WorkspacePlanner.resume")(function* (input) {
15151
+ const lease = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13722
15152
  if (lease === undefined || lease.status === "released" || lease.status === "failed")
13723
15153
  return;
13724
15154
  if (lease.sandbox_ref === undefined)
13725
- return yield* Effect72.fail(missingRef(input.executionId));
15155
+ return yield* Effect73.fail(missingRef(input.executionId));
13726
15156
  const provider = yield* providerOrMissing(input.executionId);
13727
15157
  const handle = yield* provider.resume(lease.sandbox_ref);
13728
- const running = yield* repository.markResumed({ executionId: input.executionId, sandboxRef: handle.ref, updatedAt: input.now }).pipe(Effect72.mapError(mapRepositoryError10));
15158
+ const running = yield* repository.markResumed({ executionId: input.executionId, sandboxRef: handle.ref, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13729
15159
  const sequence = yield* nextEventSequence3(eventLog, input.executionId);
13730
15160
  yield* appendWorkspaceEvent(eventLog, "workspace.resumed", running, sequence, input.now);
13731
15161
  return planResult(running, handle);
13732
15162
  }),
13733
- attach: Effect72.fn("WorkspacePlanner.attach")(function* (input) {
13734
- const lease = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15163
+ attach: Effect73.fn("WorkspacePlanner.attach")(function* (input) {
15164
+ const lease = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13735
15165
  if (lease === undefined || lease.status === "released" || lease.status === "failed")
13736
15166
  return;
13737
15167
  if (lease.sandbox_ref === undefined)
13738
- return yield* Effect72.fail(missingRef(input.executionId));
15168
+ return yield* Effect73.fail(missingRef(input.executionId));
13739
15169
  const provider = yield* providerOrMissing(input.executionId);
13740
15170
  const handle = yield* provider.resume(lease.sandbox_ref);
13741
15171
  return planResult(lease, handle);
13742
15172
  }),
13743
- release: Effect72.fn("WorkspacePlanner.release")(function* (input) {
13744
- const lease = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15173
+ release: Effect73.fn("WorkspacePlanner.release")(function* (input) {
15174
+ const lease = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13745
15175
  if (lease === undefined || lease.status === "released" || lease.status === "failed")
13746
15176
  return;
13747
15177
  if (lease.sandbox_ref === undefined)
13748
- return yield* Effect72.fail(missingRef(input.executionId));
15178
+ return yield* Effect73.fail(missingRef(input.executionId));
13749
15179
  const provider = yield* providerOrMissing(input.executionId);
13750
15180
  yield* provider.destroy(lease.sandbox_ref);
13751
- const released = yield* repository.markReleased({ executionId: input.executionId, updatedAt: input.now }).pipe(Effect72.mapError(mapRepositoryError10));
15181
+ const released = yield* repository.markReleased({ executionId: input.executionId, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13752
15182
  const sequence = yield* nextEventSequence3(eventLog, input.executionId);
13753
15183
  yield* appendWorkspaceEvent(eventLog, "workspace.lease.released", released, sequence, input.now);
13754
15184
  return released;
13755
15185
  }),
13756
- fail: Effect72.fn("WorkspacePlanner.fail")(function* (input) {
13757
- const lease = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15186
+ fail: Effect73.fn("WorkspacePlanner.fail")(function* (input) {
15187
+ const lease = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13758
15188
  if (lease === undefined || lease.status === "released" || lease.status === "failed")
13759
15189
  return;
13760
15190
  const failed = yield* repository.markFailed({
13761
15191
  executionId: input.executionId,
13762
15192
  updatedAt: input.now,
13763
15193
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
13764
- }).pipe(Effect72.mapError(mapRepositoryError10));
15194
+ }).pipe(Effect73.mapError(mapRepositoryError10));
13765
15195
  const sequence = yield* nextEventSequence3(eventLog, input.executionId);
13766
15196
  yield* appendWorkspaceEvent(eventLog, "workspace.lease.failed", failed, sequence, input.now);
13767
15197
  return failed;
13768
15198
  })
13769
15199
  });
13770
15200
  }));
13771
- var ensure2 = Effect72.fn("WorkspacePlanner.ensure.call")(function* (input) {
13772
- const service = yield* Service46;
15201
+ var ensure2 = Effect73.fn("WorkspacePlanner.ensure.call")(function* (input) {
15202
+ const service = yield* Service47;
13773
15203
  return yield* service.ensure(input);
13774
15204
  });
13775
- var suspend2 = Effect72.fn("WorkspacePlanner.suspend.call")(function* (input) {
13776
- const service = yield* Service46;
15205
+ var suspend2 = Effect73.fn("WorkspacePlanner.suspend.call")(function* (input) {
15206
+ const service = yield* Service47;
13777
15207
  return yield* service.suspend(input);
13778
15208
  });
13779
- var resume2 = Effect72.fn("WorkspacePlanner.resume.call")(function* (input) {
13780
- const service = yield* Service46;
15209
+ var resume2 = Effect73.fn("WorkspacePlanner.resume.call")(function* (input) {
15210
+ const service = yield* Service47;
13781
15211
  return yield* service.resume(input);
13782
15212
  });
13783
- var attach = Effect72.fn("WorkspacePlanner.attach.call")(function* (input) {
13784
- const service = yield* Service46;
15213
+ var attach = Effect73.fn("WorkspacePlanner.attach.call")(function* (input) {
15214
+ const service = yield* Service47;
13785
15215
  return yield* service.attach(input);
13786
15216
  });
13787
- var release2 = Effect72.fn("WorkspacePlanner.release.call")(function* (input) {
13788
- const service = yield* Service46;
15217
+ var release2 = Effect73.fn("WorkspacePlanner.release.call")(function* (input) {
15218
+ const service = yield* Service47;
13789
15219
  return yield* service.release(input);
13790
15220
  });
13791
- var fail = Effect72.fn("WorkspacePlanner.fail.call")(function* (input) {
13792
- const service = yield* Service46;
15221
+ var fail = Effect73.fn("WorkspacePlanner.fail.call")(function* (input) {
15222
+ const service = yield* Service47;
13793
15223
  return yield* service.fail(input);
13794
15224
  });
13795
15225
 
@@ -13936,17 +15366,17 @@ var resolveLocalAgentTarget = (addressId) => Activity.make({
13936
15366
  name: ActivityNames.resolveLocalAgent,
13937
15367
  success: LocalAgentTarget,
13938
15368
  error: ExecutionWorkflowFailed,
13939
- execute: resolveLocalAgent(addressId).pipe(Effect73.mapError(mapAddressResolutionError))
15369
+ execute: resolveLocalAgent(addressId).pipe(Effect74.mapError(mapAddressResolutionError))
13940
15370
  });
13941
- var resolveStartInput = Effect73.fn("ExecutionWorkflow.resolveStartInput")(function* (input) {
15371
+ var resolveStartInput = Effect74.fn("ExecutionWorkflow.resolveStartInput")(function* (input) {
13942
15372
  const pinCount = agentDefinitionPinCount(input);
13943
15373
  if (input.agent_tool_input_schema_digests !== undefined && pinCount !== 3) {
13944
- return yield* Effect73.fail(invalidAgentDefinitionDigestPin());
15374
+ return yield* Effect74.fail(invalidAgentDefinitionDigestPin());
13945
15375
  }
13946
15376
  if (pinCount === 3)
13947
15377
  return input;
13948
15378
  if (pinCount > 0)
13949
- return yield* Effect73.fail(invalidAgentDefinitionPin());
15379
+ return yield* Effect74.fail(invalidAgentDefinitionPin());
13950
15380
  const target = yield* resolveLocalAgentTarget(input.root_address_id);
13951
15381
  return {
13952
15382
  ...input,
@@ -13960,7 +15390,7 @@ var acceptExecution = (input) => Activity.make({
13960
15390
  name: ActivityNames.accept,
13961
15391
  success: exports_execution_schema.Execution,
13962
15392
  error: ExecutionWorkflowFailed,
13963
- execute: Effect73.gen(function* () {
15393
+ execute: Effect74.gen(function* () {
13964
15394
  const accepted2 = yield* accept({
13965
15395
  executionId: input.execution_id,
13966
15396
  rootAddressId: input.root_address_id,
@@ -13972,13 +15402,13 @@ var acceptExecution = (input) => Activity.make({
13972
15402
  ...input.agent_snapshot === undefined ? {} : { agentSnapshot: input.agent_snapshot },
13973
15403
  ...input.agent_tool_input_schema_digests === undefined ? {} : { agentToolInputSchemaDigests: input.agent_tool_input_schema_digests },
13974
15404
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
13975
- }).pipe(Effect73.mapError(mapExecutionError));
15405
+ }).pipe(Effect74.mapError(mapExecutionError));
13976
15406
  const skillDefinitionIds = input.agent_snapshot?.skill_definition_ids ?? [];
13977
15407
  if (skillDefinitionIds.length > 0) {
13978
15408
  yield* pinExecution2({
13979
15409
  execution_id: input.execution_id,
13980
15410
  skill_definition_ids: skillDefinitionIds
13981
- }).pipe(Effect73.mapError(mapSkillRegistryError));
15411
+ }).pipe(Effect74.mapError(mapSkillRegistryError));
13982
15412
  }
13983
15413
  return accepted2;
13984
15414
  })
@@ -13988,50 +15418,109 @@ var waitIdFromRecord = (record2) => {
13988
15418
  const waitId = record2.metadata.wait_id;
13989
15419
  return typeof waitId === "string" ? exports_ids_schema.WaitId.make(waitId) : undefined;
13990
15420
  };
13991
- var openChildStatuses = new Set(["queued", "running", "waiting"]);
13992
- var childCancelReason = "parent cancelled";
13993
- var cancelChildExecution = Effect73.fn("ExecutionWorkflow.cancelChildExecution")(function* (executionId, cancelledAt) {
15421
+ var prepareCancellation = Effect74.fn("ExecutionWorkflow.prepareCancellation")(function* (input) {
13994
15422
  const repository = yield* exports_execution_repository.Service;
13995
- const record2 = yield* repository.get(executionId).pipe(Effect73.mapError(mapRepositoryError11));
13996
- if (record2 === undefined || terminalExecutionStatuses.has(record2.status))
13997
- return;
13998
- if (record2.status === "waiting") {
13999
- const waitId = waitIdFromRecord(record2);
14000
- if (waitId === undefined) {
14001
- return yield* Effect73.fail(new ExecutionWorkflowFailed({ message: `Waiting execution missing wait id: ${record2.id}` }));
15423
+ const waits = yield* exports_envelope_repository.Service;
15424
+ const toolCalls2 = yield* exports_tool_call_repository.Service;
15425
+ const coordinator = yield* Service45;
15426
+ const eventLog = yield* Service24;
15427
+ return yield* coordinator.coordinate(Effect74.gen(function* () {
15428
+ const record2 = yield* repository.get(input.execution_id).pipe(Effect74.mapError(mapRepositoryError11));
15429
+ if (record2 === undefined) {
15430
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: `Execution not found: ${input.execution_id}` }));
14002
15431
  }
14003
- const eventLog = yield* Service24;
14004
- const eventSequence = yield* nextEventSequence4(eventLog, record2.id);
14005
- const result = yield* cancel2({
14006
- waitId,
14007
- cancelledAt,
14008
- eventSequence,
14009
- metadata: { reason: childCancelReason }
14010
- }).pipe(Effect73.mapError(mapWaitError2));
14011
- if (result.transitioned) {
14012
- yield* signalWait({
14013
- workflow_execution_id: yield* workflowExecutionIdForExecution(record2.id, workflowGenerationFromRecord(record2)),
14014
- wait_id: waitId,
14015
- state: "cancelled",
14016
- signaled_at: cancelledAt
14017
- });
15432
+ if (terminalExecutionStatuses.has(record2.status)) {
15433
+ return { record: record2, status: record2.status, signals: [], terminalNoop: true };
14018
15434
  }
14019
- return;
14020
- }
14021
- yield* repository.transition({
14022
- id: record2.id,
14023
- status: record2.status,
14024
- updatedAt: cancelledAt,
14025
- metadata: {
14026
- ...record2.metadata,
14027
- cancellation_requested: true,
14028
- cancellation_reason: childCancelReason
15435
+ const records = yield* waits.listAllWaits({ executionId: record2.id }).pipe(Effect74.mapError((error) => new ExecutionWorkflowFailed({ message: error._tag })));
15436
+ const currentWaitId = record2.status === "waiting" ? waitIdFromRecord(record2) : undefined;
15437
+ if (record2.status === "waiting" && currentWaitId === undefined) {
15438
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: `Waiting execution missing wait id: ${record2.id}` }));
15439
+ }
15440
+ const signals = [];
15441
+ const cancelledCallIds = [];
15442
+ let currentWaitState;
15443
+ for (const wait of records) {
15444
+ const isCurrent = wait.id === currentWaitId;
15445
+ const isToolWait = wait.metadata.kind === "tool-placement";
15446
+ if (wait.state === "open" && (isCurrent || isToolWait)) {
15447
+ const eventSequence = yield* nextEventSequence4(eventLog, record2.id);
15448
+ const result = yield* cancel2({
15449
+ waitId: wait.id,
15450
+ cancelledAt: input.cancelled_at,
15451
+ eventSequence,
15452
+ metadata: { reason: input.reason ?? "Execution cancelled" }
15453
+ }).pipe(Effect74.mapError(mapWaitError2));
15454
+ if (result.wait.state === "cancelled") {
15455
+ signals.push({ waitId: wait.id, state: "cancelled" });
15456
+ if (isToolWait && typeof wait.metadata.tool_call_id === "string") {
15457
+ cancelledCallIds.push(exports_ids_schema.ToolCallId.make(wait.metadata.tool_call_id));
15458
+ }
15459
+ }
15460
+ if (isCurrent && result.wait.state !== "open")
15461
+ currentWaitState = result.wait.state;
15462
+ continue;
15463
+ }
15464
+ if (isToolWait && wait.state === "cancelled" && typeof wait.metadata.tool_call_id === "string") {
15465
+ cancelledCallIds.push(exports_ids_schema.ToolCallId.make(wait.metadata.tool_call_id));
15466
+ }
15467
+ if (isCurrent && wait.state !== "open") {
15468
+ currentWaitState = wait.state;
15469
+ signals.push({ waitId: wait.id, state: wait.state });
15470
+ }
14029
15471
  }
14030
- }).pipe(Effect73.mapError(mapRepositoryError11));
15472
+ const immediateCallIds = yield* toolCalls2.listCalls(record2.id).pipe(Effect74.mapError((error) => new ExecutionWorkflowFailed({ message: error._tag })), Effect74.map((calls) => calls.filter((call) => call.placement.kind === "local" || call.placement.kind === "mcp").map((call) => call.call.id)));
15473
+ yield* toolCalls2.failOpenForExecution({
15474
+ executionId: record2.id,
15475
+ callIds: [...cancelledCallIds, ...immediateCallIds],
15476
+ message: "Tool execution cancelled",
15477
+ failedAt: input.cancelled_at
15478
+ }).pipe(Effect74.mapError((error) => new ExecutionWorkflowFailed({ message: error._tag })));
15479
+ const updated = yield* repository.transition({
15480
+ id: record2.id,
15481
+ status: record2.status,
15482
+ updatedAt: input.cancelled_at,
15483
+ metadata: {
15484
+ ...record2.metadata,
15485
+ cancellation_requested: true,
15486
+ ...input.reason === undefined ? {} : { cancellation_reason: input.reason }
15487
+ }
15488
+ }).pipe(Effect74.mapError(mapRepositoryError11));
15489
+ return {
15490
+ record: updated,
15491
+ status: currentWaitState === "cancelled" ? "cancelled" : updated.status,
15492
+ signals,
15493
+ terminalNoop: false
15494
+ };
15495
+ })).pipe(Effect74.mapError((error) => error instanceof ExecutionWorkflowFailed ? error : new ExecutionWorkflowFailed({ message: "Tool cancellation transaction failed" })));
15496
+ });
15497
+ var signalPreparedCancellation = Effect74.fn("ExecutionWorkflow.signalPreparedCancellation")(function* (prepared, signaledAt) {
15498
+ for (const pending of prepared.signals) {
15499
+ yield* signalWait({
15500
+ workflow_execution_id: yield* workflowExecutionIdForExecution(prepared.record.id, workflowGenerationFromRecord(prepared.record)),
15501
+ wait_id: pending.waitId,
15502
+ state: pending.state,
15503
+ signaled_at: signaledAt
15504
+ });
15505
+ }
14031
15506
  });
14032
- var cancelOpenChildren = Effect73.fn("ExecutionWorkflow.cancelOpenChildren")(function* (executionId, cancelledAt) {
14033
- const children = yield* exports_child_execution_repository.listByExecution(executionId).pipe(Effect73.mapError(mapChildExecutionRepositoryError));
14034
- yield* Effect73.forEach(children.filter((child) => openChildStatuses.has(child.status)), (child) => Effect73.gen(function* () {
15507
+ var openChildStatuses = new Set(["queued", "running", "waiting"]);
15508
+ var childCancelReason = "parent cancelled";
15509
+ var cancelChildExecution = Effect74.fn("ExecutionWorkflow.cancelChildExecution")(function* (executionId, cancelledAt) {
15510
+ const repository = yield* exports_execution_repository.Service;
15511
+ const record2 = yield* repository.get(executionId).pipe(Effect74.mapError(mapRepositoryError11));
15512
+ if (record2 === undefined)
15513
+ return;
15514
+ const prepared = yield* prepareCancellation({
15515
+ execution_id: executionId,
15516
+ cancelled_at: cancelledAt,
15517
+ reason: childCancelReason
15518
+ });
15519
+ yield* signalPreparedCancellation(prepared, cancelledAt);
15520
+ });
15521
+ var cancelOpenChildren = Effect74.fn("ExecutionWorkflow.cancelOpenChildren")(function* (executionId, cancelledAt) {
15522
+ const children = yield* exports_child_execution_repository.listByExecution(executionId).pipe(Effect74.mapError(mapChildExecutionRepositoryError));
15523
+ yield* Effect74.forEach(children.filter((child) => openChildStatuses.has(child.status)), (child) => Effect74.gen(function* () {
14035
15524
  yield* exports_child_execution_repository.updateStatus({
14036
15525
  id: child.id,
14037
15526
  status: "cancelled",
@@ -14042,7 +15531,7 @@ var cancelOpenChildren = Effect73.fn("ExecutionWorkflow.cancelOpenChildren")(fun
14042
15531
  cancellation_reason: childCancelReason,
14043
15532
  cancellation_requested_at: cancelledAt
14044
15533
  }
14045
- }).pipe(Effect73.mapError(mapChildExecutionRepositoryError));
15534
+ }).pipe(Effect74.mapError(mapChildExecutionRepositoryError));
14046
15535
  yield* cancelChildExecution(exports_ids_schema.ExecutionId.make(child.id), cancelledAt);
14047
15536
  }), { discard: true });
14048
15537
  });
@@ -14050,7 +15539,7 @@ var cancelExecution = (input, turn, reason) => Activity.make({
14050
15539
  name: ActivityNames.cancel(turn),
14051
15540
  success: exports_execution_schema.Execution,
14052
15541
  error: ExecutionWorkflowFailed,
14053
- execute: Effect73.gen(function* () {
15542
+ execute: Effect74.gen(function* () {
14054
15543
  yield* cancelOpenChildren(input.execution_id, input.completed_at);
14055
15544
  const eventLog = yield* Service24;
14056
15545
  const eventSequence = yield* nextEventSequence4(eventLog, input.execution_id);
@@ -14059,16 +15548,16 @@ var cancelExecution = (input, turn, reason) => Activity.make({
14059
15548
  eventSequence,
14060
15549
  cancelledAt: input.completed_at,
14061
15550
  reason
14062
- }).pipe(Effect73.mapError(mapExecutionError));
15551
+ }).pipe(Effect74.mapError(mapExecutionError));
14063
15552
  })
14064
15553
  });
14065
15554
  var loadCancellationRequested = (input, turn) => Activity.make({
14066
15555
  name: ActivityNames.checkCancel(turn),
14067
15556
  success: Schema69.Boolean,
14068
15557
  error: ExecutionWorkflowFailed,
14069
- execute: Effect73.gen(function* () {
15558
+ execute: Effect74.gen(function* () {
14070
15559
  const repository = yield* exports_execution_repository.Service;
14071
- const record2 = yield* repository.get(input.execution_id).pipe(Effect73.mapError(mapRepositoryError11));
15560
+ const record2 = yield* repository.get(input.execution_id).pipe(Effect74.mapError(mapRepositoryError11));
14072
15561
  return record2?.metadata?.cancellation_requested === true;
14073
15562
  })
14074
15563
  });
@@ -14076,7 +15565,7 @@ var loadWait = (name, waitId) => Activity.make({
14076
15565
  name,
14077
15566
  success: Schema69.UndefinedOr(WaitSnapshot),
14078
15567
  error: ExecutionWorkflowFailed,
14079
- execute: get11(waitId).pipe(Effect73.map((record2) => record2 === undefined ? undefined : toWaitSnapshot(record2)), Effect73.mapError(mapWaitError2))
15568
+ execute: get11(waitId).pipe(Effect74.map((record2) => record2 === undefined ? undefined : toWaitSnapshot(record2)), Effect74.mapError(mapWaitError2))
14080
15569
  });
14081
15570
  var markWaiting = (input, repository, wait) => Activity.make({
14082
15571
  name: ActivityNames.markWaiting(wait.id),
@@ -14091,7 +15580,7 @@ var markWaiting = (input, repository, wait) => Activity.make({
14091
15580
  wait_state: wait.state,
14092
15581
  ...generationMetadata(workflowGenerationForStart(input))
14093
15582
  }
14094
- }).pipe(Effect73.mapError(mapRepositoryError11), Effect73.map((record2) => ({
15583
+ }).pipe(Effect74.mapError(mapRepositoryError11), Effect74.map((record2) => ({
14095
15584
  id: record2.id,
14096
15585
  root_address_id: record2.rootAddressId,
14097
15586
  ...record2.sessionId === undefined ? {} : { session_id: record2.sessionId },
@@ -14130,26 +15619,26 @@ var metadataSetting = (input, key2) => {
14130
15619
  var executionMetadataSetting = (input, key2) => hasMetadataKey(input.metadata, key2) ? input.metadata?.[key2] : undefined;
14131
15620
  var decodeOptionalNumberSetting = (value, key2, valid) => {
14132
15621
  if (value === undefined)
14133
- return Effect73.succeed(undefined);
15622
+ return Effect74.succeed(undefined);
14134
15623
  if (value === null || value === false)
14135
- return Effect73.succeed(null);
15624
+ return Effect74.succeed(null);
14136
15625
  if (typeof value === "number" && Number.isFinite(value) && valid(value))
14137
- return Effect73.succeed(value);
14138
- return Effect73.fail(new ExecutionWorkflowFailed({ message: `${key2} metadata value is invalid` }));
15626
+ return Effect74.succeed(value);
15627
+ return Effect74.fail(new ExecutionWorkflowFailed({ message: `${key2} metadata value is invalid` }));
14139
15628
  };
14140
- var optionalNumberForStart = (input, key2, valid) => decodeOptionalNumberSetting(metadataSetting(input, key2), key2, valid).pipe(Effect73.map((value) => value === null ? undefined : value));
15629
+ var optionalNumberForStart = (input, key2, valid) => decodeOptionalNumberSetting(metadataSetting(input, key2), key2, valid).pipe(Effect74.map((value) => value === null ? undefined : value));
14141
15630
  var continueAsNewAfterTurnsForStart = (input) => optionalNumberForStart(input, continueAsNewAfterTurnsMetadataKey, (value) => Number.isInteger(value) && value > 0);
14142
15631
  var toolOutputMaxBytesForStart = (input) => decodeOptionalNumberSetting(metadataSetting(input, toolOutputMaxBytesMetadataKey), toolOutputMaxBytesMetadataKey, (value) => value >= 0);
14143
15632
  var decodeCompactionEnabled = (value) => {
14144
15633
  if (value === undefined)
14145
- return Effect73.succeed(undefined);
15634
+ return Effect74.succeed(undefined);
14146
15635
  if (value === null || value === false)
14147
- return Effect73.succeed(null);
15636
+ return Effect74.succeed(null);
14148
15637
  if (value === true)
14149
- return Effect73.succeed(true);
14150
- return Effect73.fail(new ExecutionWorkflowFailed({ message: "compaction_enabled metadata value must be true or false" }));
15638
+ return Effect74.succeed(true);
15639
+ return Effect74.fail(new ExecutionWorkflowFailed({ message: "compaction_enabled metadata value must be true or false" }));
14151
15640
  };
14152
- var compactionForStart = Effect73.fn("ExecutionWorkflow.compactionForStart")(function* (input) {
15641
+ var compactionForStart = Effect74.fn("ExecutionWorkflow.compactionForStart")(function* (input) {
14153
15642
  const executionEnabled = yield* decodeCompactionEnabled(executionMetadataSetting(input, compactionEnabledMetadataKey));
14154
15643
  if (executionEnabled === null)
14155
15644
  return null;
@@ -14165,8 +15654,8 @@ var compactionForStart = Effect73.fn("ExecutionWorkflow.compactionForStart")(fun
14165
15654
  ...keepRecentTokens === undefined ? {} : { keepRecentTokens }
14166
15655
  };
14167
15656
  });
14168
- var decodeMemorySubject = (value) => typeof value === "string" ? Schema69.decodeUnknownEffect(exports_ids_schema.MemorySubjectId)(value).pipe(Effect73.mapError(() => new ExecutionWorkflowFailed({ message: `Invalid memory_subject_id metadata value: ${value}` }))) : Effect73.fail(new ExecutionWorkflowFailed({ message: "memory_subject_id metadata value must be a string" }));
14169
- var memorySubjectForStart = Effect73.fn("ExecutionWorkflow.memorySubjectForStart")(function* (input) {
15657
+ var decodeMemorySubject = (value) => typeof value === "string" ? Schema69.decodeUnknownEffect(exports_ids_schema.MemorySubjectId)(value).pipe(Effect74.mapError(() => new ExecutionWorkflowFailed({ message: `Invalid memory_subject_id metadata value: ${value}` }))) : Effect74.fail(new ExecutionWorkflowFailed({ message: "memory_subject_id metadata value must be a string" }));
15658
+ var memorySubjectForStart = Effect74.fn("ExecutionWorkflow.memorySubjectForStart")(function* (input) {
14170
15659
  const executionSubject = memorySubjectFromMetadata(input.metadata);
14171
15660
  if (executionSubject !== undefined)
14172
15661
  return yield* decodeMemorySubject(executionSubject);
@@ -14180,21 +15669,21 @@ var steeringEnabledForStart = (input) => {
14180
15669
  return executionSetting === true;
14181
15670
  return steeringMetadataValue(input.agent_snapshot?.metadata) === true;
14182
15671
  };
14183
- var nextEventSequence4 = (eventLog, executionId) => eventLog.maxSequence(executionId).pipe(Effect73.map((max) => max === undefined ? 0 : max + 1), Effect73.mapError(mapEventLogError6));
15672
+ var nextEventSequence4 = (eventLog, executionId) => eventLog.maxSequence(executionId).pipe(Effect74.map((max) => max === undefined ? 0 : max + 1), Effect74.mapError(mapEventLogError6));
14184
15673
  var ensureWorkspace = (input) => Activity.make({
14185
15674
  name: ActivityNames.ensureWorkspace,
14186
15675
  success: Schema69.UndefinedOr(exports_workspace_schema.WorkspaceLeaseRecord),
14187
15676
  error: ExecutionWorkflowFailed,
14188
- execute: Effect73.gen(function* () {
15677
+ execute: Effect74.gen(function* () {
14189
15678
  if (input.agent_snapshot === undefined)
14190
- return yield* Effect73.fail(missingAgentSnapshot());
15679
+ return yield* Effect74.fail(missingAgentSnapshot());
14191
15680
  const tools = yield* Service26;
14192
15681
  const plan2 = yield* ensure2({
14193
15682
  executionId: input.execution_id,
14194
15683
  agent: input.agent_snapshot,
14195
15684
  toolDefinitions: yield* tools.definitions,
14196
15685
  now: input.started_at
14197
- }).pipe(Effect73.mapError(mapWorkspaceError));
15686
+ }).pipe(Effect74.mapError(mapWorkspaceError));
14198
15687
  return plan2?.lease;
14199
15688
  })
14200
15689
  });
@@ -14202,34 +15691,34 @@ var suspendWorkspace = (input, key2) => Activity.make({
14202
15691
  name: ActivityNames.suspendWorkspace(key2),
14203
15692
  success: Schema69.UndefinedOr(exports_workspace_schema.WorkspaceLeaseRecord),
14204
15693
  error: ExecutionWorkflowFailed,
14205
- execute: suspend2({ executionId: input.execution_id, now: input.started_at }).pipe(Effect73.mapError(mapWorkspaceError))
15694
+ execute: suspend2({ executionId: input.execution_id, now: input.started_at }).pipe(Effect74.mapError(mapWorkspaceError))
14206
15695
  });
14207
15696
  var resumeWorkspace = (input, key2) => Activity.make({
14208
15697
  name: ActivityNames.resumeWorkspace(key2),
14209
15698
  success: Schema69.UndefinedOr(exports_workspace_schema.WorkspaceLeaseRecord),
14210
15699
  error: ExecutionWorkflowFailed,
14211
- execute: resume2({ executionId: input.execution_id, now: input.started_at }).pipe(Effect73.map((plan2) => plan2?.lease), Effect73.mapError(mapWorkspaceError))
15700
+ execute: resume2({ executionId: input.execution_id, now: input.started_at }).pipe(Effect74.map((plan2) => plan2?.lease), Effect74.mapError(mapWorkspaceError))
14212
15701
  });
14213
15702
  var releaseWorkspace = (input) => Activity.make({
14214
15703
  name: ActivityNames.releaseWorkspace,
14215
15704
  success: Schema69.UndefinedOr(exports_workspace_schema.WorkspaceLeaseRecord),
14216
15705
  error: ExecutionWorkflowFailed,
14217
- execute: release2({ executionId: input.execution_id, now: input.completed_at }).pipe(Effect73.mapError(mapWorkspaceError))
15706
+ execute: release2({ executionId: input.execution_id, now: input.completed_at }).pipe(Effect74.mapError(mapWorkspaceError))
14218
15707
  });
14219
15708
  var failWorkspace = (input, error) => fail({
14220
15709
  executionId: input.execution_id,
14221
15710
  now: input.completed_at,
14222
15711
  metadata: { message: error.message }
14223
- }).pipe(Effect73.catch(() => Effect73.void));
14224
- var attachWorkspace = (input) => attach({ executionId: input.execution_id, now: input.started_at }).pipe(Effect73.mapError(mapWorkspaceError));
15712
+ }).pipe(Effect74.catch(() => Effect74.void));
15713
+ var attachWorkspace = (input) => attach({ executionId: input.execution_id, now: input.started_at }).pipe(Effect74.mapError(mapWorkspaceError));
14225
15714
  var sessionEntryScope = (input, turn) => `${input.execution_id}:${workflowGenerationForStart(input)}:complete:${turn}`;
14226
15715
  var completeExecution = (input, waitId, waitState, workspaceRuntimeLayer, turn, pendingToolCall) => Activity.make({
14227
15716
  name: ActivityNames.complete(turn),
14228
15717
  success: exports_execution_schema.Execution,
14229
15718
  error: ExecutionWorkflowFailed,
14230
- execute: Effect73.gen(function* () {
15719
+ execute: Effect74.gen(function* () {
14231
15720
  if (input.agent_snapshot === undefined)
14232
- return yield* Effect73.fail(missingAgentSnapshot());
15721
+ return yield* Effect74.fail(missingAgentSnapshot());
14233
15722
  const agentLoop = yield* Service41;
14234
15723
  const eventLog = yield* Service24;
14235
15724
  const runEventSequence = yield* nextEventSequence4(eventLog, input.execution_id);
@@ -14268,18 +15757,18 @@ var completeExecution = (input, waitId, waitState, workspaceRuntimeLayer, turn,
14268
15757
  agent_snapshot: child.agentSnapshot,
14269
15758
  ...child.agentToolInputSchemaDigests === undefined ? {} : { agent_tool_input_schema_digests: child.agentToolInputSchemaDigests },
14270
15759
  metadata: child.metadata
14271
- }, { discard: true }).pipe(Effect73.asVoid)
15760
+ }, { discard: true }).pipe(Effect74.asVoid)
14272
15761
  });
14273
- const skillLoopProgram = skillDefinitionIds.length === 0 ? loopProgram : loopProgram.pipe(Effect73.provideService(exports_skill_source.SkillSource, yield* sourceForExecution(input.execution_id).pipe(Effect73.mapError((error) => new ExecutionWorkflowFailed({ message: error.message })))));
14274
- const workspaceLoopProgram = workspaceRuntimeLayer === undefined ? skillLoopProgram : skillLoopProgram.pipe(Effect73.provide(workspaceRuntimeLayer));
14275
- const program = workspaceLoopProgram.pipe(Effect73.map((result) => ({
15762
+ const skillLoopProgram = skillDefinitionIds.length === 0 ? loopProgram : loopProgram.pipe(Effect74.provideService(exports_skill_source.SkillSource, yield* sourceForExecution(input.execution_id).pipe(Effect74.mapError((error) => new ExecutionWorkflowFailed({ message: error.message })))));
15763
+ const workspaceLoopProgram = workspaceRuntimeLayer === undefined ? skillLoopProgram : skillLoopProgram.pipe(Effect74.provide(workspaceRuntimeLayer));
15764
+ const program = workspaceLoopProgram.pipe(Effect74.map((result) => ({
14276
15765
  metadata: {
14277
15766
  ...result.metadata,
14278
15767
  ...waitId === undefined ? {} : { wait_id: waitId },
14279
15768
  ...waitId === undefined || waitState === undefined ? {} : { wait_state: waitState }
14280
15769
  },
14281
15770
  nextEventSequence: result.nextEventSequence
14282
- })), Effect73.catchTag("AgentLoopWaitRequested", (wait) => Effect73.succeed({
15771
+ })), Effect74.catchTag("AgentLoopWaitRequested", (wait) => Effect74.succeed({
14283
15772
  _tag: "waiting",
14284
15773
  waitId: wait.wait_id,
14285
15774
  metadata: {
@@ -14289,14 +15778,14 @@ var completeExecution = (input, waitId, waitState, workspaceRuntimeLayer, turn,
14289
15778
  ...generationMetadata(workflowGenerationForStart(input))
14290
15779
  },
14291
15780
  nextEventSequence: wait.next_event_sequence
14292
- })), Effect73.mapError(mapAgentLoopError));
15781
+ })), Effect74.mapError(mapAgentLoopError));
14293
15782
  return yield* run4({
14294
15783
  executionId: input.execution_id,
14295
15784
  eventSequence: runEventSequence,
14296
15785
  startedAt: input.started_at,
14297
15786
  completedAt: input.completed_at,
14298
15787
  program
14299
- }).pipe(Effect73.mapError(mapExecutionError));
15788
+ }).pipe(Effect74.mapError(mapExecutionError));
14300
15789
  })
14301
15790
  });
14302
15791
  var childDispatchContext = (input) => {
@@ -14315,11 +15804,11 @@ var loadChildCancellationRequested = (input) => Activity.make({
14315
15804
  name: ActivityNames.checkQueuedChildCancellation,
14316
15805
  success: Schema69.Boolean,
14317
15806
  error: ExecutionWorkflowFailed,
14318
- execute: Effect73.gen(function* () {
15807
+ execute: Effect74.gen(function* () {
14319
15808
  const context = childDispatchContext(input);
14320
15809
  if (context === undefined)
14321
15810
  return false;
14322
- const child = yield* exports_child_execution_repository.get(context.childExecutionId).pipe(Effect73.mapError(mapChildExecutionRepositoryError));
15811
+ const child = yield* exports_child_execution_repository.get(context.childExecutionId).pipe(Effect74.mapError(mapChildExecutionRepositoryError));
14323
15812
  return child?.status === "cancelled" || child?.metadata.cancellation_requested === true;
14324
15813
  })
14325
15814
  });
@@ -14327,8 +15816,8 @@ var notifyParentActivity = (input, context, status, output) => Activity.make({
14327
15816
  name: ActivityNames.notifyParent(status),
14328
15817
  success: Schema69.Void,
14329
15818
  error: ExecutionWorkflowFailed,
14330
- execute: Effect73.gen(function* () {
14331
- const notifier = yield* Effect73.serviceOption(Service42);
15819
+ execute: Effect74.gen(function* () {
15820
+ const notifier = yield* Effect74.serviceOption(Service42);
14332
15821
  if (Option26.isNone(notifier))
14333
15822
  return;
14334
15823
  yield* notifier.value.notify({
@@ -14338,12 +15827,12 @@ var notifyParentActivity = (input, context, status, output) => Activity.make({
14338
15827
  status,
14339
15828
  output,
14340
15829
  notifiedAt: input.completed_at
14341
- }).pipe(Effect73.mapError((error) => new ExecutionWorkflowFailed({ message: error.message })));
15830
+ }).pipe(Effect74.mapError((error) => new ExecutionWorkflowFailed({ message: error.message })));
14342
15831
  })
14343
15832
  });
14344
15833
  var notifyParent = (input, status, output) => {
14345
15834
  const context = childDispatchContext(input);
14346
- return context === undefined ? Effect73.void : notifyParentActivity(input, context, status, output);
15835
+ return context === undefined ? Effect74.void : notifyParentActivity(input, context, status, output);
14347
15836
  };
14348
15837
  var terminalOutput = (execution) => {
14349
15838
  const output = execution.metadata?.model_output;
@@ -14351,12 +15840,12 @@ var terminalOutput = (execution) => {
14351
15840
  };
14352
15841
  var missingWait = (waitId) => new ExecutionWorkflowFailed({ message: `Wait not found: ${waitId}` });
14353
15842
  var stillOpen = (waitId) => new ExecutionWorkflowFailed({ message: `Wait remained open after wake: ${waitId}` });
14354
- var resolveWaitState = Effect73.fn("ExecutionWorkflow.resolveWaitState")(function* (input, repository) {
15843
+ var resolveWaitState = Effect74.fn("ExecutionWorkflow.resolveWaitState")(function* (input, repository) {
14355
15844
  if (input.wait_id === undefined)
14356
15845
  return;
14357
15846
  const before = yield* loadWait(ActivityNames.loadWaitBeforeSleep(input.wait_id), input.wait_id);
14358
15847
  if (before === undefined)
14359
- return yield* Effect73.fail(missingWait(input.wait_id));
15848
+ return yield* Effect74.fail(missingWait(input.wait_id));
14360
15849
  const beforeTerminal = terminalWaitState(before);
14361
15850
  if (beforeTerminal !== undefined)
14362
15851
  return beforeTerminal;
@@ -14366,10 +15855,10 @@ var resolveWaitState = Effect73.fn("ExecutionWorkflow.resolveWaitState")(functio
14366
15855
  yield* resumeWorkspace(input, input.wait_id);
14367
15856
  const after = yield* loadWait(ActivityNames.loadWaitAfterWake(input.wait_id), input.wait_id);
14368
15857
  if (after === undefined)
14369
- return yield* Effect73.fail(missingWait(input.wait_id));
15858
+ return yield* Effect74.fail(missingWait(input.wait_id));
14370
15859
  const afterTerminal = terminalWaitState(after);
14371
15860
  if (afterTerminal === undefined)
14372
- return yield* Effect73.fail(stillOpen(input.wait_id));
15861
+ return yield* Effect74.fail(stillOpen(input.wait_id));
14373
15862
  return afterTerminal;
14374
15863
  });
14375
15864
  var waitIdFromExecution = (execution) => {
@@ -14380,7 +15869,7 @@ var pendingToolCallFromExecution = (execution) => {
14380
15869
  const pending = execution.metadata?.pending_tool_call;
14381
15870
  return Schema69.decodeUnknownOption(exports_tool_schema.Call)(pending).pipe(Option26.getOrUndefined);
14382
15871
  };
14383
- var finishCancelledWait = Effect73.fn("ExecutionWorkflow.finishCancelledWait")(function* (startInput, turn, waitId) {
15872
+ var finishCancelledWait = Effect74.fn("ExecutionWorkflow.finishCancelledWait")(function* (startInput, turn, waitId) {
14384
15873
  const cancelled = yield* cancelExecution(startInput, turn, "wait cancelled");
14385
15874
  yield* releaseWorkspace(startInput);
14386
15875
  yield* notifyParent(startInput, "cancelled", []);
@@ -14403,7 +15892,7 @@ var continueAsNew = (startInput, turn, waitId, pendingToolCall) => Activity.make
14403
15892
  workflow_generation: workflowGenerationForStart(startInput) + 1
14404
15893
  })
14405
15894
  });
14406
- var runWorkflow = Effect73.fn("ExecutionWorkflow.run")(function* (input) {
15895
+ var runWorkflow = Effect74.fn("ExecutionWorkflow.run")(function* (input) {
14407
15896
  const repository = yield* exports_execution_repository.Service;
14408
15897
  const startInput = yield* resolveStartInput(input);
14409
15898
  const generation = workflowGenerationForStart(startInput);
@@ -14420,7 +15909,7 @@ var runWorkflow = Effect73.fn("ExecutionWorkflow.run")(function* (input) {
14420
15909
  ...cancelled.metadata === undefined ? {} : { metadata: cancelled.metadata }
14421
15910
  };
14422
15911
  }
14423
- return yield* Effect73.gen(function* () {
15912
+ return yield* Effect74.gen(function* () {
14424
15913
  if (generation === 0)
14425
15914
  yield* ensureWorkspace(startInput);
14426
15915
  let activeWaitId = startInput.wait_id;
@@ -14451,13 +15940,13 @@ var runWorkflow = Effect73.fn("ExecutionWorkflow.run")(function* (input) {
14451
15940
  if (execution.status !== "waiting")
14452
15941
  break;
14453
15942
  if (turn >= maxWaitTurns)
14454
- return yield* Effect73.fail(new ExecutionWorkflowFailed({ message: "Agent wait turn limit exceeded" }));
15943
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: "Agent wait turn limit exceeded" }));
14455
15944
  const waitId = waitIdFromExecution(execution);
14456
15945
  if (waitId === undefined)
14457
- return yield* Effect73.fail(new ExecutionWorkflowFailed({ message: "Waiting execution missing wait id" }));
15946
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: "Waiting execution missing wait id" }));
14458
15947
  pendingToolCall = pendingToolCallFromExecution(execution);
14459
15948
  if (pendingToolCall === undefined) {
14460
- return yield* Effect73.fail(new ExecutionWorkflowFailed({ message: "Waiting execution missing pending tool call" }));
15949
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: "Waiting execution missing pending tool call" }));
14461
15950
  }
14462
15951
  activeWaitId = waitId;
14463
15952
  waitState = yield* resolveWaitState({ ...startInput, wait_id: waitId }, repository);
@@ -14478,7 +15967,7 @@ var runWorkflow = Effect73.fn("ExecutionWorkflow.run")(function* (input) {
14478
15967
  ...waitState === undefined ? {} : { wait_state: waitState },
14479
15968
  ...execution.metadata === undefined ? {} : { metadata: execution.metadata }
14480
15969
  };
14481
- }).pipe(Effect73.catch((error) => failWorkspace(startInput, error).pipe(Effect73.flatMap(() => notifyParent(startInput, "failed", [])), Effect73.flatMap(() => Effect73.fail(error)))));
15970
+ }).pipe(Effect74.catch((error) => failWorkspace(startInput, error).pipe(Effect74.flatMap(() => notifyParent(startInput, "failed", [])), Effect74.flatMap(() => Effect74.fail(error)))));
14482
15971
  });
14483
15972
  var waitingResult = (input) => ({
14484
15973
  execution_id: input.execution_id,
@@ -14486,69 +15975,36 @@ var waitingResult = (input) => ({
14486
15975
  ...input.wait_id === undefined ? {} : { wait_id: input.wait_id },
14487
15976
  metadata: input.wait_id === undefined ? {} : { wait_id: input.wait_id, wait_state: "open" }
14488
15977
  });
14489
- var awaitStartResult = Effect73.fn("ExecutionWorkflow.awaitStartResult")(function* (input, workflowExecutionId) {
14490
- const result = yield* StartExecutionWorkflow.poll(workflowExecutionId).pipe(Effect73.tap((pollResult) => Option26.isSome(pollResult) ? Effect73.void : Effect73.yieldNow), Effect73.repeat({ times: 31, until: Option26.isSome }));
15978
+ var awaitStartResult = Effect74.fn("ExecutionWorkflow.awaitStartResult")(function* (input, workflowExecutionId) {
15979
+ const result = yield* StartExecutionWorkflow.poll(workflowExecutionId).pipe(Effect74.tap((pollResult) => Option26.isSome(pollResult) ? Effect74.void : Effect74.yieldNow), Effect74.repeat({ times: 31, until: Option26.isSome }));
14491
15980
  if (Option26.isSome(result)) {
14492
15981
  if (result.value._tag === "Suspended")
14493
15982
  return waitingResult(input);
14494
15983
  if (Exit2.isSuccess(result.value.exit))
14495
15984
  return result.value.exit.value;
14496
- return yield* Effect73.fail(new ExecutionWorkflowFailed({ message: "Execution workflow failed" }));
15985
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: "Execution workflow failed" }));
14497
15986
  }
14498
15987
  return waitingResult(input);
14499
15988
  });
14500
- var layer48 = StartExecutionWorkflow.toLayer(runWorkflow);
15989
+ var layer49 = StartExecutionWorkflow.toLayer(runWorkflow);
14501
15990
  var start = (input, options) => StartExecutionWorkflow.execute(input, options);
14502
- var startRequest = Effect73.fn("ExecutionWorkflow.startRequest")(function* (input) {
15991
+ var startRequest = Effect74.fn("ExecutionWorkflow.startRequest")(function* (input) {
14503
15992
  if (input.wait_id === undefined)
14504
15993
  return yield* start(input);
14505
15994
  const workflowExecutionId = yield* start(input, { discard: true });
14506
15995
  return yield* awaitStartResult(input, workflowExecutionId);
14507
15996
  });
14508
- var cancelRequest = Effect73.fn("ExecutionWorkflow.cancelRequest")(function* (input) {
14509
- const repository = yield* exports_execution_repository.Service;
14510
- const record2 = yield* repository.get(input.execution_id).pipe(Effect73.mapError(mapRepositoryError11));
14511
- if (record2 === undefined) {
14512
- return yield* Effect73.fail(new ExecutionWorkflowFailed({ message: `Execution not found: ${input.execution_id}` }));
14513
- }
14514
- if (terminalExecutionStatuses.has(record2.status)) {
14515
- return { execution_id: record2.id, status: record2.status };
14516
- }
14517
- yield* cancelOpenChildren(record2.id, input.cancelled_at);
14518
- if (record2.status === "waiting") {
14519
- const waitId = waitIdFromRecord(record2);
14520
- if (waitId === undefined) {
14521
- return yield* Effect73.fail(new ExecutionWorkflowFailed({ message: `Waiting execution missing wait id: ${record2.id}` }));
14522
- }
14523
- const eventLog = yield* Service24;
14524
- const eventSequence = yield* nextEventSequence4(eventLog, record2.id);
14525
- const result = yield* cancel2({
14526
- waitId,
14527
- cancelledAt: input.cancelled_at,
14528
- eventSequence,
14529
- ...input.reason === undefined ? {} : { metadata: { reason: input.reason } }
14530
- }).pipe(Effect73.mapError(mapWaitError2));
14531
- if (result.transitioned) {
14532
- yield* signalWait({
14533
- workflow_execution_id: yield* workflowExecutionIdForExecution(record2.id, workflowGenerationFromRecord(record2)),
14534
- wait_id: waitId,
14535
- state: "cancelled",
14536
- signaled_at: input.cancelled_at
14537
- });
14538
- }
14539
- return { execution_id: record2.id, status: "cancelled" };
15997
+ var dispatchRequest = Effect74.fn("ExecutionWorkflow.dispatchRequest")(function* (input) {
15998
+ yield* start(input, { discard: true });
15999
+ });
16000
+ var cancelRequest = Effect74.fn("ExecutionWorkflow.cancelRequest")(function* (input) {
16001
+ const prepared = yield* prepareCancellation(input);
16002
+ if (prepared.terminalNoop) {
16003
+ return { execution_id: prepared.record.id, status: prepared.status };
14540
16004
  }
14541
- yield* repository.transition({
14542
- id: record2.id,
14543
- status: record2.status,
14544
- updatedAt: input.cancelled_at,
14545
- metadata: {
14546
- ...record2.metadata,
14547
- cancellation_requested: true,
14548
- ...input.reason === undefined ? {} : { cancellation_reason: input.reason }
14549
- }
14550
- }).pipe(Effect73.mapError(mapRepositoryError11));
14551
- return { execution_id: record2.id, status: record2.status };
16005
+ yield* signalPreparedCancellation(prepared, input.cancelled_at);
16006
+ yield* cancelOpenChildren(prepared.record.id, input.cancelled_at);
16007
+ return { execution_id: prepared.record.id, status: prepared.status };
14552
16008
  });
14553
16009
  var poll = (executionId) => StartExecutionWorkflow.poll(executionId);
14554
16010
  var resume3 = (executionId) => StartExecutionWorkflow.resume(executionId);
@@ -14562,12 +16018,12 @@ var workflowExecutionIdForExecution = (executionId, workflowGeneration = 0) => S
14562
16018
  completed_at: 0,
14563
16019
  workflow_generation: workflowGeneration
14564
16020
  });
14565
- var activeWorkflowExecutionIdForExecution = Effect73.fn("ExecutionWorkflow.activeWorkflowExecutionIdForExecution")(function* (executionId) {
16021
+ var activeWorkflowExecutionIdForExecution = Effect74.fn("ExecutionWorkflow.activeWorkflowExecutionIdForExecution")(function* (executionId) {
14566
16022
  const repository = yield* exports_execution_repository.Service;
14567
- const record2 = yield* repository.get(executionId).pipe(Effect73.mapError(mapRepositoryError11));
16023
+ const record2 = yield* repository.get(executionId).pipe(Effect74.mapError(mapRepositoryError11));
14568
16024
  return yield* workflowExecutionIdForExecution(executionId, record2 === undefined ? 0 : workflowGenerationFromRecord(record2));
14569
16025
  });
14570
- var signalWait = Effect73.fn("ExecutionWorkflow.signalWait")(function* (input) {
16026
+ var signalWait = Effect74.fn("ExecutionWorkflow.signalWait")(function* (input) {
14571
16027
  const deferred = waitSignal(input.wait_id);
14572
16028
  const token = DurableDeferred.tokenFromExecutionId(deferred, {
14573
16029
  workflow: StartExecutionWorkflow,
@@ -14595,14 +16051,25 @@ var SignalWait = Rpc.make("signalWait", {
14595
16051
  success: Schema70.Void,
14596
16052
  error: ExecutionWorkflowFailed
14597
16053
  }).annotate(ClusterSchema.Persisted, true).annotate(ClusterSchema.Uninterruptible, "server");
16054
+ var Dispatch = Rpc.make("dispatch", {
16055
+ payload: StartInput,
16056
+ success: Schema70.Void,
16057
+ error: ExecutionWorkflowFailed
16058
+ }).annotate(ClusterSchema.Persisted, true).annotate(ClusterSchema.Uninterruptible, "server");
14598
16059
  var Cancel = Rpc.make("cancel", {
14599
16060
  payload: CancelExecutionInput,
14600
16061
  success: CancelExecutionResult,
14601
16062
  error: ExecutionWorkflowFailed
14602
16063
  }).annotate(ClusterSchema.Persisted, true).annotate(ClusterSchema.Uninterruptible, "server");
14603
- var entity = Entity.make("Relay/Execution", [Start, SignalWait, Cancel]).annotate(ClusterSchema.ShardGroup, () => "execution");
14604
- var layer49 = entity.toLayer(entity.of({
16064
+ var entity = Entity.make("Relay/Execution", [
16065
+ Start,
16066
+ Dispatch,
16067
+ SignalWait,
16068
+ Cancel
16069
+ ]).annotate(ClusterSchema.ShardGroup, () => "execution");
16070
+ var layer50 = entity.toLayer(entity.of({
14605
16071
  start: (request) => startRequest(request.payload),
16072
+ dispatch: (request) => dispatchRequest(request.payload),
14606
16073
  signalWait: (request) => signalWait(request.payload),
14607
16074
  cancel: (request) => cancelRequest(request.payload)
14608
16075
  }), { concurrency: "unbounded" });
@@ -14612,15 +16079,15 @@ var exports_envelope_service = {};
14612
16079
  __export(exports_envelope_service, {
14613
16080
  testLayer: () => testLayer49,
14614
16081
  send: () => send2,
14615
- memoryLayer: () => memoryLayer33,
14616
- layer: () => layer50,
14617
- Service: () => Service47,
16082
+ memoryLayer: () => memoryLayer34,
16083
+ layer: () => layer51,
16084
+ Service: () => Service48,
14618
16085
  EnvelopeServiceError: () => EnvelopeServiceError,
14619
16086
  EnvelopeRouteUnavailable: () => EnvelopeRouteUnavailable,
14620
16087
  EnvelopeRouteDeferred: () => EnvelopeRouteDeferred,
14621
16088
  EnvelopeAddressNotFound: () => EnvelopeAddressNotFound
14622
16089
  });
14623
- import { Context as Context60, Effect as Effect74, Layer as Layer67, Schema as Schema71 } from "effect";
16090
+ import { Context as Context61, Effect as Effect75, Layer as Layer68, Schema as Schema71 } from "effect";
14624
16091
  class EnvelopeAddressNotFound extends Schema71.TaggedErrorClass()("EnvelopeAddressNotFound", {
14625
16092
  address_id: exports_ids_schema.AddressId
14626
16093
  }) {
@@ -14643,7 +16110,7 @@ class EnvelopeServiceError extends Schema71.TaggedErrorClass()("EnvelopeServiceE
14643
16110
  }) {
14644
16111
  }
14645
16112
 
14646
- class Service47 extends Context60.Service()("@relayfx/runtime/EnvelopeService") {
16113
+ class Service48 extends Context61.Service()("@relayfx/runtime/EnvelopeService") {
14647
16114
  }
14648
16115
  var mapAddressBookError2 = (error) => {
14649
16116
  if (error._tag === "AddressNotFound")
@@ -14727,20 +16194,20 @@ var readyEvent = (input, ready) => ({
14727
16194
  },
14728
16195
  created_at: input.createdAt + 2
14729
16196
  });
14730
- var layer50 = Layer67.effect(Service47, Effect74.gen(function* () {
16197
+ var layer51 = Layer68.effect(Service48, Effect75.gen(function* () {
14731
16198
  const addressBook = yield* Service23;
14732
16199
  const repository = yield* exports_envelope_repository.Service;
14733
16200
  const eventLog = yield* Service24;
14734
- return Service47.of({
14735
- send: Effect74.fn("EnvelopeService.send")(function* (input) {
14736
- yield* Effect74.annotateCurrentSpan({
16201
+ return Service48.of({
16202
+ send: Effect75.fn("EnvelopeService.send")(function* (input) {
16203
+ yield* Effect75.annotateCurrentSpan({
14737
16204
  "relay.envelope.id": input.envelopeId,
14738
16205
  "relay.execution.id": input.executionId,
14739
16206
  "relay.address.from": input.input.from,
14740
16207
  "relay.address.to": input.input.to
14741
16208
  });
14742
- const route2 = yield* addressBook.resolve(input.input.to).pipe(Effect74.mapError(mapAddressBookError2));
14743
- yield* Effect74.annotateCurrentSpan({
16209
+ const route2 = yield* addressBook.resolve(input.input.to).pipe(Effect75.mapError(mapAddressBookError2));
16210
+ yield* Effect75.annotateCurrentSpan({
14744
16211
  "relay.route.kind": route2.kind,
14745
16212
  "relay.route.key": route2.route_key
14746
16213
  });
@@ -14751,21 +16218,21 @@ var layer50 = Layer67.effect(Service47, Effect74.gen(function* () {
14751
16218
  envelope,
14752
16219
  ...waitId === undefined ? {} : { waitId },
14753
16220
  ...ready === undefined ? {} : { ready }
14754
- }).pipe(Effect74.mapError(mapRepositoryError12));
14755
- yield* eventLog.append(acceptedEvent2(input)).pipe(Effect74.mapError(mapEventLogError7));
14756
- yield* eventLog.append(routedEvent(input, route2)).pipe(Effect74.mapError(mapEventLogError7));
16221
+ }).pipe(Effect75.mapError(mapRepositoryError12));
16222
+ yield* eventLog.append(acceptedEvent2(input)).pipe(Effect75.mapError(mapEventLogError7));
16223
+ yield* eventLog.append(routedEvent(input, route2)).pipe(Effect75.mapError(mapEventLogError7));
14757
16224
  if (ready !== undefined) {
14758
- yield* eventLog.append(readyEvent(input, ready)).pipe(Effect74.mapError(mapEventLogError7));
16225
+ yield* eventLog.append(readyEvent(input, ready)).pipe(Effect75.mapError(mapEventLogError7));
14759
16226
  }
14760
16227
  yield* recordEnvelopeSent(route2.kind);
14761
16228
  return accepted2;
14762
16229
  })
14763
16230
  });
14764
16231
  }));
14765
- var memoryLayer33 = (routes = []) => layer50.pipe(Layer67.provide(memoryLayer20(routes)), Layer67.provide(exports_envelope_repository.memoryLayer), Layer67.provide(memoryLayer21));
14766
- var testLayer49 = (implementation) => Layer67.succeed(Service47, Service47.of(implementation));
14767
- var send2 = Effect74.fn("EnvelopeService.send.call")(function* (input) {
14768
- const service = yield* Service47;
16232
+ var memoryLayer34 = (routes = []) => layer51.pipe(Layer68.provide(memoryLayer20(routes)), Layer68.provide(exports_envelope_repository.memoryLayer), Layer68.provide(memoryLayer21));
16233
+ var testLayer49 = (implementation) => Layer68.succeed(Service48, Service48.of(implementation));
16234
+ var send2 = Effect75.fn("EnvelopeService.send.call")(function* (input) {
16235
+ const service = yield* Service48;
14769
16236
  return yield* service.send(input);
14770
16237
  });
14771
16238
  // ../runtime/src/runner/runner-runtime-service.ts
@@ -14784,20 +16251,20 @@ __export(exports_runner_runtime_service, {
14784
16251
  layerWithLanguageModelService: () => layerWithLanguageModelService,
14785
16252
  layerWithClient: () => layerWithClient,
14786
16253
  layerWith: () => layerWith,
14787
- layer: () => layer52,
16254
+ layer: () => layer53,
14788
16255
  clusterShardingConfigLayer: () => clusterShardingConfigLayer,
14789
16256
  clusterLayerHttpClientOnly: () => clusterLayerHttpClientOnly,
14790
16257
  clusterLayerHttp: () => clusterLayerHttp,
14791
16258
  check: () => check2,
14792
16259
  assertRunnerAddressAvailable: () => assertRunnerAddressAvailable,
14793
16260
  assertClusterConfig: () => assertClusterConfig,
14794
- Service: () => Service49,
16261
+ Service: () => Service50,
14795
16262
  RunnerRuntimeError: () => RunnerRuntimeError,
14796
16263
  ReadinessStatus: () => ReadinessStatus,
14797
16264
  DatabaseMode: () => DatabaseMode,
14798
16265
  ClusterConfigMismatch: () => ClusterConfigMismatch
14799
16266
  });
14800
- import { Config as Config5, Context as Context62, Crypto as Crypto4, Duration as Duration5, Effect as Effect77, Layer as Layer69, Option as Option27, Schema as Schema73, Stream as Stream10 } from "effect";
16267
+ import { Config as Config5, Context as Context63, Crypto as Crypto4, Duration as Duration5, Effect as Effect78, Layer as Layer70, Option as Option27, Schema as Schema73, Stream as Stream10 } from "effect";
14801
16268
  import {
14802
16269
  ClusterWorkflowEngine,
14803
16270
  HttpRunner,
@@ -14812,7 +16279,7 @@ import {
14812
16279
  SqlRunnerStorage
14813
16280
  } from "effect/unstable/cluster";
14814
16281
  import { FetchHttpClient } from "effect/unstable/http";
14815
- import { SqlClient as SqlClient22 } from "effect/unstable/sql/SqlClient";
16282
+ import { SqlClient as SqlClient23 } from "effect/unstable/sql/SqlClient";
14816
16283
  import { RpcSerialization } from "effect/unstable/rpc";
14817
16284
  import { WorkflowEngine } from "effect/unstable/workflow";
14818
16285
  import { LanguageModel as LanguageModel7 } from "effect/unstable/ai";
@@ -14826,24 +16293,24 @@ __export(exports_scheduler_service, {
14826
16293
  runOnce: () => runOnce2,
14827
16294
  pollIntervalMillisConfig: () => pollIntervalMillisConfig,
14828
16295
  parseCron: () => parseCron,
14829
- memoryLayer: () => memoryLayer34,
14830
- make: () => make14,
14831
- layer: () => layer51,
16296
+ memoryLayer: () => memoryLayer35,
16297
+ make: () => make15,
16298
+ layer: () => layer52,
14832
16299
  enabledConfig: () => enabledConfig,
14833
16300
  claimTtlMillisConfig: () => claimTtlMillisConfig,
14834
- Service: () => Service48,
16301
+ Service: () => Service49,
14835
16302
  SchedulerError: () => SchedulerError,
14836
16303
  ScheduleCronInvalid: () => ScheduleCronInvalid
14837
16304
  });
14838
- import { Clock as Clock10, Config as Config4, Context as Context61, Cron, Duration as Duration4, Effect as Effect76, Layer as Layer68, Random, Result as Result3, Schema as Schema72 } from "effect";
16305
+ import { Clock as Clock10, Config as Config4, Context as Context62, Cron, Duration as Duration4, Effect as Effect77, Layer as Layer69, Random, Result as Result3, Schema as Schema72 } from "effect";
14839
16306
 
14840
16307
  // ../runtime/src/wait/wait-signal.ts
14841
16308
  var exports_wait_signal = {};
14842
16309
  __export(exports_wait_signal, {
14843
16310
  signalWorkflowWait: () => signalWorkflowWait
14844
16311
  });
14845
- import { Effect as Effect75 } from "effect";
14846
- var signalWorkflowWait = Effect75.fn("WaitSignal.signalWorkflowWait")(function* (input) {
16312
+ import { Effect as Effect76 } from "effect";
16313
+ var signalWorkflowWait = Effect76.fn("WaitSignal.signalWorkflowWait")(function* (input) {
14847
16314
  const workflowExecutionId2 = yield* activeWorkflowExecutionIdForExecution(input.executionId);
14848
16315
  const client3 = input.makeExecutionClient(input.executionId);
14849
16316
  yield* client3.signalWait({
@@ -14866,7 +16333,7 @@ class ScheduleCronInvalid extends Schema72.TaggedErrorClass()("ScheduleCronInval
14866
16333
  }) {
14867
16334
  }
14868
16335
 
14869
- class Service48 extends Context61.Service()("@relayfx/runtime/SchedulerService") {
16336
+ class Service49 extends Context62.Service()("@relayfx/runtime/SchedulerService") {
14870
16337
  }
14871
16338
  var pollIntervalMillisConfig = Config4.int("RELAY_SCHEDULER_POLL_INTERVAL_MILLIS").pipe(Config4.withDefault(1000));
14872
16339
  var claimTtlMillisConfig = Config4.int("RELAY_SCHEDULER_CLAIM_TTL_MILLIS").pipe(Config4.withDefault(30000));
@@ -14875,7 +16342,7 @@ var processWorkerId = `scheduler:${globalThis.crypto.randomUUID()}`;
14875
16342
  var workerIdConfig = Config4.string("RELAY_SCHEDULER_WORKER_ID").pipe(Config4.withDefault(processWorkerId));
14876
16343
  var parseCron = (cronExpr) => {
14877
16344
  const parsed = Cron.parse(cronExpr);
14878
- return Result3.isFailure(parsed) ? Effect76.fail(new ScheduleCronInvalid({ cron_expr: cronExpr, message: String(parsed.failure) })) : Effect76.succeed(parsed.success);
16345
+ return Result3.isFailure(parsed) ? Effect77.fail(new ScheduleCronInvalid({ cron_expr: cronExpr, message: String(parsed.failure) })) : Effect77.succeed(parsed.success);
14879
16346
  };
14880
16347
  var startIdempotencyKey = (schedule) => `schedule:${schedule.id}:${schedule.next_run_at}`;
14881
16348
  var errorMessage3 = (error) => {
@@ -14891,11 +16358,11 @@ var dispatchMetadata = (schedule) => ({
14891
16358
  source: "schedule",
14892
16359
  schedule_id: schedule.id
14893
16360
  });
14894
- var nextEventSequence5 = Effect76.fn("SchedulerService.nextEventSequence")(function* (eventLog, executionId) {
14895
- const max = yield* eventLog.maxSequence(executionId).pipe(Effect76.mapError(toSchedulerError));
16361
+ var nextEventSequence5 = Effect77.fn("SchedulerService.nextEventSequence")(function* (eventLog, executionId) {
16362
+ const max = yield* eventLog.maxSequence(executionId).pipe(Effect77.mapError(toSchedulerError));
14896
16363
  return max === undefined ? 0 : max + 1;
14897
16364
  });
14898
- var make14 = Effect76.gen(function* () {
16365
+ var make15 = Effect77.gen(function* () {
14899
16366
  const schedules = yield* exports_schedule_repository.Service;
14900
16367
  const waits = yield* Service25;
14901
16368
  const eventLog = yield* Service24;
@@ -14904,10 +16371,10 @@ var make14 = Effect76.gen(function* () {
14904
16371
  const workerId = yield* workerIdConfig;
14905
16372
  const claimTtlMillis = yield* claimTtlMillisConfig;
14906
16373
  const pollIntervalMillis = yield* pollIntervalMillisConfig;
14907
- const dispatchStartExecution = (schedule, now) => Effect76.gen(function* () {
16374
+ const dispatchStartExecution = (schedule, now) => Effect77.gen(function* () {
14908
16375
  const addressId = schedule.address_id;
14909
16376
  if (addressId === undefined) {
14910
- return yield* Effect76.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing address_id` }));
16377
+ return yield* Effect77.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing address_id` }));
14911
16378
  }
14912
16379
  const idempotencyKey = startIdempotencyKey(schedule);
14913
16380
  const executionId = exports_ids_schema.ExecutionId.make(`execution:${idempotencyKey}`);
@@ -14924,19 +16391,19 @@ var make14 = Effect76.gen(function* () {
14924
16391
  ...dispatchMetadata(schedule),
14925
16392
  idempotency_key: idempotencyKey
14926
16393
  }
14927
- }).pipe(Effect76.mapError(toSchedulerError));
14928
- }).pipe(Effect76.withSpan("SchedulerService.dispatchStartExecution"));
14929
- const dispatchWaitTransition = (schedule, now) => Effect76.gen(function* () {
16394
+ }).pipe(Effect77.mapError(toSchedulerError));
16395
+ }).pipe(Effect77.withSpan("SchedulerService.dispatchStartExecution"));
16396
+ const dispatchWaitTransition = (schedule, now) => Effect77.gen(function* () {
14930
16397
  const waitId = schedule.wait_id;
14931
16398
  if (waitId === undefined) {
14932
- return yield* Effect76.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing wait_id` }));
16399
+ return yield* Effect77.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing wait_id` }));
14933
16400
  }
14934
- const wait = yield* waits.get(waitId).pipe(Effect76.mapError(toSchedulerError));
16401
+ const wait = yield* waits.get(waitId).pipe(Effect77.mapError(toSchedulerError));
14935
16402
  if (wait === undefined || wait.state !== "open")
14936
16403
  return;
14937
16404
  const eventSequence = yield* nextEventSequence5(eventLog, wait.executionId);
14938
16405
  const metadata11 = dispatchMetadata(schedule);
14939
- const result = schedule.target_kind === "wake-wait" ? yield* waits.wake({ waitId, resolvedAt: now, eventSequence, metadata: metadata11 }).pipe(Effect76.mapError(toSchedulerError)) : yield* waits.timeout({ waitId, timedOutAt: now, eventSequence, metadata: metadata11 }).pipe(Effect76.mapError(toSchedulerError));
16406
+ const result = schedule.target_kind === "wake-wait" ? yield* waits.wake({ waitId, resolvedAt: now, eventSequence, metadata: metadata11 }).pipe(Effect77.mapError(toSchedulerError)) : yield* waits.timeout({ waitId, timedOutAt: now, eventSequence, metadata: metadata11 }).pipe(Effect77.mapError(toSchedulerError));
14940
16407
  if (!result.transitioned)
14941
16408
  return;
14942
16409
  yield* signalWorkflowWait({
@@ -14945,19 +16412,19 @@ var make14 = Effect76.gen(function* () {
14945
16412
  waitId: result.wait.id,
14946
16413
  state: schedule.target_kind === "wake-wait" ? "resolved" : "timed_out",
14947
16414
  signaledAt: now
14948
- }).pipe(Effect76.provideService(exports_execution_repository.Service, executionRepository), Effect76.mapError(toSchedulerError));
14949
- }).pipe(Effect76.withSpan("SchedulerService.dispatchWaitTransition"));
16415
+ }).pipe(Effect77.provideService(exports_execution_repository.Service, executionRepository), Effect77.mapError(toSchedulerError));
16416
+ }).pipe(Effect77.withSpan("SchedulerService.dispatchWaitTransition"));
14950
16417
  const dispatch = (schedule, now) => schedule.target_kind === "start-execution" ? dispatchStartExecution(schedule, now) : dispatchWaitTransition(schedule, now);
14951
- const nextCronRunAt = (schedule, now) => Effect76.gen(function* () {
16418
+ const nextCronRunAt = (schedule, now) => Effect77.gen(function* () {
14952
16419
  if (schedule.kind !== "cron")
14953
16420
  return;
14954
16421
  if (schedule.cron_expr === undefined) {
14955
- return yield* Effect76.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing cron_expr` }));
16422
+ return yield* Effect77.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing cron_expr` }));
14956
16423
  }
14957
- const cron = yield* parseCron(schedule.cron_expr).pipe(Effect76.mapError(toSchedulerError));
16424
+ const cron = yield* parseCron(schedule.cron_expr).pipe(Effect77.mapError(toSchedulerError));
14958
16425
  return Cron.next(cron, new Date(now)).getTime();
14959
- }).pipe(Effect76.withSpan("SchedulerService.nextCronRunAt"));
14960
- const settle = (schedule, now) => dispatch(schedule, now).pipe(Effect76.flatMap(() => nextCronRunAt(schedule, now)), Effect76.matchEffect({
16426
+ }).pipe(Effect77.withSpan("SchedulerService.nextCronRunAt"));
16427
+ const settle = (schedule, now) => dispatch(schedule, now).pipe(Effect77.flatMap(() => nextCronRunAt(schedule, now)), Effect77.matchEffect({
14961
16428
  onSuccess: (nextRunAt) => schedules.ack({
14962
16429
  id: schedule.id,
14963
16430
  workerId,
@@ -14970,45 +16437,45 @@ var make14 = Effect76.gen(function* () {
14970
16437
  nextAvailableAt: now + pollIntervalMillis,
14971
16438
  error: error.message
14972
16439
  })
14973
- }), Effect76.catchTag("ScheduleClaimMismatch", () => Effect76.void), Effect76.mapError(toSchedulerError), Effect76.withSpan("SchedulerService.settle"));
14974
- const runOnce2 = Effect76.gen(function* () {
16440
+ }), Effect77.catchTag("ScheduleClaimMismatch", () => Effect77.void), Effect77.mapError(toSchedulerError), Effect77.withSpan("SchedulerService.settle"));
16441
+ const runOnce2 = Effect77.gen(function* () {
14975
16442
  let dispatched = 0;
14976
16443
  while (true) {
14977
16444
  const now = yield* Clock10.currentTimeMillis;
14978
- const claimed = yield* schedules.claimDue({ workerId, now, claimExpiresAt: now + claimTtlMillis }).pipe(Effect76.mapError(toSchedulerError));
16445
+ const claimed = yield* schedules.claimDue({ workerId, now, claimExpiresAt: now + claimTtlMillis }).pipe(Effect77.mapError(toSchedulerError));
14979
16446
  if (claimed === undefined)
14980
16447
  return dispatched;
14981
16448
  yield* settle(claimed, now);
14982
16449
  dispatched += 1;
14983
16450
  }
14984
- }).pipe(Effect76.withSpan("SchedulerService.runOnce"));
14985
- return Service48.of({ runOnce: runOnce2 });
16451
+ }).pipe(Effect77.withSpan("SchedulerService.runOnce"));
16452
+ return Service49.of({ runOnce: runOnce2 });
14986
16453
  });
14987
- var jitteredSleep = (pollIntervalMillis) => Effect76.gen(function* () {
16454
+ var jitteredSleep = (pollIntervalMillis) => Effect77.gen(function* () {
14988
16455
  const jitter = yield* Random.nextBetween(0.8, 1.2);
14989
- yield* Effect76.sleep(Duration4.millis(pollIntervalMillis * jitter));
16456
+ yield* Effect77.sleep(Duration4.millis(pollIntervalMillis * jitter));
14990
16457
  });
14991
- var pollLoop = (service, pollIntervalMillis) => Effect76.gen(function* () {
16458
+ var pollLoop = (service, pollIntervalMillis) => Effect77.gen(function* () {
14992
16459
  while (true) {
14993
- const dispatched = yield* service.runOnce.pipe(Effect76.catch((error) => Effect76.logWarning("relay scheduler poll failed", { message: error.message }).pipe(Effect76.as(0))));
16460
+ const dispatched = yield* service.runOnce.pipe(Effect77.catch((error) => Effect77.logWarning("relay scheduler poll failed", { message: error.message }).pipe(Effect77.as(0))));
14994
16461
  if (dispatched === 0) {
14995
16462
  yield* jitteredSleep(pollIntervalMillis);
14996
16463
  }
14997
16464
  }
14998
16465
  });
14999
- var layer51 = Layer68.effect(Service48, Effect76.gen(function* () {
15000
- const service = yield* make14;
16466
+ var layer52 = Layer69.effect(Service49, Effect77.gen(function* () {
16467
+ const service = yield* make15;
15001
16468
  const enabled2 = yield* enabledConfig;
15002
16469
  const pollIntervalMillis = yield* pollIntervalMillisConfig;
15003
16470
  if (enabled2) {
15004
- yield* Effect76.forkScoped(pollLoop(service, pollIntervalMillis));
16471
+ yield* Effect77.forkScoped(pollLoop(service, pollIntervalMillis));
15005
16472
  }
15006
16473
  return service;
15007
16474
  }));
15008
- var memoryLayer34 = Layer68.effect(Service48, make14);
15009
- var testLayer50 = (implementation) => Layer68.succeed(Service48, Service48.of(implementation));
15010
- var runOnce2 = Effect76.fn("SchedulerService.runOnce.call")(function* () {
15011
- const service = yield* Service48;
16475
+ var memoryLayer35 = Layer69.effect(Service49, make15);
16476
+ var testLayer50 = (implementation) => Layer69.succeed(Service49, Service49.of(implementation));
16477
+ var runOnce2 = Effect77.fn("SchedulerService.runOnce.call")(function* () {
16478
+ const service = yield* Service49;
15012
16479
  return yield* service.runOnce;
15013
16480
  });
15014
16481
 
@@ -15035,20 +16502,20 @@ class ClusterConfigMismatch extends Schema73.TaggedErrorClass()("ClusterConfigMi
15035
16502
  }) {
15036
16503
  }
15037
16504
 
15038
- class Service49 extends Context62.Service()("@relayfx/runtime/RunnerRuntime") {
16505
+ class Service50 extends Context63.Service()("@relayfx/runtime/RunnerRuntime") {
15039
16506
  }
15040
16507
  var shardingConfig = {
15041
16508
  availableShardGroups: ["default", "execution"],
15042
16509
  assignedShardGroups: ["default", "execution"]
15043
16510
  };
15044
- var memoryClusterLayer = Sharding.layer.pipe(Layer69.provideMerge(Runners.layerNoop), Layer69.provideMerge(MessageStorage.layerMemory), Layer69.provide([RunnerStorage.layerMemory, RunnerHealth.layerNoop]), Layer69.provideMerge(ShardingConfig2.layer(shardingConfig)));
16511
+ var memoryClusterLayer = Sharding.layer.pipe(Layer70.provideMerge(Runners.layerNoop), Layer70.provideMerge(MessageStorage.layerMemory), Layer70.provide([RunnerStorage.layerMemory, RunnerHealth.layerNoop]), Layer70.provideMerge(ShardingConfig2.layer(shardingConfig)));
15045
16512
  var clusterHost = Config5.string("RELAY_CLUSTER_HOST").pipe(Config5.withDefault("localhost"));
15046
16513
  var clusterPort = Config5.int("RELAY_CLUSTER_PORT").pipe(Config5.withDefault(34431));
15047
16514
  var clusterShardsPerGroup = Config5.int("RELAY_CLUSTER_SHARDS_PER_GROUP").pipe(Config5.withDefault(300));
15048
16515
  var clusterShardGroups = Config5.schema(Config5.Array(Schema73.String), "RELAY_CLUSTER_SHARD_GROUPS").pipe(Config5.withDefault(["default", "execution"]));
15049
16516
  var runnerAddressKey = (address) => `${address.host}:${address.port}`;
15050
16517
  var runnerAddressEquals = (left, right) => left.host === right.host && left.port === right.port;
15051
- var shardingConfigFromEnv = () => Layer69.effect(ShardingConfig2.ShardingConfig, Effect77.gen(function* () {
16518
+ var shardingConfigFromEnv = () => Layer70.effect(ShardingConfig2.ShardingConfig, Effect78.gen(function* () {
15052
16519
  const host = yield* clusterHost;
15053
16520
  const port = yield* clusterPort;
15054
16521
  const shardsPerGroup = yield* clusterShardsPerGroup;
@@ -15073,14 +16540,14 @@ var clusterShardingConfigLayer = (options) => ShardingConfig2.layer({
15073
16540
  ...options.shardLockExpiration !== undefined && { shardLockExpiration: options.shardLockExpiration }
15074
16541
  });
15075
16542
  var runnerAddressPreflightTimeout = Duration5.seconds(5);
15076
- var assertRunnerAddressAvailable = Effect77.fn("RunnerRuntime.assertRunnerAddressAvailable")(function* (options = {}) {
16543
+ var assertRunnerAddressAvailable = Effect78.fn("RunnerRuntime.assertRunnerAddressAvailable")(function* (options = {}) {
15077
16544
  const config = yield* ShardingConfig2.ShardingConfig;
15078
16545
  if (Option27.isNone(config.runnerAddress)) {
15079
16546
  return;
15080
16547
  }
15081
16548
  const storage = yield* RunnerStorage.RunnerStorage;
15082
16549
  const localAddress = config.runnerAddress.value;
15083
- const runners = yield* storage.getRunners.pipe(Effect77.mapError((error) => new ClusterConfigMismatch({
16550
+ const runners = yield* storage.getRunners.pipe(Effect78.mapError((error) => new ClusterConfigMismatch({
15084
16551
  field: "runnerAddress",
15085
16552
  expected: `${runnerAddressKey(localAddress)} available`,
15086
16553
  actual: `registry unavailable: ${String(error)}`
@@ -15088,7 +16555,7 @@ var assertRunnerAddressAvailable = Effect77.fn("RunnerRuntime.assertRunnerAddres
15088
16555
  const collision = runners.find(([runner, healthy]) => healthy && runnerAddressEquals(runner.address, localAddress));
15089
16556
  if (collision === undefined)
15090
16557
  return;
15091
- const reachable = options.isAddressReachable === undefined ? false : yield* options.isAddressReachable(collision[0].address).pipe(Effect77.timeoutOption(runnerAddressPreflightTimeout), Effect77.map(Option27.getOrElse(() => false)));
16558
+ const reachable = options.isAddressReachable === undefined ? false : yield* options.isAddressReachable(collision[0].address).pipe(Effect78.timeoutOption(runnerAddressPreflightTimeout), Effect78.map(Option27.getOrElse(() => false)));
15092
16559
  if (reachable) {
15093
16560
  return yield* new ClusterConfigMismatch({
15094
16561
  field: "runnerAddress",
@@ -15097,14 +16564,14 @@ var assertRunnerAddressAvailable = Effect77.fn("RunnerRuntime.assertRunnerAddres
15097
16564
  });
15098
16565
  }
15099
16566
  });
15100
- var runnerAddressPreflightHttpLayer = Layer69.effectDiscard(Effect77.gen(function* () {
16567
+ var runnerAddressPreflightHttpLayer = Layer70.effectDiscard(Effect78.gen(function* () {
15101
16568
  const runners = yield* Runners.Runners;
15102
16569
  yield* assertRunnerAddressAvailable({
15103
- isAddressReachable: (address) => runners.ping(address).pipe(Effect77.as(true), Effect77.catch(() => Effect77.succeed(false)))
16570
+ isAddressReachable: (address) => runners.ping(address).pipe(Effect78.as(true), Effect78.catch(() => Effect78.succeed(false)))
15104
16571
  });
15105
- })).pipe(Layer69.provide(Runners.layerRpc), Layer69.provide(HttpRunner.layerClientProtocolHttpDefault), Layer69.provide(RpcSerialization.layerNdjson), Layer69.provide(FetchHttpClient.layer));
15106
- var sqlClusterLayer = Sharding.layer.pipe(Layer69.provideMerge(runnerAddressPreflightHttpLayer), Layer69.provideMerge(Runners.layerNoop), Layer69.provideMerge(SqlMessageStorage.layer), Layer69.provide([Layer69.orDie(SqlRunnerStorage.layer), RunnerHealth.layerNoop]), Layer69.provideMerge(shardingConfigFromEnv()));
15107
- var clusterLayerHttp = (options) => HttpRunner.layerHttp.pipe(Layer69.provideMerge(runnerAddressPreflightHttpLayer), Layer69.provideMerge(SqlMessageStorage.layer), Layer69.provide([Layer69.orDie(SqlRunnerStorage.layer), RunnerHealth.layerNoop]), Layer69.provide(RpcSerialization.layerNdjson), Layer69.provide(FetchHttpClient.layer), Layer69.provideMerge(clusterShardingConfigLayer({
16572
+ })).pipe(Layer70.provide(Runners.layerRpc), Layer70.provide(HttpRunner.layerClientProtocolHttpDefault), Layer70.provide(RpcSerialization.layerNdjson), Layer70.provide(FetchHttpClient.layer));
16573
+ var sqlClusterLayer = Sharding.layer.pipe(Layer70.provideMerge(runnerAddressPreflightHttpLayer), Layer70.provideMerge(Runners.layerNoop), Layer70.provideMerge(SqlMessageStorage.layer), Layer70.provide([Layer70.orDie(SqlRunnerStorage.layer), RunnerHealth.layerNoop]), Layer70.provideMerge(shardingConfigFromEnv()));
16574
+ var clusterLayerHttp = (options) => HttpRunner.layerHttp.pipe(Layer70.provideMerge(runnerAddressPreflightHttpLayer), Layer70.provideMerge(SqlMessageStorage.layer), Layer70.provide([Layer70.orDie(SqlRunnerStorage.layer), RunnerHealth.layerNoop]), Layer70.provide(RpcSerialization.layerNdjson), Layer70.provide(FetchHttpClient.layer), Layer70.provideMerge(clusterShardingConfigLayer({
15108
16575
  runnerAddress: Option27.some(RunnerAddress.make(options.runnerHost, options.rpcPort)),
15109
16576
  assignedShardGroups: options.assignedShardGroups,
15110
16577
  availableShardGroups: options.availableShardGroups,
@@ -15113,7 +16580,7 @@ var clusterLayerHttp = (options) => HttpRunner.layerHttp.pipe(Layer69.provideMer
15113
16580
  shardLockExpiration: options.shardLockExpiration,
15114
16581
  shardLockDisableAdvisory: options.shardLockDisableAdvisory
15115
16582
  })));
15116
- var clusterLayerHttpClientOnly = (options = {}) => HttpRunner.layerHttpClientOnly.pipe(Layer69.provideMerge(SqlMessageStorage.layer), Layer69.provide(Layer69.orDie(SqlRunnerStorage.layer)), Layer69.provide(RpcSerialization.layerNdjson), Layer69.provide(FetchHttpClient.layer), Layer69.provideMerge(clusterShardingConfigLayer({
16583
+ var clusterLayerHttpClientOnly = (options = {}) => HttpRunner.layerHttpClientOnly.pipe(Layer70.provideMerge(SqlMessageStorage.layer), Layer70.provide(Layer70.orDie(SqlRunnerStorage.layer)), Layer70.provide(RpcSerialization.layerNdjson), Layer70.provide(FetchHttpClient.layer), Layer70.provideMerge(clusterShardingConfigLayer({
15117
16584
  runnerAddress: Option27.none(),
15118
16585
  assignedShardGroups: [],
15119
16586
  availableShardGroups: options.availableShardGroups,
@@ -15122,7 +16589,7 @@ var clusterLayerHttpClientOnly = (options = {}) => HttpRunner.layerHttpClientOnl
15122
16589
  shardLockExpiration: options.shardLockExpiration,
15123
16590
  shardLockDisableAdvisory: options.shardLockDisableAdvisory
15124
16591
  })));
15125
- var assertClusterConfig = Effect77.fn("RunnerRuntime.assertClusterConfig")(function* (expected) {
16592
+ var assertClusterConfig = Effect78.fn("RunnerRuntime.assertClusterConfig")(function* (expected) {
15126
16593
  const config = yield* ShardingConfig2.ShardingConfig;
15127
16594
  if (config.shardsPerGroup !== expected.shardsPerGroup) {
15128
16595
  return yield* new ClusterConfigMismatch({
@@ -15137,15 +16604,15 @@ var assertClusterConfig = Effect77.fn("RunnerRuntime.assertClusterConfig")(funct
15137
16604
  return yield* new ClusterConfigMismatch({ field: "availableShardGroups", expected: want, actual });
15138
16605
  }
15139
16606
  });
15140
- var sqlRepositoryLayer = Layer69.mergeAll(exports_address_book_repository.layer, exports_agent_chat_repository.layer, exports_agent_definition_repository.layer, exports_child_execution_repository.layer, exports_cluster_registry_repository.layer, exports_compaction_repository.layer, exports_context_epoch_repository.layer, exports_execution_repository.layer, exports_envelope_repository.layer, exports_execution_event_repository.layerWithBus, exports_memory_repository.layer, exports_permission_rule_repository.layer, exports_schedule_repository.layer, exports_session_repository.layer, exports_skill_definition_repository.layer, exports_steering_repository.layer, exports_tool_call_repository.layer, exports_workspace_lease_repository.layer);
15141
- var memoryRepositoryLayer = Layer69.mergeAll(exports_address_book_repository.memoryLayer, exports_agent_chat_repository.memoryLayer, exports_agent_definition_repository.memoryLayer, exports_child_execution_repository.memoryLayer, exports_cluster_registry_repository.memoryLayer, exports_compaction_repository.memoryLayer, exports_context_epoch_repository.memoryLayer, exports_execution_repository.memoryLayer, exports_envelope_repository.memoryLayer, exports_execution_event_repository.memoryLayer, exports_memory_repository.memoryLayer, exports_permission_rule_repository.memoryLayer, exports_schedule_repository.memoryLayer, exports_session_repository.memoryLayer, exports_skill_definition_repository.memoryLayer, exports_steering_repository.memoryLayer, exports_tool_call_repository.memoryLayer, exports_workspace_lease_repository.memoryLayer);
15142
- var testCryptoLayer = Layer69.succeed(Crypto4.Crypto, Crypto4.make({
16607
+ var sqlRepositoryLayer = Layer70.mergeAll(exports_address_book_repository.layer, exports_agent_chat_repository.layer, exports_agent_definition_repository.layer, exports_child_execution_repository.layer, exports_cluster_registry_repository.layer, exports_compaction_repository.layer, exports_context_epoch_repository.layer, exports_execution_repository.layer, exports_envelope_repository.layer, exports_execution_event_repository.layerWithBus, exports_memory_repository.layer, exports_permission_rule_repository.layer, exports_schedule_repository.layer, exports_session_repository.layer, exports_skill_definition_repository.layer, exports_steering_repository.layer, exports_tool_call_repository.layer, exports_workspace_lease_repository.layer);
16608
+ var memoryRepositoryLayer = Layer70.mergeAll(exports_address_book_repository.memoryLayer, exports_agent_chat_repository.memoryLayer, exports_agent_definition_repository.memoryLayer, exports_child_execution_repository.memoryLayer, exports_cluster_registry_repository.memoryLayer, exports_compaction_repository.memoryLayer, exports_context_epoch_repository.memoryLayer, exports_execution_repository.memoryLayer, exports_envelope_repository.memoryLayer, exports_execution_event_repository.memoryLayer, exports_memory_repository.memoryLayer, exports_permission_rule_repository.memoryLayer, exports_schedule_repository.memoryLayer, exports_session_repository.memoryLayer, exports_skill_definition_repository.memoryLayer, exports_steering_repository.memoryLayer, exports_tool_call_repository.memoryLayer, exports_workspace_lease_repository.memoryLayer);
16609
+ var testCryptoLayer = Layer70.succeed(Crypto4.Crypto, Crypto4.make({
15143
16610
  randomBytes: (size) => new Uint8Array(size),
15144
- digest: (algorithm, data) => Effect77.promise(() => globalThis.crypto.subtle.digest(algorithm, data).then((buffer) => new Uint8Array(buffer)))
16611
+ digest: (algorithm, data) => Effect78.promise(() => globalThis.crypto.subtle.digest(algorithm, data).then((buffer) => new Uint8Array(buffer)))
15145
16612
  }));
15146
- var executionServiceLayer = layer46.pipe(Layer69.provideMerge(layer32));
15147
- var addressResolutionLayerWith = (toolRuntimeLayer) => layer25.pipe(Layer69.provideMerge(layerFromRepository), Layer69.provideMerge(layer24.pipe(Layer69.provideMerge(toolRuntimeLayer))));
15148
- var parentNotifierLayer = Layer69.effect(Service42, Effect77.gen(function* () {
16613
+ var executionServiceLayer = layer47.pipe(Layer70.provideMerge(layer33));
16614
+ var addressResolutionLayerWith = (toolRuntimeLayer) => layer25.pipe(Layer70.provideMerge(layerFromRepository), Layer70.provideMerge(layer24.pipe(Layer70.provideMerge(toolRuntimeLayer))));
16615
+ var parentNotifierLayer = Layer70.effect(Service42, Effect78.gen(function* () {
15149
16616
  const makeExecutionClient = yield* client2;
15150
16617
  const executionRepository = yield* exports_execution_repository.Service;
15151
16618
  return yield* make13({
@@ -15155,24 +16622,24 @@ var parentNotifierLayer = Layer69.effect(Service42, Effect77.gen(function* () {
15155
16622
  waitId: input.waitId,
15156
16623
  state: "resolved",
15157
16624
  signaledAt: input.signaledAt
15158
- }).pipe(Effect77.provideService(exports_execution_repository.Service, executionRepository))
16625
+ }).pipe(Effect78.provideService(exports_execution_repository.Service, executionRepository))
15159
16626
  });
15160
16627
  }));
15161
- var agentLoopLayerWith = (toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer) => layer44.pipe(Layer69.provideMerge(toolRuntimeLayer), Layer69.provideMerge(layer32), Layer69.provideMerge(layer36()), Layer69.provideMerge(promptAssemblerLayer), Layer69.provideMerge(schemaRegistryLayer));
15162
- var runtimeServicesLayerWith = (toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer) => Layer69.mergeAll(addressResolutionLayerWith(toolRuntimeLayer), layer45, executionServiceLayer, agentLoopLayerWith(toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer), layer47, parentNotifierLayer).pipe(Layer69.provideMerge(layer22), Layer69.provideMerge(layerFromRepository2));
15163
- var workflowLayerWith = (toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer) => layer48.pipe(Layer69.provideMerge(runtimeServicesLayerWith(toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer)));
15164
- var workflowAndEntityLayerWith = (toolRuntimeLayer, schedulerLayer, promptAssemblerLayer, schemaRegistryLayer) => Layer69.mergeAll(layer49, schedulerLayer).pipe(Layer69.provideMerge(workflowLayerWith(toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer)));
15165
- var makeService2 = (database, checkDatabase) => Effect77.gen(function* () {
16628
+ var agentLoopLayerWith = (toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer) => layer45.pipe(Layer70.provideMerge(toolRuntimeLayer), Layer70.provideMerge(layer33), Layer70.provideMerge(layer37()), Layer70.provideMerge(promptAssemblerLayer), Layer70.provideMerge(schemaRegistryLayer));
16629
+ var runtimeServicesLayerWith = (toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer, toolTransitionCoordinatorLayer) => Layer70.mergeAll(addressResolutionLayerWith(toolRuntimeLayer), layer46, executionServiceLayer, agentLoopLayerWith(toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer), layer48, parentNotifierLayer, toolTransitionCoordinatorLayer).pipe(Layer70.provideMerge(layer22), Layer70.provideMerge(layerFromRepository2));
16630
+ var workflowLayerWith = (toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer, toolTransitionCoordinatorLayer) => layer49.pipe(Layer70.provideMerge(runtimeServicesLayerWith(toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer, toolTransitionCoordinatorLayer)));
16631
+ var workflowAndEntityLayerWith = (toolRuntimeLayer, schedulerLayer, promptAssemblerLayer, schemaRegistryLayer, toolTransitionCoordinatorLayer) => Layer70.mergeAll(layer50, schedulerLayer).pipe(Layer70.provideMerge(workflowLayerWith(toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer, toolTransitionCoordinatorLayer)));
16632
+ var makeService2 = (database, checkDatabase) => Effect78.gen(function* () {
15166
16633
  const sharding = yield* Sharding.Sharding;
15167
16634
  const workflow = yield* WorkflowEngine.WorkflowEngine;
15168
16635
  const makeClient = yield* client2;
15169
- return Service49.of({
15170
- check: Effect77.fn("RunnerRuntime.check")(function* () {
15171
- yield* Effect77.annotateCurrentSpan("relay.database.mode", database);
16636
+ return Service50.of({
16637
+ check: Effect78.fn("RunnerRuntime.check")(function* () {
16638
+ yield* Effect78.annotateCurrentSpan("relay.database.mode", database);
15172
16639
  yield* checkDatabase;
15173
- yield* Effect77.sync(() => sharding);
15174
- yield* Effect77.sync(() => workflow);
15175
- yield* Effect77.sync(() => makeClient);
16640
+ yield* Effect78.sync(() => sharding);
16641
+ yield* Effect78.sync(() => workflow);
16642
+ yield* Effect78.sync(() => makeClient);
15176
16643
  yield* recordRunnerReadinessChecked(database);
15177
16644
  return {
15178
16645
  database,
@@ -15183,9 +16650,9 @@ var makeService2 = (database, checkDatabase) => Effect77.gen(function* () {
15183
16650
  })
15184
16651
  });
15185
16652
  });
15186
- var checkLayer = (database, checkDatabase) => Layer69.effect(Service49, makeService2(database, checkDatabase));
15187
- var memoryCheckLayer = checkLayer("memory", Effect77.void);
15188
- var detectDialect = Effect77.serviceOption(SqlClient22).pipe(Effect77.map(Option27.match({
16653
+ var checkLayer = (database, checkDatabase) => Layer70.effect(Service50, makeService2(database, checkDatabase));
16654
+ var memoryCheckLayer = checkLayer("memory", Effect78.void);
16655
+ var detectDialect = Effect78.serviceOption(SqlClient23).pipe(Effect78.map(Option27.match({
15189
16656
  onNone: () => "sql",
15190
16657
  onSome: (sqlClient) => sqlClient.onDialectOrElse({
15191
16658
  pg: () => "pg",
@@ -15194,31 +16661,31 @@ var detectDialect = Effect77.serviceOption(SqlClient22).pipe(Effect77.map(Option
15194
16661
  orElse: () => "sql"
15195
16662
  })
15196
16663
  })));
15197
- var databaseHealthCheck = Effect77.gen(function* () {
15198
- const database = yield* Effect77.serviceOption(exports_database_service.Service);
16664
+ var databaseHealthCheck = Effect78.gen(function* () {
16665
+ const database = yield* Effect78.serviceOption(exports_database_service.Service);
15199
16666
  if (Option27.isSome(database)) {
15200
- return exports_database_service.check().pipe(Effect77.mapError((error) => new RunnerRuntimeError({ message: String(error) })), Effect77.provideService(exports_database_service.Service, database.value));
16667
+ return exports_database_service.check().pipe(Effect78.mapError((error) => new RunnerRuntimeError({ message: String(error) })), Effect78.provideService(exports_database_service.Service, database.value));
15201
16668
  }
15202
- const sqlClient = yield* Effect77.serviceOption(SqlClient22);
16669
+ const sqlClient = yield* Effect78.serviceOption(SqlClient23);
15203
16670
  if (Option27.isSome(sqlClient)) {
15204
- return sqlClient.value`select 1 as ok`.pipe(Effect77.asVoid, Effect77.mapError((error) => new RunnerRuntimeError({ message: String(error) })));
16671
+ return sqlClient.value`select 1 as ok`.pipe(Effect78.asVoid, Effect78.mapError((error) => new RunnerRuntimeError({ message: String(error) })));
15205
16672
  }
15206
- return Effect77.void;
16673
+ return Effect78.void;
15207
16674
  });
15208
- var sqlCheckLayer = Layer69.effect(Service49, Effect77.gen(function* () {
16675
+ var sqlCheckLayer = Layer70.effect(Service50, Effect78.gen(function* () {
15209
16676
  const dialect2 = yield* detectDialect;
15210
16677
  const checkDatabase = yield* databaseHealthCheck;
15211
16678
  return yield* makeService2(dialect2, checkDatabase);
15212
16679
  }));
15213
- var makeClientService = (database, checkDatabase) => Effect77.gen(function* () {
16680
+ var makeClientService = (database, checkDatabase) => Effect78.gen(function* () {
15214
16681
  const sharding = yield* Sharding.Sharding;
15215
16682
  const makeClient = yield* client2;
15216
- return Service49.of({
15217
- check: Effect77.fn("RunnerRuntime.check")(function* () {
15218
- yield* Effect77.annotateCurrentSpan("relay.database.mode", database);
16683
+ return Service50.of({
16684
+ check: Effect78.fn("RunnerRuntime.check")(function* () {
16685
+ yield* Effect78.annotateCurrentSpan("relay.database.mode", database);
15219
16686
  yield* checkDatabase;
15220
- yield* Effect77.sync(() => sharding);
15221
- yield* Effect77.sync(() => makeClient);
16687
+ yield* Effect78.sync(() => sharding);
16688
+ yield* Effect78.sync(() => makeClient);
15222
16689
  yield* recordRunnerReadinessChecked(database);
15223
16690
  return {
15224
16691
  database,
@@ -15229,20 +16696,20 @@ var makeClientService = (database, checkDatabase) => Effect77.gen(function* () {
15229
16696
  })
15230
16697
  });
15231
16698
  });
15232
- var memoryClientCheckLayer = Layer69.effect(Service49, makeClientService("memory", Effect77.void));
15233
- var multiNodeDialectGuard = Layer69.effectDiscard(Effect77.gen(function* () {
16699
+ var memoryClientCheckLayer = Layer70.effect(Service50, makeClientService("memory", Effect78.void));
16700
+ var multiNodeDialectGuard = Layer70.effectDiscard(Effect78.gen(function* () {
15234
16701
  const dialect2 = yield* detectDialect;
15235
16702
  if (dialect2 === "sqlite") {
15236
- return yield* Effect77.die(new Error("SQLite supports single-process topologies only; multi-node cluster composition requires Postgres or MySQL"));
16703
+ return yield* Effect78.die(new Error("SQLite supports single-process topologies only; multi-node cluster composition requires Postgres or MySQL"));
15237
16704
  }
15238
16705
  }));
15239
- var sqlClientCheckLayer = Layer69.effect(Service49, Effect77.gen(function* () {
16706
+ var sqlClientCheckLayer = Layer70.effect(Service50, Effect78.gen(function* () {
15240
16707
  const dialect2 = yield* detectDialect;
15241
16708
  const checkDatabase = yield* databaseHealthCheck;
15242
16709
  return yield* makeClientService(dialect2, checkDatabase);
15243
16710
  }));
15244
- var deterministicTestModelLayer = Layer69.effect(LanguageModel7.LanguageModel, LanguageModel7.make({
15245
- generateText: () => Effect77.succeed([{ type: "text", text: "deterministic test response" }]),
16711
+ var deterministicTestModelLayer = Layer70.effect(LanguageModel7.LanguageModel, LanguageModel7.make({
16712
+ generateText: () => Effect78.succeed([{ type: "text", text: "deterministic test response" }]),
15246
16713
  streamText: () => Stream10.make({ type: "text-delta", id: "text", delta: "deterministic test response" })
15247
16714
  }));
15248
16715
  var testLanguageModelLayer = layerFromRegistrationEffects3([
@@ -15253,57 +16720,60 @@ var testLanguageModelLayer = layerFromRegistrationEffects3([
15253
16720
  })
15254
16721
  ]);
15255
16722
  var testEmbeddingModelLayer = deterministicTestLayer();
15256
- var defaultPromptAssemblerLayer = (blobStoreLayer = passthroughLayer, artifactStoreLayer = passthroughLayer2) => defaultLayerWithStores.pipe(Layer69.provide(Layer69.mergeAll(blobStoreLayer, artifactStoreLayer)));
16723
+ var defaultPromptAssemblerLayer = (blobStoreLayer = passthroughLayer, artifactStoreLayer = passthroughLayer2) => defaultLayerWithStores.pipe(Layer70.provide(Layer70.mergeAll(blobStoreLayer, artifactStoreLayer)));
15257
16724
  var layerWith = (options) => {
15258
16725
  const blobStoreLayer = options.blobStoreLayer ?? passthroughLayer;
15259
16726
  const artifactStoreLayer = options.artifactStoreLayer ?? passthroughLayer2;
15260
16727
  const promptAssemblerLayer = options.promptAssemblerLayer ?? defaultPromptAssemblerLayer(blobStoreLayer, artifactStoreLayer);
15261
- const schemaRegistryLayer = options.schemaRegistryLayer ?? layer37();
16728
+ const schemaRegistryLayer = options.schemaRegistryLayer ?? layer38();
15262
16729
  const embeddingModelLayer = options.embeddingModelLayer ?? memoryLayer27();
15263
- const memoryLayer35 = layer34().pipe(Layer69.provideMerge(embeddingModelLayer));
15264
- const clusterContextLayer = Layer69.mergeAll(options.languageModelLayer, memoryLayer35, blobStoreLayer, artifactStoreLayer, promptAssemblerLayer, schemaRegistryLayer);
15265
- const clusterLayer = options.clusterLayer.pipe(Layer69.provide(clusterContextLayer));
15266
- return Layer69.mergeAll(options.checkLayer, workflowAndEntityLayerWith(options.toolRuntimeLayer, options.schedulerLayer, promptAssemblerLayer, schemaRegistryLayer)).pipe(Layer69.provideMerge(options.languageModelLayer), Layer69.provide(memoryLayer35), Layer69.provideMerge(ClusterWorkflowEngine.layer), Layer69.provideMerge(clusterLayer), Layer69.provideMerge(options.repositoryLayer), Layer69.provideMerge(blobStoreLayer), Layer69.provideMerge(artifactStoreLayer));
16730
+ const memoryLayer36 = layer35().pipe(Layer70.provideMerge(embeddingModelLayer));
16731
+ const clusterContextLayer = Layer70.mergeAll(options.languageModelLayer, memoryLayer36, blobStoreLayer, artifactStoreLayer, promptAssemblerLayer, schemaRegistryLayer);
16732
+ const clusterLayer = options.clusterLayer.pipe(Layer70.provide(clusterContextLayer));
16733
+ return Layer70.mergeAll(options.checkLayer, workflowAndEntityLayerWith(options.toolRuntimeLayer, options.schedulerLayer, promptAssemblerLayer, schemaRegistryLayer, options.toolTransitionCoordinatorLayer)).pipe(Layer70.provideMerge(options.languageModelLayer), Layer70.provide(memoryLayer36), Layer70.provideMerge(ClusterWorkflowEngine.layer), Layer70.provideMerge(clusterLayer), Layer70.provideMerge(options.repositoryLayer), Layer70.provideMerge(blobStoreLayer), Layer70.provideMerge(artifactStoreLayer));
15267
16734
  };
15268
16735
  var layerWithClient = (options) => {
15269
16736
  const blobStoreLayer = options.blobStoreLayer ?? passthroughLayer;
15270
16737
  const artifactStoreLayer = options.artifactStoreLayer ?? passthroughLayer2;
15271
16738
  const promptAssemblerLayer = options.promptAssemblerLayer ?? defaultPromptAssemblerLayer(blobStoreLayer, artifactStoreLayer);
15272
- const schemaRegistryLayer = options.schemaRegistryLayer ?? layer37();
16739
+ const schemaRegistryLayer = options.schemaRegistryLayer ?? layer38();
15273
16740
  const embeddingModelLayer = options.embeddingModelLayer ?? memoryLayer27();
15274
- const memoryLayer35 = layer34().pipe(Layer69.provideMerge(embeddingModelLayer));
15275
- return Layer69.mergeAll(options.checkLayer, runtimeServicesLayerWith(options.toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer)).pipe(Layer69.provideMerge(options.languageModelLayer), Layer69.provide(memoryLayer35), Layer69.provideMerge(options.clusterLayer), Layer69.provideMerge(options.repositoryLayer), Layer69.provideMerge(blobStoreLayer), Layer69.provideMerge(artifactStoreLayer));
16741
+ const memoryLayer36 = layer35().pipe(Layer70.provideMerge(embeddingModelLayer));
16742
+ return Layer70.mergeAll(options.checkLayer, runtimeServicesLayerWith(options.toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer, options.toolTransitionCoordinatorLayer)).pipe(Layer70.provideMerge(options.languageModelLayer), Layer70.provide(memoryLayer36), Layer70.provideMerge(options.clusterLayer), Layer70.provideMerge(options.repositoryLayer), Layer70.provideMerge(blobStoreLayer), Layer70.provideMerge(artifactStoreLayer));
15276
16743
  };
15277
16744
  var layerWithServices = (options) => layerWith({
16745
+ toolTransitionCoordinatorLayer: sqlLayer,
15278
16746
  checkLayer: sqlCheckLayer,
15279
16747
  clusterLayer: sqlClusterLayer,
15280
- repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer69.provideMerge(options.databaseLayer)),
16748
+ repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer70.provideMerge(options.databaseLayer)),
15281
16749
  languageModelLayer: options.languageModelLayer,
15282
16750
  embeddingModelLayer: options.embeddingModelLayer,
15283
16751
  toolRuntimeLayer: options.toolRuntimeLayer,
15284
- schedulerLayer: layer51,
16752
+ schedulerLayer: layer52,
15285
16753
  promptAssemblerLayer: options.promptAssemblerLayer,
15286
16754
  blobStoreLayer: options.blobStoreLayer,
15287
16755
  artifactStoreLayer: options.artifactStoreLayer,
15288
16756
  schemaRegistryLayer: options.schemaRegistryLayer
15289
16757
  });
15290
16758
  var layerWithServicesMultiNode = (options) => layerWith({
15291
- checkLayer: Layer69.mergeAll(sqlCheckLayer, multiNodeDialectGuard),
16759
+ toolTransitionCoordinatorLayer: sqlLayer,
16760
+ checkLayer: Layer70.mergeAll(sqlCheckLayer, multiNodeDialectGuard),
15292
16761
  clusterLayer: clusterLayerHttp(options.cluster),
15293
- repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer69.provideMerge(options.databaseLayer)),
16762
+ repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer70.provideMerge(options.databaseLayer)),
15294
16763
  languageModelLayer: options.languageModelLayer,
15295
16764
  embeddingModelLayer: options.embeddingModelLayer,
15296
16765
  toolRuntimeLayer: options.toolRuntimeLayer,
15297
- schedulerLayer: layer51,
16766
+ schedulerLayer: layer52,
15298
16767
  promptAssemblerLayer: options.promptAssemblerLayer,
15299
16768
  blobStoreLayer: options.blobStoreLayer,
15300
16769
  artifactStoreLayer: options.artifactStoreLayer,
15301
16770
  schemaRegistryLayer: options.schemaRegistryLayer
15302
16771
  });
15303
16772
  var layerWithServicesMultiNodeClientOnly = (options) => layerWithClient({
15304
- checkLayer: Layer69.mergeAll(sqlClientCheckLayer, multiNodeDialectGuard),
16773
+ toolTransitionCoordinatorLayer: sqlLayer,
16774
+ checkLayer: Layer70.mergeAll(sqlClientCheckLayer, multiNodeDialectGuard),
15305
16775
  clusterLayer: clusterLayerHttpClientOnly(options.cluster ?? {}),
15306
- repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer69.provideMerge(options.databaseLayer)),
16776
+ repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer70.provideMerge(options.databaseLayer)),
15307
16777
  languageModelLayer: options.languageModelLayer,
15308
16778
  embeddingModelLayer: options.embeddingModelLayer,
15309
16779
  toolRuntimeLayer: options.toolRuntimeLayer,
@@ -15313,53 +16783,57 @@ var layerWithServicesMultiNodeClientOnly = (options) => layerWithClient({
15313
16783
  schemaRegistryLayer: options.schemaRegistryLayer
15314
16784
  });
15315
16785
  var layerWithLanguageModelService = (options) => layerWithServices({ ...options, toolRuntimeLayer: layer23() });
15316
- var layer52 = layerWithServices({
16786
+ var layer53 = layerWithServices({
15317
16787
  databaseLayer: exports_database_service.layerFromPgClient,
15318
16788
  languageModelLayer: memoryLayer28(),
15319
16789
  embeddingModelLayer: memoryLayer27(),
15320
16790
  toolRuntimeLayer: layer23()
15321
16791
  });
15322
16792
  var testLayerWithServices = (options) => layerWith({
16793
+ toolTransitionCoordinatorLayer: memoryLayer33,
15323
16794
  checkLayer: memoryCheckLayer,
15324
16795
  clusterLayer: memoryClusterLayer,
15325
16796
  repositoryLayer: memoryRepositoryLayer,
15326
16797
  languageModelLayer: options.languageModelLayer,
15327
16798
  embeddingModelLayer: options.embeddingModelLayer ?? testEmbeddingModelLayer,
15328
16799
  toolRuntimeLayer: options.toolRuntimeLayer,
15329
- schedulerLayer: memoryLayer34
15330
- }).pipe(Layer69.provideMerge(testCryptoLayer));
16800
+ schedulerLayer: memoryLayer35
16801
+ }).pipe(Layer70.provideMerge(testCryptoLayer));
15331
16802
  var testLayerWithLanguageModelService = (languageModelLayer) => testLayerWithServices({ languageModelLayer, toolRuntimeLayer: layer23() });
15332
16803
  var testLayer51 = testLayerWithServices({
15333
16804
  languageModelLayer: testLanguageModelLayer,
15334
16805
  toolRuntimeLayer: layer23()
15335
16806
  });
15336
16807
  var testClientLayer = layerWithClient({
16808
+ toolTransitionCoordinatorLayer: memoryLayer33,
15337
16809
  checkLayer: memoryClientCheckLayer,
15338
16810
  clusterLayer: memoryClusterLayer,
15339
16811
  repositoryLayer: memoryRepositoryLayer,
15340
16812
  languageModelLayer: testLanguageModelLayer,
15341
16813
  embeddingModelLayer: testEmbeddingModelLayer,
15342
16814
  toolRuntimeLayer: layer23()
15343
- }).pipe(Layer69.provideMerge(testCryptoLayer));
16815
+ }).pipe(Layer70.provideMerge(testCryptoLayer));
15344
16816
  var testLayerWithDatabaseCheck = (databaseLayer) => layerWith({
16817
+ toolTransitionCoordinatorLayer: memoryLayer33,
15345
16818
  checkLayer: sqlCheckLayer,
15346
16819
  clusterLayer: memoryClusterLayer,
15347
16820
  repositoryLayer: memoryRepositoryLayer,
15348
16821
  languageModelLayer: testLanguageModelLayer,
15349
16822
  embeddingModelLayer: testEmbeddingModelLayer,
15350
16823
  toolRuntimeLayer: layer23(),
15351
- schedulerLayer: memoryLayer34
15352
- }).pipe(Layer69.provide(databaseLayer), Layer69.provideMerge(testCryptoLayer));
16824
+ schedulerLayer: memoryLayer35
16825
+ }).pipe(Layer70.provide(databaseLayer), Layer70.provideMerge(testCryptoLayer));
15353
16826
  var testClientLayerWithDatabaseCheck = (databaseLayer) => layerWithClient({
16827
+ toolTransitionCoordinatorLayer: memoryLayer33,
15354
16828
  checkLayer: sqlClientCheckLayer,
15355
16829
  clusterLayer: memoryClusterLayer,
15356
16830
  repositoryLayer: memoryRepositoryLayer,
15357
16831
  languageModelLayer: testLanguageModelLayer,
15358
16832
  embeddingModelLayer: testEmbeddingModelLayer,
15359
16833
  toolRuntimeLayer: layer23()
15360
- }).pipe(Layer69.provide(databaseLayer), Layer69.provideMerge(testCryptoLayer));
15361
- var check2 = Effect77.fn("RunnerRuntime.check.call")(function* () {
15362
- const service = yield* Service49;
16834
+ }).pipe(Layer70.provide(databaseLayer), Layer70.provideMerge(testCryptoLayer));
16835
+ var check2 = Effect78.fn("RunnerRuntime.check.call")(function* () {
16836
+ const service = yield* Service50;
15363
16837
  return yield* service.check();
15364
16838
  });
15365
16839
  // ../runtime/src/workflow/activity-version-registry.ts
@@ -15375,7 +16849,7 @@ __export(exports_activity_version_registry, {
15375
16849
  ActivityManifestChange: () => ActivityManifestChange,
15376
16850
  ActivityManifest: () => ActivityManifest
15377
16851
  });
15378
- import { Crypto as Crypto5, Effect as Effect78, Schema as Schema74 } from "effect";
16852
+ import { Crypto as Crypto5, Effect as Effect79, Schema as Schema74 } from "effect";
15379
16853
  var generatedFrom = "@relayfx/runtime/ExecutionWorkflow";
15380
16854
  var ActivityManifestEntry = Schema74.Struct({
15381
16855
  name: Schema74.String,
@@ -15533,13 +17007,13 @@ var canonical = (value) => {
15533
17007
  };
15534
17008
  var canonicalStringify = (value) => JSON.stringify(canonical(value));
15535
17009
  var hex2 = (bytes) => Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
15536
- var signatureHash = Effect78.fn("ActivityVersionRegistry.signatureHash")(function* (input, success2, error) {
17010
+ var signatureHash = Effect79.fn("ActivityVersionRegistry.signatureHash")(function* (input, success2, error) {
15537
17011
  const crypto = yield* Crypto5.Crypto;
15538
17012
  const payload = new TextEncoder().encode(canonicalStringify({ input, success: success2, error }));
15539
17013
  const digest = yield* crypto.digest("SHA-256", payload);
15540
17014
  return hex2(digest);
15541
17015
  });
15542
- var manifestEntry = Effect78.fn("ActivityVersionRegistry.manifestEntry")(function* (contract) {
17016
+ var manifestEntry = Effect79.fn("ActivityVersionRegistry.manifestEntry")(function* (contract) {
15543
17017
  const input = schemaJson(contract.input);
15544
17018
  const success2 = schemaJson(contract.success);
15545
17019
  const error = schemaJson(contract.error);
@@ -15549,8 +17023,8 @@ var manifestEntry = Effect78.fn("ActivityVersionRegistry.manifestEntry")(functio
15549
17023
  signature_hash
15550
17024
  };
15551
17025
  });
15552
- var currentManifest = Effect78.fn("ActivityVersionRegistry.currentManifest")(function* () {
15553
- const activities = yield* Effect78.forEach(contracts.toSorted((left, right) => left.name.localeCompare(right.name)), manifestEntry);
17026
+ var currentManifest = Effect79.fn("ActivityVersionRegistry.currentManifest")(function* () {
17027
+ const activities = yield* Effect79.forEach(contracts.toSorted((left, right) => left.name.localeCompare(right.name)), manifestEntry);
15554
17028
  return {
15555
17029
  version: 1,
15556
17030
  generated_from: generatedFrom,
@@ -15604,11 +17078,11 @@ var evaluateGuard = (input) => {
15604
17078
  additive_changes: diff.additive
15605
17079
  };
15606
17080
  };
15607
- var guard = Effect78.fn("ActivityVersionRegistry.guard")(function* (input) {
17081
+ var guard = Effect79.fn("ActivityVersionRegistry.guard")(function* (input) {
15608
17082
  const result = evaluateGuard(input);
15609
17083
  if (result.status === "pass")
15610
17084
  return result;
15611
- return yield* Effect78.fail(new ActivityManifestGuardFailed({
17085
+ return yield* Effect79.fail(new ActivityManifestGuardFailed({
15612
17086
  message: `Activity replay contract changed while ${result.waiting_executions} waiting executions exist`,
15613
17087
  result
15614
17088
  }));
@@ -15638,9 +17112,9 @@ __export(exports_language_model_registration, {
15638
17112
  anthropic: () => anthropic
15639
17113
  });
15640
17114
 
15641
- // ../../node_modules/.bun/@batonfx+providers@0.3.7/node_modules/@batonfx/providers/src/anthropic.ts
17115
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/anthropic.ts
15642
17116
  import { AnthropicClient, AnthropicLanguageModel } from "@effect/ai-anthropic";
15643
- import { Layer as Layer70 } from "effect";
17117
+ import { Layer as Layer71 } from "effect";
15644
17118
  import { FetchHttpClient as FetchHttpClient2 } from "effect/unstable/http";
15645
17119
  var anthropic = (input) => exports_model_registry.registrationFromLayer({
15646
17120
  provider: "anthropic",
@@ -15653,16 +17127,16 @@ var anthropic = (input) => exports_model_registry.registrationFromLayer({
15653
17127
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
15654
17128
  });
15655
17129
  var anthropicClientLayerConfig = AnthropicClient.layerConfig;
15656
- var withAnthropic = (options) => exports_model_registry.layerFromRegistrationEffects([anthropic(options)]).pipe(Layer70.provide(AnthropicClient.layerConfig({ ...options.clientConfig, apiKey: options.apiKey })), Layer70.provide(FetchHttpClient2.layer));
15657
- // ../../node_modules/.bun/@batonfx+providers@0.3.7/node_modules/@batonfx/providers/src/deterministic.ts
17130
+ var withAnthropic = (options) => exports_model_registry.layerFromRegistrationEffects([anthropic(options)]).pipe(Layer71.provide(AnthropicClient.layerConfig({ ...options.clientConfig, apiKey: options.apiKey })), Layer71.provide(FetchHttpClient2.layer));
17131
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/deterministic.ts
15658
17132
  import { OpenAiClient as OpenAiClient3 } from "@effect/ai-openai";
15659
- import { Effect as Effect79, Layer as Layer72, Option as Option28, Stream as Stream11 } from "effect";
17133
+ import { Effect as Effect80, Layer as Layer73, Option as Option28, Stream as Stream11 } from "effect";
15660
17134
  import { LanguageModel as LanguageModel8, Response as Response7 } from "effect/unstable/ai";
15661
17135
  import { FetchHttpClient as FetchHttpClient4 } from "effect/unstable/http";
15662
17136
 
15663
- // ../../node_modules/.bun/@batonfx+providers@0.3.7/node_modules/@batonfx/providers/src/openai.ts
17137
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/openai.ts
15664
17138
  import { OpenAiClient as OpenAiClient2, OpenAiLanguageModel } from "@effect/ai-openai";
15665
- import { Layer as Layer71 } from "effect";
17139
+ import { Layer as Layer72 } from "effect";
15666
17140
  import { FetchHttpClient as FetchHttpClient3 } from "effect/unstable/http";
15667
17141
  var openAi = (input) => exports_model_registry.registrationFromLayer({
15668
17142
  provider: "openai",
@@ -15675,11 +17149,11 @@ var openAi = (input) => exports_model_registry.registrationFromLayer({
15675
17149
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
15676
17150
  });
15677
17151
  var openAiClientLayerConfig2 = OpenAiClient2.layerConfig;
15678
- var withOpenAi = (options) => exports_model_registry.layerFromRegistrationEffects([openAi(options)]).pipe(Layer71.provide(OpenAiClient2.layerConfig({ ...options.clientConfig, apiKey: options.apiKey })), Layer71.provide(FetchHttpClient3.layer));
17152
+ var withOpenAi = (options) => exports_model_registry.layerFromRegistrationEffects([openAi(options)]).pipe(Layer72.provide(OpenAiClient2.layerConfig({ ...options.clientConfig, apiKey: options.apiKey })), Layer72.provide(FetchHttpClient3.layer));
15679
17153
 
15680
- // ../../node_modules/.bun/@batonfx+providers@0.3.7/node_modules/@batonfx/providers/src/deterministic.ts
15681
- var deterministicModelLayer = Layer72.effect(LanguageModel8.LanguageModel, LanguageModel8.make({
15682
- generateText: () => Effect79.succeed([{ type: "text", text: "deterministic response" }]),
17154
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/deterministic.ts
17155
+ var deterministicModelLayer = Layer73.effect(LanguageModel8.LanguageModel, LanguageModel8.make({
17156
+ generateText: () => Effect80.succeed([{ type: "text", text: "deterministic response" }]),
15683
17157
  streamText: () => Stream11.make(Response7.makePart("text-delta", { id: "text", delta: "deterministic response" }))
15684
17158
  }));
15685
17159
  var deterministicModel = (input = {}) => exports_model_registry.registrationFromLayer({
@@ -15690,20 +17164,20 @@ var deterministicModel = (input = {}) => exports_model_registry.registrationFrom
15690
17164
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
15691
17165
  });
15692
17166
  var withDeterministic = (input = {}) => exports_model_registry.layerFromRegistrationEffects([deterministicModel(input)]);
15693
- var withOpenAiOrDeterministic = (options) => Layer72.unwrap(Effect79.gen(function* () {
17167
+ var withOpenAiOrDeterministic = (options) => Layer73.unwrap(Effect80.gen(function* () {
15694
17168
  const deterministic = yield* deterministicModel({
15695
17169
  provider: options.fallbackProvider ?? "deterministic",
15696
17170
  model: options.fallbackModel
15697
17171
  });
15698
- const openAiRegistration = yield* openAi(options).pipe(Effect79.provide(OpenAiClient3.layerConfig({ ...options.clientConfig, apiKey: options.apiKey })), Effect79.provide(FetchHttpClient4.layer), Effect79.asSome, Effect79.catchTag("ConfigError", () => Effect79.succeedNone));
17172
+ const openAiRegistration = yield* openAi(options).pipe(Effect80.provide(OpenAiClient3.layerConfig({ ...options.clientConfig, apiKey: options.apiKey })), Effect80.provide(FetchHttpClient4.layer), Effect80.asSome, Effect80.catchTag("ConfigError", () => Effect80.succeedNone));
15699
17173
  return exports_model_registry.layer([
15700
17174
  deterministic,
15701
17175
  ...Option28.isSome(openAiRegistration) ? [openAiRegistration.value] : []
15702
17176
  ]);
15703
17177
  }));
15704
- // ../../node_modules/.bun/@batonfx+providers@0.3.7/node_modules/@batonfx/providers/src/openai-compat.ts
17178
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/openai-compat.ts
15705
17179
  import { OpenAiClient as OpenAiClient4, OpenAiLanguageModel as OpenAiLanguageModel2 } from "@effect/ai-openai-compat";
15706
- import { Config as Config8, Layer as Layer73 } from "effect";
17180
+ import { Config as Config8, Layer as Layer74 } from "effect";
15707
17181
  import { FetchHttpClient as FetchHttpClient5 } from "effect/unstable/http";
15708
17182
  var openAiCompatible = (input) => exports_model_registry.registrationFromLayer({
15709
17183
  provider: input.provider ?? "openai-compatible",
@@ -15721,10 +17195,10 @@ var clientLayerConfig = (options) => OpenAiClient4.layerConfig({
15721
17195
  ...options.apiKey === undefined ? {} : { apiKey: options.apiKey },
15722
17196
  ...options.baseUrl === undefined ? {} : { apiUrl: Config8.succeed(options.baseUrl) }
15723
17197
  });
15724
- var withOpenAiCompatible = (options) => exports_model_registry.layerFromRegistrationEffects([openAiCompatible(options)]).pipe(Layer73.provide(clientLayerConfig(options)), Layer73.provide(FetchHttpClient5.layer));
15725
- // ../../node_modules/.bun/@batonfx+providers@0.3.7/node_modules/@batonfx/providers/src/openrouter.ts
17198
+ var withOpenAiCompatible = (options) => exports_model_registry.layerFromRegistrationEffects([openAiCompatible(options)]).pipe(Layer74.provide(clientLayerConfig(options)), Layer74.provide(FetchHttpClient5.layer));
17199
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/openrouter.ts
15726
17200
  import { OpenRouterClient, OpenRouterLanguageModel } from "@effect/ai-openrouter";
15727
- import { Layer as Layer74 } from "effect";
17201
+ import { Layer as Layer75 } from "effect";
15728
17202
  import { FetchHttpClient as FetchHttpClient6 } from "effect/unstable/http";
15729
17203
  var openRouter = (input) => exports_model_registry.registrationFromLayer({
15730
17204
  provider: "openrouter",
@@ -15737,7 +17211,7 @@ var openRouter = (input) => exports_model_registry.registrationFromLayer({
15737
17211
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
15738
17212
  });
15739
17213
  var openRouterClientLayerConfig = OpenRouterClient.layerConfig;
15740
- var withOpenRouter = (options) => exports_model_registry.layerFromRegistrationEffects([openRouter(options)]).pipe(Layer74.provide(OpenRouterClient.layerConfig({ ...options.clientConfig, apiKey: options.apiKey })), Layer74.provide(FetchHttpClient6.layer));
17214
+ var withOpenRouter = (options) => exports_model_registry.layerFromRegistrationEffects([openRouter(options)]).pipe(Layer75.provide(OpenRouterClient.layerConfig({ ...options.clientConfig, apiKey: options.apiKey })), Layer75.provide(FetchHttpClient6.layer));
15741
17215
  // src/ai.ts
15742
17216
  var relayAiPackage = "@relayfx/sdk/ai";
15743
17217
  export {
@@ -15747,7 +17221,7 @@ export {
15747
17221
  exports_tool_output as ToolOutput,
15748
17222
  exports_tool_executor as ToolExecutor,
15749
17223
  exports_tool_context as ToolContext,
15750
- Tool7 as Tool,
17224
+ Tool6 as Tool,
15751
17225
  Tokenizer3 as Tokenizer,
15752
17226
  Telemetry2 as Telemetry,
15753
17227
  exports_steering as Steering,