@relayfx/sdk 0.0.48 → 0.0.50

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 +2054 -576
  2. package/dist/index.js +2884 -860
  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,24 +6543,40 @@ 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
6362
6576
  });
6363
6577
  import { Context as Context21, Effect as Effect21, Layer as Layer21, Schema as Schema30 } from "effect";
6364
6578
  import { SqlClient as SqlClient20 } from "effect/unstable/sql/SqlClient";
6579
+ import { isSqlError as isSqlError2 } from "effect/unstable/sql/SqlError";
6365
6580
  class ToolCallRepositoryError extends Schema30.TaggedErrorClass()("ToolCallRepositoryError", {
6366
6581
  message: Schema30.String
6367
6582
  }) {
@@ -6382,6 +6597,30 @@ class DuplicateToolResult extends Schema30.TaggedErrorClass()("DuplicateToolResu
6382
6597
  }) {
6383
6598
  }
6384
6599
 
6600
+ class ToolCallConflict extends Schema30.TaggedErrorClass()("ToolCallConflict", {
6601
+ id: exports_ids_schema.ToolCallId
6602
+ }) {
6603
+ }
6604
+
6605
+ class ToolCallTransitionRejected extends Schema30.TaggedErrorClass()("ToolCallTransitionRejected", {
6606
+ id: exports_ids_schema.ToolCallId,
6607
+ message: Schema30.String
6608
+ }) {
6609
+ }
6610
+
6611
+ class ToolOutcomeConflict extends Schema30.TaggedErrorClass()("ToolOutcomeConflict", {
6612
+ id: exports_ids_schema.ToolCallId
6613
+ }) {
6614
+ }
6615
+
6616
+ class ToolClaimRejected extends Schema30.TaggedErrorClass()("ToolClaimRejected", {
6617
+ message: Schema30.String
6618
+ }) {
6619
+ }
6620
+ var lengthPrefixed = (value) => `${[...value].length}:${value}`;
6621
+ var toolCallIdempotencyKey = (tenantId2, executionId, callId) => `tool:${lengthPrefixed(tenantId2)}:${lengthPrefixed(executionId)}:${lengthPrefixed(callId)}`;
6622
+ var toolAttemptId = (attemptNumber) => exports_ids_schema.ToolAttemptId.make(`tool-attempt:${attemptNumber}`);
6623
+
6385
6624
  class Service21 extends Context21.Service()("@relayfx/store-sql/ToolCallRepository") {
6386
6625
  }
6387
6626
  var ToolCallRow = Schema30.Struct({
@@ -6389,9 +6628,34 @@ var ToolCallRow = Schema30.Struct({
6389
6628
  execution_id: Schema30.String,
6390
6629
  name: Schema30.String,
6391
6630
  input_json: Schema30.Unknown,
6631
+ definition_json: Schema30.NullishOr(Schema30.Unknown),
6632
+ placement_kind: Schema30.String,
6633
+ placement_key: Schema30.NullishOr(Schema30.String),
6634
+ state: Schema30.String,
6635
+ wait_id: Schema30.NullishOr(Schema30.String),
6636
+ idempotency_key: Schema30.String,
6637
+ available_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number]),
6638
+ active_attempt_id: Schema30.NullishOr(Schema30.String),
6639
+ claim_owner: Schema30.NullishOr(Schema30.String),
6640
+ claimed_at: Schema30.NullishOr(Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])),
6641
+ claim_expires_at: Schema30.NullishOr(Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])),
6642
+ external_outcome_json: Schema30.NullishOr(Schema30.Unknown),
6643
+ external_outcome_at: Schema30.NullishOr(Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])),
6392
6644
  metadata_json: Schema30.Unknown,
6393
- created_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])
6645
+ created_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number]),
6646
+ updated_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])
6394
6647
  }).annotate({ identifier: "Relay.ToolCall.Row" });
6648
+ var ToolAttemptRow = Schema30.Struct({
6649
+ id: Schema30.String,
6650
+ tool_call_id: Schema30.String,
6651
+ attempt_number: Schema30.Union([Schema30.Number, Schema30.String, Schema30.BigInt]),
6652
+ state: Schema30.String,
6653
+ worker_id: Schema30.NullishOr(Schema30.String),
6654
+ claim_expires_at: Schema30.NullishOr(Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])),
6655
+ error: Schema30.NullishOr(Schema30.String),
6656
+ created_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number]),
6657
+ completed_at: Schema30.NullishOr(Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number]))
6658
+ }).annotate({ identifier: "Relay.ToolAttempt.Row" });
6395
6659
  var ToolResultRow = Schema30.Struct({
6396
6660
  tool_call_id: Schema30.String,
6397
6661
  output_json: Schema30.Unknown,
@@ -6400,15 +6664,46 @@ var ToolResultRow = Schema30.Struct({
6400
6664
  created_at: Schema30.Union([Schema30.Date, Schema30.String, Schema30.Number])
6401
6665
  }).annotate({ identifier: "Relay.ToolResult.Row" });
6402
6666
  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)
6667
+ var normalizeCall = (call) => ({ ...call, metadata: metadata8(call.metadata) });
6668
+ var sameCallIdentity = (left, right) => exports_shared_schema.canonicalString(normalizeCall(left)) === exports_shared_schema.canonicalString(normalizeCall(right));
6669
+ 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 });
6670
+ var toCallRecord = (row) => {
6671
+ const definition = row.definition_json === null || row.definition_json === undefined ? undefined : Schema30.decodeUnknownSync(exports_tool_schema.Definition)(decodeJson(row.definition_json));
6672
+ const outcome = row.external_outcome_json === null || row.external_outcome_json === undefined ? undefined : Schema30.decodeUnknownSync(exports_tool_schema.ExternalOutcome)(decodeJson(row.external_outcome_json));
6673
+ return {
6674
+ executionId: exports_ids_schema.ExecutionId.make(row.execution_id),
6675
+ call: normalizeCall({
6676
+ id: exports_ids_schema.ToolCallId.make(row.id),
6677
+ name: row.name,
6678
+ input: decodeJson(row.input_json),
6679
+ metadata: decodeJson(row.metadata_json)
6680
+ }),
6681
+ ...definition === undefined ? {} : { definition },
6682
+ placement: placementFromRow(row),
6683
+ state: Schema30.decodeUnknownSync(exports_tool_schema.CallState)(row.state),
6684
+ ...row.wait_id === null || row.wait_id === undefined ? {} : { waitId: exports_ids_schema.WaitId.make(row.wait_id) },
6685
+ idempotencyKey: row.idempotency_key,
6686
+ availableAt: fromDbTimestamp(row.available_at),
6687
+ ...row.active_attempt_id === null || row.active_attempt_id === undefined ? {} : { activeAttemptId: exports_ids_schema.ToolAttemptId.make(row.active_attempt_id) },
6688
+ ...row.claim_owner === null || row.claim_owner === undefined ? {} : { claimOwner: row.claim_owner },
6689
+ ...row.claimed_at === null || row.claimed_at === undefined ? {} : { claimedAt: fromDbTimestamp(row.claimed_at) },
6690
+ ...row.claim_expires_at === null || row.claim_expires_at === undefined ? {} : { claimExpiresAt: fromDbTimestamp(row.claim_expires_at) },
6691
+ ...outcome === undefined ? {} : { externalOutcome: outcome },
6692
+ ...row.external_outcome_at === null || row.external_outcome_at === undefined ? {} : { externalOutcomeAt: fromDbTimestamp(row.external_outcome_at) },
6693
+ createdAt: fromDbTimestamp(row.created_at),
6694
+ updatedAt: fromDbTimestamp(row.updated_at)
6695
+ };
6696
+ };
6697
+ var toAttemptRecord = (row) => ({
6698
+ id: exports_ids_schema.ToolAttemptId.make(row.id),
6699
+ callId: exports_ids_schema.ToolCallId.make(row.tool_call_id),
6700
+ attemptNumber: Number(row.attempt_number),
6701
+ state: Schema30.decodeUnknownSync(exports_tool_schema.AttemptState)(row.state),
6702
+ ...row.worker_id === null || row.worker_id === undefined ? {} : { workerId: row.worker_id },
6703
+ ...row.claim_expires_at === null || row.claim_expires_at === undefined ? {} : { claimExpiresAt: fromDbTimestamp(row.claim_expires_at) },
6704
+ ...row.error === null || row.error === undefined ? {} : { error: row.error },
6705
+ createdAt: fromDbTimestamp(row.created_at),
6706
+ ...row.completed_at === null || row.completed_at === undefined ? {} : { completedAt: fromDbTimestamp(row.completed_at) }
6412
6707
  });
6413
6708
  var toResultRecord = (row) => ({
6414
6709
  result: {
@@ -6422,9 +6717,44 @@ var toResultRecord = (row) => ({
6422
6717
  var toRepositoryError17 = (error) => new ToolCallRepositoryError({ message: String(error) });
6423
6718
  var decodeCallRow = (row) => Schema30.decodeUnknownEffect(ToolCallRow)(row).pipe(Effect21.mapError(toRepositoryError17));
6424
6719
  var decodeResultRow = (row) => Schema30.decodeUnknownEffect(ToolResultRow)(row).pipe(Effect21.mapError(toRepositoryError17));
6720
+ var decodeAttemptRow = (row) => Schema30.decodeUnknownEffect(ToolAttemptRow)(row).pipe(Effect21.mapError(toRepositoryError17));
6425
6721
  var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6426
6722
  const sql3 = yield* SqlClient20;
6427
- const callColumns = sql3.literal(["id", "execution_id", "name", "input_json", "metadata_json", "created_at"].join(", "));
6723
+ const ts = (millis) => timestampParam(sql3, millis);
6724
+ const repositoryTransaction = (effect) => sql3.withTransaction(effect).pipe(Effect21.catchTag("SqlError", (error) => Effect21.fail(toRepositoryError17(error))));
6725
+ const callColumns = sql3.literal([
6726
+ "id",
6727
+ "execution_id",
6728
+ "name",
6729
+ "input_json",
6730
+ "definition_json",
6731
+ "placement_kind",
6732
+ "placement_key",
6733
+ "state",
6734
+ "wait_id",
6735
+ "idempotency_key",
6736
+ "available_at",
6737
+ "active_attempt_id",
6738
+ "claim_owner",
6739
+ "claimed_at",
6740
+ "claim_expires_at",
6741
+ "external_outcome_json",
6742
+ "external_outcome_at",
6743
+ "metadata_json",
6744
+ "created_at",
6745
+ "updated_at"
6746
+ ].join(", "));
6747
+ const attemptColumns = sql3.literal([
6748
+ "id",
6749
+ "tool_call_id",
6750
+ "attempt_number",
6751
+ "state",
6752
+ "worker_id",
6753
+ "claim_expires_at",
6754
+ "error",
6755
+ "created_at",
6756
+ "completed_at"
6757
+ ].join(", "));
6428
6758
  const resultColumns = sql3.literal(["tool_call_id", "output_json", "error", "metadata_json", "created_at"].join(", "));
6429
6759
  const selectCallByKey = (tenantId2, id2) => sql3`
6430
6760
  SELECT ${callColumns}
@@ -6436,8 +6766,8 @@ var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6436
6766
  FROM relay_tool_results
6437
6767
  WHERE tenant_id = ${tenantId2} AND tool_call_id = ${callId}
6438
6768
  `;
6439
- const insertCallStatement = (tenantId2, input) => sql3`
6440
- INSERT INTO relay_tool_calls (
6769
+ const insertCallBody = (tenantId2, input, definition, placement = { kind: "local" }) => sql3`
6770
+ (
6441
6771
  tenant_id, ${callColumns}
6442
6772
  )
6443
6773
  VALUES (
@@ -6446,17 +6776,43 @@ var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6446
6776
  ${input.executionId},
6447
6777
  ${input.call.name},
6448
6778
  ${encodeJson(input.call.input)},
6779
+ ${definition === undefined ? null : encodeJson(definition)},
6780
+ ${placement.kind},
6781
+ ${placement.kind === "remote" ? placement.queue : placement.kind === "mcp" ? placement.server_id : null},
6782
+ 'requested',
6783
+ ${null},
6784
+ ${toolCallIdempotencyKey(tenantId2, input.executionId, input.call.id)},
6785
+ ${ts(input.createdAt)},
6786
+ ${null},
6787
+ ${null},
6788
+ ${null},
6789
+ ${null},
6790
+ ${null},
6791
+ ${null},
6449
6792
  ${encodeJson(metadata8(input.call.metadata))},
6450
- ${timestampParam(sql3, input.createdAt)}
6793
+ ${ts(input.createdAt)},
6794
+ ${ts(input.createdAt)}
6451
6795
  )
6452
6796
  `;
6797
+ const insertCallStatement = (tenantId2, input, definition, placement) => sql3`
6798
+ INSERT INTO relay_tool_calls ${insertCallBody(tenantId2, input, definition, placement)}
6799
+ `;
6800
+ const insertCallIgnore = sql3.onDialectOrElse({
6801
+ mysql: () => (tenantId2, input, definition, placement) => sql3`
6802
+ INSERT IGNORE INTO relay_tool_calls ${insertCallBody(tenantId2, input, definition, placement)}
6803
+ `,
6804
+ orElse: () => (tenantId2, input, definition, placement) => sql3`
6805
+ INSERT INTO relay_tool_calls ${insertCallBody(tenantId2, input, definition, placement)}
6806
+ ON CONFLICT (tenant_id, id) DO NOTHING
6807
+ `
6808
+ });
6453
6809
  const insertCall = sql3.onDialectOrElse({
6454
- mysql: () => (tenantId2, input) => sql3.withTransaction(Effect21.gen(function* () {
6455
- yield* insertCallStatement(tenantId2, input);
6810
+ mysql: () => (tenantId2, input, definition, placement) => sql3.withTransaction(Effect21.gen(function* () {
6811
+ yield* insertCallStatement(tenantId2, input, definition, placement);
6456
6812
  return yield* selectCallByKey(tenantId2, input.call.id);
6457
6813
  })),
6458
- orElse: () => (tenantId2, input) => sql3`
6459
- ${insertCallStatement(tenantId2, input)}
6814
+ orElse: () => (tenantId2, input, definition, placement) => sql3`
6815
+ ${insertCallStatement(tenantId2, input, definition, placement)}
6460
6816
  RETURNING ${callColumns}
6461
6817
  `
6462
6818
  });
@@ -6473,16 +6829,407 @@ var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6473
6829
  ${timestampParam(sql3, input.createdAt)}
6474
6830
  )
6475
6831
  `;
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
- })),
6832
+ const selectAttempts = (tenantId2, callId) => sql3`
6833
+ SELECT ${attemptColumns}
6834
+ FROM relay_tool_attempts
6835
+ WHERE tenant_id = ${tenantId2} AND tool_call_id = ${callId}
6836
+ ORDER BY attempt_number ASC
6837
+ `;
6838
+ const lockedCallRows = sql3.onDialectOrElse({
6839
+ pg: () => (tenantId2, callId) => sql3`
6840
+ ${selectCallByKey(tenantId2, callId)}
6841
+ FOR UPDATE
6842
+ `,
6843
+ mysql: () => (tenantId2, callId) => sql3`
6844
+ ${selectCallByKey(tenantId2, callId)}
6845
+ FOR UPDATE
6846
+ `,
6847
+ orElse: () => selectCallByKey
6848
+ });
6849
+ const decodeCall = Effect21.fn("ToolCallRepository.decodeCall")(function* (row) {
6850
+ const decoded = yield* decodeCallRow(row);
6851
+ return yield* Effect21.try({ try: () => toCallRecord(decoded), catch: toRepositoryError17 });
6852
+ });
6853
+ const decodeAttempt = Effect21.fn("ToolCallRepository.decodeAttempt")(function* (row) {
6854
+ const decoded = yield* decodeAttemptRow(row);
6855
+ return yield* Effect21.try({ try: () => toAttemptRecord(decoded), catch: toRepositoryError17 });
6856
+ });
6857
+ const readLockedCall = Effect21.fn("ToolCallRepository.readLockedCall")(function* (tenantId2, callId) {
6858
+ const rows = yield* lockedCallRows(tenantId2, callId).pipe(Effect21.mapError(toRepositoryError17));
6859
+ if (rows[0] === undefined)
6860
+ return yield* Effect21.fail(new ToolCallNotFound({ id: callId }));
6861
+ return yield* decodeCall(rows[0]);
6862
+ });
6863
+ const readAttempts = Effect21.fn("ToolCallRepository.readAttempts")(function* (tenantId2, callId) {
6864
+ const rows = yield* selectAttempts(tenantId2, callId).pipe(Effect21.mapError(toRepositoryError17));
6865
+ return yield* Effect21.forEach(rows, decodeAttempt);
6866
+ });
6867
+ const nextAttemptNumber = Effect21.fn("ToolCallRepository.nextAttemptNumber")(function* (tenantId2, callId) {
6868
+ const rows = yield* sql3`
6869
+ SELECT COALESCE(MAX(attempt_number), 0) AS max_attempt
6870
+ FROM relay_tool_attempts
6871
+ WHERE tenant_id = ${tenantId2} AND tool_call_id = ${callId}
6872
+ `.pipe(Effect21.mapError(toRepositoryError17));
6873
+ const max = Number(rows[0]?.max_attempt ?? 0);
6874
+ return max + 1;
6875
+ });
6876
+ const insertAttemptNumber = Effect21.fn("ToolCallRepository.insertAttemptNumber")(function* (tenantId2, callId, attemptNumber, createdAt, workerId, claimExpiresAt) {
6877
+ const attemptId = toolAttemptId(attemptNumber);
6878
+ yield* sql3`
6879
+ INSERT INTO relay_tool_attempts (
6880
+ tenant_id, id, tool_call_id, attempt_number, state, worker_id, claim_expires_at,
6881
+ error, created_at, completed_at
6882
+ )
6883
+ VALUES (
6884
+ ${tenantId2}, ${attemptId}, ${callId}, ${attemptNumber}, 'running', ${workerId ?? null},
6885
+ ${claimExpiresAt === undefined ? null : ts(claimExpiresAt)}, ${null}, ${ts(createdAt)}, ${null}
6886
+ )
6887
+ `.pipe(Effect21.mapError(toRepositoryError17));
6888
+ return {
6889
+ id: attemptId,
6890
+ callId,
6891
+ attemptNumber,
6892
+ state: "running",
6893
+ ...workerId === undefined ? {} : { workerId },
6894
+ ...claimExpiresAt === undefined ? {} : { claimExpiresAt },
6895
+ createdAt
6896
+ };
6897
+ });
6898
+ const insertAttempt = Effect21.fn("ToolCallRepository.insertAttempt")(function* (tenantId2, callId, createdAt, workerId, claimExpiresAt) {
6899
+ const attemptNumber = yield* nextAttemptNumber(tenantId2, callId);
6900
+ return yield* insertAttemptNumber(tenantId2, callId, attemptNumber, createdAt, workerId, claimExpiresAt);
6901
+ });
6902
+ const loadAttempt = Effect21.fn("ToolCallRepository.loadAttempt")(function* (tenantId2, callId, attemptId) {
6903
+ const rows = yield* sql3`
6904
+ SELECT ${attemptColumns}
6905
+ FROM relay_tool_attempts
6906
+ WHERE tenant_id = ${tenantId2} AND tool_call_id = ${callId} AND id = ${attemptId}
6907
+ `.pipe(Effect21.mapError(toRepositoryError17));
6908
+ return rows[0] === undefined ? undefined : yield* decodeAttempt(rows[0]);
6909
+ });
6910
+ const completeAttempt = Effect21.fn("ToolCallRepository.completeAttempt")(function* (tenantId2, callId, attemptId, state, completedAt, error) {
6911
+ yield* sql3`
6912
+ UPDATE relay_tool_attempts
6913
+ SET state = ${state}, error = ${error ?? null}, completed_at = ${ts(completedAt)}
6914
+ WHERE tenant_id = ${tenantId2} AND tool_call_id = ${callId} AND id = ${attemptId} AND state = 'running'
6915
+ `.pipe(Effect21.mapError(toRepositoryError17));
6916
+ const attempt = yield* loadAttempt(tenantId2, callId, attemptId);
6917
+ if (attempt === undefined) {
6918
+ return yield* Effect21.fail(new ToolCallRepositoryError({ message: `Tool attempt not found: ${attemptId}` }));
6919
+ }
6920
+ return attempt;
6921
+ });
6922
+ const ensureCall = Effect21.fn("ToolCallRepository.ensureCall")(function* (input) {
6923
+ const tenantId2 = yield* current();
6924
+ return yield* sql3.withTransaction(Effect21.gen(function* () {
6925
+ yield* insertCallIgnore(tenantId2, input, input.definition, input.placement);
6926
+ const rows = yield* lockedCallRows(tenantId2, input.call.id);
6927
+ if (rows[0] === undefined)
6928
+ return yield* Effect21.fail(new ToolCallNotFound({ id: input.call.id }));
6929
+ const existing = yield* decodeCall(rows[0]);
6930
+ 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)) {
6931
+ return yield* Effect21.fail(new ToolCallConflict({ id: input.call.id }));
6932
+ }
6933
+ if (existing.definition === undefined) {
6934
+ return yield* Effect21.fail(new ToolCallRepositoryError({ message: "Tool call insert returned no row" }));
6935
+ }
6936
+ return existing;
6937
+ })).pipe(Effect21.retry({ times: 3, while: (error) => isSqlError2(error) && error.isRetryable }), Effect21.catchTag("SqlError", (error) => Effect21.fail(toRepositoryError17(error))));
6938
+ });
6939
+ const prepareExternalWait = Effect21.fn("ToolCallRepository.prepareExternalWait")(function* (input) {
6940
+ const tenantId2 = yield* current();
6941
+ return yield* repositoryTransaction(Effect21.gen(function* () {
6942
+ const call = yield* readLockedCall(tenantId2, input.callId);
6943
+ if (call.placement.kind !== "client" && call.placement.kind !== "remote") {
6944
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: "Tool placement is not external" }));
6945
+ }
6946
+ if (call.state === "waiting" && call.waitId === input.waitId)
6947
+ return call;
6948
+ if (call.state !== "requested") {
6949
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: `Call is ${call.state}` }));
6950
+ }
6951
+ yield* sql3`
6952
+ UPDATE relay_tool_calls
6953
+ SET state = 'waiting', wait_id = ${input.waitId}, available_at = ${ts(input.availableAt)},
6954
+ updated_at = ${ts(input.updatedAt)}
6955
+ WHERE tenant_id = ${tenantId2} AND id = ${input.callId} AND state = 'requested'
6956
+ `.pipe(Effect21.mapError(toRepositoryError17));
6957
+ return yield* readLockedCall(tenantId2, input.callId);
6958
+ }));
6959
+ });
6960
+ const beginAttempt = Effect21.fn("ToolCallRepository.beginAttempt")(function* (input) {
6961
+ const tenantId2 = yield* current();
6962
+ return yield* repositoryTransaction(Effect21.gen(function* () {
6963
+ const call = yield* readLockedCall(tenantId2, input.callId);
6964
+ if (call.placement.kind !== "local" && call.placement.kind !== "mcp") {
6965
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: "Tool placement is not immediate" }));
6966
+ }
6967
+ if (call.state === "completed" || call.state === "failed") {
6968
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: `Call is ${call.state}` }));
6969
+ }
6970
+ if (call.activeAttemptId !== undefined) {
6971
+ yield* completeAttempt(tenantId2, input.callId, call.activeAttemptId, "abandoned", input.startedAt);
6972
+ }
6973
+ const attempt = yield* insertAttempt(tenantId2, input.callId, input.startedAt);
6974
+ yield* sql3`
6975
+ UPDATE relay_tool_calls
6976
+ SET state = 'running', active_attempt_id = ${attempt.id}, updated_at = ${ts(input.startedAt)}
6977
+ WHERE tenant_id = ${tenantId2} AND id = ${input.callId}
6978
+ `.pipe(Effect21.mapError(toRepositoryError17));
6979
+ return attempt;
6980
+ }));
6981
+ });
6982
+ const acceptClientOutcome = Effect21.fn("ToolCallRepository.acceptClientOutcome")(function* (input) {
6983
+ const tenantId2 = yield* current();
6984
+ return yield* repositoryTransaction(Effect21.gen(function* () {
6985
+ const call = yield* readLockedCall(tenantId2, input.callId);
6986
+ if (call.executionId !== input.executionId || call.placement.kind !== "client") {
6987
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: "Client outcome does not match the call" }));
6988
+ }
6989
+ if (call.externalOutcome !== undefined) {
6990
+ if (exports_shared_schema.canonicalString(call.externalOutcome) !== exports_shared_schema.canonicalString(input.outcome)) {
6991
+ return yield* Effect21.fail(new ToolOutcomeConflict({ id: input.callId }));
6992
+ }
6993
+ if (call.activeAttemptId === undefined) {
6994
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: "Accepted attempt is missing" }));
6995
+ }
6996
+ const attempt2 = yield* loadAttempt(tenantId2, input.callId, call.activeAttemptId);
6997
+ if (attempt2 === undefined) {
6998
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: "Accepted attempt is missing" }));
6999
+ }
7000
+ return { call, attempt: attempt2, duplicate: true };
7001
+ }
7002
+ if (call.state !== "waiting") {
7003
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: input.callId, message: `Call is ${call.state}` }));
7004
+ }
7005
+ const running = yield* insertAttempt(tenantId2, input.callId, input.submittedAt);
7006
+ 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);
7007
+ yield* sql3`
7008
+ UPDATE relay_tool_calls
7009
+ SET state = 'submitted', active_attempt_id = ${attempt.id},
7010
+ external_outcome_json = ${encodeJson(input.outcome)},
7011
+ external_outcome_at = ${ts(input.submittedAt)}, updated_at = ${ts(input.submittedAt)}
7012
+ WHERE tenant_id = ${tenantId2} AND id = ${input.callId}
7013
+ `.pipe(Effect21.mapError(toRepositoryError17));
7014
+ const updated = yield* readLockedCall(tenantId2, input.callId);
7015
+ return { call: updated, attempt, duplicate: false };
7016
+ }));
7017
+ });
7018
+ const claimCandidate = (tenantId2, input) => sql3`
7019
+ SELECT id
7020
+ FROM relay_tool_calls
7021
+ WHERE tenant_id = ${tenantId2} AND placement_kind = 'remote' AND placement_key = ${input.queue}
7022
+ AND state = 'waiting' AND available_at <= ${ts(input.now)}
7023
+ ORDER BY available_at ASC, created_at ASC, id ASC
7024
+ LIMIT 1
7025
+ `;
7026
+ const selectClaimCandidate = sql3.onDialectOrElse({
7027
+ pg: () => (tenantId2, input) => sql3`
7028
+ ${claimCandidate(tenantId2, input)}
7029
+ FOR UPDATE SKIP LOCKED
7030
+ `,
7031
+ mysql: () => (tenantId2, input) => sql3`
7032
+ ${claimCandidate(tenantId2, input)}
7033
+ FOR UPDATE SKIP LOCKED
7034
+ `,
7035
+ orElse: () => claimCandidate
7036
+ });
7037
+ const claimCall = sql3.onDialectOrElse({
7038
+ mysql: () => (tenantId2, callId, attemptId, input) => sql3`
7039
+ UPDATE relay_tool_calls
7040
+ SET state = 'running', active_attempt_id = ${attemptId}, claim_owner = ${input.workerId},
7041
+ claimed_at = ${ts(input.now)}, claim_expires_at = ${ts(input.claimExpiresAt)},
7042
+ updated_at = ${ts(input.now)}
7043
+ WHERE tenant_id = ${tenantId2} AND id = ${callId} AND state = 'waiting'
7044
+ AND available_at <= ${ts(input.now)}
7045
+ `.pipe(Effect21.as([{ id: callId }])),
7046
+ orElse: () => (tenantId2, callId, attemptId, input) => sql3`
7047
+ UPDATE relay_tool_calls
7048
+ SET state = 'running', active_attempt_id = ${attemptId}, claim_owner = ${input.workerId},
7049
+ claimed_at = ${ts(input.now)}, claim_expires_at = ${ts(input.claimExpiresAt)},
7050
+ updated_at = ${ts(input.now)}
7051
+ WHERE tenant_id = ${tenantId2} AND id = ${callId} AND state = 'waiting'
7052
+ AND available_at <= ${ts(input.now)}
7053
+ RETURNING id
7054
+ `
7055
+ });
7056
+ const claimRemote = Effect21.fn("ToolCallRepository.claimRemote")(function* (input) {
7057
+ if (input.claimExpiresAt <= input.now) {
7058
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Claim expiry must be after now" }));
7059
+ }
7060
+ const tenantId2 = yield* current();
7061
+ return yield* repositoryTransaction(Effect21.gen(function* () {
7062
+ const expired = yield* sql3`
7063
+ SELECT id, active_attempt_id
7064
+ FROM relay_tool_calls
7065
+ WHERE tenant_id = ${tenantId2} AND placement_kind = 'remote' AND placement_key = ${input.queue}
7066
+ AND state = 'running' AND claim_expires_at IS NOT NULL AND claim_expires_at <= ${ts(input.now)}
7067
+ `.pipe(Effect21.mapError(toRepositoryError17));
7068
+ for (const row of expired) {
7069
+ if (row.active_attempt_id !== null && row.active_attempt_id !== undefined) {
7070
+ yield* completeAttempt(tenantId2, exports_ids_schema.ToolCallId.make(row.id), exports_ids_schema.ToolAttemptId.make(row.active_attempt_id), "expired", input.now);
7071
+ }
7072
+ yield* sql3`
7073
+ UPDATE relay_tool_calls
7074
+ SET state = 'waiting', active_attempt_id = NULL, claim_owner = NULL, claimed_at = NULL,
7075
+ claim_expires_at = NULL, updated_at = ${ts(input.now)}
7076
+ WHERE tenant_id = ${tenantId2} AND id = ${row.id} AND state = 'running'
7077
+ `.pipe(Effect21.mapError(toRepositoryError17));
7078
+ }
7079
+ const candidates = yield* selectClaimCandidate(tenantId2, input).pipe(Effect21.mapError(toRepositoryError17));
7080
+ const candidate = candidates[0];
7081
+ if (candidate?.id === undefined)
7082
+ return;
7083
+ const callId = exports_ids_schema.ToolCallId.make(candidate.id);
7084
+ const call = yield* readLockedCall(tenantId2, callId);
7085
+ if (call.definition === undefined || call.placement.kind !== "remote") {
7086
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: callId, message: "Remote call definition snapshot is missing" }));
7087
+ }
7088
+ const attemptNumber = yield* nextAttemptNumber(tenantId2, callId);
7089
+ const attemptId = toolAttemptId(attemptNumber);
7090
+ const claimed = yield* claimCall(tenantId2, callId, attemptId, input).pipe(Effect21.mapError(toRepositoryError17));
7091
+ if (claimed[0] === undefined)
7092
+ return;
7093
+ const attempt = yield* insertAttemptNumber(tenantId2, callId, attemptNumber, input.now, input.workerId, input.claimExpiresAt);
7094
+ const updated = yield* readLockedCall(tenantId2, callId);
7095
+ if (updated.definition === undefined || updated.placement.kind !== "remote") {
7096
+ return yield* Effect21.fail(new ToolCallTransitionRejected({ id: callId, message: "Remote call definition snapshot is missing" }));
7097
+ }
7098
+ return {
7099
+ call: { ...updated, definition: updated.definition },
7100
+ attempt,
7101
+ queue: updated.placement.queue,
7102
+ workerId: input.workerId,
7103
+ claimExpiresAt: input.claimExpiresAt,
7104
+ idempotencyKey: updated.idempotencyKey
7105
+ };
7106
+ }));
7107
+ });
7108
+ const releaseRemote = Effect21.fn("ToolCallRepository.releaseRemote")(function* (input) {
7109
+ const tenantId2 = yield* current();
7110
+ return yield* repositoryTransaction(Effect21.gen(function* () {
7111
+ const call = yield* readLockedCall(tenantId2, input.callId);
7112
+ if (call.placement.kind !== "remote" || call.state !== "running" || call.activeAttemptId !== input.attemptId || call.claimOwner !== input.workerId || call.claimExpiresAt === undefined || call.claimExpiresAt <= input.releasedAt) {
7113
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote claim is not active" }));
7114
+ }
7115
+ yield* completeAttempt(tenantId2, input.callId, input.attemptId, "released", input.releasedAt, input.error);
7116
+ yield* sql3`
7117
+ UPDATE relay_tool_calls
7118
+ SET state = 'waiting', available_at = ${ts(input.nextAvailableAt)}, active_attempt_id = NULL,
7119
+ claim_owner = NULL, claimed_at = NULL, claim_expires_at = NULL,
7120
+ updated_at = ${ts(input.releasedAt)}
7121
+ WHERE tenant_id = ${tenantId2} AND id = ${input.callId}
7122
+ `.pipe(Effect21.mapError(toRepositoryError17));
7123
+ return yield* readLockedCall(tenantId2, input.callId);
7124
+ }));
7125
+ });
7126
+ const acceptRemoteOutcome = Effect21.fn("ToolCallRepository.acceptRemoteOutcome")(function* (input) {
7127
+ const tenantId2 = yield* current();
7128
+ return yield* repositoryTransaction(Effect21.gen(function* () {
7129
+ const call = yield* readLockedCall(tenantId2, input.callId);
7130
+ if (call.externalOutcome !== undefined) {
7131
+ if (exports_shared_schema.canonicalString(call.externalOutcome) !== exports_shared_schema.canonicalString(input.outcome)) {
7132
+ return yield* Effect21.fail(new ToolOutcomeConflict({ id: input.callId }));
7133
+ }
7134
+ if (call.activeAttemptId !== input.attemptId) {
7135
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote attempt was not accepted" }));
7136
+ }
7137
+ const attempt2 = yield* loadAttempt(tenantId2, input.callId, input.attemptId);
7138
+ if (attempt2 === undefined || attempt2.callId !== input.callId || attempt2.workerId !== input.workerId) {
7139
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote attempt was not accepted" }));
7140
+ }
7141
+ return { call, attempt: attempt2, duplicate: true };
7142
+ }
7143
+ if (call.placement.kind !== "remote" || call.state !== "running" || call.activeAttemptId !== input.attemptId || call.claimOwner !== input.workerId || call.claimExpiresAt === undefined || call.claimExpiresAt <= input.submittedAt) {
7144
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote claim is not active" }));
7145
+ }
7146
+ 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);
7147
+ yield* sql3`
7148
+ UPDATE relay_tool_calls
7149
+ SET state = 'submitted', external_outcome_json = ${encodeJson(input.outcome)},
7150
+ external_outcome_at = ${ts(input.submittedAt)}, claim_owner = NULL, claimed_at = NULL,
7151
+ claim_expires_at = NULL, updated_at = ${ts(input.submittedAt)}
7152
+ WHERE tenant_id = ${tenantId2} AND id = ${input.callId}
7153
+ `.pipe(Effect21.mapError(toRepositoryError17));
7154
+ const updated = yield* readLockedCall(tenantId2, input.callId);
7155
+ return { call: updated, attempt, duplicate: false };
7156
+ }));
7157
+ });
7158
+ const listAttempts = Effect21.fn("ToolCallRepository.listAttempts")(function* (callId) {
7159
+ const tenantId2 = yield* current();
7160
+ return yield* readAttempts(tenantId2, callId);
7161
+ });
7162
+ const selectOpenCalls = sql3.onDialectOrElse({
7163
+ pg: () => (tenantId2, input) => sql3`
7164
+ SELECT ${callColumns}
7165
+ FROM relay_tool_calls
7166
+ WHERE tenant_id = ${tenantId2} AND execution_id = ${input.executionId}
7167
+ AND state NOT IN ('submitted', 'completed', 'failed')
7168
+ ORDER BY created_at ASC, id ASC
7169
+ FOR UPDATE
7170
+ `,
7171
+ mysql: () => (tenantId2, input) => sql3`
7172
+ SELECT ${callColumns}
7173
+ FROM relay_tool_calls
7174
+ WHERE tenant_id = ${tenantId2} AND execution_id = ${input.executionId}
7175
+ AND state NOT IN ('submitted', 'completed', 'failed')
7176
+ ORDER BY created_at ASC, id ASC
7177
+ FOR UPDATE
7178
+ `,
6481
7179
  orElse: () => (tenantId2, input) => sql3`
6482
- ${insertResultStatement(tenantId2, input)}
6483
- RETURNING ${resultColumns}
7180
+ SELECT ${callColumns}
7181
+ FROM relay_tool_calls
7182
+ WHERE tenant_id = ${tenantId2} AND execution_id = ${input.executionId}
7183
+ AND state NOT IN ('submitted', 'completed', 'failed')
7184
+ ORDER BY created_at ASC, id ASC
6484
7185
  `
6485
7186
  });
7187
+ const failCall = sql3.onDialectOrElse({
7188
+ mysql: () => (tenantId2, callId, failedAt) => sql3`
7189
+ UPDATE relay_tool_calls
7190
+ SET state = 'failed', claim_owner = NULL, claimed_at = NULL, claim_expires_at = NULL,
7191
+ updated_at = ${ts(failedAt)}
7192
+ WHERE tenant_id = ${tenantId2} AND id = ${callId} AND state NOT IN ('submitted', 'completed', 'failed')
7193
+ `.pipe(Effect21.as([{ id: callId }])),
7194
+ orElse: () => (tenantId2, callId, failedAt) => sql3`
7195
+ UPDATE relay_tool_calls
7196
+ SET state = 'failed', claim_owner = NULL, claimed_at = NULL, claim_expires_at = NULL,
7197
+ updated_at = ${ts(failedAt)}
7198
+ WHERE tenant_id = ${tenantId2} AND id = ${callId} AND state NOT IN ('submitted', 'completed', 'failed')
7199
+ RETURNING id
7200
+ `
7201
+ });
7202
+ const failOpenForExecution = Effect21.fn("ToolCallRepository.failOpenForExecution")(function* (input) {
7203
+ const tenantId2 = yield* current();
7204
+ return yield* repositoryTransaction(Effect21.gen(function* () {
7205
+ const rows = yield* selectOpenCalls(tenantId2, input).pipe(Effect21.mapError(toRepositoryError17));
7206
+ const open = yield* Effect21.forEach(rows, decodeCall);
7207
+ const selected = input.callIds === undefined ? undefined : new Set(input.callIds);
7208
+ const failed = [];
7209
+ for (const call of open) {
7210
+ if (selected !== undefined && !selected.has(call.call.id))
7211
+ continue;
7212
+ const transitioned = yield* failCall(tenantId2, call.call.id, input.failedAt).pipe(Effect21.mapError(toRepositoryError17));
7213
+ if (transitioned[0] === undefined)
7214
+ continue;
7215
+ if (call.activeAttemptId !== undefined) {
7216
+ const attempt = yield* loadAttempt(tenantId2, call.call.id, call.activeAttemptId);
7217
+ if (attempt?.state === "running") {
7218
+ yield* completeAttempt(tenantId2, call.call.id, call.activeAttemptId, "failed", input.failedAt, input.message);
7219
+ }
7220
+ }
7221
+ const existingResult = yield* selectResultByKey(tenantId2, call.call.id).pipe(Effect21.mapError(toRepositoryError17));
7222
+ if (existingResult[0] === undefined) {
7223
+ yield* insertResultStatement(tenantId2, {
7224
+ result: { call_id: call.call.id, output: null, error: input.message },
7225
+ createdAt: input.failedAt
7226
+ }).pipe(Effect21.mapError(toRepositoryError17));
7227
+ }
7228
+ failed.push(yield* readLockedCall(tenantId2, call.call.id));
7229
+ }
7230
+ return failed;
7231
+ }));
7232
+ });
6486
7233
  const recordCall = Effect21.fn("ToolCallRepository.recordCall")(function* (input) {
6487
7234
  const tenantId2 = yield* current();
6488
7235
  const existing = yield* selectCallByKey(tenantId2, input.call.id).pipe(Effect21.mapError(toRepositoryError17));
@@ -6493,12 +7240,12 @@ var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6493
7240
  if (row === undefined) {
6494
7241
  return yield* Effect21.fail(new ToolCallRepositoryError({ message: "Tool call insert returned no row" }));
6495
7242
  }
6496
- return toCallRecord(yield* decodeCallRow(row));
7243
+ return yield* decodeCall(row);
6497
7244
  });
6498
7245
  const getCall = Effect21.fn("ToolCallRepository.getCall")(function* (id2) {
6499
7246
  const tenantId2 = yield* current();
6500
7247
  const rows = yield* selectCallByKey(tenantId2, id2).pipe(Effect21.mapError(toRepositoryError17));
6501
- return rows[0] === undefined ? undefined : toCallRecord(yield* decodeCallRow(rows[0]));
7248
+ return rows[0] === undefined ? undefined : yield* decodeCall(rows[0]);
6502
7249
  });
6503
7250
  const listCalls = Effect21.fn("ToolCallRepository.listCalls")(function* (executionId) {
6504
7251
  const tenantId2 = yield* current();
@@ -6506,71 +7253,428 @@ var layer20 = Layer21.effect(Service21, Effect21.gen(function* () {
6506
7253
  SELECT ${callColumns}
6507
7254
  FROM relay_tool_calls
6508
7255
  WHERE tenant_id = ${tenantId2} AND execution_id = ${executionId}
6509
- ORDER BY created_at ASC
7256
+ ORDER BY created_at ASC, id ASC
6510
7257
  `.pipe(Effect21.mapError(toRepositoryError17));
6511
- const decoded = yield* Effect21.forEach(rows, decodeCallRow);
6512
- return decoded.map(toCallRecord);
7258
+ return yield* Effect21.forEach(rows, decodeCall);
6513
7259
  });
6514
7260
  const recordResult = Effect21.fn("ToolCallRepository.recordResult")(function* (input) {
6515
7261
  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));
7262
+ return yield* repositoryTransaction(Effect21.gen(function* () {
7263
+ const call = yield* readLockedCall(tenantId2, input.result.call_id);
7264
+ const existing = yield* selectResultByKey(tenantId2, input.result.call_id).pipe(Effect21.mapError(toRepositoryError17));
7265
+ if (existing[0] !== undefined) {
7266
+ return yield* Effect21.fail(new DuplicateToolResult({ call_id: input.result.call_id }));
7267
+ }
7268
+ yield* insertResultStatement(tenantId2, input).pipe(Effect21.mapError(toRepositoryError17));
7269
+ if (call.activeAttemptId !== undefined) {
7270
+ const attempt = yield* loadAttempt(tenantId2, input.result.call_id, call.activeAttemptId);
7271
+ if (attempt?.state === "running") {
7272
+ yield* completeAttempt(tenantId2, input.result.call_id, call.activeAttemptId, input.result.error === undefined ? "completed" : "failed", input.createdAt, input.result.error);
7273
+ }
7274
+ }
7275
+ yield* sql3`
7276
+ UPDATE relay_tool_calls
7277
+ SET state = ${input.result.error === undefined ? "completed" : "failed"},
7278
+ claim_owner = NULL, claimed_at = NULL, claim_expires_at = NULL,
7279
+ updated_at = ${ts(input.createdAt)}
7280
+ WHERE tenant_id = ${tenantId2} AND id = ${input.result.call_id}
7281
+ `.pipe(Effect21.mapError(toRepositoryError17));
7282
+ const rows = yield* selectResultByKey(tenantId2, input.result.call_id).pipe(Effect21.mapError(toRepositoryError17));
7283
+ if (rows[0] === undefined) {
7284
+ return yield* Effect21.fail(new ToolCallRepositoryError({ message: "Tool result insert returned no row" }));
7285
+ }
7286
+ return toResultRecord(yield* decodeResultRow(rows[0]));
7287
+ }));
6529
7288
  });
6530
7289
  const getResult = Effect21.fn("ToolCallRepository.getResult")(function* (callId) {
6531
7290
  const tenantId2 = yield* current();
6532
7291
  const rows = yield* selectResultByKey(tenantId2, callId).pipe(Effect21.mapError(toRepositoryError17));
6533
7292
  return rows[0] === undefined ? undefined : toResultRecord(yield* decodeResultRow(rows[0]));
6534
7293
  });
6535
- return Service21.of({ recordCall, getCall, listCalls, recordResult, getResult });
7294
+ return Service21.of({
7295
+ ensureCall,
7296
+ recordCall,
7297
+ getCall,
7298
+ listCalls,
7299
+ recordResult,
7300
+ getResult,
7301
+ prepareExternalWait,
7302
+ beginAttempt,
7303
+ acceptClientOutcome,
7304
+ claimRemote,
7305
+ releaseRemote,
7306
+ acceptRemoteOutcome,
7307
+ listAttempts,
7308
+ failOpenForExecution
7309
+ });
6536
7310
  }));
6537
7311
  var memoryLayer18 = Layer21.sync(Service21, () => {
6538
7312
  const calls = new Map;
7313
+ const callTenants = new Map;
6539
7314
  const results = new Map;
7315
+ const attempts = new Map;
7316
+ const key2 = (tenantId2, callId) => exports_shared_schema.canonicalString([tenantId2, callId]);
7317
+ const same = (left, right) => exports_shared_schema.canonicalString(left) === exports_shared_schema.canonicalString(right);
7318
+ const callRecord = (tenantId2, input, definition, placement = { kind: "local" }) => ({
7319
+ executionId: input.executionId,
7320
+ call: normalizeCall(input.call),
7321
+ ...definition === undefined ? {} : { definition },
7322
+ placement,
7323
+ state: "requested",
7324
+ idempotencyKey: toolCallIdempotencyKey(tenantId2, input.executionId, input.call.id),
7325
+ availableAt: input.createdAt,
7326
+ createdAt: input.createdAt,
7327
+ updatedAt: input.createdAt
7328
+ });
7329
+ const attemptsFor = (tenantId2, callId) => attempts.get(key2(tenantId2, callId)) ?? [];
7330
+ const replaceAttempt = (tenantId2, attempt) => {
7331
+ const callAttempts = attemptsFor(tenantId2, attempt.callId);
7332
+ attempts.set(key2(tenantId2, attempt.callId), callAttempts.map((existing) => existing.id === attempt.id ? attempt : existing));
7333
+ };
7334
+ const appendAttempt = (tenantId2, callId, createdAt, options = {}) => {
7335
+ const callAttempts = attemptsFor(tenantId2, callId);
7336
+ const attemptNumber = callAttempts.length + 1;
7337
+ const attempt = {
7338
+ id: toolAttemptId(attemptNumber),
7339
+ callId,
7340
+ attemptNumber,
7341
+ state: "running",
7342
+ ...options.workerId === undefined ? {} : { workerId: options.workerId },
7343
+ ...options.claimExpiresAt === undefined ? {} : { claimExpiresAt: options.claimExpiresAt },
7344
+ createdAt
7345
+ };
7346
+ attempts.set(key2(tenantId2, callId), [...callAttempts, attempt]);
7347
+ return attempt;
7348
+ };
7349
+ const requireCall = (tenantId2, callId) => {
7350
+ const record2 = calls.get(key2(tenantId2, callId));
7351
+ return record2 === undefined ? Effect21.fail(new ToolCallNotFound({ id: callId })) : Effect21.succeed(record2);
7352
+ };
7353
+ const transitionRejected = (id2, message) => Effect21.fail(new ToolCallTransitionRejected({ id: id2, message }));
6540
7354
  return Service21.of({
7355
+ ensureCall: Effect21.fn("ToolCallRepository.memory.ensureCall")(function* (input) {
7356
+ const tenantId2 = yield* current();
7357
+ const storageKey = key2(tenantId2, input.call.id);
7358
+ const existing = calls.get(storageKey);
7359
+ if (existing !== undefined) {
7360
+ if (existing.executionId !== input.executionId || !sameCallIdentity(existing.call, input.call) || !same(existing.definition, input.definition) || !same(existing.placement, input.placement)) {
7361
+ return yield* Effect21.fail(new ToolCallConflict({ id: input.call.id }));
7362
+ }
7363
+ return existing;
7364
+ }
7365
+ const record2 = callRecord(tenantId2, input, input.definition, input.placement);
7366
+ calls.set(storageKey, record2);
7367
+ callTenants.set(storageKey, tenantId2);
7368
+ return record2;
7369
+ }),
6541
7370
  recordCall: Effect21.fn("ToolCallRepository.memory.recordCall")(function* (input) {
6542
- if (calls.has(input.call.id))
7371
+ const tenantId2 = yield* current();
7372
+ const storageKey = key2(tenantId2, input.call.id);
7373
+ if (calls.has(storageKey))
6543
7374
  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));
7375
+ const record2 = callRecord(tenantId2, input);
7376
+ calls.set(storageKey, record2);
7377
+ callTenants.set(storageKey, tenantId2);
7378
+ return record2;
7379
+ }),
7380
+ getCall: Effect21.fn("ToolCallRepository.memory.getCall")(function* (id2) {
7381
+ const tenantId2 = yield* current();
7382
+ return calls.get(key2(tenantId2, id2));
7383
+ }),
7384
+ listCalls: Effect21.fn("ToolCallRepository.memory.listCalls")(function* (executionId) {
7385
+ const tenantId2 = yield* current();
7386
+ 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));
7387
+ }),
7388
+ recordResult: Effect21.fn("ToolCallRepository.memory.recordResult")(function* (input) {
7389
+ const tenantId2 = yield* current();
7390
+ const storageKey = key2(tenantId2, input.result.call_id);
7391
+ const call = calls.get(storageKey);
7392
+ if (call === undefined)
7393
+ return yield* Effect21.fail(new ToolCallNotFound({ id: input.result.call_id }));
7394
+ if (results.has(storageKey)) {
7395
+ return yield* Effect21.fail(new DuplicateToolResult({ call_id: input.result.call_id }));
7396
+ }
7397
+ if (call.activeAttemptId !== undefined) {
7398
+ const active = attemptsFor(tenantId2, input.result.call_id).find((attempt) => attempt.id === call.activeAttemptId);
7399
+ if (active?.state === "running") {
7400
+ replaceAttempt(tenantId2, {
7401
+ ...active,
7402
+ state: input.result.error === undefined ? "completed" : "failed",
7403
+ ...input.result.error === undefined ? {} : { error: input.result.error },
7404
+ completedAt: input.createdAt
7405
+ });
7406
+ }
7407
+ }
7408
+ const record2 = { result: input.result, createdAt: input.createdAt };
7409
+ results.set(storageKey, record2);
7410
+ calls.set(storageKey, {
7411
+ ...call,
7412
+ state: input.result.error === undefined ? "completed" : "failed",
7413
+ updatedAt: input.createdAt
7414
+ });
6550
7415
  return record2;
6551
7416
  }),
6552
- getCall: Effect21.fn("ToolCallRepository.memory.getCall")(function* (id2) {
6553
- return yield* Effect21.sync(() => calls.get(id2));
7417
+ getResult: Effect21.fn("ToolCallRepository.memory.getResult")(function* (callId) {
7418
+ const tenantId2 = yield* current();
7419
+ return results.get(key2(tenantId2, callId));
7420
+ }),
7421
+ prepareExternalWait: Effect21.fn("ToolCallRepository.memory.prepareExternalWait")(function* (input) {
7422
+ const tenantId2 = yield* current();
7423
+ const call = yield* requireCall(tenantId2, input.callId);
7424
+ if (call.placement.kind !== "client" && call.placement.kind !== "remote") {
7425
+ return yield* transitionRejected(input.callId, "Tool placement is not external");
7426
+ }
7427
+ if (call.state === "waiting" && call.waitId === input.waitId)
7428
+ return call;
7429
+ if (call.state !== "requested")
7430
+ return yield* transitionRejected(input.callId, `Call is ${call.state}`);
7431
+ const updated = {
7432
+ ...call,
7433
+ state: "waiting",
7434
+ waitId: input.waitId,
7435
+ availableAt: input.availableAt,
7436
+ updatedAt: input.updatedAt
7437
+ };
7438
+ calls.set(key2(tenantId2, input.callId), updated);
7439
+ return updated;
7440
+ }),
7441
+ beginAttempt: Effect21.fn("ToolCallRepository.memory.beginAttempt")(function* (input) {
7442
+ const tenantId2 = yield* current();
7443
+ const call = yield* requireCall(tenantId2, input.callId);
7444
+ if (call.placement.kind !== "local" && call.placement.kind !== "mcp") {
7445
+ return yield* transitionRejected(input.callId, "Tool placement is not immediate");
7446
+ }
7447
+ if (call.state === "completed" || call.state === "failed") {
7448
+ return yield* transitionRejected(input.callId, `Call is ${call.state}`);
7449
+ }
7450
+ if (call.activeAttemptId !== undefined) {
7451
+ const active = attemptsFor(tenantId2, input.callId).find((attempt2) => attempt2.id === call.activeAttemptId);
7452
+ if (active?.state === "running") {
7453
+ replaceAttempt(tenantId2, { ...active, state: "abandoned", completedAt: input.startedAt });
7454
+ }
7455
+ }
7456
+ const attempt = appendAttempt(tenantId2, input.callId, input.startedAt);
7457
+ calls.set(key2(tenantId2, input.callId), {
7458
+ ...call,
7459
+ state: "running",
7460
+ activeAttemptId: attempt.id,
7461
+ updatedAt: input.startedAt
7462
+ });
7463
+ return attempt;
7464
+ }),
7465
+ acceptClientOutcome: Effect21.fn("ToolCallRepository.memory.acceptClientOutcome")(function* (input) {
7466
+ const tenantId2 = yield* current();
7467
+ const call = yield* requireCall(tenantId2, input.callId);
7468
+ if (call.executionId !== input.executionId || call.placement.kind !== "client") {
7469
+ return yield* transitionRejected(input.callId, "Client outcome does not match the call");
7470
+ }
7471
+ if (call.externalOutcome !== undefined) {
7472
+ if (!same(call.externalOutcome, input.outcome)) {
7473
+ return yield* Effect21.fail(new ToolOutcomeConflict({ id: input.callId }));
7474
+ }
7475
+ const attempt2 = attemptsFor(tenantId2, input.callId).find((item) => item.id === call.activeAttemptId);
7476
+ if (attempt2 === undefined)
7477
+ return yield* transitionRejected(input.callId, "Accepted attempt is missing");
7478
+ return { call, attempt: attempt2, duplicate: true };
7479
+ }
7480
+ if (call.state !== "waiting")
7481
+ return yield* transitionRejected(input.callId, `Call is ${call.state}`);
7482
+ const running = appendAttempt(tenantId2, input.callId, input.submittedAt);
7483
+ const attempt = {
7484
+ ...running,
7485
+ state: input.outcome.kind === "success" ? "completed" : "failed",
7486
+ ...input.outcome.kind === "failure" ? { error: input.outcome.message } : {},
7487
+ completedAt: input.submittedAt
7488
+ };
7489
+ replaceAttempt(tenantId2, attempt);
7490
+ const updated = {
7491
+ ...call,
7492
+ state: "submitted",
7493
+ activeAttemptId: attempt.id,
7494
+ externalOutcome: input.outcome,
7495
+ externalOutcomeAt: input.submittedAt,
7496
+ updatedAt: input.submittedAt
7497
+ };
7498
+ calls.set(key2(tenantId2, input.callId), updated);
7499
+ return { call: updated, attempt, duplicate: false };
7500
+ }),
7501
+ claimRemote: Effect21.fn("ToolCallRepository.memory.claimRemote")(function* (input) {
7502
+ const tenantId2 = yield* current();
7503
+ if (input.claimExpiresAt <= input.now) {
7504
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Claim expiry must be after now" }));
7505
+ }
7506
+ for (const [storageKey, call] of calls) {
7507
+ if (callTenants.get(storageKey) !== tenantId2 || call.placement.kind !== "remote" || call.state !== "running" || call.claimExpiresAt === undefined || call.claimExpiresAt > input.now) {
7508
+ continue;
7509
+ }
7510
+ const active = attemptsFor(tenantId2, call.call.id).find((attempt2) => attempt2.id === call.activeAttemptId);
7511
+ if (active?.state === "running") {
7512
+ replaceAttempt(tenantId2, { ...active, state: "expired", completedAt: input.now });
7513
+ }
7514
+ calls.set(storageKey, {
7515
+ ...call,
7516
+ state: "waiting",
7517
+ activeAttemptId: undefined,
7518
+ claimOwner: undefined,
7519
+ claimedAt: undefined,
7520
+ claimExpiresAt: undefined,
7521
+ updatedAt: input.now
7522
+ });
7523
+ }
7524
+ 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];
7525
+ if (candidate === undefined)
7526
+ return;
7527
+ if (candidate.definition === undefined) {
7528
+ return yield* transitionRejected(candidate.call.id, "Remote call definition snapshot is missing");
7529
+ }
7530
+ const attempt = appendAttempt(tenantId2, candidate.call.id, input.now, {
7531
+ workerId: input.workerId,
7532
+ claimExpiresAt: input.claimExpiresAt
7533
+ });
7534
+ const updated = {
7535
+ ...candidate,
7536
+ definition: candidate.definition,
7537
+ state: "running",
7538
+ activeAttemptId: attempt.id,
7539
+ claimOwner: input.workerId,
7540
+ claimedAt: input.now,
7541
+ claimExpiresAt: input.claimExpiresAt,
7542
+ updatedAt: input.now
7543
+ };
7544
+ calls.set(key2(tenantId2, candidate.call.id), updated);
7545
+ return {
7546
+ call: updated,
7547
+ attempt,
7548
+ queue: input.queue,
7549
+ workerId: input.workerId,
7550
+ claimExpiresAt: input.claimExpiresAt,
7551
+ idempotencyKey: updated.idempotencyKey
7552
+ };
7553
+ }),
7554
+ releaseRemote: Effect21.fn("ToolCallRepository.memory.releaseRemote")(function* (input) {
7555
+ const tenantId2 = yield* current();
7556
+ const call = yield* requireCall(tenantId2, input.callId);
7557
+ const valid = call.placement.kind === "remote" && call.state === "running" && call.activeAttemptId === input.attemptId && call.claimOwner === input.workerId && call.claimExpiresAt !== undefined && call.claimExpiresAt > input.releasedAt;
7558
+ if (!valid)
7559
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote claim is not active" }));
7560
+ const attempt = attemptsFor(tenantId2, input.callId).find((item) => item.id === input.attemptId);
7561
+ if (attempt === undefined)
7562
+ return yield* transitionRejected(input.callId, "Remote attempt is missing");
7563
+ replaceAttempt(tenantId2, {
7564
+ ...attempt,
7565
+ state: "released",
7566
+ ...input.error === undefined ? {} : { error: input.error },
7567
+ completedAt: input.releasedAt
7568
+ });
7569
+ const updated = {
7570
+ ...call,
7571
+ state: "waiting",
7572
+ availableAt: input.nextAvailableAt,
7573
+ activeAttemptId: undefined,
7574
+ claimOwner: undefined,
7575
+ claimedAt: undefined,
7576
+ claimExpiresAt: undefined,
7577
+ updatedAt: input.releasedAt
7578
+ };
7579
+ calls.set(key2(tenantId2, input.callId), updated);
7580
+ return updated;
7581
+ }),
7582
+ acceptRemoteOutcome: Effect21.fn("ToolCallRepository.memory.acceptRemoteOutcome")(function* (input) {
7583
+ const tenantId2 = yield* current();
7584
+ const call = yield* requireCall(tenantId2, input.callId);
7585
+ if (call.externalOutcome !== undefined) {
7586
+ if (!same(call.externalOutcome, input.outcome)) {
7587
+ return yield* Effect21.fail(new ToolOutcomeConflict({ id: input.callId }));
7588
+ }
7589
+ if (call.activeAttemptId !== input.attemptId) {
7590
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote attempt was not accepted" }));
7591
+ }
7592
+ const attempt2 = attemptsFor(tenantId2, input.callId).find((item) => item.id === input.attemptId);
7593
+ if (attempt2 === undefined || attempt2.callId !== input.callId || attempt2.workerId !== input.workerId) {
7594
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote attempt was not accepted" }));
7595
+ }
7596
+ return { call, attempt: attempt2, duplicate: true };
7597
+ }
7598
+ const valid = call.placement.kind === "remote" && call.state === "running" && call.activeAttemptId === input.attemptId && call.claimOwner === input.workerId && call.claimExpiresAt !== undefined && call.claimExpiresAt > input.submittedAt;
7599
+ if (!valid)
7600
+ return yield* Effect21.fail(new ToolClaimRejected({ message: "Remote claim is not active" }));
7601
+ const running = attemptsFor(tenantId2, input.callId).find((item) => item.id === input.attemptId);
7602
+ if (running === undefined)
7603
+ return yield* transitionRejected(input.callId, "Remote attempt is missing");
7604
+ const attempt = {
7605
+ ...running,
7606
+ state: input.outcome.kind === "success" ? "completed" : "failed",
7607
+ ...input.outcome.kind === "failure" ? { error: input.outcome.message } : {},
7608
+ completedAt: input.submittedAt
7609
+ };
7610
+ replaceAttempt(tenantId2, attempt);
7611
+ const updated = {
7612
+ ...call,
7613
+ state: "submitted",
7614
+ externalOutcome: input.outcome,
7615
+ externalOutcomeAt: input.submittedAt,
7616
+ claimOwner: undefined,
7617
+ claimedAt: undefined,
7618
+ claimExpiresAt: undefined,
7619
+ updatedAt: input.submittedAt
7620
+ };
7621
+ calls.set(key2(tenantId2, input.callId), updated);
7622
+ return { call: updated, attempt, duplicate: false };
6554
7623
  }),
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));
7624
+ listAttempts: Effect21.fn("ToolCallRepository.memory.listAttempts")(function* (callId) {
7625
+ const tenantId2 = yield* current();
7626
+ return attemptsFor(tenantId2, callId);
6557
7627
  }),
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 }));
7628
+ failOpenForExecution: Effect21.fn("ToolCallRepository.memory.failOpenForExecution")(function* (input) {
7629
+ const tenantId2 = yield* current();
7630
+ const failed = [];
7631
+ for (const [storageKey, call] of calls) {
7632
+ 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") {
7633
+ continue;
7634
+ }
7635
+ if (call.activeAttemptId !== undefined) {
7636
+ const active = attemptsFor(tenantId2, call.call.id).find((attempt) => attempt.id === call.activeAttemptId);
7637
+ if (active?.state === "running") {
7638
+ replaceAttempt(tenantId2, {
7639
+ ...active,
7640
+ state: "failed",
7641
+ error: input.message,
7642
+ completedAt: input.failedAt
7643
+ });
7644
+ }
7645
+ }
7646
+ const updated = {
7647
+ ...call,
7648
+ state: "failed",
7649
+ claimOwner: undefined,
7650
+ claimedAt: undefined,
7651
+ claimExpiresAt: undefined,
7652
+ updatedAt: input.failedAt
7653
+ };
7654
+ calls.set(storageKey, updated);
7655
+ results.set(storageKey, {
7656
+ result: { call_id: call.call.id, output: null, error: input.message },
7657
+ createdAt: input.failedAt
7658
+ });
7659
+ failed.push(updated);
6563
7660
  }
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));
7661
+ return failed.toSorted((left, right) => left.createdAt - right.createdAt || left.call.id.localeCompare(right.call.id));
6570
7662
  })
6571
7663
  });
6572
7664
  });
6573
- var testLayer18 = (implementation) => Layer21.succeed(Service21, Service21.of(implementation));
7665
+ var unsupportedTestOperation = (operation) => Effect21.fail(new ToolCallRepositoryError({ message: `ToolCallRepository.testLayer does not implement ${operation}` }));
7666
+ var testLayer18 = (implementation) => Layer21.succeed(Service21, Service21.of({
7667
+ ensureCall: () => unsupportedTestOperation("ensureCall"),
7668
+ prepareExternalWait: () => unsupportedTestOperation("prepareExternalWait"),
7669
+ beginAttempt: () => unsupportedTestOperation("beginAttempt"),
7670
+ acceptClientOutcome: () => unsupportedTestOperation("acceptClientOutcome"),
7671
+ claimRemote: () => unsupportedTestOperation("claimRemote"),
7672
+ releaseRemote: () => unsupportedTestOperation("releaseRemote"),
7673
+ acceptRemoteOutcome: () => unsupportedTestOperation("acceptRemoteOutcome"),
7674
+ listAttempts: () => unsupportedTestOperation("listAttempts"),
7675
+ failOpenForExecution: () => unsupportedTestOperation("failOpenForExecution"),
7676
+ ...implementation
7677
+ }));
6574
7678
  var recordCall = Effect21.fn("ToolCallRepository.recordCall.call")(function* (input) {
6575
7679
  const repository = yield* Service21;
6576
7680
  return yield* repository.recordCall(input);
@@ -6591,6 +7695,42 @@ var getResult = Effect21.fn("ToolCallRepository.getResult.call")(function* (call
6591
7695
  const repository = yield* Service21;
6592
7696
  return yield* repository.getResult(callId);
6593
7697
  });
7698
+ var ensureCall = Effect21.fn("ToolCallRepository.ensureCall.call")(function* (input) {
7699
+ const repository = yield* Service21;
7700
+ return yield* repository.ensureCall(input);
7701
+ });
7702
+ var prepareExternalWait = Effect21.fn("ToolCallRepository.prepareExternalWait.call")(function* (input) {
7703
+ const repository = yield* Service21;
7704
+ return yield* repository.prepareExternalWait(input);
7705
+ });
7706
+ var beginAttempt = Effect21.fn("ToolCallRepository.beginAttempt.call")(function* (input) {
7707
+ const repository = yield* Service21;
7708
+ return yield* repository.beginAttempt(input);
7709
+ });
7710
+ var acceptClientOutcome = Effect21.fn("ToolCallRepository.acceptClientOutcome.call")(function* (input) {
7711
+ const repository = yield* Service21;
7712
+ return yield* repository.acceptClientOutcome(input);
7713
+ });
7714
+ var claimRemote = Effect21.fn("ToolCallRepository.claimRemote.call")(function* (input) {
7715
+ const repository = yield* Service21;
7716
+ return yield* repository.claimRemote(input);
7717
+ });
7718
+ var releaseRemote = Effect21.fn("ToolCallRepository.releaseRemote.call")(function* (input) {
7719
+ const repository = yield* Service21;
7720
+ return yield* repository.releaseRemote(input);
7721
+ });
7722
+ var acceptRemoteOutcome = Effect21.fn("ToolCallRepository.acceptRemoteOutcome.call")(function* (input) {
7723
+ const repository = yield* Service21;
7724
+ return yield* repository.acceptRemoteOutcome(input);
7725
+ });
7726
+ var listAttempts = Effect21.fn("ToolCallRepository.listAttempts.call")(function* (callId) {
7727
+ const repository = yield* Service21;
7728
+ return yield* repository.listAttempts(callId);
7729
+ });
7730
+ var failOpenForExecution = Effect21.fn("ToolCallRepository.failOpenForExecution.call")(function* (input) {
7731
+ const repository = yield* Service21;
7732
+ return yield* repository.failOpenForExecution(input);
7733
+ });
6594
7734
  // ../store-sql/src/workspace/workspace-lease-repository.ts
6595
7735
  var exports_workspace_lease_repository = {};
6596
7736
  __export(exports_workspace_lease_repository, {
@@ -7285,6 +8425,7 @@ __export(exports_tool_runtime_service, {
7285
8425
  tool: () => tool,
7286
8426
  testLayer: () => testLayer23,
7287
8427
  run: () => run,
8428
+ remoteTool: () => remoteTool,
7288
8429
  registeredTools: () => registeredTools,
7289
8430
  register: () => register2,
7290
8431
  memoryLayerFromToolkit: () => memoryLayerFromToolkit,
@@ -7293,6 +8434,7 @@ __export(exports_tool_runtime_service, {
7293
8434
  layer: () => layer23,
7294
8435
  dynamicTool: () => dynamicTool,
7295
8436
  definitions: () => definitions,
8437
+ clientTool: () => clientTool,
7296
8438
  ToolRuntimeError: () => ToolRuntimeError,
7297
8439
  ToolPermissionDenied: () => ToolPermissionDenied,
7298
8440
  ToolNotRegistered: () => ToolNotRegistered,
@@ -7317,6 +8459,7 @@ __export(exports_event_log_service, {
7317
8459
  layerFromRepository: () => layerFromRepository2,
7318
8460
  findFirstByTypeAfterSequence: () => findFirstByTypeAfterSequence2,
7319
8461
  findBySequenceOrCursor: () => findBySequenceOrCursor2,
8462
+ findBySequence: () => findBySequence2,
7320
8463
  findByCursor: () => findByCursor2,
7321
8464
  appendIdempotentTo: () => appendIdempotentTo,
7322
8465
  appendIdempotent: () => appendIdempotent,
@@ -7472,6 +8615,7 @@ var layerFromRepository2 = Layer24.effect(Service24, Effect26.gen(function* () {
7472
8615
  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
8616
  findBySequenceOrCursor: Effect26.fn("EventLog.repository.findBySequenceOrCursor")((input) => repository.findBySequenceOrCursor(input).pipe(Effect26.mapError(mapRepositoryFindError))),
7474
8617
  findByCursor: Effect26.fn("EventLog.repository.findByCursor")((input) => repository.findByCursor(input).pipe(Effect26.mapError(mapRepositoryFindError))),
8618
+ findBySequence: Effect26.fn("EventLog.repository.findBySequence")((input) => repository.findBySequence(input).pipe(Effect26.mapError(mapRepositoryFindError))),
7475
8619
  findFirstByTypeAfterSequence: Effect26.fn("EventLog.repository.findFirstByTypeAfterSequence")((input) => repository.findFirstByTypeAfterSequence(input).pipe(Effect26.mapError(mapRepositoryFindError))),
7476
8620
  maxSequence: Effect26.fn("EventLog.repository.maxSequence")((executionId) => repository.maxSequence(executionId).pipe(Effect26.mapError(mapRepositoryFindError))),
7477
8621
  sumUsage: Effect26.fn("EventLog.repository.sumUsage")((executionId) => repository.sumUsage(executionId).pipe(Effect26.mapError(mapRepositoryFindError)))
@@ -7531,6 +8675,11 @@ var memoryLayer21 = Layer24.effect(Service24, Effect26.gen(function* () {
7531
8675
  const event = executionEvents.find((item) => item.cursor === input.cursor);
7532
8676
  return event === undefined ? Option4.none() : Option4.some(event);
7533
8677
  }),
8678
+ findBySequence: Effect26.fn("EventLog.memory.findBySequence")(function* (input) {
8679
+ const executionEvents = yield* allEvents(input.executionId);
8680
+ const event = executionEvents.find((item) => item.sequence === input.sequence);
8681
+ return event === undefined ? Option4.none() : Option4.some(event);
8682
+ }),
7534
8683
  findFirstByTypeAfterSequence: Effect26.fn("EventLog.memory.findFirstByTypeAfterSequence")(function* (input) {
7535
8684
  const executionEvents = yield* allEvents(input.executionId);
7536
8685
  const event = executionEvents.find((item) => item.type === input.type && item.sequence > input.afterSequence);
@@ -7575,6 +8724,10 @@ var findByCursor2 = Effect26.fn("EventLog.findByCursor.call")(function* (input)
7575
8724
  const service = yield* Service24;
7576
8725
  return yield* service.findByCursor(input);
7577
8726
  });
8727
+ var findBySequence2 = Effect26.fn("EventLog.findBySequence.call")(function* (input) {
8728
+ const service = yield* Service24;
8729
+ return yield* service.findBySequence(input);
8730
+ });
7578
8731
  var findFirstByTypeAfterSequence2 = Effect26.fn("EventLog.findFirstByTypeAfterSequence.call")(function* (input) {
7579
8732
  const service = yield* Service24;
7580
8733
  return yield* service.findFirstByTypeAfterSequence(input);
@@ -7890,6 +9043,11 @@ var requestedEvent = (input) => ({
7890
9043
  },
7891
9044
  created_at: input.createdAt
7892
9045
  });
9046
+ 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 ?? {});
9047
+ var ensureToolEvent = (eventLog, event) => eventLog.findByCursor({ executionId: event.execution_id, cursor: event.cursor }).pipe(Effect28.mapError(mapEventLogError2), Effect28.flatMap(Option6.match({
9048
+ onNone: () => appendIdempotentTo(eventLog, event).pipe(Effect28.mapError(mapEventLogError2), Effect28.asVoid),
9049
+ onSome: (existing) => sameToolEventPayload(existing, event) ? Effect28.void : Effect28.fail(new ToolRuntimeError({ message: "EventLogError" }))
9050
+ })));
7893
9051
  var resultEvent = (input, result) => ({
7894
9052
  id: exports_ids_schema.EventId.make(`event:${input.call.id}:tool-result`),
7895
9053
  execution_id: input.executionId,
@@ -7941,13 +9099,17 @@ var runHandledToolkitTool = (toolkit, name, input) => toolkit.handle(name, input
7941
9099
  onNone: () => Effect28.fail("Tool handler did not produce a final result"),
7942
9100
  onSome: (result) => result.isFailure ? Effect28.fail(result.result) : Effect28.succeed(jsonValue(result.encodedResult))
7943
9101
  })));
7944
- var finalToolResult = (tool, input) => Effect28.gen(function* () {
9102
+ var finalToolResult = (tool, input, idempotencyKey) => Effect28.gen(function* () {
9103
+ if (tool.run === undefined) {
9104
+ return yield* Effect28.fail(new ToolRuntimeError({ message: `Tool ${tool.definition.name} has no local handler` }));
9105
+ }
7945
9106
  const context = {
7946
9107
  executionId: input.executionId,
7947
9108
  call: input.call,
7948
9109
  permissions: input.permissions,
7949
9110
  eventSequence: input.eventSequence,
7950
- createdAt: input.createdAt
9111
+ createdAt: input.createdAt,
9112
+ idempotencyKey
7951
9113
  };
7952
9114
  const callInfo = ToolCallInfo.of(context);
7953
9115
  const output = yield* tool.run(input.call.input, context).pipe(Effect28.provideService(ToolCallInfo, callInfo), Effect28.mapError((error) => preserveToolError(input.call.name, error)));
@@ -8021,11 +9183,17 @@ var resolveApproval = (waits, eventLog, input) => Effect28.gen(function* () {
8021
9183
  return { _tag: "approved" };
8022
9184
  return { _tag: "denied", reason: deniedReason(existing.state) };
8023
9185
  });
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
- }));
9186
+ var recordRequested = (repository, eventLog, input, tool) => repository.ensureCall({
9187
+ executionId: input.executionId,
9188
+ call: input.call,
9189
+ definition: tool.definition,
9190
+ placement: tool.placement ?? { kind: "local" },
9191
+ createdAt: input.createdAt
9192
+ }).pipe(Effect28.mapError(mapRepositoryError4), Effect28.tap((call) => ensureToolEvent(eventLog, requestedEvent({ ...input, createdAt: call.createdAt }))));
9193
+ var repairResultEvent = (eventLog, input, record2) => {
9194
+ const event = resultEvent({ ...input, createdAt: record2.createdAt - 1 }, record2.result);
9195
+ return ensureToolEvent(eventLog, event);
9196
+ };
8029
9197
  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
9198
  var nonEmptyName = (name) => Schema35.decodeUnknownSync(exports_shared_schema.NonEmptyString)(name);
8031
9199
  var needsApprovalFromEffectTool = (tool) => tool.needsApproval === undefined ? undefined : typeof tool.needsApproval === "boolean" ? tool.needsApproval : true;
@@ -8046,6 +9214,7 @@ var registeredToolFromToolkit = (toolkit, modelTool, options = {}) => {
8046
9214
  return {
8047
9215
  definition: definitionFromEffectTool(modelTool, { ...toolOptions, needsApproval }),
8048
9216
  tool: modelTool,
9217
+ ...toolOptions.placement === undefined ? {} : { placement: toolOptions.placement },
8049
9218
  ...toolOptions.requiredPermissions === undefined ? {} : { requiredPermissions: toolOptions.requiredPermissions },
8050
9219
  validateInput: (input) => Schema35.decodeUnknownEffect(parametersSchemaFromEffectTool(modelTool))(input).pipe(Effect28.mapError((error) => new ToolInputInvalid({ tool_name: modelTool.name, message: error.message })), Effect28.asVoid),
8051
9220
  run: (input) => runHandledToolkitTool(toolkit, modelTool.name, input)
@@ -8064,6 +9233,7 @@ var tool = (name, options) => {
8064
9233
  return {
8065
9234
  definition,
8066
9235
  tool: effectTool,
9236
+ ...options.placement === undefined ? {} : { placement: options.placement },
8067
9237
  ...options.requiredPermissions === undefined ? {} : { requiredPermissions: options.requiredPermissions },
8068
9238
  validateInput: (input) => Schema35.decodeUnknownEffect(options.input)(input).pipe(Effect28.mapError((error) => new ToolInputInvalid({ tool_name: name, message: error.message })), Effect28.asVoid),
8069
9239
  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 +9259,78 @@ var dynamicTool = (name, options) => {
8089
9259
  ...options.metadata === undefined ? {} : { metadata: options.metadata }
8090
9260
  },
8091
9261
  tool: modelTool,
9262
+ ...options.placement === undefined ? {} : { placement: options.placement },
8092
9263
  ...options.requiredPermissions === undefined ? {} : { requiredPermissions: options.requiredPermissions },
8093
9264
  run: options.run
8094
9265
  };
8095
9266
  };
9267
+ var placedTool = (modelTool, placement, options = {}) => ({
9268
+ definition: definitionFromEffectTool(modelTool, options),
9269
+ tool: modelTool,
9270
+ placement,
9271
+ ...options.requiredPermissions === undefined ? {} : { requiredPermissions: options.requiredPermissions },
9272
+ validateInput: (input) => Schema35.decodeUnknownEffect(parametersSchemaFromEffectTool(modelTool))(input).pipe(Effect28.mapError((error) => new ToolInputInvalid({ tool_name: modelTool.name, message: error.message })), Effect28.asVoid)
9273
+ });
9274
+ var clientTool = (modelTool, options = {}) => placedTool(modelTool, { kind: "client" }, options);
9275
+ var remoteTool = (modelTool, options) => placedTool(modelTool, { kind: "remote", queue: options.queue }, options);
9276
+ var placementWaitId = (input) => exports_ids_schema.WaitId.make(`wait:tool:${input.call.id}`);
9277
+ var placementFailureResult = (input, message) => ({
9278
+ call_id: input.call.id,
9279
+ output: null,
9280
+ error: message
9281
+ });
9282
+ var externalOutcomeResult = (call, input) => {
9283
+ if (call.definition === undefined) {
9284
+ return Effect28.fail(new ToolRuntimeError({ message: "Tool call definition snapshot is missing" }));
9285
+ }
9286
+ if (call.externalOutcome === undefined) {
9287
+ return Effect28.fail(new ToolRuntimeError({ message: "Resolved tool wait has no mirrored external outcome" }));
9288
+ }
9289
+ if (call.externalOutcome.kind === "failure") {
9290
+ return Effect28.succeed(placementFailureResult(input, call.externalOutcome.message));
9291
+ }
9292
+ const placement = call.placement.kind;
9293
+ 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}`))));
9294
+ };
9295
+ var runExternalTool = (repository, waits, call, input) => Effect28.gen(function* () {
9296
+ const waitId = placementWaitId(input);
9297
+ let wait = yield* waits.get(waitId).pipe(Effect28.mapError(mapWaitServiceError));
9298
+ if (wait === undefined) {
9299
+ wait = yield* waits.createDetached({
9300
+ waitId,
9301
+ executionId: input.executionId,
9302
+ mode: "event",
9303
+ correlationKey: input.call.id,
9304
+ metadata: {
9305
+ kind: "tool-placement",
9306
+ tool_call_id: input.call.id,
9307
+ tool_name: input.call.name,
9308
+ placement: call.placement
9309
+ },
9310
+ eventSequence: input.eventSequence + 1,
9311
+ createdAt: input.createdAt
9312
+ }).pipe(Effect28.mapError(mapWaitServiceError));
9313
+ }
9314
+ const waitingCall = call.state === "requested" ? yield* repository.prepareExternalWait({
9315
+ callId: input.call.id,
9316
+ waitId,
9317
+ availableAt: input.createdAt,
9318
+ updatedAt: input.createdAt
9319
+ }).pipe(Effect28.mapError(mapRepositoryError4)) : call;
9320
+ if (wait.state === "open")
9321
+ return yield* waitRequested(input, waitId);
9322
+ if (wait.state === "timed_out")
9323
+ return placementFailureResult(input, "Tool execution timed out");
9324
+ if (wait.state === "cancelled")
9325
+ return placementFailureResult(input, "Tool execution cancelled");
9326
+ 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({
9327
+ executionId: input.executionId,
9328
+ callId: input.call.id,
9329
+ outcome,
9330
+ submittedAt: wait.resolvedAt ?? input.createdAt
9331
+ }).pipe(Effect28.mapError(mapRepositoryError4), Effect28.map((accepted2) => accepted2.call)))) : waitingCall;
9332
+ return yield* externalOutcomeResult(repairedCall, input);
9333
+ });
8096
9334
  var makeService = (initialTools) => Effect28.gen(function* () {
8097
9335
  const repository = yield* exports_tool_call_repository.Service;
8098
9336
  const eventLog = yield* Service24;
@@ -8109,13 +9347,15 @@ var makeService = (initialTools) => Effect28.gen(function* () {
8109
9347
  if (registeredTool === undefined) {
8110
9348
  return yield* Effect28.fail(new ToolNotRegistered({ tool_name: input.call.name }));
8111
9349
  }
8112
- const existingResult = yield* repository.getResult(input.call.id).pipe(Effect28.mapError(mapRepositoryError4));
8113
- if (existingResult !== undefined)
8114
- return existingResult.result;
8115
9350
  return yield* Effect28.gen(function* () {
8116
9351
  yield* ensureAllowed(registeredTool, input);
8117
9352
  yield* validateInput(registeredTool, input);
8118
- yield* recordRequested(repository, eventLog, input);
9353
+ const call = yield* recordRequested(repository, eventLog, input, registeredTool);
9354
+ const existingResult = yield* repository.getResult(input.call.id).pipe(Effect28.mapError(mapRepositoryError4));
9355
+ if (existingResult !== undefined) {
9356
+ yield* repairResultEvent(eventLog, input, existingResult);
9357
+ return existingResult.result;
9358
+ }
8119
9359
  let effectiveInput = input;
8120
9360
  if (registeredTool.definition.needs_approval === true) {
8121
9361
  const bypass = yield* hasPermissionApprovalBypass(waits, input);
@@ -8133,7 +9373,7 @@ var makeService = (initialTools) => Effect28.gen(function* () {
8133
9373
  }
8134
9374
  }
8135
9375
  }
8136
- const rawResult = yield* finalToolResult(registeredTool, effectiveInput);
9376
+ 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
9377
  const result = input.transformResult === undefined || rawResult.error !== undefined ? rawResult : yield* input.transformResult(rawResult);
8138
9378
  const received = yield* recordReceived(repository, eventLog, effectiveInput, result);
8139
9379
  yield* recordToolCall(input.call.name, result.error === undefined ? "success" : "failure");
@@ -8213,12 +9453,53 @@ var firstDuplicate = (values) => {
8213
9453
  };
8214
9454
  var missingFrom = (values, allowed) => values.find((value) => !HashSet4.has(allowed, value));
8215
9455
  var transferToolName = (name) => `transfer_to_${name.trim().toLowerCase().replaceAll(/[^a-z0-9]+/g, "_").replaceAll(/^_+|_+$/g, "")}`;
9456
+ var validateTurnPolicySnapshot = Effect29.fn("AgentRegistry.validateTurnPolicySnapshot")(function* (snapshot) {
9457
+ if (snapshot === undefined)
9458
+ return;
9459
+ 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" })));
9460
+ let nodes = 0;
9461
+ const pending = [
9462
+ { snapshot: decoded, depth: 1 }
9463
+ ];
9464
+ while (pending.length > 0) {
9465
+ const current2 = pending.pop();
9466
+ if (current2 === undefined)
9467
+ continue;
9468
+ nodes += 1;
9469
+ if (current2.depth > exports_agent_schema.maxTurnPolicySnapshotDepth) {
9470
+ return yield* Effect29.fail(new AgentDefinitionInvalid({
9471
+ message: `definition.turn_policy depth exceeds ${exports_agent_schema.maxTurnPolicySnapshotDepth}`
9472
+ }));
9473
+ }
9474
+ if (nodes > exports_agent_schema.maxTurnPolicySnapshotNodes) {
9475
+ return yield* Effect29.fail(new AgentDefinitionInvalid({
9476
+ message: `definition.turn_policy node count exceeds ${exports_agent_schema.maxTurnPolicySnapshotNodes}`
9477
+ }));
9478
+ }
9479
+ switch (current2.snapshot.kind) {
9480
+ case "recurs":
9481
+ if (!Number.isInteger(current2.snapshot.count) || current2.snapshot.count < 0) {
9482
+ return yield* Effect29.fail(new AgentDefinitionInvalid({
9483
+ message: "definition.turn_policy recurs count must be a non-negative integer"
9484
+ }));
9485
+ }
9486
+ break;
9487
+ case "until-tool-call":
9488
+ yield* requireText(current2.snapshot.name, "definition.turn_policy until-tool-call name");
9489
+ break;
9490
+ case "both":
9491
+ pending.push({ snapshot: current2.snapshot.second, depth: current2.depth + 1 }, { snapshot: current2.snapshot.first, depth: current2.depth + 1 });
9492
+ break;
9493
+ }
9494
+ }
9495
+ });
8216
9496
  var validateDefinition = Effect29.fn("AgentRegistry.validateDefinition")(function* (definition) {
8217
9497
  yield* requireText(definition.name, "definition.name");
8218
9498
  yield* requireOptionalText(definition.instructions, "definition.instructions");
8219
9499
  yield* requireText(definition.model.provider, "definition.model.provider");
8220
9500
  yield* requireText(definition.model.model, "definition.model.model");
8221
9501
  yield* requireOptionalText(definition.output_schema_ref, "definition.output_schema_ref");
9502
+ yield* validateTurnPolicySnapshot(definition.turn_policy);
8222
9503
  for (const toolName of definition.tool_names) {
8223
9504
  yield* requireText(toolName, "definition.tool_names[]");
8224
9505
  }
@@ -8420,7 +9701,7 @@ __export(exports_agent_loop_service, {
8420
9701
  testLayer: () => testLayer46,
8421
9702
  run: () => run3,
8422
9703
  mapBoundaryError: () => mapBoundaryError,
8423
- layer: () => layer44,
9704
+ layer: () => layer45,
8424
9705
  Service: () => Service41,
8425
9706
  STRUCTURED_TURN_PROMPT: () => STRUCTURED_TURN_PROMPT,
8426
9707
  AgentLoopWaitRequested: () => AgentLoopWaitRequested,
@@ -8428,7 +9709,7 @@ __export(exports_agent_loop_service, {
8428
9709
  AgentLoopBudgetExceeded: () => AgentLoopBudgetExceeded
8429
9710
  });
8430
9711
 
8431
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/agent.ts
9712
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/agent.ts
8432
9713
  var exports_agent = {};
8433
9714
  __export(exports_agent, {
8434
9715
  streamObject: () => streamObject,
@@ -8439,9 +9720,9 @@ __export(exports_agent, {
8439
9720
  defaultObjectPrompt: () => defaultObjectPrompt
8440
9721
  });
8441
9722
  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";
9723
+ 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
9724
 
8444
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/agent-event.ts
9725
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/agent-event.ts
8445
9726
  var exports_agent_event = {};
8446
9727
  __export(exports_agent_event, {
8447
9728
  addUsage: () => addUsage,
@@ -8498,7 +9779,7 @@ class AgentSuspended extends Schema38.TaggedErrorClass()("@batonfx/core/AgentSus
8498
9779
  }) {
8499
9780
  }
8500
9781
 
8501
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/approvals.ts
9782
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/approvals.ts
8502
9783
  var exports_approvals = {};
8503
9784
  __export(exports_approvals, {
8504
9785
  testLayer: () => testLayer26,
@@ -8514,25 +9795,30 @@ var autoApprove = Layer29.succeed(Approvals, Approvals.of({ check: () => Effect3
8514
9795
  var denyAll = Layer29.succeed(Approvals, Approvals.of({ check: () => Effect31.succeed({ _tag: "Denied" }) }));
8515
9796
  var testLayer26 = (implementation) => Layer29.succeed(Approvals, Approvals.of(implementation));
8516
9797
 
8517
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/compaction.ts
9798
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/compaction.ts
8518
9799
  var exports_compaction = {};
8519
9800
  __export(exports_compaction, {
8520
9801
  truncate: () => truncate,
9802
+ toolOutputBound: () => toolOutputBound,
8521
9803
  testLayer: () => testLayer29,
9804
+ structuredSummary: () => structuredSummary,
9805
+ strategy: () => strategy,
8522
9806
  make: () => make2,
8523
9807
  layer: () => layer26,
9808
+ keepRecent: () => keepRecent,
8524
9809
  isContextOverflow: () => isContextOverflow,
8525
9810
  defaultStrategy: () => defaultStrategy,
8526
9811
  SUMMARY_TEMPLATE: () => SUMMARY_TEMPLATE,
8527
9812
  DEFAULT_RESERVE_TOKENS: () => DEFAULT_RESERVE_TOKENS,
8528
9813
  DEFAULT_KEEP_RECENT_TOKENS: () => DEFAULT_KEEP_RECENT_TOKENS,
8529
9814
  CompactionError: () => CompactionError,
8530
- Compaction: () => Compaction
9815
+ Compaction: () => Compaction,
9816
+ AgentSummary: () => AgentSummary
8531
9817
  });
8532
9818
  import { Context as Context32, Effect as Effect34, Layer as Layer32, Option as Option10, Schema as Schema41 } from "effect";
8533
9819
  import { LanguageModel, Prompt as Prompt3, Tokenizer, Toolkit as Toolkit2 } from "effect/unstable/ai";
8534
9820
 
8535
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/session.ts
9821
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/session.ts
8536
9822
  var exports_session = {};
8537
9823
  __export(exports_session, {
8538
9824
  testLayer: () => testLayer27,
@@ -8705,7 +9991,7 @@ var memoryLayer24 = Layer30.effect(SessionStore, Ref7.make(initialState).pipe(Ef
8705
9991
  }))));
8706
9992
  var testLayer27 = (implementation) => Layer30.succeed(SessionStore, SessionStore.of(implementation));
8707
9993
 
8708
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/tool-output.ts
9994
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/tool-output.ts
8709
9995
  var exports_tool_output = {};
8710
9996
  __export(exports_tool_output, {
8711
9997
  testLayer: () => testLayer28,
@@ -8765,7 +10051,7 @@ var bound = (result, options) => Effect33.gen(function* () {
8765
10051
  return { _tag: "Success", result: output, encodedResult: output };
8766
10052
  });
8767
10053
 
8768
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/compaction.ts
10054
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/compaction.ts
8769
10055
  var DEFAULT_RESERVE_TOKENS = 16384;
8770
10056
  var DEFAULT_KEEP_RECENT_TOKENS = 20000;
8771
10057
  var SUMMARY_TEMPLATE = `Summarize the conversation so another agent can continue seamlessly.
@@ -8783,6 +10069,13 @@ Use Markdown with these sections:
8783
10069
  ## Critical Context
8784
10070
 
8785
10071
  Do not mention that context was compacted.`;
10072
+ var AgentSummary = Schema41.Struct({
10073
+ goal: Schema41.String,
10074
+ facts: Schema41.Array(Schema41.String),
10075
+ decisions: Schema41.Array(Schema41.String),
10076
+ openQuestions: Schema41.Array(Schema41.String),
10077
+ toolFindings: Schema41.Array(Schema41.String)
10078
+ });
8786
10079
 
8787
10080
  class CompactionError extends Schema41.TaggedErrorClass()("@batonfx/core/CompactionError", {
8788
10081
  message: Schema41.String,
@@ -8796,6 +10089,27 @@ var serialized2 = (value) => {
8796
10089
  const json = JSON.stringify(value);
8797
10090
  return json === undefined ? String(value) : json;
8798
10091
  };
10092
+ var safeNonNegativeInteger = (name, value) => {
10093
+ if (!Number.isSafeInteger(value) || value < 0)
10094
+ throw new TypeError(`${name} must be a non-negative safe integer`);
10095
+ return value;
10096
+ };
10097
+ var markdownList = (items) => items.length === 0 ? "- None" : items.map((item) => `- ${item}`).join(`
10098
+ `);
10099
+ var renderAgentSummary = (summary) => [
10100
+ `## Goal
10101
+ ${summary.goal}`,
10102
+ `## Facts
10103
+ ${markdownList(summary.facts)}`,
10104
+ `## Decisions
10105
+ ${markdownList(summary.decisions)}`,
10106
+ `## Open Questions
10107
+ ${markdownList(summary.openQuestions)}`,
10108
+ `## Tool Findings
10109
+ ${markdownList(summary.toolFindings)}`
10110
+ ].join(`
10111
+
10112
+ `);
8799
10113
  var APPROX_CHARS_PER_TOKEN = 4;
8800
10114
  var estimateTokens = (text3) => Math.ceil(text3.length / APPROX_CHARS_PER_TOKEN);
8801
10115
  var estimateEntryTokens = (entry) => estimateTokens(serialized2(entry));
@@ -8856,7 +10170,7 @@ var summaryPrompt = (template, prompt) => Prompt3.make(`${template}
8856
10170
  Conversation to summarize:
8857
10171
  ${serialized2(prompt.content)}`);
8858
10172
  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));
10173
+ var compactedHistory = (summary, head, recent) => Prompt3.concat(Prompt3.fromMessages([...systemMessages(head), checkpointMessage2(summary)]), recent);
8860
10174
  var normalizeUsage = (usage, options) => ({
8861
10175
  contextTokens: Number.isFinite(usage.contextTokens) ? usage.contextTokens : 0,
8862
10176
  contextWindow: Number.isFinite(usage.contextWindow) ? usage.contextWindow : options.contextWindow ?? Number.POSITIVE_INFINITY,
@@ -8900,38 +10214,77 @@ var defaultStrategy = (options = {}) => ({
8900
10214
  return options.summaryModel === undefined ? effect : effect.pipe(Effect34.provide(options.summaryModel));
8901
10215
  }
8902
10216
  });
8903
- var make2 = (strategy, options = {}) => ({
10217
+ var strategy = (parts, base = defaultStrategy()) => parts.reduce((current2, part) => ({
10218
+ shouldCompact: part.shouldCompact ?? current2.shouldCompact,
10219
+ cut: part.cut ?? current2.cut,
10220
+ summarize: part.summarize ?? current2.summarize,
10221
+ ...part.toolOutputMaxBytes !== undefined ? { toolOutputMaxBytes: part.toolOutputMaxBytes } : current2.toolOutputMaxBytes === undefined ? {} : { toolOutputMaxBytes: current2.toolOutputMaxBytes },
10222
+ ...part.keepRecentTokens !== undefined ? { keepRecentTokens: part.keepRecentTokens } : current2.keepRecentTokens === undefined ? {} : { keepRecentTokens: current2.keepRecentTokens }
10223
+ }), base);
10224
+ var toolOutputBound = (options) => ({
10225
+ toolOutputMaxBytes: safeNonNegativeInteger("ToolOutputBoundOptions.maxBytes", options.maxBytes)
10226
+ });
10227
+ var keepRecent = (options) => ({
10228
+ keepRecentTokens: safeNonNegativeInteger("KeepRecentOptions.tokens", options.tokens)
10229
+ });
10230
+ var structuredSummary = (options = {}) => ({
10231
+ summarize: (plan2, request) => {
10232
+ const effect = Effect34.gen(function* () {
10233
+ const head = buildContext(plan2.head);
10234
+ const [compactedHead] = request.toolOutputMaxBytes === undefined ? [head, false] : yield* microcompactPrompt(head, request.toolOutputMaxBytes);
10235
+ const prompt = summaryPrompt(options.summaryPrompt ?? SUMMARY_TEMPLATE, compactedHead);
10236
+ const model = yield* LanguageModel.LanguageModel;
10237
+ return yield* model.generateObject({
10238
+ prompt,
10239
+ schema: AgentSummary,
10240
+ objectName: options.objectName ?? "AgentSummary",
10241
+ toolChoice: "none"
10242
+ }).pipe(Effect34.map((response) => renderAgentSummary(response.value)), Effect34.mapError((error) => new CompactionError({ message: String(error), cause: error })));
10243
+ });
10244
+ return options.summaryModel === undefined ? effect : effect.pipe(Effect34.provide(options.summaryModel));
10245
+ }
10246
+ });
10247
+ var make2 = (compactionStrategy, options = {}) => ({
8904
10248
  maybeCompact: (input) => Effect34.gen(function* () {
8905
10249
  const usage = normalizeUsage(input.usage, options);
8906
- const shouldCompact = input.overflow || strategy.shouldCompact(usage);
10250
+ const shouldCompact = input.overflow || compactionStrategy.shouldCompact(usage);
8907
10251
  if (!shouldCompact)
8908
10252
  return Option10.none();
8909
10253
  let history = input.history;
8910
10254
  let prompt = input.prompt;
8911
10255
  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);
10256
+ const toolOutputMaxBytes = input.toolOutputMaxBytes ?? compactionStrategy.toolOutputMaxBytes;
10257
+ if (toolOutputMaxBytes !== undefined) {
10258
+ const [compactedHistoryPrompt, historyChanged] = yield* microcompactPrompt(history, toolOutputMaxBytes);
10259
+ const [compactedPrompt, promptChanged] = yield* microcompactPrompt(prompt, toolOutputMaxBytes);
8915
10260
  history = compactedHistoryPrompt;
8916
10261
  prompt = compactedPrompt;
8917
10262
  changed = historyChanged || promptChanged;
8918
10263
  if (changed && fits(history, prompt, usage))
8919
10264
  return Option10.some(makeMicrocompact(history, prompt));
8920
10265
  }
8921
- const plan2 = strategy.cut(input.path ?? [], options.keepRecentTokens ?? DEFAULT_KEEP_RECENT_TOKENS);
10266
+ const plan2 = compactionStrategy.cut(input.path ?? [], compactionStrategy.keepRecentTokens ?? options.keepRecentTokens ?? DEFAULT_KEEP_RECENT_TOKENS);
8922
10267
  if (Option10.isNone(plan2))
8923
10268
  return changed ? Option10.some(makeMicrocompact(history, prompt)) : Option10.none();
8924
- const summary = yield* strategy.summarize(plan2.value, { ...input, history, prompt, usage });
10269
+ const summary = yield* compactionStrategy.summarize(plan2.value, {
10270
+ ...input,
10271
+ history,
10272
+ prompt,
10273
+ usage,
10274
+ ...toolOutputMaxBytes === undefined ? {} : { toolOutputMaxBytes }
10275
+ });
10276
+ const recent = buildContext(plan2.value.recent);
10277
+ const [compactedRecent] = toolOutputMaxBytes === undefined ? [recent, false] : yield* microcompactPrompt(recent, toolOutputMaxBytes);
8925
10278
  return Option10.some({
8926
10279
  _tag: "Summarize",
8927
- history: compactedHistory(summary, plan2.value.head, plan2.value.recent),
10280
+ history: compactedHistory(summary, plan2.value.head, compactedRecent),
8928
10281
  prompt,
8929
10282
  summary,
8930
10283
  firstKeptEntryId: plan2.value.firstKeptEntryId
8931
10284
  });
8932
10285
  })
8933
10286
  });
8934
- var layer26 = (options = {}, strategy = defaultStrategy(options)) => Layer32.succeed(Compaction, Compaction.of(make2(strategy, options)));
10287
+ var layer26 = (options = {}, providedStrategy = options.strategy ?? defaultStrategy(options)) => Layer32.succeed(Compaction, Compaction.of(make2(providedStrategy, options)));
8935
10288
  var truncate = (maxTokens) => ({
8936
10289
  maybeCompact: (input) => Effect34.gen(function* () {
8937
10290
  const usage = input.usage;
@@ -8948,7 +10301,7 @@ var truncate = (maxTokens) => ({
8948
10301
  var testLayer29 = (implementation) => Layer32.succeed(Compaction, Compaction.of(implementation));
8949
10302
  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
10303
 
8951
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/instructions.ts
10304
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/instructions.ts
8952
10305
  var exports_instructions = {};
8953
10306
  __export(exports_instructions, {
8954
10307
  testLayer: () => testLayer30,
@@ -8997,7 +10350,7 @@ var renderUpdate = (epoch, context) => Effect35.gen(function* () {
8997
10350
  var layer27 = (sources) => Layer33.succeed(Instructions, Instructions.of({ sources: [...sources] }));
8998
10351
  var testLayer30 = (implementation) => Layer33.succeed(Instructions, Instructions.of(implementation));
8999
10352
 
9000
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/memory.ts
10353
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/memory.ts
9001
10354
  var exports_memory = {};
9002
10355
  __export(exports_memory, {
9003
10356
  testLayer: () => testLayer31,
@@ -9028,7 +10381,7 @@ var merge = (first, second) => ({
9028
10381
  var noopLayer = Layer34.succeed(Memory, Memory.of(noop));
9029
10382
  var testLayer31 = (implementation) => Layer34.succeed(Memory, Memory.of(implementation));
9030
10383
 
9031
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/model-middleware.ts
10384
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/model-middleware.ts
9032
10385
  var exports_model_middleware = {};
9033
10386
  __export(exports_model_middleware, {
9034
10387
  layer: () => layer28,
@@ -9042,7 +10395,7 @@ class ModelMiddleware extends Context35.Service()("@batonfx/core/ModelMiddleware
9042
10395
  var identityLayer = Layer35.succeed(ModelMiddleware, []);
9043
10396
  var layer28 = (middleware) => Layer35.succeed(ModelMiddleware, middleware);
9044
10397
 
9045
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/model-registry.ts
10398
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/model-registry.ts
9046
10399
  var exports_model_registry = {};
9047
10400
  __export(exports_model_registry, {
9048
10401
  testLayer: () => testLayer32,
@@ -9131,7 +10484,7 @@ var provide = (selection, effect) => Effect38.gen(function* () {
9131
10484
  return yield* service.provide(selection, effect);
9132
10485
  });
9133
10486
 
9134
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/model-resilience.ts
10487
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/model-resilience.ts
9135
10488
  var exports_model_resilience = {};
9136
10489
  __export(exports_model_resilience, {
9137
10490
  testLayer: () => testLayer33,
@@ -9177,7 +10530,7 @@ var apply = (model, resilience) => ({
9177
10530
  }).pipe(Stream5.retry(retryStreamSchedule(resilience)))
9178
10531
  });
9179
10532
 
9180
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/permissions.ts
10533
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/permissions.ts
9181
10534
  var exports_permissions = {};
9182
10535
  __export(exports_permissions, {
9183
10536
  testLayer: () => testLayer34,
@@ -9307,12 +10660,14 @@ var ruleStoreMemory = (initialRules = []) => Layer38.effect(RuleStore, Ref10.mak
9307
10660
  var ruleStoreTestLayer = (implementation) => Layer38.succeed(RuleStore, RuleStore.of(implementation));
9308
10661
  var testLayer34 = (implementation) => Layer38.succeed(Permissions, Permissions.of(implementation));
9309
10662
 
9310
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/skill-source.ts
10663
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/skill-source.ts
9311
10664
  var exports_skill_source = {};
9312
10665
  __export(exports_skill_source, {
9313
10666
  testLayer: () => testLayer35,
9314
10667
  selectListings: () => selectListings,
10668
+ merge: () => merge2,
9315
10669
  makeListing: () => makeListing,
10670
+ layer: () => layer31,
9316
10671
  fromSkills: () => fromSkills,
9317
10672
  empty: () => empty,
9318
10673
  SkillSourceError: () => SkillSourceError,
@@ -9327,7 +10682,7 @@ class SkillSourceError extends Schema45.TaggedErrorClass()("@batonfx/core/SkillS
9327
10682
  cause: Schema45.optionalKey(Schema45.Defect())
9328
10683
  }) {
9329
10684
  }
9330
- var DESCRIPTION_CAP = 1536;
10685
+ var DESCRIPTION_CAP = 1024;
9331
10686
 
9332
10687
  class SkillSource extends Context39.Service()("@batonfx/core/SkillSource") {
9333
10688
  }
@@ -9342,6 +10697,25 @@ var fromSkills = (skills) => {
9342
10697
  };
9343
10698
  var empty = fromSkills([]);
9344
10699
  var testLayer35 = (implementation) => Layer39.succeed(SkillSource, SkillSource.of(implementation));
10700
+ var merge2 = (sources) => ({
10701
+ all: Effect41.forEach(sources, (source) => source.all).pipe(Effect41.map((groups) => {
10702
+ const byName = new Map;
10703
+ for (const skills of groups) {
10704
+ for (const skill of skills)
10705
+ byName.set(skill.frontmatter.name, skill);
10706
+ }
10707
+ return [...byName.values()];
10708
+ })),
10709
+ get: (name) => Effect41.gen(function* () {
10710
+ for (const source of sources.toReversed()) {
10711
+ const found = yield* source.get(name);
10712
+ if (found !== undefined)
10713
+ return found;
10714
+ }
10715
+ return;
10716
+ })
10717
+ });
10718
+ var layer31 = (sources) => Layer39.effect(SkillSource, Effect41.forEach(sources, (source) => source).pipe(Effect41.map((built) => SkillSource.of(merge2(built)))));
9345
10719
  var estimatedTokens = (listing) => Math.ceil(listing.length / 4);
9346
10720
  var usageRank = (skill, recentlyUsed) => {
9347
10721
  const index2 = recentlyUsed.indexOf(skill.frontmatter.name);
@@ -9365,11 +10739,11 @@ var selectListings = (skills, budgetTokens, recentlyUsed) => {
9365
10739
  return selected;
9366
10740
  };
9367
10741
 
9368
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/steering.ts
10742
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/steering.ts
9369
10743
  var exports_steering = {};
9370
10744
  __export(exports_steering, {
9371
10745
  testLayer: () => testLayer36,
9372
- layer: () => layer31,
10746
+ layer: () => layer32,
9373
10747
  SteeringQueueFull: () => SteeringQueueFull,
9374
10748
  Steering: () => Steering
9375
10749
  });
@@ -9388,8 +10762,8 @@ var resolvePolicy = (policy, mode) => ({
9388
10762
  ...policy?.capacity === undefined ? {} : { capacity: policy.capacity },
9389
10763
  onFull: policy?.onFull ?? "fail"
9390
10764
  });
9391
- var queueStrategy = (strategy) => {
9392
- switch (strategy) {
10765
+ var queueStrategy = (strategy2) => {
10766
+ switch (strategy2) {
9393
10767
  case "drop-oldest":
9394
10768
  return "sliding";
9395
10769
  case "drop-newest":
@@ -9410,7 +10784,7 @@ var drainOne = (queue) => Effect42.sync(() => {
9410
10784
  return taken === undefined || !Exit.isSuccess(taken) ? [] : [taken.value];
9411
10785
  });
9412
10786
  var drain = (queue, mode) => mode === "all" ? Queue.clear(queue) : drainOne(queue);
9413
- var layer31 = (options = {}) => Layer40.effect(Steering, Effect42.gen(function* () {
10787
+ var layer32 = (options = {}) => Layer40.effect(Steering, Effect42.gen(function* () {
9414
10788
  const steeringQueue = yield* makeQueue("steering", resolvePolicy(options.steering, "all"));
9415
10789
  const followUpQueue = yield* makeQueue("followUp", resolvePolicy(options.followUp, "one-at-a-time"));
9416
10790
  return Steering.of({
@@ -9422,7 +10796,7 @@ var layer31 = (options = {}) => Layer40.effect(Steering, Effect42.gen(function*
9422
10796
  }));
9423
10797
  var testLayer36 = (implementation) => Layer40.succeed(Steering, Steering.of(implementation));
9424
10798
 
9425
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/tool-context.ts
10799
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/tool-context.ts
9426
10800
  var exports_tool_context = {};
9427
10801
  __export(exports_tool_context, {
9428
10802
  testLayer: () => testLayer37,
@@ -9440,7 +10814,7 @@ var layerDefault = Layer41.sync(ToolContext, () => ToolContext.of({
9440
10814
  }));
9441
10815
  var testLayer37 = (implementation) => Layer41.succeed(ToolContext, ToolContext.of(implementation));
9442
10816
 
9443
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/tool-executor.ts
10817
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/tool-executor.ts
9444
10818
  var exports_tool_executor = {};
9445
10819
  __export(exports_tool_executor, {
9446
10820
  testLayer: () => testLayer38,
@@ -9566,7 +10940,7 @@ function router(routes) {
9566
10940
  }
9567
10941
  var testLayer38 = (implementation) => Layer42.succeed(ToolExecutor, ToolExecutor.of(implementation));
9568
10942
 
9569
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/turn-policy.ts
10943
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/turn-policy.ts
9570
10944
  var exports_turn_policy = {};
9571
10945
  __export(exports_turn_policy, {
9572
10946
  untilToolCall: () => untilToolCall,
@@ -9585,8 +10959,14 @@ var decision = {
9585
10959
  stop: { _tag: "Stop" }
9586
10960
  };
9587
10961
  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()));
10962
+ var recurs = (n) => ({
10963
+ decide: (info) => Effect45.succeed(info.turn < n + 1 ? decision.continue() : decision.stop),
10964
+ ...Number.isFinite(n) ? { snapshot: { _tag: "Recurs", count: n } } : {}
10965
+ });
10966
+ var untilToolCall = (name) => ({
10967
+ decide: (info) => Effect45.succeed(info.pendingToolResults.some((result) => result.name === name) ? decision.stop : decision.continue()),
10968
+ snapshot: { _tag: "UntilToolCall", name }
10969
+ });
9590
10970
  var mergeOverrides = (first, second) => {
9591
10971
  if (first === undefined)
9592
10972
  return second;
@@ -9594,18 +10974,21 @@ var mergeOverrides = (first, second) => {
9594
10974
  return first;
9595
10975
  return { ...first, ...second };
9596
10976
  };
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
- }));
10977
+ var both = (first, second) => ({
10978
+ decide: (info) => Effect45.gen(function* () {
10979
+ const left = yield* first.decide(info);
10980
+ if (left._tag === "Stop")
10981
+ return decision.stop;
10982
+ const right = yield* second.decide(info);
10983
+ if (right._tag === "Stop")
10984
+ return decision.stop;
10985
+ return decision.continue(mergeOverrides(left.overrides, right.overrides));
10986
+ }),
10987
+ ...first.snapshot === undefined || second.snapshot === undefined ? {} : { snapshot: { _tag: "Both", first: first.snapshot, second: second.snapshot } }
10988
+ });
9606
10989
  var defaultPolicy = recurs(8);
9607
10990
 
9608
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/agent.ts
10991
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/agent.ts
9609
10992
  function make5(nameOrOptions, options = {}) {
9610
10993
  const resolved = typeof nameOrOptions === "string" ? { ...options, name: nameOrOptions } : nameOrOptions;
9611
10994
  return {
@@ -9628,7 +11011,7 @@ var steeringDrainedEvent = (turn, queue, messages) => ({
9628
11011
  var skillListingBudgetTokens = 2048;
9629
11012
  var activateSkillToolName = "activate_skill";
9630
11013
  var activateSkillParameters = Schema48.Struct({ name: Schema48.String });
9631
- var activateSkillTool = Tool4.make(activateSkillToolName, {
11014
+ var activateSkillTool = Tool3.make(activateSkillToolName, {
9632
11015
  description: "Load the full body for one listed Baton skill by name before applying that skill.",
9633
11016
  parameters: activateSkillParameters,
9634
11017
  success: Schema48.Struct({
@@ -10302,13 +11685,13 @@ var generateObject = (agent, options) => Stream7.runFold(streamObject(agent, opt
10302
11685
  })
10303
11686
  })
10304
11687
  })));
10305
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/agent-tool.ts
11688
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/agent-tool.ts
10306
11689
  var exports_agent_tool = {};
10307
11690
  __export(exports_agent_tool, {
10308
11691
  asTool: () => asTool
10309
11692
  });
10310
11693
  import { Cause as Cause4, Effect as Effect47, Schema as Schema49 } from "effect";
10311
- import { Tool as Tool5, Toolkit as Toolkit4 } from "effect/unstable/ai";
11694
+ import { Tool as Tool4, Toolkit as Toolkit4 } from "effect/unstable/ai";
10312
11695
  var defaultParameters = Schema49.Struct({ prompt: Schema49.String });
10313
11696
  var errorMessage2 = (error) => {
10314
11697
  if (error instanceof AgentSuspended) {
@@ -10338,7 +11721,7 @@ var asTool = (agent, options = {}) => {
10338
11721
  const success2 = options.success ?? Schema49.String;
10339
11722
  const toPrompt = options.toPrompt ?? ((params) => params.prompt);
10340
11723
  const fromResult = options.fromResult ?? ((result) => result.text);
10341
- const tool2 = Tool5.make(name, {
11724
+ const tool2 = Tool4.make(name, {
10342
11725
  ...options.description === undefined ? {} : { description: options.description },
10343
11726
  parameters,
10344
11727
  success: success2,
@@ -10357,7 +11740,7 @@ var asTool = (agent, options = {}) => {
10357
11740
  });
10358
11741
  return lazyHandled(toolkit, name, handler);
10359
11742
  };
10360
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/guardrail.ts
11743
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/guardrail.ts
10361
11744
  var exports_guardrail = {};
10362
11745
  __export(exports_guardrail, {
10363
11746
  validateInput: () => validateInput2,
@@ -10437,7 +11820,7 @@ var redactOutput = (options) => ({
10437
11820
  var filterOutput = (keep) => ({
10438
11821
  transformPart: (part, context) => Effect48.succeed(part.type === "tool-call" || keep(part, context) ? Option17.some(part) : Option17.none())
10439
11822
  });
10440
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/handoff.ts
11823
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/handoff.ts
10441
11824
  var exports_handoff = {};
10442
11825
  __export(exports_handoff, {
10443
11826
  transferTool: () => transferTool,
@@ -10501,7 +11884,7 @@ var supervisor = (options) => {
10501
11884
  };
10502
11885
  };
10503
11886
 
10504
- // ../../node_modules/.bun/@batonfx+core@0.3.7/node_modules/@batonfx/core/src/index.ts
11887
+ // ../../node_modules/.bun/@batonfx+core@0.4.0/node_modules/@batonfx/core/src/index.ts
10505
11888
  import {
10506
11889
  AiError as AiError3,
10507
11890
  Chat as Chat2,
@@ -10514,7 +11897,7 @@ import {
10514
11897
  ResponseIdTracker,
10515
11898
  Telemetry as Telemetry2,
10516
11899
  Tokenizer as Tokenizer3,
10517
- Tool as Tool7,
11900
+ Tool as Tool6,
10518
11901
  Toolkit as Toolkit6
10519
11902
  } from "effect/unstable/ai";
10520
11903
 
@@ -10530,7 +11913,7 @@ __export(exports_child_run_service, {
10530
11913
  spawnDynamic: () => spawnDynamic,
10531
11914
  resolveForDispatch: () => resolveForDispatch,
10532
11915
  memoryLayer: () => memoryLayer26,
10533
- layer: () => layer32,
11916
+ layer: () => layer33,
10534
11917
  childDefinition: () => childDefinition,
10535
11918
  StaticChildRunPresetNotFound: () => StaticChildRunPresetNotFound,
10536
11919
  Service: () => Service31,
@@ -10755,7 +12138,7 @@ var persistChild = Effect51.fn("ChildRunService.persistChild")(function* (reposi
10755
12138
  yield* eventLog.append(spawnedEvent(input, kind, context, presetName, workspaceRef)).pipe(Effect51.mapError(mapEventLogError3));
10756
12139
  return acceptedOutput(input);
10757
12140
  });
10758
- var layer32 = Layer45.effect(Service31, Effect51.gen(function* () {
12141
+ var layer33 = Layer45.effect(Service31, Effect51.gen(function* () {
10759
12142
  const repository = yield* exports_child_execution_repository.Service;
10760
12143
  const eventLog = yield* Service24;
10761
12144
  return Service31.of({
@@ -10789,7 +12172,7 @@ var layer32 = Layer45.effect(Service31, Effect51.gen(function* () {
10789
12172
  })
10790
12173
  });
10791
12174
  }));
10792
- var memoryLayer26 = layer32.pipe(Layer45.provide(exports_child_execution_repository.memoryLayer), Layer45.provide(memoryLayer21));
12175
+ var memoryLayer26 = layer33.pipe(Layer45.provide(exports_child_execution_repository.memoryLayer), Layer45.provide(memoryLayer21));
10793
12176
  var testLayer39 = (implementation) => Layer45.succeed(Service31, Service31.of(implementation));
10794
12177
  var agentContextFromSchema = (input) => ({
10795
12178
  toolNames: input.tool_names,
@@ -10831,6 +12214,10 @@ var childDefinition = (parentDefinition, context) => context.model === undefined
10831
12214
  tool_names: [...context.toolNames],
10832
12215
  permissions: parentDefinition.permissions.filter((permission) => context.permissions.includes(permission.name)),
10833
12216
  child_run_presets: {},
12217
+ ...parentDefinition.turn_policy === undefined ? {} : { turn_policy: parentDefinition.turn_policy },
12218
+ ...parentDefinition.max_tool_turns === undefined ? {} : { max_tool_turns: parentDefinition.max_tool_turns },
12219
+ ...parentDefinition.max_wait_turns === undefined ? {} : { max_wait_turns: parentDefinition.max_wait_turns },
12220
+ ...parentDefinition.token_budget === undefined ? {} : { token_budget: parentDefinition.token_budget },
10834
12221
  ...context.instructions === undefined ? {} : { instructions: context.instructions },
10835
12222
  ...context.outputSchemaRef === undefined ? {} : { output_schema_ref: context.outputSchemaRef }
10836
12223
  });
@@ -11094,14 +12481,14 @@ var resolveDefault = (registrations2, options) => {
11094
12481
  }
11095
12482
  return registrations2.length === 1 ? registrations2[0] : undefined;
11096
12483
  };
11097
- var registrationFromLayer2 = (input) => Model3.make(input.provider, input.model, input.layer).captureRequirements.pipe(Effect53.map((layer33) => toRegistration({
12484
+ var registrationFromLayer2 = (input) => Model3.make(input.provider, input.model, input.layer).captureRequirements.pipe(Effect53.map((layer34) => toRegistration({
11098
12485
  provider: input.provider,
11099
12486
  model: input.model,
11100
12487
  ...input.registrationKey === undefined ? {} : { registrationKey: input.registrationKey },
11101
- layer: layer33,
12488
+ layer: layer34,
11102
12489
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
11103
12490
  })));
11104
- var layer33 = (initialRegistrations = [], options) => Layer46.effect(Service32, Effect53.gen(function* () {
12491
+ var layer34 = (initialRegistrations = [], options) => Layer46.effect(Service32, Effect53.gen(function* () {
11105
12492
  const registry = yield* Ref13.make([...initialRegistrations]);
11106
12493
  const register5 = Effect53.fn("EmbeddingModelService.register")(function* (input) {
11107
12494
  const registration = toRegistration(input);
@@ -11130,8 +12517,8 @@ var layer33 = (initialRegistrations = [], options) => Layer46.effect(Service32,
11130
12517
  };
11131
12518
  return Service32.of({ register: register5, registrations: registrations2, provide: provide2, provideDefault, provideForAgent });
11132
12519
  }));
11133
- var layerFromRegistrationEffects2 = (registrations2, options) => Layer46.unwrap(Effect53.all(registrations2).pipe(Effect53.map((items) => layer33(items, options))));
11134
- var memoryLayer27 = layer33;
12520
+ var layerFromRegistrationEffects2 = (registrations2, options) => Layer46.unwrap(Effect53.all(registrations2).pipe(Effect53.map((items) => layer34(items, options))));
12521
+ var memoryLayer27 = layer34;
11135
12522
  var words = (input) => input.toLowerCase().match(/[a-z0-9]+/g) ?? [];
11136
12523
  var hashWord = (word) => {
11137
12524
  let hash = 2166136261;
@@ -11312,7 +12699,7 @@ var batonLayer = Layer47.effect(exports_memory.Memory, Effect54.gen(function* ()
11312
12699
  const service = yield* Service33;
11313
12700
  return exports_memory.Memory.of(service);
11314
12701
  }));
11315
- var layer34 = (options) => batonLayer.pipe(Layer47.provideMerge(serviceLayer(options)));
12702
+ var layer35 = (options) => batonLayer.pipe(Layer47.provideMerge(serviceLayer(options)));
11316
12703
  var recall = Effect54.fn("MemoryService.recall.call")(function* (input) {
11317
12704
  const service = yield* Service33;
11318
12705
  return yield* service.recall(input);
@@ -11337,7 +12724,7 @@ __export(exports_language_model_service, {
11337
12724
  provide: () => provide2,
11338
12725
  memoryLayer: () => memoryLayer28,
11339
12726
  layerFromRegistrationEffects: () => layerFromRegistrationEffects3,
11340
- layer: () => layer35,
12727
+ layer: () => layer36,
11341
12728
  Service: () => Service34,
11342
12729
  LanguageModelNotRegistered: () => LanguageModelNotRegistered2
11343
12730
  });
@@ -11352,7 +12739,7 @@ var toSelection = (selection) => ({
11352
12739
  class Service34 extends Context47.Service()("@relayfx/runtime/LanguageModelService") {
11353
12740
  }
11354
12741
  var registrationFromLayer3 = exports_model_registry.registrationFromLayer;
11355
- var layer35 = (initialRegistrations = [], options) => Layer48.effect(Service34, Effect55.gen(function* () {
12742
+ var layer36 = (initialRegistrations = [], options) => Layer48.effect(Service34, Effect55.gen(function* () {
11356
12743
  const registry = yield* exports_model_registry.Service;
11357
12744
  return Service34.of({
11358
12745
  register: (input) => registry.register(input),
@@ -11361,8 +12748,8 @@ var layer35 = (initialRegistrations = [], options) => Layer48.effect(Service34,
11361
12748
  provideForAgent: (agent, effect) => registry.provide(toSelection(agent.model), effect)
11362
12749
  });
11363
12750
  })).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;
12751
+ var layerFromRegistrationEffects3 = (registrations3, options) => Layer48.unwrap(Effect55.all(registrations3).pipe(Effect55.map((items) => layer36(items, options))));
12752
+ var memoryLayer28 = layer36;
11366
12753
  var testLayer40 = (implementation) => Layer48.succeed(Service34, Service34.of(implementation));
11367
12754
  var register6 = Effect55.fn("LanguageModelService.register.call")(function* (input) {
11368
12755
  const service = yield* Service34;
@@ -11387,7 +12774,7 @@ __export(exports_model_call_policy, {
11387
12774
  testLayer: () => testLayer41,
11388
12775
  noRetryLayer: () => noRetryLayer,
11389
12776
  make: () => make7,
11390
- layer: () => layer36,
12777
+ layer: () => layer37,
11391
12778
  defaultSchedule: () => defaultSchedule,
11392
12779
  defaultClassify: () => defaultClassify2,
11393
12780
  Service: () => Service35
@@ -11404,8 +12791,8 @@ var make7 = (input) => ({
11404
12791
  classify: input?.classify ?? defaultClassify2,
11405
12792
  retrySchedule: input?.retrySchedule ?? defaultSchedule
11406
12793
  });
11407
- var layer36 = (input) => Layer49.succeed(Service35, Service35.of(make7(input)));
11408
- var noRetryLayer = layer36({ retrySchedule: Schedule4.recurs(0) });
12794
+ var layer37 = (input) => Layer49.succeed(Service35, Service35.of(make7(input)));
12795
+ var noRetryLayer = layer37({ retrySchedule: Schedule4.recurs(0) });
11409
12796
  var testLayer41 = (implementation) => Layer49.succeed(Service35, Service35.of(implementation));
11410
12797
 
11411
12798
  // ../runtime/src/schema-registry/schema-registry-service.ts
@@ -11416,7 +12803,7 @@ __export(exports_schema_registry_service, {
11416
12803
  registrations: () => registrations4,
11417
12804
  register: () => register7,
11418
12805
  memoryLayer: () => memoryLayer29,
11419
- layer: () => layer37,
12806
+ layer: () => layer38,
11420
12807
  Service: () => Service36,
11421
12808
  SchemaRefNotRegistered: () => SchemaRefNotRegistered
11422
12809
  });
@@ -11433,7 +12820,7 @@ var upsertRegistration2 = (registry, registration) => {
11433
12820
  return [...registry, registration];
11434
12821
  return registry.map((item) => item.ref === registration.ref ? registration : item);
11435
12822
  };
11436
- var layer37 = (initialRegistrations = []) => Layer50.effect(Service36, Effect56.gen(function* () {
12823
+ var layer38 = (initialRegistrations = []) => Layer50.effect(Service36, Effect56.gen(function* () {
11437
12824
  const registry = yield* Ref14.make(initialRegistrations.reduce(upsertRegistration2, []));
11438
12825
  const register7 = Effect56.fn("SchemaRegistry.register")(function* (registration) {
11439
12826
  yield* Ref14.update(registry, (items) => upsertRegistration2(items, registration));
@@ -11449,7 +12836,7 @@ var layer37 = (initialRegistrations = []) => Layer50.effect(Service36, Effect56.
11449
12836
  });
11450
12837
  return Service36.of({ register: register7, registrations: registrations4, resolve: resolve4 });
11451
12838
  }));
11452
- var memoryLayer29 = layer37;
12839
+ var memoryLayer29 = layer38;
11453
12840
  var testLayer42 = (implementation) => Layer50.succeed(Service36, Service36.of(implementation));
11454
12841
  var register7 = Effect56.fn("SchemaRegistry.register.call")(function* (registration) {
11455
12842
  const service = yield* Service36;
@@ -11738,7 +13125,7 @@ var put3 = Effect58.fn("BlobStore.put.call")(function* (input) {
11738
13125
  var exports_prompt_assembler_service = {};
11739
13126
  __export(exports_prompt_assembler_service, {
11740
13127
  testLayer: () => testLayer45,
11741
- layer: () => layer38,
13128
+ layer: () => layer39,
11742
13129
  defaultLayerWithStores: () => defaultLayerWithStores,
11743
13130
  defaultLayer: () => defaultLayer,
11744
13131
  contentToPromptPart: () => contentToPromptPart,
@@ -11898,7 +13285,7 @@ var defaultLayerWithStores = Layer54.effect(Service40, Effect60.gen(function* ()
11898
13285
  return Service40.of(makeDefaultInterface(blobs, artifacts));
11899
13286
  }));
11900
13287
  var defaultLayer = defaultLayerWithStores.pipe(Layer54.provide(Layer54.mergeAll(passthroughLayer, passthroughLayer2)));
11901
- var layer38 = (implementation) => Layer54.succeed(Service40, Service40.of(implementation));
13288
+ var layer39 = (implementation) => Layer54.succeed(Service40, Service40.of(implementation));
11902
13289
  var testLayer45 = (implementation) => Layer54.succeed(Service40, Service40.of(implementation));
11903
13290
  var assemble = Effect60.fn("PromptAssembler.assemble.call")(function* (input) {
11904
13291
  const service = yield* Service40;
@@ -11906,7 +13293,7 @@ var assemble = Effect60.fn("PromptAssembler.assemble.call")(function* (input) {
11906
13293
  });
11907
13294
 
11908
13295
  // ../runtime/src/agent/relay-approvals.ts
11909
- var layer39 = exports_approvals.autoApprove;
13296
+ var layer40 = exports_approvals.autoApprove;
11910
13297
 
11911
13298
  // ../runtime/src/agent/relay-compaction.ts
11912
13299
  import { Clock as Clock5, Effect as Effect61, Layer as Layer55 } from "effect";
@@ -11918,11 +13305,10 @@ var defaultOptions = (options) => ({
11918
13305
  ...options?.reserveTokens === undefined ? {} : { reserveTokens: options.reserveTokens },
11919
13306
  ...options?.keepRecentTokens === undefined ? {} : { keepRecentTokens: options.keepRecentTokens }
11920
13307
  });
11921
- var strategy = (config) => {
11922
- const base = exports_compaction.defaultStrategy(defaultOptions(config.options));
13308
+ var strategy2 = (config) => {
13309
+ const base = config.strategy ?? exports_compaction.defaultStrategy(defaultOptions(config.options));
11923
13310
  return {
11924
- shouldCompact: base.shouldCompact,
11925
- cut: base.cut,
13311
+ ...base,
11926
13312
  summarize: (plan2, request) => {
11927
13313
  const id2 = checkpointId({
11928
13314
  executionId: config.executionId,
@@ -11952,7 +13338,7 @@ var strategy = (config) => {
11952
13338
  }
11953
13339
  };
11954
13340
  };
11955
- var make9 = (config) => exports_compaction.make(strategy(config), defaultOptions(config.options));
13341
+ var make9 = (config) => exports_compaction.make(strategy2(config), defaultOptions(config.options));
11956
13342
 
11957
13343
  // ../runtime/src/agent/relay-instructions.ts
11958
13344
  var layerFromEpoch = (epoch) => exports_instructions.layer(epoch.baseline.length === 0 ? [] : [exports_instructions.staticSource("relay:context-epoch", epoch.baseline)]);
@@ -12133,7 +13519,7 @@ var rememberRule = Effect62.fn("RelayPermissions.rememberRule")(function* (confi
12133
13519
  createdAt
12134
13520
  }).pipe(Effect62.mapError((error) => permissionError(error.message)));
12135
13521
  });
12136
- var layer40 = (config) => Layer56.mergeAll(Layer56.succeed(exports_permissions.Permissions, exports_permissions.Permissions.of({
13522
+ var layer41 = (config) => Layer56.mergeAll(Layer56.succeed(exports_permissions.Permissions, exports_permissions.Permissions.of({
12137
13523
  evaluate: (request) => evaluateDecision(config, request),
12138
13524
  await: (pending) => awaitAnswer(config, pending)
12139
13525
  })), Layer56.succeed(exports_permissions.RuleStore, exports_permissions.RuleStore.of({
@@ -12213,7 +13599,7 @@ var append4 = (config, kind, message) => Clock7.currentTimeMillis.pipe(Effect63.
12213
13599
  content: contentFromMessage(message),
12214
13600
  createdAt
12215
13601
  })), Effect63.asVoid);
12216
- var layer41 = (config) => Layer57.succeed(exports_steering.Steering, exports_steering.Steering.of({
13602
+ var layer42 = (config) => Layer57.succeed(exports_steering.Steering, exports_steering.Steering.of({
12217
13603
  steer: (message) => append4(config, "steering", message).pipe(Effect63.orDie),
12218
13604
  followUp: (message) => append4(config, "follow_up", message).pipe(Effect63.orDie),
12219
13605
  takeSteering: () => drain2(config, "steering", "all").pipe(Effect63.orDie),
@@ -12274,7 +13660,7 @@ var make10 = (config) => ({
12274
13660
  }))))));
12275
13661
  })
12276
13662
  });
12277
- var layer42 = (config) => Layer58.succeed(exports_tool_executor.ToolExecutor, exports_tool_executor.ToolExecutor.of(make10(config)));
13663
+ var layer43 = (config) => Layer58.succeed(exports_tool_executor.ToolExecutor, exports_tool_executor.ToolExecutor.of(make10(config)));
12278
13664
 
12279
13665
  // ../runtime/src/agent/relay-tool-output.ts
12280
13666
  import { Effect as Effect65, Layer as Layer59, Option as Option21 } from "effect";
@@ -12318,7 +13704,7 @@ var store = (blobStore, toolCallId, content) => {
12318
13704
  var make11 = (blobStore) => ({
12319
13705
  put: (toolCallId, content) => store(blobStore, toolCallId, content)
12320
13706
  });
12321
- var layer43 = Layer59.effect(exports_tool_output.ToolOutputStore, Service38.pipe(Effect65.map((blobStore) => exports_tool_output.ToolOutputStore.of(make11(blobStore)))));
13707
+ var layer44 = Layer59.effect(exports_tool_output.ToolOutputStore, Service38.pipe(Effect65.map((blobStore) => exports_tool_output.ToolOutputStore.of(make11(blobStore)))));
12322
13708
 
12323
13709
  // ../runtime/src/agent/sequence-allocator.ts
12324
13710
  import { Effect as Effect66, Ref as Ref17 } from "effect";
@@ -12353,6 +13739,20 @@ class Service41 extends Context54.Service()("@relayfx/runtime/AgentLoop") {
12353
13739
  }
12354
13740
  var jsonValue6 = (value) => Schema63.decodeUnknownSync(exports_shared_schema.JsonValue)(value);
12355
13741
  var toolNames = (agent) => HashSet6.fromIterable(agent.tool_names);
13742
+ var turnPolicyFromSnapshot = (snapshot2) => {
13743
+ switch (snapshot2.kind) {
13744
+ case "recurs":
13745
+ return exports_turn_policy.recurs(snapshot2.count);
13746
+ case "until-tool-call":
13747
+ return exports_turn_policy.untilToolCall(snapshot2.name);
13748
+ case "both":
13749
+ return exports_turn_policy.both(turnPolicyFromSnapshot(snapshot2.first), turnPolicyFromSnapshot(snapshot2.second));
13750
+ }
13751
+ };
13752
+ var turnPolicyFromDefinition = (agent) => {
13753
+ const cap = exports_turn_policy.recurs(agent.max_tool_turns ?? exports_agent_schema.defaultMaxToolTurns);
13754
+ return agent.turn_policy === undefined ? cap : exports_turn_policy.both(cap, turnPolicyFromSnapshot(agent.turn_policy));
13755
+ };
12356
13756
  var availableRegisteredTools = (agent, registered) => {
12357
13757
  const names = toolNames(agent);
12358
13758
  return registered.filter((tool2) => tool2.definition.name !== toolName && HashSet6.has(names, tool2.definition.name));
@@ -12666,7 +14066,7 @@ var compactionOptionsFromAgentMetadata = Effect67.fn("AgentLoop.compactionOption
12666
14066
  };
12667
14067
  });
12668
14068
  var effectiveCompactionOptions = (input) => input.compaction !== undefined ? Effect67.succeed(input.compaction ?? undefined) : compactionOptionsFromAgentMetadata(input);
12669
- var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
14069
+ var layer45 = Layer60.effect(Service41, Effect67.gen(function* () {
12670
14070
  const eventLog = yield* Service24;
12671
14071
  const languageModels = yield* Service34;
12672
14072
  const tools = yield* Service26;
@@ -12709,7 +14109,7 @@ var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
12709
14109
  const permissionsLayer = input.agent.permission_rules === undefined ? Layer60.empty : Option22.isNone(permissionRules) || Option22.isNone(waits) ? yield* Effect67.fail(new AgentLoopError({
12710
14110
  message: "Execution permission rules require PermissionRuleRepository and WaitService in context",
12711
14111
  next_event_sequence: input.eventSequence + 1
12712
- })) : layer40({
14112
+ })) : layer41({
12713
14113
  ruleset: input.agent.permission_rules,
12714
14114
  repository: permissionRules.value,
12715
14115
  waits: waits.value,
@@ -12724,7 +14124,7 @@ var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
12724
14124
  const steeringLayer = input.steeringEnabled !== true ? Layer60.empty : Option22.isNone(steeringRepository) ? yield* Effect67.fail(new AgentLoopError({
12725
14125
  message: "Execution steering requires SteeringRepository in context",
12726
14126
  next_event_sequence: input.eventSequence + 1
12727
- })) : layer41({
14127
+ })) : layer42({
12728
14128
  repository: steeringRepository.value,
12729
14129
  eventLog,
12730
14130
  allocator,
@@ -12764,7 +14164,7 @@ var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
12764
14164
  const agent = exports_agent.make({
12765
14165
  name: input.agent.name,
12766
14166
  toolkit,
12767
- policy: exports_turn_policy.recurs(input.agent.max_tool_turns ?? exports_agent_schema.defaultMaxToolTurns)
14167
+ policy: turnPolicyFromDefinition(input.agent)
12768
14168
  });
12769
14169
  if (toolOutputMaxBytes !== undefined && Option22.isNone(blobStore)) {
12770
14170
  return yield* Effect67.fail(new AgentLoopError({
@@ -12796,7 +14196,7 @@ var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
12796
14196
  ...toolOutputMaxBytes === undefined ? {} : { toolOutputMaxBytes },
12797
14197
  ...batonCompaction === undefined ? {} : { compaction: batonCompaction }
12798
14198
  };
12799
- const executorLayer = layer42({
14199
+ const executorLayer = layer43({
12800
14200
  toolRuntime: tools,
12801
14201
  eventLog,
12802
14202
  allocator,
@@ -12882,7 +14282,7 @@ var layer44 = Layer60.effect(Service41, Effect67.gen(function* () {
12882
14282
  const runFold = Effect67.gen(function* () {
12883
14283
  const base = yield* LanguageModel6.LanguageModel;
12884
14284
  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));
14285
+ 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
14286
  const withToolOutput = toolOutputStore === undefined ? folded : folded.pipe(Effect67.provideService(exports_tool_output.ToolOutputStore, toolOutputStore));
12887
14287
  const withCompaction = compactionService === undefined ? withToolOutput : withToolOutput.pipe(Effect67.provideService(exports_compaction.Compaction, compactionService));
12888
14288
  const withSession = sessionStore === undefined ? withCompaction : withCompaction.pipe(Effect67.provideService(exports_session.SessionStore, sessionStore));
@@ -12919,11 +14319,12 @@ var run3 = Effect67.fn("AgentLoop.run.call")(function* (input) {
12919
14319
  // ../runtime/src/cluster/execution-entity.ts
12920
14320
  var exports_execution_entity = {};
12921
14321
  __export(exports_execution_entity, {
12922
- layer: () => layer49,
14322
+ layer: () => layer50,
12923
14323
  entity: () => entity,
12924
14324
  client: () => client2,
12925
14325
  Start: () => Start,
12926
14326
  SignalWait: () => SignalWait,
14327
+ Dispatch: () => Dispatch,
12927
14328
  Cancel: () => Cancel
12928
14329
  });
12929
14330
  import { ClusterSchema, Entity } from "effect/unstable/cluster";
@@ -12941,7 +14342,8 @@ __export(exports_execution_workflow, {
12941
14342
  sessionEntryScope: () => sessionEntryScope,
12942
14343
  resume: () => resume3,
12943
14344
  poll: () => poll,
12944
- layer: () => layer48,
14345
+ layer: () => layer49,
14346
+ dispatchRequest: () => dispatchRequest,
12945
14347
  cancelRequest: () => cancelRequest,
12946
14348
  activeWorkflowExecutionIdForExecution: () => activeWorkflowExecutionIdForExecution,
12947
14349
  WaitSnapshot: () => WaitSnapshot,
@@ -12959,7 +14361,7 @@ __export(exports_execution_workflow, {
12959
14361
  ActivityNameTemplates: () => ActivityNameTemplates
12960
14362
  });
12961
14363
  import { Activity, DurableDeferred, Workflow } from "effect/unstable/workflow";
12962
- import { Effect as Effect73, Exit as Exit2, Option as Option26, Schema as Schema69 } from "effect";
14364
+ import { Effect as Effect74, Exit as Exit2, Option as Option26, Schema as Schema69 } from "effect";
12963
14365
 
12964
14366
  // ../runtime/src/child/parent-notifier-service.ts
12965
14367
  import { Context as Context55, Effect as Effect68, Layer as Layer61, Option as Option23, Ref as Ref19, Schema as Schema64 } from "effect";
@@ -13058,7 +14460,7 @@ __export(exports_skill_registry_service, {
13058
14460
  listRevisions: () => listRevisions4,
13059
14461
  listPins: () => listPins2,
13060
14462
  list: () => list12,
13061
- layer: () => layer45,
14463
+ layer: () => layer46,
13062
14464
  getRevision: () => getRevision4,
13063
14465
  getPinned: () => getPinned2,
13064
14466
  get: () => get13,
@@ -13139,7 +14541,7 @@ var toBatonSkill = (pin) => {
13139
14541
  };
13140
14542
  };
13141
14543
  var sourceError = (error) => new exports_skill_source.SkillSourceError({ source: "relay.skill_registry", message: error.message });
13142
- var layer45 = Layer62.effect(Service43, Effect69.gen(function* () {
14544
+ var layer46 = Layer62.effect(Service43, Effect69.gen(function* () {
13143
14545
  const repository = yield* exports_skill_definition_repository.Service;
13144
14546
  return Service43.of({
13145
14547
  register: Effect69.fn("SkillRegistry.register")(function* (input) {
@@ -13237,7 +14639,7 @@ __export(exports_execution_service, {
13237
14639
  send: () => send,
13238
14640
  run: () => run4,
13239
14641
  memoryLayer: () => memoryLayer32,
13240
- layer: () => layer46,
14642
+ layer: () => layer47,
13241
14643
  cancel: () => cancel3,
13242
14644
  accept: () => accept,
13243
14645
  Service: () => Service44,
@@ -13268,7 +14670,7 @@ var toExecution = (record2) => ({
13268
14670
  });
13269
14671
  var mapRepositoryError9 = (error) => new ExecutionServiceError({ message: error._tag });
13270
14672
  var mapEventLogError4 = (error) => new ExecutionServiceError({ message: error._tag });
13271
- var mapChildRunError2 = (error) => new ExecutionServiceError({ message: error._tag });
14673
+ var mapChildRunError2 = (error) => new ExecutionServiceError({ message: error._tag === "ChildRunServiceError" ? error.message : error._tag });
13272
14674
  var childExecutionId2 = (input) => input.child_execution_id ?? exports_ids_schema.ChildExecutionId.make(`${input.execution_id}:child:${input.address_id}`);
13273
14675
  var hasCompleteAgentDefinitionPin2 = (input) => {
13274
14676
  const present = [input.agentId !== undefined, input.agentRevision !== undefined, input.agentSnapshot !== undefined];
@@ -13416,7 +14818,7 @@ var updateStatus2 = Effect70.fn("ExecutionService.updateStatus")(function* (repo
13416
14818
  }).pipe(Effect70.mapError(mapRepositoryError9));
13417
14819
  return toExecution(record2);
13418
14820
  });
13419
- var layer46 = Layer63.effect(Service44, Effect70.gen(function* () {
14821
+ var layer47 = Layer63.effect(Service44, Effect70.gen(function* () {
13420
14822
  const repository = yield* exports_execution_repository.Service;
13421
14823
  const eventLog = yield* Service24;
13422
14824
  const childRuns = yield* Service31;
@@ -13538,7 +14940,7 @@ var layer46 = Layer63.effect(Service44, Effect70.gen(function* () {
13538
14940
  stream: (input) => eventLog.stream(input).pipe(Stream9.take(input.limit ?? 1000), Stream9.mapError((error) => mapEventLogError4(error)))
13539
14941
  });
13540
14942
  }));
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() })));
14943
+ 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
14944
  var testLayer48 = (implementation) => Layer63.succeed(Service44, Service44.of(implementation));
13543
14945
  var accept = Effect70.fn("ExecutionService.accept.call")(function* (input) {
13544
14946
  const service = yield* Service44;
@@ -13562,37 +14964,69 @@ var spawnChildRun = Effect70.fn("ExecutionService.spawnChildRun.call")(function*
13562
14964
  });
13563
14965
  var stream3 = (input) => Stream9.unwrap(Service44.pipe(Effect70.map((service) => service.stream(input))));
13564
14966
 
14967
+ // ../runtime/src/tool/tool-transition-coordinator.ts
14968
+ var exports_tool_transition_coordinator = {};
14969
+ __export(exports_tool_transition_coordinator, {
14970
+ sqlLayer: () => sqlLayer,
14971
+ memoryLayer: () => memoryLayer33,
14972
+ coordinate: () => coordinate,
14973
+ Service: () => Service45
14974
+ });
14975
+ import { Context as Context58, Effect as Effect71, Layer as Layer64, Semaphore as Semaphore4 } from "effect";
14976
+ import { SqlClient as SqlClient22 } from "effect/unstable/sql/SqlClient";
14977
+
14978
+ class Service45 extends Context58.Service()("@relayfx/runtime/ToolTransitionCoordinator") {
14979
+ }
14980
+ var make14 = Effect71.gen(function* () {
14981
+ const semaphore = yield* Semaphore4.make(1);
14982
+ return Service45.of({
14983
+ coordinate: (effect) => semaphore.withPermit(effect)
14984
+ });
14985
+ });
14986
+ var memoryLayer33 = Layer64.effect(Service45, make14);
14987
+ var sqlLayer = Layer64.effect(Service45, Effect71.gen(function* () {
14988
+ const sql3 = yield* SqlClient22;
14989
+ const semaphore = yield* Semaphore4.make(1);
14990
+ return Service45.of({
14991
+ coordinate: (effect) => semaphore.withPermit(sql3.withTransaction(effect))
14992
+ });
14993
+ }));
14994
+ var coordinate = Effect71.fn("ToolTransitionCoordinator.coordinate")(function* (effect) {
14995
+ const service = yield* Service45;
14996
+ return yield* service.coordinate(effect);
14997
+ });
14998
+
13565
14999
  // ../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";
15000
+ import { Context as Context60, Effect as Effect73, HashSet as HashSet7, Layer as Layer66, Option as Option25, Schema as Schema68 } from "effect";
13567
15001
 
13568
15002
  // ../runtime/src/workspace/workspace-runtime-service.ts
13569
- import { Context as Context58, Effect as Effect71, Layer as Layer64, Schema as Schema67 } from "effect";
15003
+ import { Context as Context59, Effect as Effect72, Layer as Layer65, Schema as Schema67 } from "effect";
13570
15004
 
13571
15005
  class WorkspaceRuntimeError extends Schema67.TaggedErrorClass()("WorkspaceRuntimeError", {
13572
15006
  message: Schema67.String
13573
15007
  }) {
13574
15008
  }
13575
15009
 
13576
- class Service45 extends Context58.Service()("@relayfx/runtime/WorkspaceRuntime") {
15010
+ class Service46 extends Context59.Service()("@relayfx/runtime/WorkspaceRuntime") {
13577
15011
  }
13578
15012
  var mapRuntimeError = (error) => new WorkspaceRuntimeError({
13579
15013
  message: error._tag === "WorkspaceNotFound" ? `Workspace not found: ${error.sandbox_ref}` : error.message
13580
15014
  });
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 }))))
15015
+ var layerFromHandle = (handle) => Layer65.succeed(Service46, Service46.of({
15016
+ readFile: Effect72.fn("WorkspaceRuntime.readFile")((path2) => handle.readFile(path2).pipe(Effect72.mapError(mapRuntimeError))),
15017
+ writeFile: Effect72.fn("WorkspaceRuntime.writeFile")((path2, content) => handle.writeFile(path2, content).pipe(Effect72.mapError(mapRuntimeError))),
15018
+ exec: Effect72.fn("WorkspaceRuntime.exec")((input) => handle.exec(input).pipe(Effect72.mapError((error) => new WorkspaceRuntimeError({ message: error.message }))))
13585
15019
  }));
13586
- var readFile = Effect71.fn("WorkspaceRuntime.readFile.call")(function* (path2) {
13587
- const service = yield* Service45;
15020
+ var readFile = Effect72.fn("WorkspaceRuntime.readFile.call")(function* (path2) {
15021
+ const service = yield* Service46;
13588
15022
  return yield* service.readFile(path2);
13589
15023
  });
13590
- var writeFile = Effect71.fn("WorkspaceRuntime.writeFile.call")(function* (path2, content) {
13591
- const service = yield* Service45;
15024
+ var writeFile = Effect72.fn("WorkspaceRuntime.writeFile.call")(function* (path2, content) {
15025
+ const service = yield* Service46;
13592
15026
  return yield* service.writeFile(path2, content);
13593
15027
  });
13594
- var exec = Effect71.fn("WorkspaceRuntime.exec.call")(function* (input) {
13595
- const service = yield* Service45;
15028
+ var exec = Effect72.fn("WorkspaceRuntime.exec.call")(function* (input) {
15029
+ const service = yield* Service46;
13596
15030
  return yield* service.exec(input);
13597
15031
  });
13598
15032
 
@@ -13612,7 +15046,7 @@ class WorkspacePlannerError extends Schema68.TaggedErrorClass()("WorkspacePlanne
13612
15046
  }) {
13613
15047
  }
13614
15048
 
13615
- class Service46 extends Context59.Service()("@relayfx/runtime/WorkspacePlanner") {
15049
+ class Service47 extends Context60.Service()("@relayfx/runtime/WorkspacePlanner") {
13616
15050
  }
13617
15051
  var selectedToolNames = (agent) => HashSet7.fromIterable(agent.tool_names);
13618
15052
  var selectedDefinitions = (input) => {
@@ -13624,11 +15058,11 @@ var needsWorkspace = (input) => selectedDefinitions(input).some(requiresWorkspac
13624
15058
  var leaseId = (executionId) => exports_ids_schema.WorkspaceLeaseId.make(`workspace-lease:${executionId}`);
13625
15059
  var mapRepositoryError10 = (error) => new WorkspacePlannerError({ message: error._tag });
13626
15060
  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
15061
+ var providerOrMissing = (executionId) => Effect73.serviceOption(Service30).pipe(Effect73.flatMap((provider) => Option25.match(provider, {
15062
+ onNone: () => Effect73.fail(new WorkspaceRuntimeMissing({ execution_id: executionId })),
15063
+ onSome: Effect73.succeed
13630
15064
  })));
13631
- var nextEventSequence3 = (eventLog, executionId) => eventLog.maxSequence(executionId).pipe(Effect72.map((max) => max === undefined ? 0 : max + 1), Effect72.catch(() => Effect72.succeed(0)));
15065
+ var nextEventSequence3 = (eventLog, executionId) => eventLog.maxSequence(executionId).pipe(Effect73.map((max) => max === undefined ? 0 : max + 1), Effect73.catch(() => Effect73.succeed(0)));
13632
15066
  var workspaceEvent = (type, lease, sequence, createdAt) => ({
13633
15067
  id: exports_ids_schema.EventId.make(`event:${lease.execution_id}:workspace:${type}:${sequence}`),
13634
15068
  execution_id: lease.execution_id,
@@ -13644,7 +15078,7 @@ var workspaceEvent = (type, lease, sequence, createdAt) => ({
13644
15078
  },
13645
15079
  created_at: createdAt
13646
15080
  });
13647
- var appendWorkspaceEvent = (eventLog, type, lease, sequence, createdAt) => appendIdempotentTo(eventLog, workspaceEvent(type, lease, sequence, createdAt)).pipe(Effect72.mapError(mapEventLogError5), Effect72.asVoid);
15081
+ var appendWorkspaceEvent = (eventLog, type, lease, sequence, createdAt) => appendIdempotentTo(eventLog, workspaceEvent(type, lease, sequence, createdAt)).pipe(Effect73.mapError(mapEventLogError5), Effect73.asVoid);
13648
15082
  var providerAcquireSpec = (input) => ({
13649
15083
  executionId: input.executionId,
13650
15084
  ...input.request === undefined ? {} : { request: input.request }
@@ -13661,50 +15095,50 @@ var planResult = (lease, handle) => ({
13661
15095
  runtimeLayer: layerFromHandle(handle)
13662
15096
  });
13663
15097
  var missingRef = (executionId) => new WorkspaceLeaseMissingRef({ execution_id: executionId });
13664
- var ensureFromExisting = Effect72.fn("WorkspacePlanner.ensureFromExisting")(function* (repository, eventLog, provider, lease, input) {
15098
+ var ensureFromExisting = Effect73.fn("WorkspacePlanner.ensureFromExisting")(function* (repository, eventLog, provider, lease, input) {
13665
15099
  if (lease.sandbox_ref === undefined) {
13666
15100
  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));
15101
+ const running2 = yield* repository.markRunning({ executionId: input.executionId, sandboxRef: handle2.ref, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13668
15102
  const sequence2 = yield* nextEventSequence3(eventLog, input.executionId);
13669
15103
  yield* appendWorkspaceEvent(eventLog, "workspace.lease.acquired", running2, sequence2, input.now);
13670
15104
  return planResult(running2, handle2);
13671
15105
  }
13672
15106
  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));
15107
+ const running = yield* repository.markResumed({ executionId: input.executionId, sandboxRef: handle.ref, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13674
15108
  const sequence = yield* nextEventSequence3(eventLog, input.executionId);
13675
15109
  yield* appendWorkspaceEvent(eventLog, "workspace.resumed", running, sequence, input.now);
13676
15110
  return planResult(running, handle);
13677
15111
  });
13678
- var layer47 = Layer65.effect(Service46, Effect72.gen(function* () {
15112
+ var layer48 = Layer66.effect(Service47, Effect73.gen(function* () {
13679
15113
  const repository = yield* exports_workspace_lease_repository.Service;
13680
15114
  const eventLog = yield* Service24;
13681
- return Service46.of({
13682
- ensure: Effect72.fn("WorkspacePlanner.ensure")(function* (input) {
15115
+ return Service47.of({
15116
+ ensure: Effect73.fn("WorkspacePlanner.ensure")(function* (input) {
13683
15117
  if (!needsWorkspace(input))
13684
15118
  return;
13685
15119
  const provider = yield* providerOrMissing(input.executionId);
13686
- const existing = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15120
+ const existing = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13687
15121
  if (existing !== undefined && existing.status !== "released" && existing.status !== "failed") {
13688
15122
  return yield* ensureFromExisting(repository, eventLog, provider, existing, input);
13689
15123
  }
13690
- const planned = yield* repository.plan(planInput(input, provider)).pipe(Effect72.mapError(mapRepositoryError10));
15124
+ const planned = yield* repository.plan(planInput(input, provider)).pipe(Effect73.mapError(mapRepositoryError10));
13691
15125
  let sequence = yield* nextEventSequence3(eventLog, input.executionId);
13692
15126
  yield* appendWorkspaceEvent(eventLog, "workspace.lease.planned", planned, sequence, input.now);
13693
15127
  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));
15128
+ const running = yield* repository.markRunning({ executionId: input.executionId, sandboxRef: handle.ref, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13695
15129
  sequence += 1;
13696
15130
  yield* appendWorkspaceEvent(eventLog, "workspace.lease.acquired", running, sequence, input.now);
13697
15131
  return planResult(running, handle);
13698
15132
  }),
13699
- suspend: Effect72.fn("WorkspacePlanner.suspend")(function* (input) {
13700
- const lease = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15133
+ suspend: Effect73.fn("WorkspacePlanner.suspend")(function* (input) {
15134
+ const lease = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13701
15135
  if (lease === undefined || lease.status === "released" || lease.status === "failed")
13702
15136
  return;
13703
15137
  if (lease.sandbox_ref === undefined)
13704
- return yield* Effect72.fail(missingRef(input.executionId));
15138
+ return yield* Effect73.fail(missingRef(input.executionId));
13705
15139
  const provider = yield* providerOrMissing(input.executionId);
13706
15140
  if (!provider.capabilities.can_suspend && !provider.capabilities.persistent_by_default) {
13707
- return yield* Effect72.fail(new WorkspaceCapabilityUnsupported({
15141
+ return yield* Effect73.fail(new WorkspaceCapabilityUnsupported({
13708
15142
  capability: "suspend",
13709
15143
  provider_key: provider.providerKey
13710
15144
  }));
@@ -13712,84 +15146,84 @@ var layer47 = Layer65.effect(Service46, Effect72.gen(function* () {
13712
15146
  if (provider.capabilities.can_suspend) {
13713
15147
  yield* provider.suspend(lease.sandbox_ref);
13714
15148
  }
13715
- const suspended2 = yield* repository.markSuspended({ executionId: input.executionId, updatedAt: input.now }).pipe(Effect72.mapError(mapRepositoryError10));
15149
+ const suspended2 = yield* repository.markSuspended({ executionId: input.executionId, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13716
15150
  const sequence = yield* nextEventSequence3(eventLog, input.executionId);
13717
15151
  yield* appendWorkspaceEvent(eventLog, "workspace.suspended", suspended2, sequence, input.now);
13718
15152
  return suspended2;
13719
15153
  }),
13720
- resume: Effect72.fn("WorkspacePlanner.resume")(function* (input) {
13721
- const lease = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15154
+ resume: Effect73.fn("WorkspacePlanner.resume")(function* (input) {
15155
+ const lease = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13722
15156
  if (lease === undefined || lease.status === "released" || lease.status === "failed")
13723
15157
  return;
13724
15158
  if (lease.sandbox_ref === undefined)
13725
- return yield* Effect72.fail(missingRef(input.executionId));
15159
+ return yield* Effect73.fail(missingRef(input.executionId));
13726
15160
  const provider = yield* providerOrMissing(input.executionId);
13727
15161
  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));
15162
+ const running = yield* repository.markResumed({ executionId: input.executionId, sandboxRef: handle.ref, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13729
15163
  const sequence = yield* nextEventSequence3(eventLog, input.executionId);
13730
15164
  yield* appendWorkspaceEvent(eventLog, "workspace.resumed", running, sequence, input.now);
13731
15165
  return planResult(running, handle);
13732
15166
  }),
13733
- attach: Effect72.fn("WorkspacePlanner.attach")(function* (input) {
13734
- const lease = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15167
+ attach: Effect73.fn("WorkspacePlanner.attach")(function* (input) {
15168
+ const lease = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13735
15169
  if (lease === undefined || lease.status === "released" || lease.status === "failed")
13736
15170
  return;
13737
15171
  if (lease.sandbox_ref === undefined)
13738
- return yield* Effect72.fail(missingRef(input.executionId));
15172
+ return yield* Effect73.fail(missingRef(input.executionId));
13739
15173
  const provider = yield* providerOrMissing(input.executionId);
13740
15174
  const handle = yield* provider.resume(lease.sandbox_ref);
13741
15175
  return planResult(lease, handle);
13742
15176
  }),
13743
- release: Effect72.fn("WorkspacePlanner.release")(function* (input) {
13744
- const lease = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15177
+ release: Effect73.fn("WorkspacePlanner.release")(function* (input) {
15178
+ const lease = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13745
15179
  if (lease === undefined || lease.status === "released" || lease.status === "failed")
13746
15180
  return;
13747
15181
  if (lease.sandbox_ref === undefined)
13748
- return yield* Effect72.fail(missingRef(input.executionId));
15182
+ return yield* Effect73.fail(missingRef(input.executionId));
13749
15183
  const provider = yield* providerOrMissing(input.executionId);
13750
15184
  yield* provider.destroy(lease.sandbox_ref);
13751
- const released = yield* repository.markReleased({ executionId: input.executionId, updatedAt: input.now }).pipe(Effect72.mapError(mapRepositoryError10));
15185
+ const released = yield* repository.markReleased({ executionId: input.executionId, updatedAt: input.now }).pipe(Effect73.mapError(mapRepositoryError10));
13752
15186
  const sequence = yield* nextEventSequence3(eventLog, input.executionId);
13753
15187
  yield* appendWorkspaceEvent(eventLog, "workspace.lease.released", released, sequence, input.now);
13754
15188
  return released;
13755
15189
  }),
13756
- fail: Effect72.fn("WorkspacePlanner.fail")(function* (input) {
13757
- const lease = yield* repository.getByExecution(input.executionId).pipe(Effect72.mapError(mapRepositoryError10));
15190
+ fail: Effect73.fn("WorkspacePlanner.fail")(function* (input) {
15191
+ const lease = yield* repository.getByExecution(input.executionId).pipe(Effect73.mapError(mapRepositoryError10));
13758
15192
  if (lease === undefined || lease.status === "released" || lease.status === "failed")
13759
15193
  return;
13760
15194
  const failed = yield* repository.markFailed({
13761
15195
  executionId: input.executionId,
13762
15196
  updatedAt: input.now,
13763
15197
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
13764
- }).pipe(Effect72.mapError(mapRepositoryError10));
15198
+ }).pipe(Effect73.mapError(mapRepositoryError10));
13765
15199
  const sequence = yield* nextEventSequence3(eventLog, input.executionId);
13766
15200
  yield* appendWorkspaceEvent(eventLog, "workspace.lease.failed", failed, sequence, input.now);
13767
15201
  return failed;
13768
15202
  })
13769
15203
  });
13770
15204
  }));
13771
- var ensure2 = Effect72.fn("WorkspacePlanner.ensure.call")(function* (input) {
13772
- const service = yield* Service46;
15205
+ var ensure2 = Effect73.fn("WorkspacePlanner.ensure.call")(function* (input) {
15206
+ const service = yield* Service47;
13773
15207
  return yield* service.ensure(input);
13774
15208
  });
13775
- var suspend2 = Effect72.fn("WorkspacePlanner.suspend.call")(function* (input) {
13776
- const service = yield* Service46;
15209
+ var suspend2 = Effect73.fn("WorkspacePlanner.suspend.call")(function* (input) {
15210
+ const service = yield* Service47;
13777
15211
  return yield* service.suspend(input);
13778
15212
  });
13779
- var resume2 = Effect72.fn("WorkspacePlanner.resume.call")(function* (input) {
13780
- const service = yield* Service46;
15213
+ var resume2 = Effect73.fn("WorkspacePlanner.resume.call")(function* (input) {
15214
+ const service = yield* Service47;
13781
15215
  return yield* service.resume(input);
13782
15216
  });
13783
- var attach = Effect72.fn("WorkspacePlanner.attach.call")(function* (input) {
13784
- const service = yield* Service46;
15217
+ var attach = Effect73.fn("WorkspacePlanner.attach.call")(function* (input) {
15218
+ const service = yield* Service47;
13785
15219
  return yield* service.attach(input);
13786
15220
  });
13787
- var release2 = Effect72.fn("WorkspacePlanner.release.call")(function* (input) {
13788
- const service = yield* Service46;
15221
+ var release2 = Effect73.fn("WorkspacePlanner.release.call")(function* (input) {
15222
+ const service = yield* Service47;
13789
15223
  return yield* service.release(input);
13790
15224
  });
13791
- var fail = Effect72.fn("WorkspacePlanner.fail.call")(function* (input) {
13792
- const service = yield* Service46;
15225
+ var fail = Effect73.fn("WorkspacePlanner.fail.call")(function* (input) {
15226
+ const service = yield* Service47;
13793
15227
  return yield* service.fail(input);
13794
15228
  });
13795
15229
 
@@ -13936,17 +15370,17 @@ var resolveLocalAgentTarget = (addressId) => Activity.make({
13936
15370
  name: ActivityNames.resolveLocalAgent,
13937
15371
  success: LocalAgentTarget,
13938
15372
  error: ExecutionWorkflowFailed,
13939
- execute: resolveLocalAgent(addressId).pipe(Effect73.mapError(mapAddressResolutionError))
15373
+ execute: resolveLocalAgent(addressId).pipe(Effect74.mapError(mapAddressResolutionError))
13940
15374
  });
13941
- var resolveStartInput = Effect73.fn("ExecutionWorkflow.resolveStartInput")(function* (input) {
15375
+ var resolveStartInput = Effect74.fn("ExecutionWorkflow.resolveStartInput")(function* (input) {
13942
15376
  const pinCount = agentDefinitionPinCount(input);
13943
15377
  if (input.agent_tool_input_schema_digests !== undefined && pinCount !== 3) {
13944
- return yield* Effect73.fail(invalidAgentDefinitionDigestPin());
15378
+ return yield* Effect74.fail(invalidAgentDefinitionDigestPin());
13945
15379
  }
13946
15380
  if (pinCount === 3)
13947
15381
  return input;
13948
15382
  if (pinCount > 0)
13949
- return yield* Effect73.fail(invalidAgentDefinitionPin());
15383
+ return yield* Effect74.fail(invalidAgentDefinitionPin());
13950
15384
  const target = yield* resolveLocalAgentTarget(input.root_address_id);
13951
15385
  return {
13952
15386
  ...input,
@@ -13960,7 +15394,7 @@ var acceptExecution = (input) => Activity.make({
13960
15394
  name: ActivityNames.accept,
13961
15395
  success: exports_execution_schema.Execution,
13962
15396
  error: ExecutionWorkflowFailed,
13963
- execute: Effect73.gen(function* () {
15397
+ execute: Effect74.gen(function* () {
13964
15398
  const accepted2 = yield* accept({
13965
15399
  executionId: input.execution_id,
13966
15400
  rootAddressId: input.root_address_id,
@@ -13972,13 +15406,13 @@ var acceptExecution = (input) => Activity.make({
13972
15406
  ...input.agent_snapshot === undefined ? {} : { agentSnapshot: input.agent_snapshot },
13973
15407
  ...input.agent_tool_input_schema_digests === undefined ? {} : { agentToolInputSchemaDigests: input.agent_tool_input_schema_digests },
13974
15408
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
13975
- }).pipe(Effect73.mapError(mapExecutionError));
15409
+ }).pipe(Effect74.mapError(mapExecutionError));
13976
15410
  const skillDefinitionIds = input.agent_snapshot?.skill_definition_ids ?? [];
13977
15411
  if (skillDefinitionIds.length > 0) {
13978
15412
  yield* pinExecution2({
13979
15413
  execution_id: input.execution_id,
13980
15414
  skill_definition_ids: skillDefinitionIds
13981
- }).pipe(Effect73.mapError(mapSkillRegistryError));
15415
+ }).pipe(Effect74.mapError(mapSkillRegistryError));
13982
15416
  }
13983
15417
  return accepted2;
13984
15418
  })
@@ -13988,50 +15422,109 @@ var waitIdFromRecord = (record2) => {
13988
15422
  const waitId = record2.metadata.wait_id;
13989
15423
  return typeof waitId === "string" ? exports_ids_schema.WaitId.make(waitId) : undefined;
13990
15424
  };
13991
- var openChildStatuses = new Set(["queued", "running", "waiting"]);
13992
- var childCancelReason = "parent cancelled";
13993
- var cancelChildExecution = Effect73.fn("ExecutionWorkflow.cancelChildExecution")(function* (executionId, cancelledAt) {
15425
+ var prepareCancellation = Effect74.fn("ExecutionWorkflow.prepareCancellation")(function* (input) {
13994
15426
  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}` }));
15427
+ const waits = yield* exports_envelope_repository.Service;
15428
+ const toolCalls2 = yield* exports_tool_call_repository.Service;
15429
+ const coordinator = yield* Service45;
15430
+ const eventLog = yield* Service24;
15431
+ return yield* coordinator.coordinate(Effect74.gen(function* () {
15432
+ const record2 = yield* repository.get(input.execution_id).pipe(Effect74.mapError(mapRepositoryError11));
15433
+ if (record2 === undefined) {
15434
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: `Execution not found: ${input.execution_id}` }));
14002
15435
  }
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
- });
15436
+ if (terminalExecutionStatuses.has(record2.status)) {
15437
+ return { record: record2, status: record2.status, signals: [], terminalNoop: true };
14018
15438
  }
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
15439
+ const records = yield* waits.listAllWaits({ executionId: record2.id }).pipe(Effect74.mapError((error) => new ExecutionWorkflowFailed({ message: error._tag })));
15440
+ const currentWaitId = record2.status === "waiting" ? waitIdFromRecord(record2) : undefined;
15441
+ if (record2.status === "waiting" && currentWaitId === undefined) {
15442
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: `Waiting execution missing wait id: ${record2.id}` }));
15443
+ }
15444
+ const signals = [];
15445
+ const cancelledCallIds = [];
15446
+ let currentWaitState;
15447
+ for (const wait of records) {
15448
+ const isCurrent = wait.id === currentWaitId;
15449
+ const isToolWait = wait.metadata.kind === "tool-placement";
15450
+ if (wait.state === "open" && (isCurrent || isToolWait)) {
15451
+ const eventSequence = yield* nextEventSequence4(eventLog, record2.id);
15452
+ const result = yield* cancel2({
15453
+ waitId: wait.id,
15454
+ cancelledAt: input.cancelled_at,
15455
+ eventSequence,
15456
+ metadata: { reason: input.reason ?? "Execution cancelled" }
15457
+ }).pipe(Effect74.mapError(mapWaitError2));
15458
+ if (result.wait.state === "cancelled") {
15459
+ signals.push({ waitId: wait.id, state: "cancelled" });
15460
+ if (isToolWait && typeof wait.metadata.tool_call_id === "string") {
15461
+ cancelledCallIds.push(exports_ids_schema.ToolCallId.make(wait.metadata.tool_call_id));
15462
+ }
15463
+ }
15464
+ if (isCurrent && result.wait.state !== "open")
15465
+ currentWaitState = result.wait.state;
15466
+ continue;
15467
+ }
15468
+ if (isToolWait && wait.state === "cancelled" && typeof wait.metadata.tool_call_id === "string") {
15469
+ cancelledCallIds.push(exports_ids_schema.ToolCallId.make(wait.metadata.tool_call_id));
15470
+ }
15471
+ if (isCurrent && wait.state !== "open") {
15472
+ currentWaitState = wait.state;
15473
+ signals.push({ waitId: wait.id, state: wait.state });
15474
+ }
14029
15475
  }
14030
- }).pipe(Effect73.mapError(mapRepositoryError11));
15476
+ 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)));
15477
+ yield* toolCalls2.failOpenForExecution({
15478
+ executionId: record2.id,
15479
+ callIds: [...cancelledCallIds, ...immediateCallIds],
15480
+ message: "Tool execution cancelled",
15481
+ failedAt: input.cancelled_at
15482
+ }).pipe(Effect74.mapError((error) => new ExecutionWorkflowFailed({ message: error._tag })));
15483
+ const updated = yield* repository.transition({
15484
+ id: record2.id,
15485
+ status: record2.status,
15486
+ updatedAt: input.cancelled_at,
15487
+ metadata: {
15488
+ ...record2.metadata,
15489
+ cancellation_requested: true,
15490
+ ...input.reason === undefined ? {} : { cancellation_reason: input.reason }
15491
+ }
15492
+ }).pipe(Effect74.mapError(mapRepositoryError11));
15493
+ return {
15494
+ record: updated,
15495
+ status: currentWaitState === "cancelled" ? "cancelled" : updated.status,
15496
+ signals,
15497
+ terminalNoop: false
15498
+ };
15499
+ })).pipe(Effect74.mapError((error) => error instanceof ExecutionWorkflowFailed ? error : new ExecutionWorkflowFailed({ message: "Tool cancellation transaction failed" })));
15500
+ });
15501
+ var signalPreparedCancellation = Effect74.fn("ExecutionWorkflow.signalPreparedCancellation")(function* (prepared, signaledAt) {
15502
+ for (const pending of prepared.signals) {
15503
+ yield* signalWait({
15504
+ workflow_execution_id: yield* workflowExecutionIdForExecution(prepared.record.id, workflowGenerationFromRecord(prepared.record)),
15505
+ wait_id: pending.waitId,
15506
+ state: pending.state,
15507
+ signaled_at: signaledAt
15508
+ });
15509
+ }
14031
15510
  });
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* () {
15511
+ var openChildStatuses = new Set(["queued", "running", "waiting"]);
15512
+ var childCancelReason = "parent cancelled";
15513
+ var cancelChildExecution = Effect74.fn("ExecutionWorkflow.cancelChildExecution")(function* (executionId, cancelledAt) {
15514
+ const repository = yield* exports_execution_repository.Service;
15515
+ const record2 = yield* repository.get(executionId).pipe(Effect74.mapError(mapRepositoryError11));
15516
+ if (record2 === undefined)
15517
+ return;
15518
+ const prepared = yield* prepareCancellation({
15519
+ execution_id: executionId,
15520
+ cancelled_at: cancelledAt,
15521
+ reason: childCancelReason
15522
+ });
15523
+ yield* signalPreparedCancellation(prepared, cancelledAt);
15524
+ });
15525
+ var cancelOpenChildren = Effect74.fn("ExecutionWorkflow.cancelOpenChildren")(function* (executionId, cancelledAt) {
15526
+ const children = yield* exports_child_execution_repository.listByExecution(executionId).pipe(Effect74.mapError(mapChildExecutionRepositoryError));
15527
+ yield* Effect74.forEach(children.filter((child) => openChildStatuses.has(child.status)), (child) => Effect74.gen(function* () {
14035
15528
  yield* exports_child_execution_repository.updateStatus({
14036
15529
  id: child.id,
14037
15530
  status: "cancelled",
@@ -14042,7 +15535,7 @@ var cancelOpenChildren = Effect73.fn("ExecutionWorkflow.cancelOpenChildren")(fun
14042
15535
  cancellation_reason: childCancelReason,
14043
15536
  cancellation_requested_at: cancelledAt
14044
15537
  }
14045
- }).pipe(Effect73.mapError(mapChildExecutionRepositoryError));
15538
+ }).pipe(Effect74.mapError(mapChildExecutionRepositoryError));
14046
15539
  yield* cancelChildExecution(exports_ids_schema.ExecutionId.make(child.id), cancelledAt);
14047
15540
  }), { discard: true });
14048
15541
  });
@@ -14050,7 +15543,7 @@ var cancelExecution = (input, turn, reason) => Activity.make({
14050
15543
  name: ActivityNames.cancel(turn),
14051
15544
  success: exports_execution_schema.Execution,
14052
15545
  error: ExecutionWorkflowFailed,
14053
- execute: Effect73.gen(function* () {
15546
+ execute: Effect74.gen(function* () {
14054
15547
  yield* cancelOpenChildren(input.execution_id, input.completed_at);
14055
15548
  const eventLog = yield* Service24;
14056
15549
  const eventSequence = yield* nextEventSequence4(eventLog, input.execution_id);
@@ -14059,16 +15552,16 @@ var cancelExecution = (input, turn, reason) => Activity.make({
14059
15552
  eventSequence,
14060
15553
  cancelledAt: input.completed_at,
14061
15554
  reason
14062
- }).pipe(Effect73.mapError(mapExecutionError));
15555
+ }).pipe(Effect74.mapError(mapExecutionError));
14063
15556
  })
14064
15557
  });
14065
15558
  var loadCancellationRequested = (input, turn) => Activity.make({
14066
15559
  name: ActivityNames.checkCancel(turn),
14067
15560
  success: Schema69.Boolean,
14068
15561
  error: ExecutionWorkflowFailed,
14069
- execute: Effect73.gen(function* () {
15562
+ execute: Effect74.gen(function* () {
14070
15563
  const repository = yield* exports_execution_repository.Service;
14071
- const record2 = yield* repository.get(input.execution_id).pipe(Effect73.mapError(mapRepositoryError11));
15564
+ const record2 = yield* repository.get(input.execution_id).pipe(Effect74.mapError(mapRepositoryError11));
14072
15565
  return record2?.metadata?.cancellation_requested === true;
14073
15566
  })
14074
15567
  });
@@ -14076,7 +15569,7 @@ var loadWait = (name, waitId) => Activity.make({
14076
15569
  name,
14077
15570
  success: Schema69.UndefinedOr(WaitSnapshot),
14078
15571
  error: ExecutionWorkflowFailed,
14079
- execute: get11(waitId).pipe(Effect73.map((record2) => record2 === undefined ? undefined : toWaitSnapshot(record2)), Effect73.mapError(mapWaitError2))
15572
+ execute: get11(waitId).pipe(Effect74.map((record2) => record2 === undefined ? undefined : toWaitSnapshot(record2)), Effect74.mapError(mapWaitError2))
14080
15573
  });
14081
15574
  var markWaiting = (input, repository, wait) => Activity.make({
14082
15575
  name: ActivityNames.markWaiting(wait.id),
@@ -14091,7 +15584,7 @@ var markWaiting = (input, repository, wait) => Activity.make({
14091
15584
  wait_state: wait.state,
14092
15585
  ...generationMetadata(workflowGenerationForStart(input))
14093
15586
  }
14094
- }).pipe(Effect73.mapError(mapRepositoryError11), Effect73.map((record2) => ({
15587
+ }).pipe(Effect74.mapError(mapRepositoryError11), Effect74.map((record2) => ({
14095
15588
  id: record2.id,
14096
15589
  root_address_id: record2.rootAddressId,
14097
15590
  ...record2.sessionId === undefined ? {} : { session_id: record2.sessionId },
@@ -14130,26 +15623,26 @@ var metadataSetting = (input, key2) => {
14130
15623
  var executionMetadataSetting = (input, key2) => hasMetadataKey(input.metadata, key2) ? input.metadata?.[key2] : undefined;
14131
15624
  var decodeOptionalNumberSetting = (value, key2, valid) => {
14132
15625
  if (value === undefined)
14133
- return Effect73.succeed(undefined);
15626
+ return Effect74.succeed(undefined);
14134
15627
  if (value === null || value === false)
14135
- return Effect73.succeed(null);
15628
+ return Effect74.succeed(null);
14136
15629
  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` }));
15630
+ return Effect74.succeed(value);
15631
+ return Effect74.fail(new ExecutionWorkflowFailed({ message: `${key2} metadata value is invalid` }));
14139
15632
  };
14140
- var optionalNumberForStart = (input, key2, valid) => decodeOptionalNumberSetting(metadataSetting(input, key2), key2, valid).pipe(Effect73.map((value) => value === null ? undefined : value));
15633
+ var optionalNumberForStart = (input, key2, valid) => decodeOptionalNumberSetting(metadataSetting(input, key2), key2, valid).pipe(Effect74.map((value) => value === null ? undefined : value));
14141
15634
  var continueAsNewAfterTurnsForStart = (input) => optionalNumberForStart(input, continueAsNewAfterTurnsMetadataKey, (value) => Number.isInteger(value) && value > 0);
14142
15635
  var toolOutputMaxBytesForStart = (input) => decodeOptionalNumberSetting(metadataSetting(input, toolOutputMaxBytesMetadataKey), toolOutputMaxBytesMetadataKey, (value) => value >= 0);
14143
15636
  var decodeCompactionEnabled = (value) => {
14144
15637
  if (value === undefined)
14145
- return Effect73.succeed(undefined);
15638
+ return Effect74.succeed(undefined);
14146
15639
  if (value === null || value === false)
14147
- return Effect73.succeed(null);
15640
+ return Effect74.succeed(null);
14148
15641
  if (value === true)
14149
- return Effect73.succeed(true);
14150
- return Effect73.fail(new ExecutionWorkflowFailed({ message: "compaction_enabled metadata value must be true or false" }));
15642
+ return Effect74.succeed(true);
15643
+ return Effect74.fail(new ExecutionWorkflowFailed({ message: "compaction_enabled metadata value must be true or false" }));
14151
15644
  };
14152
- var compactionForStart = Effect73.fn("ExecutionWorkflow.compactionForStart")(function* (input) {
15645
+ var compactionForStart = Effect74.fn("ExecutionWorkflow.compactionForStart")(function* (input) {
14153
15646
  const executionEnabled = yield* decodeCompactionEnabled(executionMetadataSetting(input, compactionEnabledMetadataKey));
14154
15647
  if (executionEnabled === null)
14155
15648
  return null;
@@ -14165,8 +15658,8 @@ var compactionForStart = Effect73.fn("ExecutionWorkflow.compactionForStart")(fun
14165
15658
  ...keepRecentTokens === undefined ? {} : { keepRecentTokens }
14166
15659
  };
14167
15660
  });
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) {
15661
+ 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" }));
15662
+ var memorySubjectForStart = Effect74.fn("ExecutionWorkflow.memorySubjectForStart")(function* (input) {
14170
15663
  const executionSubject = memorySubjectFromMetadata(input.metadata);
14171
15664
  if (executionSubject !== undefined)
14172
15665
  return yield* decodeMemorySubject(executionSubject);
@@ -14180,21 +15673,21 @@ var steeringEnabledForStart = (input) => {
14180
15673
  return executionSetting === true;
14181
15674
  return steeringMetadataValue(input.agent_snapshot?.metadata) === true;
14182
15675
  };
14183
- var nextEventSequence4 = (eventLog, executionId) => eventLog.maxSequence(executionId).pipe(Effect73.map((max) => max === undefined ? 0 : max + 1), Effect73.mapError(mapEventLogError6));
15676
+ var nextEventSequence4 = (eventLog, executionId) => eventLog.maxSequence(executionId).pipe(Effect74.map((max) => max === undefined ? 0 : max + 1), Effect74.mapError(mapEventLogError6));
14184
15677
  var ensureWorkspace = (input) => Activity.make({
14185
15678
  name: ActivityNames.ensureWorkspace,
14186
15679
  success: Schema69.UndefinedOr(exports_workspace_schema.WorkspaceLeaseRecord),
14187
15680
  error: ExecutionWorkflowFailed,
14188
- execute: Effect73.gen(function* () {
15681
+ execute: Effect74.gen(function* () {
14189
15682
  if (input.agent_snapshot === undefined)
14190
- return yield* Effect73.fail(missingAgentSnapshot());
15683
+ return yield* Effect74.fail(missingAgentSnapshot());
14191
15684
  const tools = yield* Service26;
14192
15685
  const plan2 = yield* ensure2({
14193
15686
  executionId: input.execution_id,
14194
15687
  agent: input.agent_snapshot,
14195
15688
  toolDefinitions: yield* tools.definitions,
14196
15689
  now: input.started_at
14197
- }).pipe(Effect73.mapError(mapWorkspaceError));
15690
+ }).pipe(Effect74.mapError(mapWorkspaceError));
14198
15691
  return plan2?.lease;
14199
15692
  })
14200
15693
  });
@@ -14202,34 +15695,34 @@ var suspendWorkspace = (input, key2) => Activity.make({
14202
15695
  name: ActivityNames.suspendWorkspace(key2),
14203
15696
  success: Schema69.UndefinedOr(exports_workspace_schema.WorkspaceLeaseRecord),
14204
15697
  error: ExecutionWorkflowFailed,
14205
- execute: suspend2({ executionId: input.execution_id, now: input.started_at }).pipe(Effect73.mapError(mapWorkspaceError))
15698
+ execute: suspend2({ executionId: input.execution_id, now: input.started_at }).pipe(Effect74.mapError(mapWorkspaceError))
14206
15699
  });
14207
15700
  var resumeWorkspace = (input, key2) => Activity.make({
14208
15701
  name: ActivityNames.resumeWorkspace(key2),
14209
15702
  success: Schema69.UndefinedOr(exports_workspace_schema.WorkspaceLeaseRecord),
14210
15703
  error: ExecutionWorkflowFailed,
14211
- execute: resume2({ executionId: input.execution_id, now: input.started_at }).pipe(Effect73.map((plan2) => plan2?.lease), Effect73.mapError(mapWorkspaceError))
15704
+ execute: resume2({ executionId: input.execution_id, now: input.started_at }).pipe(Effect74.map((plan2) => plan2?.lease), Effect74.mapError(mapWorkspaceError))
14212
15705
  });
14213
15706
  var releaseWorkspace = (input) => Activity.make({
14214
15707
  name: ActivityNames.releaseWorkspace,
14215
15708
  success: Schema69.UndefinedOr(exports_workspace_schema.WorkspaceLeaseRecord),
14216
15709
  error: ExecutionWorkflowFailed,
14217
- execute: release2({ executionId: input.execution_id, now: input.completed_at }).pipe(Effect73.mapError(mapWorkspaceError))
15710
+ execute: release2({ executionId: input.execution_id, now: input.completed_at }).pipe(Effect74.mapError(mapWorkspaceError))
14218
15711
  });
14219
15712
  var failWorkspace = (input, error) => fail({
14220
15713
  executionId: input.execution_id,
14221
15714
  now: input.completed_at,
14222
15715
  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));
15716
+ }).pipe(Effect74.catch(() => Effect74.void));
15717
+ var attachWorkspace = (input) => attach({ executionId: input.execution_id, now: input.started_at }).pipe(Effect74.mapError(mapWorkspaceError));
14225
15718
  var sessionEntryScope = (input, turn) => `${input.execution_id}:${workflowGenerationForStart(input)}:complete:${turn}`;
14226
15719
  var completeExecution = (input, waitId, waitState, workspaceRuntimeLayer, turn, pendingToolCall) => Activity.make({
14227
15720
  name: ActivityNames.complete(turn),
14228
15721
  success: exports_execution_schema.Execution,
14229
15722
  error: ExecutionWorkflowFailed,
14230
- execute: Effect73.gen(function* () {
15723
+ execute: Effect74.gen(function* () {
14231
15724
  if (input.agent_snapshot === undefined)
14232
- return yield* Effect73.fail(missingAgentSnapshot());
15725
+ return yield* Effect74.fail(missingAgentSnapshot());
14233
15726
  const agentLoop = yield* Service41;
14234
15727
  const eventLog = yield* Service24;
14235
15728
  const runEventSequence = yield* nextEventSequence4(eventLog, input.execution_id);
@@ -14268,18 +15761,18 @@ var completeExecution = (input, waitId, waitState, workspaceRuntimeLayer, turn,
14268
15761
  agent_snapshot: child.agentSnapshot,
14269
15762
  ...child.agentToolInputSchemaDigests === undefined ? {} : { agent_tool_input_schema_digests: child.agentToolInputSchemaDigests },
14270
15763
  metadata: child.metadata
14271
- }, { discard: true }).pipe(Effect73.asVoid)
15764
+ }, { discard: true }).pipe(Effect74.asVoid)
14272
15765
  });
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) => ({
15766
+ 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 })))));
15767
+ const workspaceLoopProgram = workspaceRuntimeLayer === undefined ? skillLoopProgram : skillLoopProgram.pipe(Effect74.provide(workspaceRuntimeLayer));
15768
+ const program = workspaceLoopProgram.pipe(Effect74.map((result) => ({
14276
15769
  metadata: {
14277
15770
  ...result.metadata,
14278
15771
  ...waitId === undefined ? {} : { wait_id: waitId },
14279
15772
  ...waitId === undefined || waitState === undefined ? {} : { wait_state: waitState }
14280
15773
  },
14281
15774
  nextEventSequence: result.nextEventSequence
14282
- })), Effect73.catchTag("AgentLoopWaitRequested", (wait) => Effect73.succeed({
15775
+ })), Effect74.catchTag("AgentLoopWaitRequested", (wait) => Effect74.succeed({
14283
15776
  _tag: "waiting",
14284
15777
  waitId: wait.wait_id,
14285
15778
  metadata: {
@@ -14289,14 +15782,14 @@ var completeExecution = (input, waitId, waitState, workspaceRuntimeLayer, turn,
14289
15782
  ...generationMetadata(workflowGenerationForStart(input))
14290
15783
  },
14291
15784
  nextEventSequence: wait.next_event_sequence
14292
- })), Effect73.mapError(mapAgentLoopError));
15785
+ })), Effect74.mapError(mapAgentLoopError));
14293
15786
  return yield* run4({
14294
15787
  executionId: input.execution_id,
14295
15788
  eventSequence: runEventSequence,
14296
15789
  startedAt: input.started_at,
14297
15790
  completedAt: input.completed_at,
14298
15791
  program
14299
- }).pipe(Effect73.mapError(mapExecutionError));
15792
+ }).pipe(Effect74.mapError(mapExecutionError));
14300
15793
  })
14301
15794
  });
14302
15795
  var childDispatchContext = (input) => {
@@ -14315,11 +15808,11 @@ var loadChildCancellationRequested = (input) => Activity.make({
14315
15808
  name: ActivityNames.checkQueuedChildCancellation,
14316
15809
  success: Schema69.Boolean,
14317
15810
  error: ExecutionWorkflowFailed,
14318
- execute: Effect73.gen(function* () {
15811
+ execute: Effect74.gen(function* () {
14319
15812
  const context = childDispatchContext(input);
14320
15813
  if (context === undefined)
14321
15814
  return false;
14322
- const child = yield* exports_child_execution_repository.get(context.childExecutionId).pipe(Effect73.mapError(mapChildExecutionRepositoryError));
15815
+ const child = yield* exports_child_execution_repository.get(context.childExecutionId).pipe(Effect74.mapError(mapChildExecutionRepositoryError));
14323
15816
  return child?.status === "cancelled" || child?.metadata.cancellation_requested === true;
14324
15817
  })
14325
15818
  });
@@ -14327,8 +15820,8 @@ var notifyParentActivity = (input, context, status, output) => Activity.make({
14327
15820
  name: ActivityNames.notifyParent(status),
14328
15821
  success: Schema69.Void,
14329
15822
  error: ExecutionWorkflowFailed,
14330
- execute: Effect73.gen(function* () {
14331
- const notifier = yield* Effect73.serviceOption(Service42);
15823
+ execute: Effect74.gen(function* () {
15824
+ const notifier = yield* Effect74.serviceOption(Service42);
14332
15825
  if (Option26.isNone(notifier))
14333
15826
  return;
14334
15827
  yield* notifier.value.notify({
@@ -14338,12 +15831,12 @@ var notifyParentActivity = (input, context, status, output) => Activity.make({
14338
15831
  status,
14339
15832
  output,
14340
15833
  notifiedAt: input.completed_at
14341
- }).pipe(Effect73.mapError((error) => new ExecutionWorkflowFailed({ message: error.message })));
15834
+ }).pipe(Effect74.mapError((error) => new ExecutionWorkflowFailed({ message: error.message })));
14342
15835
  })
14343
15836
  });
14344
15837
  var notifyParent = (input, status, output) => {
14345
15838
  const context = childDispatchContext(input);
14346
- return context === undefined ? Effect73.void : notifyParentActivity(input, context, status, output);
15839
+ return context === undefined ? Effect74.void : notifyParentActivity(input, context, status, output);
14347
15840
  };
14348
15841
  var terminalOutput = (execution) => {
14349
15842
  const output = execution.metadata?.model_output;
@@ -14351,12 +15844,12 @@ var terminalOutput = (execution) => {
14351
15844
  };
14352
15845
  var missingWait = (waitId) => new ExecutionWorkflowFailed({ message: `Wait not found: ${waitId}` });
14353
15846
  var stillOpen = (waitId) => new ExecutionWorkflowFailed({ message: `Wait remained open after wake: ${waitId}` });
14354
- var resolveWaitState = Effect73.fn("ExecutionWorkflow.resolveWaitState")(function* (input, repository) {
15847
+ var resolveWaitState = Effect74.fn("ExecutionWorkflow.resolveWaitState")(function* (input, repository) {
14355
15848
  if (input.wait_id === undefined)
14356
15849
  return;
14357
15850
  const before = yield* loadWait(ActivityNames.loadWaitBeforeSleep(input.wait_id), input.wait_id);
14358
15851
  if (before === undefined)
14359
- return yield* Effect73.fail(missingWait(input.wait_id));
15852
+ return yield* Effect74.fail(missingWait(input.wait_id));
14360
15853
  const beforeTerminal = terminalWaitState(before);
14361
15854
  if (beforeTerminal !== undefined)
14362
15855
  return beforeTerminal;
@@ -14366,10 +15859,10 @@ var resolveWaitState = Effect73.fn("ExecutionWorkflow.resolveWaitState")(functio
14366
15859
  yield* resumeWorkspace(input, input.wait_id);
14367
15860
  const after = yield* loadWait(ActivityNames.loadWaitAfterWake(input.wait_id), input.wait_id);
14368
15861
  if (after === undefined)
14369
- return yield* Effect73.fail(missingWait(input.wait_id));
15862
+ return yield* Effect74.fail(missingWait(input.wait_id));
14370
15863
  const afterTerminal = terminalWaitState(after);
14371
15864
  if (afterTerminal === undefined)
14372
- return yield* Effect73.fail(stillOpen(input.wait_id));
15865
+ return yield* Effect74.fail(stillOpen(input.wait_id));
14373
15866
  return afterTerminal;
14374
15867
  });
14375
15868
  var waitIdFromExecution = (execution) => {
@@ -14380,7 +15873,7 @@ var pendingToolCallFromExecution = (execution) => {
14380
15873
  const pending = execution.metadata?.pending_tool_call;
14381
15874
  return Schema69.decodeUnknownOption(exports_tool_schema.Call)(pending).pipe(Option26.getOrUndefined);
14382
15875
  };
14383
- var finishCancelledWait = Effect73.fn("ExecutionWorkflow.finishCancelledWait")(function* (startInput, turn, waitId) {
15876
+ var finishCancelledWait = Effect74.fn("ExecutionWorkflow.finishCancelledWait")(function* (startInput, turn, waitId) {
14384
15877
  const cancelled = yield* cancelExecution(startInput, turn, "wait cancelled");
14385
15878
  yield* releaseWorkspace(startInput);
14386
15879
  yield* notifyParent(startInput, "cancelled", []);
@@ -14403,7 +15896,7 @@ var continueAsNew = (startInput, turn, waitId, pendingToolCall) => Activity.make
14403
15896
  workflow_generation: workflowGenerationForStart(startInput) + 1
14404
15897
  })
14405
15898
  });
14406
- var runWorkflow = Effect73.fn("ExecutionWorkflow.run")(function* (input) {
15899
+ var runWorkflow = Effect74.fn("ExecutionWorkflow.run")(function* (input) {
14407
15900
  const repository = yield* exports_execution_repository.Service;
14408
15901
  const startInput = yield* resolveStartInput(input);
14409
15902
  const generation = workflowGenerationForStart(startInput);
@@ -14420,7 +15913,7 @@ var runWorkflow = Effect73.fn("ExecutionWorkflow.run")(function* (input) {
14420
15913
  ...cancelled.metadata === undefined ? {} : { metadata: cancelled.metadata }
14421
15914
  };
14422
15915
  }
14423
- return yield* Effect73.gen(function* () {
15916
+ return yield* Effect74.gen(function* () {
14424
15917
  if (generation === 0)
14425
15918
  yield* ensureWorkspace(startInput);
14426
15919
  let activeWaitId = startInput.wait_id;
@@ -14451,13 +15944,13 @@ var runWorkflow = Effect73.fn("ExecutionWorkflow.run")(function* (input) {
14451
15944
  if (execution.status !== "waiting")
14452
15945
  break;
14453
15946
  if (turn >= maxWaitTurns)
14454
- return yield* Effect73.fail(new ExecutionWorkflowFailed({ message: "Agent wait turn limit exceeded" }));
15947
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: "Agent wait turn limit exceeded" }));
14455
15948
  const waitId = waitIdFromExecution(execution);
14456
15949
  if (waitId === undefined)
14457
- return yield* Effect73.fail(new ExecutionWorkflowFailed({ message: "Waiting execution missing wait id" }));
15950
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: "Waiting execution missing wait id" }));
14458
15951
  pendingToolCall = pendingToolCallFromExecution(execution);
14459
15952
  if (pendingToolCall === undefined) {
14460
- return yield* Effect73.fail(new ExecutionWorkflowFailed({ message: "Waiting execution missing pending tool call" }));
15953
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: "Waiting execution missing pending tool call" }));
14461
15954
  }
14462
15955
  activeWaitId = waitId;
14463
15956
  waitState = yield* resolveWaitState({ ...startInput, wait_id: waitId }, repository);
@@ -14478,7 +15971,7 @@ var runWorkflow = Effect73.fn("ExecutionWorkflow.run")(function* (input) {
14478
15971
  ...waitState === undefined ? {} : { wait_state: waitState },
14479
15972
  ...execution.metadata === undefined ? {} : { metadata: execution.metadata }
14480
15973
  };
14481
- }).pipe(Effect73.catch((error) => failWorkspace(startInput, error).pipe(Effect73.flatMap(() => notifyParent(startInput, "failed", [])), Effect73.flatMap(() => Effect73.fail(error)))));
15974
+ }).pipe(Effect74.catch((error) => failWorkspace(startInput, error).pipe(Effect74.flatMap(() => notifyParent(startInput, "failed", [])), Effect74.flatMap(() => Effect74.fail(error)))));
14482
15975
  });
14483
15976
  var waitingResult = (input) => ({
14484
15977
  execution_id: input.execution_id,
@@ -14486,69 +15979,36 @@ var waitingResult = (input) => ({
14486
15979
  ...input.wait_id === undefined ? {} : { wait_id: input.wait_id },
14487
15980
  metadata: input.wait_id === undefined ? {} : { wait_id: input.wait_id, wait_state: "open" }
14488
15981
  });
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 }));
15982
+ var awaitStartResult = Effect74.fn("ExecutionWorkflow.awaitStartResult")(function* (input, workflowExecutionId) {
15983
+ 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
15984
  if (Option26.isSome(result)) {
14492
15985
  if (result.value._tag === "Suspended")
14493
15986
  return waitingResult(input);
14494
15987
  if (Exit2.isSuccess(result.value.exit))
14495
15988
  return result.value.exit.value;
14496
- return yield* Effect73.fail(new ExecutionWorkflowFailed({ message: "Execution workflow failed" }));
15989
+ return yield* Effect74.fail(new ExecutionWorkflowFailed({ message: "Execution workflow failed" }));
14497
15990
  }
14498
15991
  return waitingResult(input);
14499
15992
  });
14500
- var layer48 = StartExecutionWorkflow.toLayer(runWorkflow);
15993
+ var layer49 = StartExecutionWorkflow.toLayer(runWorkflow);
14501
15994
  var start = (input, options) => StartExecutionWorkflow.execute(input, options);
14502
- var startRequest = Effect73.fn("ExecutionWorkflow.startRequest")(function* (input) {
15995
+ var startRequest = Effect74.fn("ExecutionWorkflow.startRequest")(function* (input) {
14503
15996
  if (input.wait_id === undefined)
14504
15997
  return yield* start(input);
14505
15998
  const workflowExecutionId = yield* start(input, { discard: true });
14506
15999
  return yield* awaitStartResult(input, workflowExecutionId);
14507
16000
  });
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" };
16001
+ var dispatchRequest = Effect74.fn("ExecutionWorkflow.dispatchRequest")(function* (input) {
16002
+ yield* start(input, { discard: true });
16003
+ });
16004
+ var cancelRequest = Effect74.fn("ExecutionWorkflow.cancelRequest")(function* (input) {
16005
+ const prepared = yield* prepareCancellation(input);
16006
+ if (prepared.terminalNoop) {
16007
+ return { execution_id: prepared.record.id, status: prepared.status };
14540
16008
  }
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 };
16009
+ yield* signalPreparedCancellation(prepared, input.cancelled_at);
16010
+ yield* cancelOpenChildren(prepared.record.id, input.cancelled_at);
16011
+ return { execution_id: prepared.record.id, status: prepared.status };
14552
16012
  });
14553
16013
  var poll = (executionId) => StartExecutionWorkflow.poll(executionId);
14554
16014
  var resume3 = (executionId) => StartExecutionWorkflow.resume(executionId);
@@ -14562,12 +16022,12 @@ var workflowExecutionIdForExecution = (executionId, workflowGeneration = 0) => S
14562
16022
  completed_at: 0,
14563
16023
  workflow_generation: workflowGeneration
14564
16024
  });
14565
- var activeWorkflowExecutionIdForExecution = Effect73.fn("ExecutionWorkflow.activeWorkflowExecutionIdForExecution")(function* (executionId) {
16025
+ var activeWorkflowExecutionIdForExecution = Effect74.fn("ExecutionWorkflow.activeWorkflowExecutionIdForExecution")(function* (executionId) {
14566
16026
  const repository = yield* exports_execution_repository.Service;
14567
- const record2 = yield* repository.get(executionId).pipe(Effect73.mapError(mapRepositoryError11));
16027
+ const record2 = yield* repository.get(executionId).pipe(Effect74.mapError(mapRepositoryError11));
14568
16028
  return yield* workflowExecutionIdForExecution(executionId, record2 === undefined ? 0 : workflowGenerationFromRecord(record2));
14569
16029
  });
14570
- var signalWait = Effect73.fn("ExecutionWorkflow.signalWait")(function* (input) {
16030
+ var signalWait = Effect74.fn("ExecutionWorkflow.signalWait")(function* (input) {
14571
16031
  const deferred = waitSignal(input.wait_id);
14572
16032
  const token = DurableDeferred.tokenFromExecutionId(deferred, {
14573
16033
  workflow: StartExecutionWorkflow,
@@ -14595,14 +16055,25 @@ var SignalWait = Rpc.make("signalWait", {
14595
16055
  success: Schema70.Void,
14596
16056
  error: ExecutionWorkflowFailed
14597
16057
  }).annotate(ClusterSchema.Persisted, true).annotate(ClusterSchema.Uninterruptible, "server");
16058
+ var Dispatch = Rpc.make("dispatch", {
16059
+ payload: StartInput,
16060
+ success: Schema70.Void,
16061
+ error: ExecutionWorkflowFailed
16062
+ }).annotate(ClusterSchema.Persisted, true).annotate(ClusterSchema.Uninterruptible, "server");
14598
16063
  var Cancel = Rpc.make("cancel", {
14599
16064
  payload: CancelExecutionInput,
14600
16065
  success: CancelExecutionResult,
14601
16066
  error: ExecutionWorkflowFailed
14602
16067
  }).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({
16068
+ var entity = Entity.make("Relay/Execution", [
16069
+ Start,
16070
+ Dispatch,
16071
+ SignalWait,
16072
+ Cancel
16073
+ ]).annotate(ClusterSchema.ShardGroup, () => "execution");
16074
+ var layer50 = entity.toLayer(entity.of({
14605
16075
  start: (request) => startRequest(request.payload),
16076
+ dispatch: (request) => dispatchRequest(request.payload),
14606
16077
  signalWait: (request) => signalWait(request.payload),
14607
16078
  cancel: (request) => cancelRequest(request.payload)
14608
16079
  }), { concurrency: "unbounded" });
@@ -14612,15 +16083,15 @@ var exports_envelope_service = {};
14612
16083
  __export(exports_envelope_service, {
14613
16084
  testLayer: () => testLayer49,
14614
16085
  send: () => send2,
14615
- memoryLayer: () => memoryLayer33,
14616
- layer: () => layer50,
14617
- Service: () => Service47,
16086
+ memoryLayer: () => memoryLayer34,
16087
+ layer: () => layer51,
16088
+ Service: () => Service48,
14618
16089
  EnvelopeServiceError: () => EnvelopeServiceError,
14619
16090
  EnvelopeRouteUnavailable: () => EnvelopeRouteUnavailable,
14620
16091
  EnvelopeRouteDeferred: () => EnvelopeRouteDeferred,
14621
16092
  EnvelopeAddressNotFound: () => EnvelopeAddressNotFound
14622
16093
  });
14623
- import { Context as Context60, Effect as Effect74, Layer as Layer67, Schema as Schema71 } from "effect";
16094
+ import { Context as Context61, Effect as Effect75, Layer as Layer68, Schema as Schema71 } from "effect";
14624
16095
  class EnvelopeAddressNotFound extends Schema71.TaggedErrorClass()("EnvelopeAddressNotFound", {
14625
16096
  address_id: exports_ids_schema.AddressId
14626
16097
  }) {
@@ -14643,7 +16114,7 @@ class EnvelopeServiceError extends Schema71.TaggedErrorClass()("EnvelopeServiceE
14643
16114
  }) {
14644
16115
  }
14645
16116
 
14646
- class Service47 extends Context60.Service()("@relayfx/runtime/EnvelopeService") {
16117
+ class Service48 extends Context61.Service()("@relayfx/runtime/EnvelopeService") {
14647
16118
  }
14648
16119
  var mapAddressBookError2 = (error) => {
14649
16120
  if (error._tag === "AddressNotFound")
@@ -14727,20 +16198,20 @@ var readyEvent = (input, ready) => ({
14727
16198
  },
14728
16199
  created_at: input.createdAt + 2
14729
16200
  });
14730
- var layer50 = Layer67.effect(Service47, Effect74.gen(function* () {
16201
+ var layer51 = Layer68.effect(Service48, Effect75.gen(function* () {
14731
16202
  const addressBook = yield* Service23;
14732
16203
  const repository = yield* exports_envelope_repository.Service;
14733
16204
  const eventLog = yield* Service24;
14734
- return Service47.of({
14735
- send: Effect74.fn("EnvelopeService.send")(function* (input) {
14736
- yield* Effect74.annotateCurrentSpan({
16205
+ return Service48.of({
16206
+ send: Effect75.fn("EnvelopeService.send")(function* (input) {
16207
+ yield* Effect75.annotateCurrentSpan({
14737
16208
  "relay.envelope.id": input.envelopeId,
14738
16209
  "relay.execution.id": input.executionId,
14739
16210
  "relay.address.from": input.input.from,
14740
16211
  "relay.address.to": input.input.to
14741
16212
  });
14742
- const route2 = yield* addressBook.resolve(input.input.to).pipe(Effect74.mapError(mapAddressBookError2));
14743
- yield* Effect74.annotateCurrentSpan({
16213
+ const route2 = yield* addressBook.resolve(input.input.to).pipe(Effect75.mapError(mapAddressBookError2));
16214
+ yield* Effect75.annotateCurrentSpan({
14744
16215
  "relay.route.kind": route2.kind,
14745
16216
  "relay.route.key": route2.route_key
14746
16217
  });
@@ -14751,21 +16222,21 @@ var layer50 = Layer67.effect(Service47, Effect74.gen(function* () {
14751
16222
  envelope,
14752
16223
  ...waitId === undefined ? {} : { waitId },
14753
16224
  ...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));
16225
+ }).pipe(Effect75.mapError(mapRepositoryError12));
16226
+ yield* eventLog.append(acceptedEvent2(input)).pipe(Effect75.mapError(mapEventLogError7));
16227
+ yield* eventLog.append(routedEvent(input, route2)).pipe(Effect75.mapError(mapEventLogError7));
14757
16228
  if (ready !== undefined) {
14758
- yield* eventLog.append(readyEvent(input, ready)).pipe(Effect74.mapError(mapEventLogError7));
16229
+ yield* eventLog.append(readyEvent(input, ready)).pipe(Effect75.mapError(mapEventLogError7));
14759
16230
  }
14760
16231
  yield* recordEnvelopeSent(route2.kind);
14761
16232
  return accepted2;
14762
16233
  })
14763
16234
  });
14764
16235
  }));
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;
16236
+ var memoryLayer34 = (routes = []) => layer51.pipe(Layer68.provide(memoryLayer20(routes)), Layer68.provide(exports_envelope_repository.memoryLayer), Layer68.provide(memoryLayer21));
16237
+ var testLayer49 = (implementation) => Layer68.succeed(Service48, Service48.of(implementation));
16238
+ var send2 = Effect75.fn("EnvelopeService.send.call")(function* (input) {
16239
+ const service = yield* Service48;
14769
16240
  return yield* service.send(input);
14770
16241
  });
14771
16242
  // ../runtime/src/runner/runner-runtime-service.ts
@@ -14784,20 +16255,20 @@ __export(exports_runner_runtime_service, {
14784
16255
  layerWithLanguageModelService: () => layerWithLanguageModelService,
14785
16256
  layerWithClient: () => layerWithClient,
14786
16257
  layerWith: () => layerWith,
14787
- layer: () => layer52,
16258
+ layer: () => layer53,
14788
16259
  clusterShardingConfigLayer: () => clusterShardingConfigLayer,
14789
16260
  clusterLayerHttpClientOnly: () => clusterLayerHttpClientOnly,
14790
16261
  clusterLayerHttp: () => clusterLayerHttp,
14791
16262
  check: () => check2,
14792
16263
  assertRunnerAddressAvailable: () => assertRunnerAddressAvailable,
14793
16264
  assertClusterConfig: () => assertClusterConfig,
14794
- Service: () => Service49,
16265
+ Service: () => Service50,
14795
16266
  RunnerRuntimeError: () => RunnerRuntimeError,
14796
16267
  ReadinessStatus: () => ReadinessStatus,
14797
16268
  DatabaseMode: () => DatabaseMode,
14798
16269
  ClusterConfigMismatch: () => ClusterConfigMismatch
14799
16270
  });
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";
16271
+ 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
16272
  import {
14802
16273
  ClusterWorkflowEngine,
14803
16274
  HttpRunner,
@@ -14812,7 +16283,7 @@ import {
14812
16283
  SqlRunnerStorage
14813
16284
  } from "effect/unstable/cluster";
14814
16285
  import { FetchHttpClient } from "effect/unstable/http";
14815
- import { SqlClient as SqlClient22 } from "effect/unstable/sql/SqlClient";
16286
+ import { SqlClient as SqlClient23 } from "effect/unstable/sql/SqlClient";
14816
16287
  import { RpcSerialization } from "effect/unstable/rpc";
14817
16288
  import { WorkflowEngine } from "effect/unstable/workflow";
14818
16289
  import { LanguageModel as LanguageModel7 } from "effect/unstable/ai";
@@ -14826,24 +16297,24 @@ __export(exports_scheduler_service, {
14826
16297
  runOnce: () => runOnce2,
14827
16298
  pollIntervalMillisConfig: () => pollIntervalMillisConfig,
14828
16299
  parseCron: () => parseCron,
14829
- memoryLayer: () => memoryLayer34,
14830
- make: () => make14,
14831
- layer: () => layer51,
16300
+ memoryLayer: () => memoryLayer35,
16301
+ make: () => make15,
16302
+ layer: () => layer52,
14832
16303
  enabledConfig: () => enabledConfig,
14833
16304
  claimTtlMillisConfig: () => claimTtlMillisConfig,
14834
- Service: () => Service48,
16305
+ Service: () => Service49,
14835
16306
  SchedulerError: () => SchedulerError,
14836
16307
  ScheduleCronInvalid: () => ScheduleCronInvalid
14837
16308
  });
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";
16309
+ 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
16310
 
14840
16311
  // ../runtime/src/wait/wait-signal.ts
14841
16312
  var exports_wait_signal = {};
14842
16313
  __export(exports_wait_signal, {
14843
16314
  signalWorkflowWait: () => signalWorkflowWait
14844
16315
  });
14845
- import { Effect as Effect75 } from "effect";
14846
- var signalWorkflowWait = Effect75.fn("WaitSignal.signalWorkflowWait")(function* (input) {
16316
+ import { Effect as Effect76 } from "effect";
16317
+ var signalWorkflowWait = Effect76.fn("WaitSignal.signalWorkflowWait")(function* (input) {
14847
16318
  const workflowExecutionId2 = yield* activeWorkflowExecutionIdForExecution(input.executionId);
14848
16319
  const client3 = input.makeExecutionClient(input.executionId);
14849
16320
  yield* client3.signalWait({
@@ -14866,7 +16337,7 @@ class ScheduleCronInvalid extends Schema72.TaggedErrorClass()("ScheduleCronInval
14866
16337
  }) {
14867
16338
  }
14868
16339
 
14869
- class Service48 extends Context61.Service()("@relayfx/runtime/SchedulerService") {
16340
+ class Service49 extends Context62.Service()("@relayfx/runtime/SchedulerService") {
14870
16341
  }
14871
16342
  var pollIntervalMillisConfig = Config4.int("RELAY_SCHEDULER_POLL_INTERVAL_MILLIS").pipe(Config4.withDefault(1000));
14872
16343
  var claimTtlMillisConfig = Config4.int("RELAY_SCHEDULER_CLAIM_TTL_MILLIS").pipe(Config4.withDefault(30000));
@@ -14875,7 +16346,7 @@ var processWorkerId = `scheduler:${globalThis.crypto.randomUUID()}`;
14875
16346
  var workerIdConfig = Config4.string("RELAY_SCHEDULER_WORKER_ID").pipe(Config4.withDefault(processWorkerId));
14876
16347
  var parseCron = (cronExpr) => {
14877
16348
  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);
16349
+ return Result3.isFailure(parsed) ? Effect77.fail(new ScheduleCronInvalid({ cron_expr: cronExpr, message: String(parsed.failure) })) : Effect77.succeed(parsed.success);
14879
16350
  };
14880
16351
  var startIdempotencyKey = (schedule) => `schedule:${schedule.id}:${schedule.next_run_at}`;
14881
16352
  var errorMessage3 = (error) => {
@@ -14891,11 +16362,11 @@ var dispatchMetadata = (schedule) => ({
14891
16362
  source: "schedule",
14892
16363
  schedule_id: schedule.id
14893
16364
  });
14894
- var nextEventSequence5 = Effect76.fn("SchedulerService.nextEventSequence")(function* (eventLog, executionId) {
14895
- const max = yield* eventLog.maxSequence(executionId).pipe(Effect76.mapError(toSchedulerError));
16365
+ var nextEventSequence5 = Effect77.fn("SchedulerService.nextEventSequence")(function* (eventLog, executionId) {
16366
+ const max = yield* eventLog.maxSequence(executionId).pipe(Effect77.mapError(toSchedulerError));
14896
16367
  return max === undefined ? 0 : max + 1;
14897
16368
  });
14898
- var make14 = Effect76.gen(function* () {
16369
+ var make15 = Effect77.gen(function* () {
14899
16370
  const schedules = yield* exports_schedule_repository.Service;
14900
16371
  const waits = yield* Service25;
14901
16372
  const eventLog = yield* Service24;
@@ -14904,10 +16375,10 @@ var make14 = Effect76.gen(function* () {
14904
16375
  const workerId = yield* workerIdConfig;
14905
16376
  const claimTtlMillis = yield* claimTtlMillisConfig;
14906
16377
  const pollIntervalMillis = yield* pollIntervalMillisConfig;
14907
- const dispatchStartExecution = (schedule, now) => Effect76.gen(function* () {
16378
+ const dispatchStartExecution = (schedule, now) => Effect77.gen(function* () {
14908
16379
  const addressId = schedule.address_id;
14909
16380
  if (addressId === undefined) {
14910
- return yield* Effect76.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing address_id` }));
16381
+ return yield* Effect77.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing address_id` }));
14911
16382
  }
14912
16383
  const idempotencyKey = startIdempotencyKey(schedule);
14913
16384
  const executionId = exports_ids_schema.ExecutionId.make(`execution:${idempotencyKey}`);
@@ -14924,19 +16395,19 @@ var make14 = Effect76.gen(function* () {
14924
16395
  ...dispatchMetadata(schedule),
14925
16396
  idempotency_key: idempotencyKey
14926
16397
  }
14927
- }).pipe(Effect76.mapError(toSchedulerError));
14928
- }).pipe(Effect76.withSpan("SchedulerService.dispatchStartExecution"));
14929
- const dispatchWaitTransition = (schedule, now) => Effect76.gen(function* () {
16398
+ }).pipe(Effect77.mapError(toSchedulerError));
16399
+ }).pipe(Effect77.withSpan("SchedulerService.dispatchStartExecution"));
16400
+ const dispatchWaitTransition = (schedule, now) => Effect77.gen(function* () {
14930
16401
  const waitId = schedule.wait_id;
14931
16402
  if (waitId === undefined) {
14932
- return yield* Effect76.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing wait_id` }));
16403
+ return yield* Effect77.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing wait_id` }));
14933
16404
  }
14934
- const wait = yield* waits.get(waitId).pipe(Effect76.mapError(toSchedulerError));
16405
+ const wait = yield* waits.get(waitId).pipe(Effect77.mapError(toSchedulerError));
14935
16406
  if (wait === undefined || wait.state !== "open")
14936
16407
  return;
14937
16408
  const eventSequence = yield* nextEventSequence5(eventLog, wait.executionId);
14938
16409
  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));
16410
+ 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
16411
  if (!result.transitioned)
14941
16412
  return;
14942
16413
  yield* signalWorkflowWait({
@@ -14945,19 +16416,19 @@ var make14 = Effect76.gen(function* () {
14945
16416
  waitId: result.wait.id,
14946
16417
  state: schedule.target_kind === "wake-wait" ? "resolved" : "timed_out",
14947
16418
  signaledAt: now
14948
- }).pipe(Effect76.provideService(exports_execution_repository.Service, executionRepository), Effect76.mapError(toSchedulerError));
14949
- }).pipe(Effect76.withSpan("SchedulerService.dispatchWaitTransition"));
16419
+ }).pipe(Effect77.provideService(exports_execution_repository.Service, executionRepository), Effect77.mapError(toSchedulerError));
16420
+ }).pipe(Effect77.withSpan("SchedulerService.dispatchWaitTransition"));
14950
16421
  const dispatch = (schedule, now) => schedule.target_kind === "start-execution" ? dispatchStartExecution(schedule, now) : dispatchWaitTransition(schedule, now);
14951
- const nextCronRunAt = (schedule, now) => Effect76.gen(function* () {
16422
+ const nextCronRunAt = (schedule, now) => Effect77.gen(function* () {
14952
16423
  if (schedule.kind !== "cron")
14953
16424
  return;
14954
16425
  if (schedule.cron_expr === undefined) {
14955
- return yield* Effect76.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing cron_expr` }));
16426
+ return yield* Effect77.fail(new SchedulerError({ message: `Schedule ${schedule.id} is missing cron_expr` }));
14956
16427
  }
14957
- const cron = yield* parseCron(schedule.cron_expr).pipe(Effect76.mapError(toSchedulerError));
16428
+ const cron = yield* parseCron(schedule.cron_expr).pipe(Effect77.mapError(toSchedulerError));
14958
16429
  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({
16430
+ }).pipe(Effect77.withSpan("SchedulerService.nextCronRunAt"));
16431
+ const settle = (schedule, now) => dispatch(schedule, now).pipe(Effect77.flatMap(() => nextCronRunAt(schedule, now)), Effect77.matchEffect({
14961
16432
  onSuccess: (nextRunAt) => schedules.ack({
14962
16433
  id: schedule.id,
14963
16434
  workerId,
@@ -14970,45 +16441,45 @@ var make14 = Effect76.gen(function* () {
14970
16441
  nextAvailableAt: now + pollIntervalMillis,
14971
16442
  error: error.message
14972
16443
  })
14973
- }), Effect76.catchTag("ScheduleClaimMismatch", () => Effect76.void), Effect76.mapError(toSchedulerError), Effect76.withSpan("SchedulerService.settle"));
14974
- const runOnce2 = Effect76.gen(function* () {
16444
+ }), Effect77.catchTag("ScheduleClaimMismatch", () => Effect77.void), Effect77.mapError(toSchedulerError), Effect77.withSpan("SchedulerService.settle"));
16445
+ const runOnce2 = Effect77.gen(function* () {
14975
16446
  let dispatched = 0;
14976
16447
  while (true) {
14977
16448
  const now = yield* Clock10.currentTimeMillis;
14978
- const claimed = yield* schedules.claimDue({ workerId, now, claimExpiresAt: now + claimTtlMillis }).pipe(Effect76.mapError(toSchedulerError));
16449
+ const claimed = yield* schedules.claimDue({ workerId, now, claimExpiresAt: now + claimTtlMillis }).pipe(Effect77.mapError(toSchedulerError));
14979
16450
  if (claimed === undefined)
14980
16451
  return dispatched;
14981
16452
  yield* settle(claimed, now);
14982
16453
  dispatched += 1;
14983
16454
  }
14984
- }).pipe(Effect76.withSpan("SchedulerService.runOnce"));
14985
- return Service48.of({ runOnce: runOnce2 });
16455
+ }).pipe(Effect77.withSpan("SchedulerService.runOnce"));
16456
+ return Service49.of({ runOnce: runOnce2 });
14986
16457
  });
14987
- var jitteredSleep = (pollIntervalMillis) => Effect76.gen(function* () {
16458
+ var jitteredSleep = (pollIntervalMillis) => Effect77.gen(function* () {
14988
16459
  const jitter = yield* Random.nextBetween(0.8, 1.2);
14989
- yield* Effect76.sleep(Duration4.millis(pollIntervalMillis * jitter));
16460
+ yield* Effect77.sleep(Duration4.millis(pollIntervalMillis * jitter));
14990
16461
  });
14991
- var pollLoop = (service, pollIntervalMillis) => Effect76.gen(function* () {
16462
+ var pollLoop = (service, pollIntervalMillis) => Effect77.gen(function* () {
14992
16463
  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))));
16464
+ const dispatched = yield* service.runOnce.pipe(Effect77.catch((error) => Effect77.logWarning("relay scheduler poll failed", { message: error.message }).pipe(Effect77.as(0))));
14994
16465
  if (dispatched === 0) {
14995
16466
  yield* jitteredSleep(pollIntervalMillis);
14996
16467
  }
14997
16468
  }
14998
16469
  });
14999
- var layer51 = Layer68.effect(Service48, Effect76.gen(function* () {
15000
- const service = yield* make14;
16470
+ var layer52 = Layer69.effect(Service49, Effect77.gen(function* () {
16471
+ const service = yield* make15;
15001
16472
  const enabled2 = yield* enabledConfig;
15002
16473
  const pollIntervalMillis = yield* pollIntervalMillisConfig;
15003
16474
  if (enabled2) {
15004
- yield* Effect76.forkScoped(pollLoop(service, pollIntervalMillis));
16475
+ yield* Effect77.forkScoped(pollLoop(service, pollIntervalMillis));
15005
16476
  }
15006
16477
  return service;
15007
16478
  }));
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;
16479
+ var memoryLayer35 = Layer69.effect(Service49, make15);
16480
+ var testLayer50 = (implementation) => Layer69.succeed(Service49, Service49.of(implementation));
16481
+ var runOnce2 = Effect77.fn("SchedulerService.runOnce.call")(function* () {
16482
+ const service = yield* Service49;
15012
16483
  return yield* service.runOnce;
15013
16484
  });
15014
16485
 
@@ -15035,20 +16506,20 @@ class ClusterConfigMismatch extends Schema73.TaggedErrorClass()("ClusterConfigMi
15035
16506
  }) {
15036
16507
  }
15037
16508
 
15038
- class Service49 extends Context62.Service()("@relayfx/runtime/RunnerRuntime") {
16509
+ class Service50 extends Context63.Service()("@relayfx/runtime/RunnerRuntime") {
15039
16510
  }
15040
16511
  var shardingConfig = {
15041
16512
  availableShardGroups: ["default", "execution"],
15042
16513
  assignedShardGroups: ["default", "execution"]
15043
16514
  };
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)));
16515
+ 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
16516
  var clusterHost = Config5.string("RELAY_CLUSTER_HOST").pipe(Config5.withDefault("localhost"));
15046
16517
  var clusterPort = Config5.int("RELAY_CLUSTER_PORT").pipe(Config5.withDefault(34431));
15047
16518
  var clusterShardsPerGroup = Config5.int("RELAY_CLUSTER_SHARDS_PER_GROUP").pipe(Config5.withDefault(300));
15048
16519
  var clusterShardGroups = Config5.schema(Config5.Array(Schema73.String), "RELAY_CLUSTER_SHARD_GROUPS").pipe(Config5.withDefault(["default", "execution"]));
15049
16520
  var runnerAddressKey = (address) => `${address.host}:${address.port}`;
15050
16521
  var runnerAddressEquals = (left, right) => left.host === right.host && left.port === right.port;
15051
- var shardingConfigFromEnv = () => Layer69.effect(ShardingConfig2.ShardingConfig, Effect77.gen(function* () {
16522
+ var shardingConfigFromEnv = () => Layer70.effect(ShardingConfig2.ShardingConfig, Effect78.gen(function* () {
15052
16523
  const host = yield* clusterHost;
15053
16524
  const port = yield* clusterPort;
15054
16525
  const shardsPerGroup = yield* clusterShardsPerGroup;
@@ -15073,14 +16544,14 @@ var clusterShardingConfigLayer = (options) => ShardingConfig2.layer({
15073
16544
  ...options.shardLockExpiration !== undefined && { shardLockExpiration: options.shardLockExpiration }
15074
16545
  });
15075
16546
  var runnerAddressPreflightTimeout = Duration5.seconds(5);
15076
- var assertRunnerAddressAvailable = Effect77.fn("RunnerRuntime.assertRunnerAddressAvailable")(function* (options = {}) {
16547
+ var assertRunnerAddressAvailable = Effect78.fn("RunnerRuntime.assertRunnerAddressAvailable")(function* (options = {}) {
15077
16548
  const config = yield* ShardingConfig2.ShardingConfig;
15078
16549
  if (Option27.isNone(config.runnerAddress)) {
15079
16550
  return;
15080
16551
  }
15081
16552
  const storage = yield* RunnerStorage.RunnerStorage;
15082
16553
  const localAddress = config.runnerAddress.value;
15083
- const runners = yield* storage.getRunners.pipe(Effect77.mapError((error) => new ClusterConfigMismatch({
16554
+ const runners = yield* storage.getRunners.pipe(Effect78.mapError((error) => new ClusterConfigMismatch({
15084
16555
  field: "runnerAddress",
15085
16556
  expected: `${runnerAddressKey(localAddress)} available`,
15086
16557
  actual: `registry unavailable: ${String(error)}`
@@ -15088,7 +16559,7 @@ var assertRunnerAddressAvailable = Effect77.fn("RunnerRuntime.assertRunnerAddres
15088
16559
  const collision = runners.find(([runner, healthy]) => healthy && runnerAddressEquals(runner.address, localAddress));
15089
16560
  if (collision === undefined)
15090
16561
  return;
15091
- const reachable = options.isAddressReachable === undefined ? false : yield* options.isAddressReachable(collision[0].address).pipe(Effect77.timeoutOption(runnerAddressPreflightTimeout), Effect77.map(Option27.getOrElse(() => false)));
16562
+ const reachable = options.isAddressReachable === undefined ? false : yield* options.isAddressReachable(collision[0].address).pipe(Effect78.timeoutOption(runnerAddressPreflightTimeout), Effect78.map(Option27.getOrElse(() => false)));
15092
16563
  if (reachable) {
15093
16564
  return yield* new ClusterConfigMismatch({
15094
16565
  field: "runnerAddress",
@@ -15097,14 +16568,14 @@ var assertRunnerAddressAvailable = Effect77.fn("RunnerRuntime.assertRunnerAddres
15097
16568
  });
15098
16569
  }
15099
16570
  });
15100
- var runnerAddressPreflightHttpLayer = Layer69.effectDiscard(Effect77.gen(function* () {
16571
+ var runnerAddressPreflightHttpLayer = Layer70.effectDiscard(Effect78.gen(function* () {
15101
16572
  const runners = yield* Runners.Runners;
15102
16573
  yield* assertRunnerAddressAvailable({
15103
- isAddressReachable: (address) => runners.ping(address).pipe(Effect77.as(true), Effect77.catch(() => Effect77.succeed(false)))
16574
+ isAddressReachable: (address) => runners.ping(address).pipe(Effect78.as(true), Effect78.catch(() => Effect78.succeed(false)))
15104
16575
  });
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({
16576
+ })).pipe(Layer70.provide(Runners.layerRpc), Layer70.provide(HttpRunner.layerClientProtocolHttpDefault), Layer70.provide(RpcSerialization.layerNdjson), Layer70.provide(FetchHttpClient.layer));
16577
+ 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()));
16578
+ 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
16579
  runnerAddress: Option27.some(RunnerAddress.make(options.runnerHost, options.rpcPort)),
15109
16580
  assignedShardGroups: options.assignedShardGroups,
15110
16581
  availableShardGroups: options.availableShardGroups,
@@ -15113,7 +16584,7 @@ var clusterLayerHttp = (options) => HttpRunner.layerHttp.pipe(Layer69.provideMer
15113
16584
  shardLockExpiration: options.shardLockExpiration,
15114
16585
  shardLockDisableAdvisory: options.shardLockDisableAdvisory
15115
16586
  })));
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({
16587
+ 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
16588
  runnerAddress: Option27.none(),
15118
16589
  assignedShardGroups: [],
15119
16590
  availableShardGroups: options.availableShardGroups,
@@ -15122,7 +16593,7 @@ var clusterLayerHttpClientOnly = (options = {}) => HttpRunner.layerHttpClientOnl
15122
16593
  shardLockExpiration: options.shardLockExpiration,
15123
16594
  shardLockDisableAdvisory: options.shardLockDisableAdvisory
15124
16595
  })));
15125
- var assertClusterConfig = Effect77.fn("RunnerRuntime.assertClusterConfig")(function* (expected) {
16596
+ var assertClusterConfig = Effect78.fn("RunnerRuntime.assertClusterConfig")(function* (expected) {
15126
16597
  const config = yield* ShardingConfig2.ShardingConfig;
15127
16598
  if (config.shardsPerGroup !== expected.shardsPerGroup) {
15128
16599
  return yield* new ClusterConfigMismatch({
@@ -15137,15 +16608,15 @@ var assertClusterConfig = Effect77.fn("RunnerRuntime.assertClusterConfig")(funct
15137
16608
  return yield* new ClusterConfigMismatch({ field: "availableShardGroups", expected: want, actual });
15138
16609
  }
15139
16610
  });
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({
16611
+ 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);
16612
+ 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);
16613
+ var testCryptoLayer = Layer70.succeed(Crypto4.Crypto, Crypto4.make({
15143
16614
  randomBytes: (size) => new Uint8Array(size),
15144
- digest: (algorithm, data) => Effect77.promise(() => globalThis.crypto.subtle.digest(algorithm, data).then((buffer) => new Uint8Array(buffer)))
16615
+ digest: (algorithm, data) => Effect78.promise(() => globalThis.crypto.subtle.digest(algorithm, data).then((buffer) => new Uint8Array(buffer)))
15145
16616
  }));
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* () {
16617
+ var executionServiceLayer = layer47.pipe(Layer70.provideMerge(layer33));
16618
+ var addressResolutionLayerWith = (toolRuntimeLayer) => layer25.pipe(Layer70.provideMerge(layerFromRepository), Layer70.provideMerge(layer24.pipe(Layer70.provideMerge(toolRuntimeLayer))));
16619
+ var parentNotifierLayer = Layer70.effect(Service42, Effect78.gen(function* () {
15149
16620
  const makeExecutionClient = yield* client2;
15150
16621
  const executionRepository = yield* exports_execution_repository.Service;
15151
16622
  return yield* make13({
@@ -15155,24 +16626,24 @@ var parentNotifierLayer = Layer69.effect(Service42, Effect77.gen(function* () {
15155
16626
  waitId: input.waitId,
15156
16627
  state: "resolved",
15157
16628
  signaledAt: input.signaledAt
15158
- }).pipe(Effect77.provideService(exports_execution_repository.Service, executionRepository))
16629
+ }).pipe(Effect78.provideService(exports_execution_repository.Service, executionRepository))
15159
16630
  });
15160
16631
  }));
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* () {
16632
+ var agentLoopLayerWith = (toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer) => layer45.pipe(Layer70.provideMerge(toolRuntimeLayer), Layer70.provideMerge(layer33), Layer70.provideMerge(layer37()), Layer70.provideMerge(promptAssemblerLayer), Layer70.provideMerge(schemaRegistryLayer));
16633
+ 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));
16634
+ var workflowLayerWith = (toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer, toolTransitionCoordinatorLayer) => layer49.pipe(Layer70.provideMerge(runtimeServicesLayerWith(toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer, toolTransitionCoordinatorLayer)));
16635
+ var workflowAndEntityLayerWith = (toolRuntimeLayer, schedulerLayer, promptAssemblerLayer, schemaRegistryLayer, toolTransitionCoordinatorLayer) => Layer70.mergeAll(layer50, schedulerLayer).pipe(Layer70.provideMerge(workflowLayerWith(toolRuntimeLayer, promptAssemblerLayer, schemaRegistryLayer, toolTransitionCoordinatorLayer)));
16636
+ var makeService2 = (database, checkDatabase) => Effect78.gen(function* () {
15166
16637
  const sharding = yield* Sharding.Sharding;
15167
16638
  const workflow = yield* WorkflowEngine.WorkflowEngine;
15168
16639
  const makeClient = yield* client2;
15169
- return Service49.of({
15170
- check: Effect77.fn("RunnerRuntime.check")(function* () {
15171
- yield* Effect77.annotateCurrentSpan("relay.database.mode", database);
16640
+ return Service50.of({
16641
+ check: Effect78.fn("RunnerRuntime.check")(function* () {
16642
+ yield* Effect78.annotateCurrentSpan("relay.database.mode", database);
15172
16643
  yield* checkDatabase;
15173
- yield* Effect77.sync(() => sharding);
15174
- yield* Effect77.sync(() => workflow);
15175
- yield* Effect77.sync(() => makeClient);
16644
+ yield* Effect78.sync(() => sharding);
16645
+ yield* Effect78.sync(() => workflow);
16646
+ yield* Effect78.sync(() => makeClient);
15176
16647
  yield* recordRunnerReadinessChecked(database);
15177
16648
  return {
15178
16649
  database,
@@ -15183,9 +16654,9 @@ var makeService2 = (database, checkDatabase) => Effect77.gen(function* () {
15183
16654
  })
15184
16655
  });
15185
16656
  });
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({
16657
+ var checkLayer = (database, checkDatabase) => Layer70.effect(Service50, makeService2(database, checkDatabase));
16658
+ var memoryCheckLayer = checkLayer("memory", Effect78.void);
16659
+ var detectDialect = Effect78.serviceOption(SqlClient23).pipe(Effect78.map(Option27.match({
15189
16660
  onNone: () => "sql",
15190
16661
  onSome: (sqlClient) => sqlClient.onDialectOrElse({
15191
16662
  pg: () => "pg",
@@ -15194,31 +16665,31 @@ var detectDialect = Effect77.serviceOption(SqlClient22).pipe(Effect77.map(Option
15194
16665
  orElse: () => "sql"
15195
16666
  })
15196
16667
  })));
15197
- var databaseHealthCheck = Effect77.gen(function* () {
15198
- const database = yield* Effect77.serviceOption(exports_database_service.Service);
16668
+ var databaseHealthCheck = Effect78.gen(function* () {
16669
+ const database = yield* Effect78.serviceOption(exports_database_service.Service);
15199
16670
  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));
16671
+ return exports_database_service.check().pipe(Effect78.mapError((error) => new RunnerRuntimeError({ message: String(error) })), Effect78.provideService(exports_database_service.Service, database.value));
15201
16672
  }
15202
- const sqlClient = yield* Effect77.serviceOption(SqlClient22);
16673
+ const sqlClient = yield* Effect78.serviceOption(SqlClient23);
15203
16674
  if (Option27.isSome(sqlClient)) {
15204
- return sqlClient.value`select 1 as ok`.pipe(Effect77.asVoid, Effect77.mapError((error) => new RunnerRuntimeError({ message: String(error) })));
16675
+ return sqlClient.value`select 1 as ok`.pipe(Effect78.asVoid, Effect78.mapError((error) => new RunnerRuntimeError({ message: String(error) })));
15205
16676
  }
15206
- return Effect77.void;
16677
+ return Effect78.void;
15207
16678
  });
15208
- var sqlCheckLayer = Layer69.effect(Service49, Effect77.gen(function* () {
16679
+ var sqlCheckLayer = Layer70.effect(Service50, Effect78.gen(function* () {
15209
16680
  const dialect2 = yield* detectDialect;
15210
16681
  const checkDatabase = yield* databaseHealthCheck;
15211
16682
  return yield* makeService2(dialect2, checkDatabase);
15212
16683
  }));
15213
- var makeClientService = (database, checkDatabase) => Effect77.gen(function* () {
16684
+ var makeClientService = (database, checkDatabase) => Effect78.gen(function* () {
15214
16685
  const sharding = yield* Sharding.Sharding;
15215
16686
  const makeClient = yield* client2;
15216
- return Service49.of({
15217
- check: Effect77.fn("RunnerRuntime.check")(function* () {
15218
- yield* Effect77.annotateCurrentSpan("relay.database.mode", database);
16687
+ return Service50.of({
16688
+ check: Effect78.fn("RunnerRuntime.check")(function* () {
16689
+ yield* Effect78.annotateCurrentSpan("relay.database.mode", database);
15219
16690
  yield* checkDatabase;
15220
- yield* Effect77.sync(() => sharding);
15221
- yield* Effect77.sync(() => makeClient);
16691
+ yield* Effect78.sync(() => sharding);
16692
+ yield* Effect78.sync(() => makeClient);
15222
16693
  yield* recordRunnerReadinessChecked(database);
15223
16694
  return {
15224
16695
  database,
@@ -15229,20 +16700,20 @@ var makeClientService = (database, checkDatabase) => Effect77.gen(function* () {
15229
16700
  })
15230
16701
  });
15231
16702
  });
15232
- var memoryClientCheckLayer = Layer69.effect(Service49, makeClientService("memory", Effect77.void));
15233
- var multiNodeDialectGuard = Layer69.effectDiscard(Effect77.gen(function* () {
16703
+ var memoryClientCheckLayer = Layer70.effect(Service50, makeClientService("memory", Effect78.void));
16704
+ var multiNodeDialectGuard = Layer70.effectDiscard(Effect78.gen(function* () {
15234
16705
  const dialect2 = yield* detectDialect;
15235
16706
  if (dialect2 === "sqlite") {
15236
- return yield* Effect77.die(new Error("SQLite supports single-process topologies only; multi-node cluster composition requires Postgres or MySQL"));
16707
+ return yield* Effect78.die(new Error("SQLite supports single-process topologies only; multi-node cluster composition requires Postgres or MySQL"));
15237
16708
  }
15238
16709
  }));
15239
- var sqlClientCheckLayer = Layer69.effect(Service49, Effect77.gen(function* () {
16710
+ var sqlClientCheckLayer = Layer70.effect(Service50, Effect78.gen(function* () {
15240
16711
  const dialect2 = yield* detectDialect;
15241
16712
  const checkDatabase = yield* databaseHealthCheck;
15242
16713
  return yield* makeClientService(dialect2, checkDatabase);
15243
16714
  }));
15244
- var deterministicTestModelLayer = Layer69.effect(LanguageModel7.LanguageModel, LanguageModel7.make({
15245
- generateText: () => Effect77.succeed([{ type: "text", text: "deterministic test response" }]),
16715
+ var deterministicTestModelLayer = Layer70.effect(LanguageModel7.LanguageModel, LanguageModel7.make({
16716
+ generateText: () => Effect78.succeed([{ type: "text", text: "deterministic test response" }]),
15246
16717
  streamText: () => Stream10.make({ type: "text-delta", id: "text", delta: "deterministic test response" })
15247
16718
  }));
15248
16719
  var testLanguageModelLayer = layerFromRegistrationEffects3([
@@ -15253,57 +16724,60 @@ var testLanguageModelLayer = layerFromRegistrationEffects3([
15253
16724
  })
15254
16725
  ]);
15255
16726
  var testEmbeddingModelLayer = deterministicTestLayer();
15256
- var defaultPromptAssemblerLayer = (blobStoreLayer = passthroughLayer, artifactStoreLayer = passthroughLayer2) => defaultLayerWithStores.pipe(Layer69.provide(Layer69.mergeAll(blobStoreLayer, artifactStoreLayer)));
16727
+ var defaultPromptAssemblerLayer = (blobStoreLayer = passthroughLayer, artifactStoreLayer = passthroughLayer2) => defaultLayerWithStores.pipe(Layer70.provide(Layer70.mergeAll(blobStoreLayer, artifactStoreLayer)));
15257
16728
  var layerWith = (options) => {
15258
16729
  const blobStoreLayer = options.blobStoreLayer ?? passthroughLayer;
15259
16730
  const artifactStoreLayer = options.artifactStoreLayer ?? passthroughLayer2;
15260
16731
  const promptAssemblerLayer = options.promptAssemblerLayer ?? defaultPromptAssemblerLayer(blobStoreLayer, artifactStoreLayer);
15261
- const schemaRegistryLayer = options.schemaRegistryLayer ?? layer37();
16732
+ const schemaRegistryLayer = options.schemaRegistryLayer ?? layer38();
15262
16733
  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));
16734
+ const memoryLayer36 = layer35().pipe(Layer70.provideMerge(embeddingModelLayer));
16735
+ const clusterContextLayer = Layer70.mergeAll(options.languageModelLayer, memoryLayer36, blobStoreLayer, artifactStoreLayer, promptAssemblerLayer, schemaRegistryLayer);
16736
+ const clusterLayer = options.clusterLayer.pipe(Layer70.provide(clusterContextLayer));
16737
+ 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
16738
  };
15268
16739
  var layerWithClient = (options) => {
15269
16740
  const blobStoreLayer = options.blobStoreLayer ?? passthroughLayer;
15270
16741
  const artifactStoreLayer = options.artifactStoreLayer ?? passthroughLayer2;
15271
16742
  const promptAssemblerLayer = options.promptAssemblerLayer ?? defaultPromptAssemblerLayer(blobStoreLayer, artifactStoreLayer);
15272
- const schemaRegistryLayer = options.schemaRegistryLayer ?? layer37();
16743
+ const schemaRegistryLayer = options.schemaRegistryLayer ?? layer38();
15273
16744
  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));
16745
+ const memoryLayer36 = layer35().pipe(Layer70.provideMerge(embeddingModelLayer));
16746
+ 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
16747
  };
15277
16748
  var layerWithServices = (options) => layerWith({
16749
+ toolTransitionCoordinatorLayer: sqlLayer,
15278
16750
  checkLayer: sqlCheckLayer,
15279
16751
  clusterLayer: sqlClusterLayer,
15280
- repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer69.provideMerge(options.databaseLayer)),
16752
+ repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer70.provideMerge(options.databaseLayer)),
15281
16753
  languageModelLayer: options.languageModelLayer,
15282
16754
  embeddingModelLayer: options.embeddingModelLayer,
15283
16755
  toolRuntimeLayer: options.toolRuntimeLayer,
15284
- schedulerLayer: layer51,
16756
+ schedulerLayer: layer52,
15285
16757
  promptAssemblerLayer: options.promptAssemblerLayer,
15286
16758
  blobStoreLayer: options.blobStoreLayer,
15287
16759
  artifactStoreLayer: options.artifactStoreLayer,
15288
16760
  schemaRegistryLayer: options.schemaRegistryLayer
15289
16761
  });
15290
16762
  var layerWithServicesMultiNode = (options) => layerWith({
15291
- checkLayer: Layer69.mergeAll(sqlCheckLayer, multiNodeDialectGuard),
16763
+ toolTransitionCoordinatorLayer: sqlLayer,
16764
+ checkLayer: Layer70.mergeAll(sqlCheckLayer, multiNodeDialectGuard),
15292
16765
  clusterLayer: clusterLayerHttp(options.cluster),
15293
- repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer69.provideMerge(options.databaseLayer)),
16766
+ repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer70.provideMerge(options.databaseLayer)),
15294
16767
  languageModelLayer: options.languageModelLayer,
15295
16768
  embeddingModelLayer: options.embeddingModelLayer,
15296
16769
  toolRuntimeLayer: options.toolRuntimeLayer,
15297
- schedulerLayer: layer51,
16770
+ schedulerLayer: layer52,
15298
16771
  promptAssemblerLayer: options.promptAssemblerLayer,
15299
16772
  blobStoreLayer: options.blobStoreLayer,
15300
16773
  artifactStoreLayer: options.artifactStoreLayer,
15301
16774
  schemaRegistryLayer: options.schemaRegistryLayer
15302
16775
  });
15303
16776
  var layerWithServicesMultiNodeClientOnly = (options) => layerWithClient({
15304
- checkLayer: Layer69.mergeAll(sqlClientCheckLayer, multiNodeDialectGuard),
16777
+ toolTransitionCoordinatorLayer: sqlLayer,
16778
+ checkLayer: Layer70.mergeAll(sqlClientCheckLayer, multiNodeDialectGuard),
15305
16779
  clusterLayer: clusterLayerHttpClientOnly(options.cluster ?? {}),
15306
- repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer69.provideMerge(options.databaseLayer)),
16780
+ repositoryLayer: options.databaseLayer === undefined ? sqlRepositoryLayer : sqlRepositoryLayer.pipe(Layer70.provideMerge(options.databaseLayer)),
15307
16781
  languageModelLayer: options.languageModelLayer,
15308
16782
  embeddingModelLayer: options.embeddingModelLayer,
15309
16783
  toolRuntimeLayer: options.toolRuntimeLayer,
@@ -15313,53 +16787,57 @@ var layerWithServicesMultiNodeClientOnly = (options) => layerWithClient({
15313
16787
  schemaRegistryLayer: options.schemaRegistryLayer
15314
16788
  });
15315
16789
  var layerWithLanguageModelService = (options) => layerWithServices({ ...options, toolRuntimeLayer: layer23() });
15316
- var layer52 = layerWithServices({
16790
+ var layer53 = layerWithServices({
15317
16791
  databaseLayer: exports_database_service.layerFromPgClient,
15318
16792
  languageModelLayer: memoryLayer28(),
15319
16793
  embeddingModelLayer: memoryLayer27(),
15320
16794
  toolRuntimeLayer: layer23()
15321
16795
  });
15322
16796
  var testLayerWithServices = (options) => layerWith({
16797
+ toolTransitionCoordinatorLayer: memoryLayer33,
15323
16798
  checkLayer: memoryCheckLayer,
15324
16799
  clusterLayer: memoryClusterLayer,
15325
16800
  repositoryLayer: memoryRepositoryLayer,
15326
16801
  languageModelLayer: options.languageModelLayer,
15327
16802
  embeddingModelLayer: options.embeddingModelLayer ?? testEmbeddingModelLayer,
15328
16803
  toolRuntimeLayer: options.toolRuntimeLayer,
15329
- schedulerLayer: memoryLayer34
15330
- }).pipe(Layer69.provideMerge(testCryptoLayer));
16804
+ schedulerLayer: memoryLayer35
16805
+ }).pipe(Layer70.provideMerge(testCryptoLayer));
15331
16806
  var testLayerWithLanguageModelService = (languageModelLayer) => testLayerWithServices({ languageModelLayer, toolRuntimeLayer: layer23() });
15332
16807
  var testLayer51 = testLayerWithServices({
15333
16808
  languageModelLayer: testLanguageModelLayer,
15334
16809
  toolRuntimeLayer: layer23()
15335
16810
  });
15336
16811
  var testClientLayer = layerWithClient({
16812
+ toolTransitionCoordinatorLayer: memoryLayer33,
15337
16813
  checkLayer: memoryClientCheckLayer,
15338
16814
  clusterLayer: memoryClusterLayer,
15339
16815
  repositoryLayer: memoryRepositoryLayer,
15340
16816
  languageModelLayer: testLanguageModelLayer,
15341
16817
  embeddingModelLayer: testEmbeddingModelLayer,
15342
16818
  toolRuntimeLayer: layer23()
15343
- }).pipe(Layer69.provideMerge(testCryptoLayer));
16819
+ }).pipe(Layer70.provideMerge(testCryptoLayer));
15344
16820
  var testLayerWithDatabaseCheck = (databaseLayer) => layerWith({
16821
+ toolTransitionCoordinatorLayer: memoryLayer33,
15345
16822
  checkLayer: sqlCheckLayer,
15346
16823
  clusterLayer: memoryClusterLayer,
15347
16824
  repositoryLayer: memoryRepositoryLayer,
15348
16825
  languageModelLayer: testLanguageModelLayer,
15349
16826
  embeddingModelLayer: testEmbeddingModelLayer,
15350
16827
  toolRuntimeLayer: layer23(),
15351
- schedulerLayer: memoryLayer34
15352
- }).pipe(Layer69.provide(databaseLayer), Layer69.provideMerge(testCryptoLayer));
16828
+ schedulerLayer: memoryLayer35
16829
+ }).pipe(Layer70.provide(databaseLayer), Layer70.provideMerge(testCryptoLayer));
15353
16830
  var testClientLayerWithDatabaseCheck = (databaseLayer) => layerWithClient({
16831
+ toolTransitionCoordinatorLayer: memoryLayer33,
15354
16832
  checkLayer: sqlClientCheckLayer,
15355
16833
  clusterLayer: memoryClusterLayer,
15356
16834
  repositoryLayer: memoryRepositoryLayer,
15357
16835
  languageModelLayer: testLanguageModelLayer,
15358
16836
  embeddingModelLayer: testEmbeddingModelLayer,
15359
16837
  toolRuntimeLayer: layer23()
15360
- }).pipe(Layer69.provide(databaseLayer), Layer69.provideMerge(testCryptoLayer));
15361
- var check2 = Effect77.fn("RunnerRuntime.check.call")(function* () {
15362
- const service = yield* Service49;
16838
+ }).pipe(Layer70.provide(databaseLayer), Layer70.provideMerge(testCryptoLayer));
16839
+ var check2 = Effect78.fn("RunnerRuntime.check.call")(function* () {
16840
+ const service = yield* Service50;
15363
16841
  return yield* service.check();
15364
16842
  });
15365
16843
  // ../runtime/src/workflow/activity-version-registry.ts
@@ -15375,7 +16853,7 @@ __export(exports_activity_version_registry, {
15375
16853
  ActivityManifestChange: () => ActivityManifestChange,
15376
16854
  ActivityManifest: () => ActivityManifest
15377
16855
  });
15378
- import { Crypto as Crypto5, Effect as Effect78, Schema as Schema74 } from "effect";
16856
+ import { Crypto as Crypto5, Effect as Effect79, Schema as Schema74 } from "effect";
15379
16857
  var generatedFrom = "@relayfx/runtime/ExecutionWorkflow";
15380
16858
  var ActivityManifestEntry = Schema74.Struct({
15381
16859
  name: Schema74.String,
@@ -15533,13 +17011,13 @@ var canonical = (value) => {
15533
17011
  };
15534
17012
  var canonicalStringify = (value) => JSON.stringify(canonical(value));
15535
17013
  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) {
17014
+ var signatureHash = Effect79.fn("ActivityVersionRegistry.signatureHash")(function* (input, success2, error) {
15537
17015
  const crypto = yield* Crypto5.Crypto;
15538
17016
  const payload = new TextEncoder().encode(canonicalStringify({ input, success: success2, error }));
15539
17017
  const digest = yield* crypto.digest("SHA-256", payload);
15540
17018
  return hex2(digest);
15541
17019
  });
15542
- var manifestEntry = Effect78.fn("ActivityVersionRegistry.manifestEntry")(function* (contract) {
17020
+ var manifestEntry = Effect79.fn("ActivityVersionRegistry.manifestEntry")(function* (contract) {
15543
17021
  const input = schemaJson(contract.input);
15544
17022
  const success2 = schemaJson(contract.success);
15545
17023
  const error = schemaJson(contract.error);
@@ -15549,8 +17027,8 @@ var manifestEntry = Effect78.fn("ActivityVersionRegistry.manifestEntry")(functio
15549
17027
  signature_hash
15550
17028
  };
15551
17029
  });
15552
- var currentManifest = Effect78.fn("ActivityVersionRegistry.currentManifest")(function* () {
15553
- const activities = yield* Effect78.forEach(contracts.toSorted((left, right) => left.name.localeCompare(right.name)), manifestEntry);
17030
+ var currentManifest = Effect79.fn("ActivityVersionRegistry.currentManifest")(function* () {
17031
+ const activities = yield* Effect79.forEach(contracts.toSorted((left, right) => left.name.localeCompare(right.name)), manifestEntry);
15554
17032
  return {
15555
17033
  version: 1,
15556
17034
  generated_from: generatedFrom,
@@ -15604,11 +17082,11 @@ var evaluateGuard = (input) => {
15604
17082
  additive_changes: diff.additive
15605
17083
  };
15606
17084
  };
15607
- var guard = Effect78.fn("ActivityVersionRegistry.guard")(function* (input) {
17085
+ var guard = Effect79.fn("ActivityVersionRegistry.guard")(function* (input) {
15608
17086
  const result = evaluateGuard(input);
15609
17087
  if (result.status === "pass")
15610
17088
  return result;
15611
- return yield* Effect78.fail(new ActivityManifestGuardFailed({
17089
+ return yield* Effect79.fail(new ActivityManifestGuardFailed({
15612
17090
  message: `Activity replay contract changed while ${result.waiting_executions} waiting executions exist`,
15613
17091
  result
15614
17092
  }));
@@ -15638,9 +17116,9 @@ __export(exports_language_model_registration, {
15638
17116
  anthropic: () => anthropic
15639
17117
  });
15640
17118
 
15641
- // ../../node_modules/.bun/@batonfx+providers@0.3.7/node_modules/@batonfx/providers/src/anthropic.ts
17119
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/anthropic.ts
15642
17120
  import { AnthropicClient, AnthropicLanguageModel } from "@effect/ai-anthropic";
15643
- import { Layer as Layer70 } from "effect";
17121
+ import { Layer as Layer71 } from "effect";
15644
17122
  import { FetchHttpClient as FetchHttpClient2 } from "effect/unstable/http";
15645
17123
  var anthropic = (input) => exports_model_registry.registrationFromLayer({
15646
17124
  provider: "anthropic",
@@ -15653,16 +17131,16 @@ var anthropic = (input) => exports_model_registry.registrationFromLayer({
15653
17131
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
15654
17132
  });
15655
17133
  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
17134
+ var withAnthropic = (options) => exports_model_registry.layerFromRegistrationEffects([anthropic(options)]).pipe(Layer71.provide(AnthropicClient.layerConfig({ ...options.clientConfig, apiKey: options.apiKey })), Layer71.provide(FetchHttpClient2.layer));
17135
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/deterministic.ts
15658
17136
  import { OpenAiClient as OpenAiClient3 } from "@effect/ai-openai";
15659
- import { Effect as Effect79, Layer as Layer72, Option as Option28, Stream as Stream11 } from "effect";
17137
+ import { Effect as Effect80, Layer as Layer73, Option as Option28, Stream as Stream11 } from "effect";
15660
17138
  import { LanguageModel as LanguageModel8, Response as Response7 } from "effect/unstable/ai";
15661
17139
  import { FetchHttpClient as FetchHttpClient4 } from "effect/unstable/http";
15662
17140
 
15663
- // ../../node_modules/.bun/@batonfx+providers@0.3.7/node_modules/@batonfx/providers/src/openai.ts
17141
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/openai.ts
15664
17142
  import { OpenAiClient as OpenAiClient2, OpenAiLanguageModel } from "@effect/ai-openai";
15665
- import { Layer as Layer71 } from "effect";
17143
+ import { Layer as Layer72 } from "effect";
15666
17144
  import { FetchHttpClient as FetchHttpClient3 } from "effect/unstable/http";
15667
17145
  var openAi = (input) => exports_model_registry.registrationFromLayer({
15668
17146
  provider: "openai",
@@ -15675,11 +17153,11 @@ var openAi = (input) => exports_model_registry.registrationFromLayer({
15675
17153
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
15676
17154
  });
15677
17155
  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));
17156
+ var withOpenAi = (options) => exports_model_registry.layerFromRegistrationEffects([openAi(options)]).pipe(Layer72.provide(OpenAiClient2.layerConfig({ ...options.clientConfig, apiKey: options.apiKey })), Layer72.provide(FetchHttpClient3.layer));
15679
17157
 
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" }]),
17158
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/deterministic.ts
17159
+ var deterministicModelLayer = Layer73.effect(LanguageModel8.LanguageModel, LanguageModel8.make({
17160
+ generateText: () => Effect80.succeed([{ type: "text", text: "deterministic response" }]),
15683
17161
  streamText: () => Stream11.make(Response7.makePart("text-delta", { id: "text", delta: "deterministic response" }))
15684
17162
  }));
15685
17163
  var deterministicModel = (input = {}) => exports_model_registry.registrationFromLayer({
@@ -15690,20 +17168,20 @@ var deterministicModel = (input = {}) => exports_model_registry.registrationFrom
15690
17168
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
15691
17169
  });
15692
17170
  var withDeterministic = (input = {}) => exports_model_registry.layerFromRegistrationEffects([deterministicModel(input)]);
15693
- var withOpenAiOrDeterministic = (options) => Layer72.unwrap(Effect79.gen(function* () {
17171
+ var withOpenAiOrDeterministic = (options) => Layer73.unwrap(Effect80.gen(function* () {
15694
17172
  const deterministic = yield* deterministicModel({
15695
17173
  provider: options.fallbackProvider ?? "deterministic",
15696
17174
  model: options.fallbackModel
15697
17175
  });
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));
17176
+ 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
17177
  return exports_model_registry.layer([
15700
17178
  deterministic,
15701
17179
  ...Option28.isSome(openAiRegistration) ? [openAiRegistration.value] : []
15702
17180
  ]);
15703
17181
  }));
15704
- // ../../node_modules/.bun/@batonfx+providers@0.3.7/node_modules/@batonfx/providers/src/openai-compat.ts
17182
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/openai-compat.ts
15705
17183
  import { OpenAiClient as OpenAiClient4, OpenAiLanguageModel as OpenAiLanguageModel2 } from "@effect/ai-openai-compat";
15706
- import { Config as Config8, Layer as Layer73 } from "effect";
17184
+ import { Config as Config8, Layer as Layer74 } from "effect";
15707
17185
  import { FetchHttpClient as FetchHttpClient5 } from "effect/unstable/http";
15708
17186
  var openAiCompatible = (input) => exports_model_registry.registrationFromLayer({
15709
17187
  provider: input.provider ?? "openai-compatible",
@@ -15721,10 +17199,10 @@ var clientLayerConfig = (options) => OpenAiClient4.layerConfig({
15721
17199
  ...options.apiKey === undefined ? {} : { apiKey: options.apiKey },
15722
17200
  ...options.baseUrl === undefined ? {} : { apiUrl: Config8.succeed(options.baseUrl) }
15723
17201
  });
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
17202
+ var withOpenAiCompatible = (options) => exports_model_registry.layerFromRegistrationEffects([openAiCompatible(options)]).pipe(Layer74.provide(clientLayerConfig(options)), Layer74.provide(FetchHttpClient5.layer));
17203
+ // ../../node_modules/.bun/@batonfx+providers@0.4.0/node_modules/@batonfx/providers/src/openrouter.ts
15726
17204
  import { OpenRouterClient, OpenRouterLanguageModel } from "@effect/ai-openrouter";
15727
- import { Layer as Layer74 } from "effect";
17205
+ import { Layer as Layer75 } from "effect";
15728
17206
  import { FetchHttpClient as FetchHttpClient6 } from "effect/unstable/http";
15729
17207
  var openRouter = (input) => exports_model_registry.registrationFromLayer({
15730
17208
  provider: "openrouter",
@@ -15737,7 +17215,7 @@ var openRouter = (input) => exports_model_registry.registrationFromLayer({
15737
17215
  ...input.metadata === undefined ? {} : { metadata: input.metadata }
15738
17216
  });
15739
17217
  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));
17218
+ var withOpenRouter = (options) => exports_model_registry.layerFromRegistrationEffects([openRouter(options)]).pipe(Layer75.provide(OpenRouterClient.layerConfig({ ...options.clientConfig, apiKey: options.apiKey })), Layer75.provide(FetchHttpClient6.layer));
15741
17219
  // src/ai.ts
15742
17220
  var relayAiPackage = "@relayfx/sdk/ai";
15743
17221
  export {
@@ -15747,7 +17225,7 @@ export {
15747
17225
  exports_tool_output as ToolOutput,
15748
17226
  exports_tool_executor as ToolExecutor,
15749
17227
  exports_tool_context as ToolContext,
15750
- Tool7 as Tool,
17228
+ Tool6 as Tool,
15751
17229
  Tokenizer3 as Tokenizer,
15752
17230
  Telemetry2 as Telemetry,
15753
17231
  exports_steering as Steering,