@relayfx/sdk 0.0.47 → 0.0.49

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