effect-agent 0.1.0-beta.113 → 0.1.0-beta.115

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 (137) hide show
  1. package/dist/Agent-1DMSO_Fl.mjs.map +1 -1
  2. package/dist/{Agent-DriBcXBN.d.mts → Agent-D9cXqfF3.d.mts} +9 -2
  3. package/dist/{AgentRuntime-DLwPoEVH.mjs → AgentRuntime-Cp1hAb-W.mjs} +8 -4
  4. package/dist/AgentRuntime-Cp1hAb-W.mjs.map +1 -0
  5. package/dist/{AgentRuntime-CWkHuzyt.d.mts → AgentRuntime-DyZv8uu2.d.mts} +6 -6
  6. package/dist/{DurableAgentRuntime-BIrgxwRl.mjs → DurableAgentRuntime-tNrkJZNo.mjs} +254 -162
  7. package/dist/DurableAgentRuntime-tNrkJZNo.mjs.map +1 -0
  8. package/dist/{DurableFailpoint-mx3-nsxU.d.mts → DurableFailpoint-Cnr3wx1L.d.mts} +3 -3
  9. package/dist/{EventSource-ARs56eBq.d.mts → EventSource-DPRdlvhV.d.mts} +3 -3
  10. package/dist/{Messaging-DaZDlBqh.d.mts → Messaging-JYYN3oYS.d.mts} +3 -3
  11. package/dist/{MessagingHost-e1Sbzfao.d.mts → MessagingHost-CqzpxbGz.d.mts} +3 -3
  12. package/dist/{MessagingHost-D89X7ma8.mjs → MessagingHost-DfsbMPvq.mjs} +2 -2
  13. package/dist/{MessagingHost-D89X7ma8.mjs.map → MessagingHost-DfsbMPvq.mjs.map} +1 -1
  14. package/dist/{Output-CAFJTAbP.d.mts → Output-V-6YL1_Z.d.mts} +2 -2
  15. package/dist/{PreparedInputAdmission-_WYg-D0f.d.mts → PreparedInputAdmission-DqQUjA9k.d.mts} +4 -4
  16. package/dist/{Records-BtxMy8xD.d.mts → Records-Byeb70tt.d.mts} +89 -31
  17. package/dist/{RunOptions-BoESJrxw.d.mts → RunOptions-CSBsSj0X.d.mts} +3 -3
  18. package/dist/{Schedule-DGPyXBzK.d.mts → Schedule-krSnBcbU.d.mts} +2 -2
  19. package/dist/{Subagent-D9eYdGTl.mjs → Subagent-Di8EEjWZ.mjs} +67 -105
  20. package/dist/Subagent-Di8EEjWZ.mjs.map +1 -0
  21. package/dist/{Subagent-F72tuaxy.d.mts → Subagent-gw9KD6eb.d.mts} +310 -35
  22. package/dist/{SubagentHost-CmiNTOBZ.d.mts → SubagentHost-P9zB_TfV.d.mts} +24 -18
  23. package/dist/{Subscription-B9VszlF9.d.mts → Subscription-Xnwd42Sm.d.mts} +6 -3
  24. package/dist/{SubscriptionInput-BJWZqCWP.d.mts → SubscriptionInput-CqtJ58vl.d.mts} +3 -3
  25. package/dist/{Worker-T_3RbaKc.mjs → Worker-CfwzMZEK.mjs} +66 -5
  26. package/dist/Worker-CfwzMZEK.mjs.map +1 -0
  27. package/dist/{Worker-Du9dhVnp.d.mts → Worker-fwWkBg12.d.mts} +199 -6
  28. package/dist/{agent-registration-B5CI-Ygk.mjs → agent-registration-CKNsrpwo.mjs} +7 -7
  29. package/dist/agent-registration-CKNsrpwo.mjs.map +1 -0
  30. package/dist/capabilities/Commands.d.mts +1 -1
  31. package/dist/capabilities/Messaging.d.mts +1 -1
  32. package/dist/capabilities/Messaging.mjs +2 -2
  33. package/dist/capabilities/RunHooks.d.mts +1 -1
  34. package/dist/capabilities/Subagent.d.mts +3 -3
  35. package/dist/capabilities/Subagent.mjs +3 -3
  36. package/dist/core/Agent.d.mts +1 -1
  37. package/dist/core/Worker.d.mts +2 -2
  38. package/dist/core/Worker.mjs +2 -2
  39. package/dist/durable/ActivityStore.d.mts +1 -1
  40. package/dist/durable/Admin.d.mts +1 -1
  41. package/dist/durable/AgentRegistration.d.mts +1 -1
  42. package/dist/durable/AgentRegistration.mjs +1 -1
  43. package/dist/durable/Certification.d.mts +2 -2
  44. package/dist/durable/CommittedActivity.d.mts +1 -1
  45. package/dist/durable/Digest.d.mts +1 -1
  46. package/dist/durable/DurableAgentRuntime.d.mts +1 -1
  47. package/dist/durable/DurableAgentRuntime.mjs +1 -1
  48. package/dist/durable/DurableFailpoint.d.mts +1 -1
  49. package/dist/durable/DurableFailpoint.mjs +4 -0
  50. package/dist/durable/DurableFailpoint.mjs.map +1 -1
  51. package/dist/durable/DurableFailpointTestControl.d.mts +1 -1
  52. package/dist/durable/EventSource.d.mts +1 -1
  53. package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
  54. package/dist/durable/MessageDelivery.d.mts +20 -3
  55. package/dist/durable/MessageDelivery.mjs +12 -4
  56. package/dist/durable/MessageDelivery.mjs.map +1 -1
  57. package/dist/durable/MessageDeliveryStoreConformance.d.mts +41 -39
  58. package/dist/durable/MessageDeliveryStoreConformance.mjs +1 -1
  59. package/dist/durable/PersistentHistory.d.mts +1 -1
  60. package/dist/durable/PreparedInputAdmission.d.mts +1 -1
  61. package/dist/durable/Records.d.mts +2 -2
  62. package/dist/durable/Records.mjs +12 -5
  63. package/dist/durable/Records.mjs.map +1 -1
  64. package/dist/durable/Recovery.d.mts +1 -1
  65. package/dist/durable/RunJournal.d.mts +1 -1
  66. package/dist/durable/Schedule.d.mts +1 -1
  67. package/dist/durable/ScheduleStoreConformance.d.mts +1 -1
  68. package/dist/durable/ScheduleTransition.d.mts +1 -1
  69. package/dist/durable/Scheduling.d.mts +2 -2
  70. package/dist/durable/SqlMessageDeliveryStore.mjs +7 -1
  71. package/dist/durable/SqlMessageDeliveryStore.mjs.map +1 -1
  72. package/dist/durable/SqlStorageV2Upgrade.d.mts +2 -2
  73. package/dist/durable/SqlSubscriptionStore.d.mts +2 -2
  74. package/dist/durable/SqlThreadNativeReads.d.mts +5 -1
  75. package/dist/durable/SqlThreadNativeReads.mjs +6 -0
  76. package/dist/durable/SqlThreadNativeReads.mjs.map +1 -1
  77. package/dist/durable/SubmissionLedger.d.mts +2 -2
  78. package/dist/durable/SubmissionLedger.mjs +34 -4
  79. package/dist/durable/SubmissionLedger.mjs.map +1 -1
  80. package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
  81. package/dist/durable/SubmissionLedgerConformance.mjs +899 -706
  82. package/dist/durable/SubmissionLedgerConformance.mjs.map +1 -1
  83. package/dist/durable/SubmissionStatus.d.mts +1 -1
  84. package/dist/durable/Subscription.d.mts +1 -1
  85. package/dist/durable/Subscription.mjs +1 -1
  86. package/dist/durable/SubscriptionInput.d.mts +1 -1
  87. package/dist/durable/SubscriptionInput.mjs +1 -1
  88. package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
  89. package/dist/durable/SubscriptionTools.d.mts +3 -3
  90. package/dist/durable/SubscriptionTransition.d.mts +1 -1
  91. package/dist/durable/Subscriptions.d.mts +5 -5
  92. package/dist/durable/ThreadContextHistory.d.mts +1 -1
  93. package/dist/durable/ThreadContextHistoryProjection.d.mts +1 -1
  94. package/dist/durable/ThreadInvariants.d.mts +1 -1
  95. package/dist/durable/ThreadProjection.d.mts +1 -1
  96. package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
  97. package/dist/durable/ThreadStore.d.mts +1 -1
  98. package/dist/durable/ThreadStore.mjs +5 -0
  99. package/dist/durable/ThreadStore.mjs.map +1 -1
  100. package/dist/durable/ThreadStoreConformance.d.mts +1 -1
  101. package/dist/durable/WorkerHost.d.mts +3 -3
  102. package/dist/durable/WorkerHost.mjs +1 -1
  103. package/dist/engine/AgentRuntime.d.mts +1 -1
  104. package/dist/engine/AgentRuntime.mjs +1 -1
  105. package/dist/engine/MessagingHost.d.mts +1 -1
  106. package/dist/engine/MessagingHost.mjs +1 -1
  107. package/dist/engine/Output.d.mts +1 -1
  108. package/dist/engine/RunOptions.d.mts +1 -1
  109. package/dist/engine/SubagentHost.d.mts +2 -2
  110. package/dist/engine/SubagentHost.mjs +5 -1
  111. package/dist/engine/SubagentHost.mjs.map +1 -1
  112. package/dist/index.d.mts +16 -16
  113. package/dist/index.mjs +5 -5
  114. package/package.json +1 -1
  115. package/src/capabilities/Subagent.ts +2 -1
  116. package/src/capabilities/internal/subagent-background.ts +86 -57
  117. package/src/capabilities/internal/subagent-reporting.ts +3 -128
  118. package/src/core/Agent.ts +8 -1
  119. package/src/core/Worker.ts +58 -2
  120. package/src/durable/DurableAgentRuntime.ts +2 -0
  121. package/src/durable/DurableFailpoint.ts +4 -0
  122. package/src/durable/MessageDelivery.ts +17 -2
  123. package/src/durable/Records.ts +12 -2
  124. package/src/durable/SqlMessageDeliveryStore.ts +15 -1
  125. package/src/durable/SqlThreadNativeReads.ts +14 -0
  126. package/src/durable/SubmissionLedger.ts +48 -1
  127. package/src/durable/SubmissionLedgerConformance.ts +260 -42
  128. package/src/durable/ThreadStore.ts +5 -0
  129. package/src/durable/internal/agent-registration.ts +13 -48
  130. package/src/durable/internal/worker-host.ts +490 -341
  131. package/src/engine/SubagentHost.ts +37 -13
  132. package/src/engine/internal/agent-runtime.ts +17 -2
  133. package/dist/AgentRuntime-DLwPoEVH.mjs.map +0 -1
  134. package/dist/DurableAgentRuntime-BIrgxwRl.mjs.map +0 -1
  135. package/dist/Subagent-D9eYdGTl.mjs.map +0 -1
  136. package/dist/Worker-T_3RbaKc.mjs.map +0 -1
  137. package/dist/agent-registration-B5CI-Ygk.mjs.map +0 -1
@@ -139,7 +139,13 @@ const makeSqlMessageDeliveryStore = Effect.fn("SqlMessageDeliveryStore.make")(fu
139
139
  change,
140
140
  list: Effect.fn("SqlMessageDeliveryStore.list")(function* (request) {
141
141
  const input = yield* validateMessageDelivery(MessageDeliveryPageRequest, request, "list");
142
- const rows = yield* query("list", sql`SELECT owner_thread_id, message_id, version, state, deadline_at_millis, record_json FROM effect_agent_message_deliveries WHERE owner_thread_id = ${input.ownerThreadId} ${input.after === void 0 ? sql`` : sql`AND message_id > ${input.after}`} ${input.pendingOnly ? sql`AND state NOT IN ('processed', 'refused')` : sql``} ORDER BY message_id LIMIT ${input.limit + 1}`);
142
+ const rows = yield* query("list", sql`SELECT owner_thread_id, message_id, version, state, deadline_at_millis, record_json FROM effect_agent_message_deliveries WHERE owner_thread_id = ${input.ownerThreadId} ${input.after === void 0 ? sql`` : sql`AND message_id > ${input.after}`} ${input.pendingOnly ? sql`AND state NOT IN ('processed', 'refused')` : sql``}
143
+ ${input.workerStarts === void 0 ? sql`` : sql`AND json_extract(record_json, '$.envelope.workerAdmission.origin.worker.delegationId') = ${input.workerStarts.delegationId}
144
+ AND json_extract(record_json, '$.envelope.workerAdmission.origin.worker.targetAgentId') = ${input.workerStarts.targetAgentId}
145
+ AND message_id = json_extract(record_json, '$.envelope.workerAdmission.origin.firstMessageId')`}
146
+ ${input.pendingWorker === void 0 ? sql`` : sql`AND json_extract(record_json, '$.envelope.workerAdmission.origin.worker.threadId') = ${input.pendingWorker}
147
+ AND state IN ('pending', 'parked') AND json_extract(record_json, '$.receipt') IS NULL`}
148
+ ORDER BY message_id LIMIT ${input.limit + 1}`);
143
149
  const records = yield* decodeRows(rows);
144
150
  const items = records.slice(0, input.limit);
145
151
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"SqlMessageDeliveryStore.mjs","names":[],"sources":["../../src/durable/SqlMessageDeliveryStore.ts"],"sourcesContent":["import { Context, Effect, Schema } from \"effect\";\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\";\nimport type { SqlError } from \"effect/unstable/sql/SqlError\";\n\nimport { ThreadId } from \"../core/Identifiers.ts\";\nimport {\n applyMessageDeliveryChange,\n defaultMessageDeliveryStoreLimits,\n MessageDeliveryChange,\n MessageDeliveryError,\n type MessageDeliveryFailure,\n MessageDeliveryFailpoint,\n MessageDeliveryKey,\n MessageDeliveryPageRequest,\n MessageDeliveryRecord,\n MessageDeliveryStore,\n MessageDeliveryStoreLimits,\n messageDeliveryDeadline,\n isWorkerUpdateDelivery,\n messageDeliveryCapacity,\n sameMessageDeliveryIdentity,\n validateMessageDelivery,\n} from \"./MessageDelivery.ts\";\nimport { ScheduleInstant } from \"./Schedule.ts\";\nimport { IdempotencyKey } from \"./SubmissionLedger.ts\";\n\n/** The adapter owns the atomic transaction and any associated native wake/alarm update. */\nexport class SqlMessageDeliveryTransaction extends Context.Service<\n SqlMessageDeliveryTransaction,\n {\n readonly run: <A>(\n body: Effect.Effect<A, MessageDeliveryFailure>,\n ) => Effect.Effect<A, MessageDeliveryFailure>;\n }\n>()(\"@effect-agent/thread/SqlMessageDeliveryTransaction\") {}\n\nexport interface SqlMessageDeliveryStoreOptions {\n /** UTF-8 bound on the complete persisted record, including a processed Settlement. */\n readonly maxStoredValueBytes?: number;\n}\n\nconst Row = Schema.Struct({\n owner_thread_id: ThreadId,\n message_id: IdempotencyKey,\n version: Schema.Int,\n state: Schema.String,\n deadline_at_millis: Schema.NullOr(ScheduleInstant),\n record_json: Schema.String,\n});\n\nconst Count = Schema.Struct({ retained: Schema.Natural, pending: Schema.Natural });\nconst Deadline = Schema.Struct({ deadline: Schema.NullOr(ScheduleInstant) });\n\nconst Scan = Schema.Struct({\n nowMillis: ScheduleInstant,\n limit: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(100)),\n ownerThreadId: Schema.optionalKey(ThreadId),\n});\n\nconst codec = Schema.fromJsonString(MessageDeliveryRecord);\nconst bytes = (text: string): number => new TextEncoder().encode(text).byteLength;\n\nconst storage = (operation: string, cause?: unknown) =>\n MessageDeliveryError.make({\n reason: \"storage\",\n operation,\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst corrupt = (operation: string, cause?: unknown) =>\n MessageDeliveryError.make({\n reason: \"corrupt\",\n operation,\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst query = <A>(operation: string, effect: Effect.Effect<A, SqlError>) =>\n effect.pipe(Effect.mapError((cause) => storage(operation, cause)));\n\n/**\n * Shared SQL implementation over the adapter-owned effect_agent_message_deliveries table.\n * Required columns: owner_thread_id, message_id (composite primary key), version, state,\n * deadline_at_millis (nullable effective wake deadline), record_json. Index non-null deadlines\n * by (deadline_at_millis, owner_thread_id, message_id). No source/receiver ledger joins.\n * Before failpoints precede the atomic transaction; after failpoints run after its commit.\n */\nexport const makeSqlMessageDeliveryStore = Effect.fn(\"SqlMessageDeliveryStore.make\")(function* (\n limits: MessageDeliveryStoreLimits = defaultMessageDeliveryStoreLimits,\n options: SqlMessageDeliveryStoreOptions = {},\n) {\n const config = yield* validateMessageDelivery(MessageDeliveryStoreLimits, limits, \"limits\");\n\n const maxStoredValueBytes = yield* validateMessageDelivery(\n Schema.Int.check(Schema.isGreaterThan(0)),\n options.maxStoredValueBytes ?? 16 * 1_024 * 1_024,\n \"stored-value-limit\",\n );\n\n const sql = yield* SqlClient.SqlClient;\n const transaction = yield* SqlMessageDeliveryTransaction;\n const failpoint = yield* MessageDeliveryFailpoint;\n\n const encode = Effect.fn(\"SqlMessageDeliveryStore.encode\")(function* (\n record: MessageDeliveryRecord,\n ) {\n const text = yield* Schema.encodeEffect(codec)(record).pipe(\n Effect.mapError((cause) => corrupt(\"encode\", cause)),\n );\n\n if (bytes(text) > maxStoredValueBytes)\n return yield* MessageDeliveryError.make({\n reason: \"capacity\",\n operation: \"stored-value-bytes\",\n });\n\n return text;\n });\n\n const decode = Effect.fn(\"SqlMessageDeliveryStore.decode\")(function* (row: typeof Row.Type) {\n if (bytes(row.record_json) > maxStoredValueBytes) return yield* corrupt(\"stored-value-bytes\");\n\n const record = yield* Schema.decodeEffect(codec)(row.record_json).pipe(\n Effect.mapError((cause) => corrupt(\"decode\", cause)),\n );\n\n if (\n record.key.ownerThreadId !== row.owner_thread_id ||\n record.key.messageId !== row.message_id ||\n record.version !== row.version ||\n record.status !== row.state ||\n messageDeliveryDeadline(record) !== row.deadline_at_millis\n ) {\n return yield* corrupt(\"row-metadata\");\n }\n\n return record;\n });\n\n const decodeRows = (rows: unknown) =>\n Schema.decodeUnknownEffect(Schema.Array(Row))(rows).pipe(\n Effect.mapError((cause) => corrupt(\"rows\", cause)),\n Effect.flatMap((rows) => Effect.forEach(rows, decode)),\n );\n\n const get: MessageDeliveryStore[\"Service\"][\"get\"] = Effect.fn(\"SqlMessageDeliveryStore.get\")(\n function* (key) {\n const input = yield* validateMessageDelivery(MessageDeliveryKey, key, \"get\");\n\n const rows = yield* query(\n \"get\",\n sql`SELECT owner_thread_id, message_id, version, state, deadline_at_millis, record_json FROM effect_agent_message_deliveries WHERE owner_thread_id = ${input.ownerThreadId} AND message_id = ${input.messageId}`,\n );\n\n return (yield* decodeRows(rows))[0] ?? null;\n },\n );\n\n const insert: MessageDeliveryStore[\"Service\"][\"insert\"] = Effect.fn(\n \"SqlMessageDeliveryStore.insert\",\n )(function* (record) {\n const text = yield* encode(record);\n\n const input = yield* Schema.decodeEffect(codec)(text).pipe(\n Effect.mapError((cause) => corrupt(\"insert\", cause)),\n );\n\n if (\n input.version !== 1 ||\n input.status !== \"pending\" ||\n input.leaseUntilMillis !== null ||\n input.retry.attempts !== 0 ||\n input.retry.generation !== 0 ||\n input.retry.automaticAttempts !== 0 ||\n input.retry.nextAttemptAtMillis !== input.createdAtMillis ||\n input.retry.lastAttemptAtMillis !== null ||\n input.retry.lastFailure !== null ||\n input.deadlineAtMillis !== input.initialDeadlineAtMillis\n ) {\n return yield* MessageDeliveryError.make({ reason: \"validation\", operation: \"insert-state\" });\n }\n if (bytes(JSON.stringify(input.envelope)) > config.maxEnvelopeBytes)\n return yield* MessageDeliveryError.make({ reason: \"capacity\", operation: \"envelope-bytes\" });\n yield* failpoint.hit(\"message-delivery:insert:before\");\n\n const result = yield* transaction.run(\n Effect.gen(function* () {\n const existing = yield* get(input.key);\n\n if (existing !== null) {\n if (!sameMessageDeliveryIdentity(existing, input))\n return yield* MessageDeliveryError.make({ reason: \"conflict\", operation: \"insert\" });\n\n return existing;\n }\n\n const update = isWorkerUpdateDelivery(input);\n const capacity = messageDeliveryCapacity(config, update);\n\n const counts = yield* query(\n \"count\",\n sql`SELECT COUNT(*) AS retained, COALESCE(SUM(CASE WHEN state IN ('pending', 'accepted', 'parked') THEN 1 ELSE 0 END), 0) AS pending FROM effect_agent_message_deliveries WHERE owner_thread_id = ${input.key.ownerThreadId} AND COALESCE(json_extract(record_json, '$.envelope.messageAdmission._tag'), '') ${update ? sql`= 'WorkerUpdate'` : sql`<> 'WorkerUpdate'`}`,\n );\n\n const count = (yield* Schema.decodeUnknownEffect(Schema.Array(Count))(counts).pipe(\n Effect.mapError((cause) => corrupt(\"count\", cause)),\n ))[0];\n\n if (count === undefined) return yield* corrupt(\"count\");\n if (count.retained >= capacity.retained || count.pending >= capacity.pending)\n return yield* MessageDeliveryError.make({ reason: \"capacity\", operation: \"insert\" });\n yield* query(\n \"insert\",\n sql`INSERT INTO effect_agent_message_deliveries (owner_thread_id, message_id, version, state, deadline_at_millis, record_json) VALUES (${input.key.ownerThreadId}, ${input.key.messageId}, ${input.version}, ${input.status}, ${messageDeliveryDeadline(input)}, ${text})`,\n );\n\n return input;\n }),\n );\n\n yield* failpoint.hit(\"message-delivery:insert:after\");\n\n return result;\n });\n\n const change: MessageDeliveryStore[\"Service\"][\"change\"] = Effect.fn(\n \"SqlMessageDeliveryStore.change\",\n )(function* (key, change) {\n const decodedKey = yield* validateMessageDelivery(MessageDeliveryKey, key, \"change\");\n const input = yield* validateMessageDelivery(MessageDeliveryChange, change, \"change\");\n const point = `message-delivery:${input._tag.toLowerCase()}`;\n\n yield* failpoint.hit(`${point}:before`);\n\n const result = yield* transaction.run(\n Effect.gen(function* () {\n const current = yield* get(decodedKey);\n\n if (current === null)\n return yield* MessageDeliveryError.make({ reason: \"not-found\", operation: \"change\" });\n const next = yield* Effect.fromResult(applyMessageDeliveryChange(current, input));\n const text = yield* encode(next);\n\n const updated = yield* query(\n \"change\",\n sql`UPDATE effect_agent_message_deliveries SET version = ${next.version}, state = ${next.status}, deadline_at_millis = ${messageDeliveryDeadline(next)}, record_json = ${text} WHERE owner_thread_id = ${decodedKey.ownerThreadId} AND message_id = ${decodedKey.messageId} AND version = ${input.expectedVersion} RETURNING owner_thread_id, message_id, version, state, deadline_at_millis, record_json`,\n );\n\n const rows = yield* decodeRows(updated);\n\n if (rows.length !== 1 || rows[0] === undefined)\n return yield* MessageDeliveryError.make({ reason: \"conflict\", operation: \"change\" });\n\n return rows[0];\n }),\n );\n\n yield* failpoint.hit(`${point}:after`);\n\n return result;\n });\n\n return MessageDeliveryStore.of({\n limits: config,\n maxStoredValueBytes,\n insert,\n get,\n change,\n list: Effect.fn(\"SqlMessageDeliveryStore.list\")(function* (request) {\n const input = yield* validateMessageDelivery(MessageDeliveryPageRequest, request, \"list\");\n\n const rows = yield* query(\n \"list\",\n sql`SELECT owner_thread_id, message_id, version, state, deadline_at_millis, record_json FROM effect_agent_message_deliveries WHERE owner_thread_id = ${input.ownerThreadId} ${input.after === undefined ? sql`` : sql`AND message_id > ${input.after}`} ${input.pendingOnly ? sql`AND state NOT IN ('processed', 'refused')` : sql``} ORDER BY message_id LIMIT ${input.limit + 1}`,\n );\n\n const records = yield* decodeRows(rows);\n const items = records.slice(0, input.limit);\n\n return {\n items,\n next: records.length > input.limit ? (items.at(-1)?.key.messageId ?? null) : null,\n };\n }),\n due: Effect.fn(\"SqlMessageDeliveryStore.due\")(function* (nowMillis, limit, ownerThreadId) {\n const input = yield* validateMessageDelivery(\n Scan,\n { nowMillis, limit, ...(ownerThreadId === undefined ? {} : { ownerThreadId }) },\n \"due\",\n );\n\n const rows = yield* query(\n \"due\",\n sql`SELECT owner_thread_id, message_id, version, state, deadline_at_millis, record_json FROM effect_agent_message_deliveries WHERE deadline_at_millis IS NOT NULL AND deadline_at_millis <= ${input.nowMillis} ${input.ownerThreadId === undefined ? sql`` : sql`AND owner_thread_id = ${input.ownerThreadId}`} ORDER BY deadline_at_millis, owner_thread_id, message_id LIMIT ${input.limit}`,\n );\n\n return (yield* decodeRows(rows)).map((record) => record.key);\n }),\n nextDeadline: Effect.fn(\"SqlMessageDeliveryStore.nextDeadline\")(function* (ownerThreadId) {\n if (ownerThreadId !== undefined)\n yield* validateMessageDelivery(ThreadId, ownerThreadId, \"nextDeadline\");\n\n const rows = yield* query(\n \"next-deadline\",\n sql`SELECT MIN(deadline_at_millis) AS deadline FROM effect_agent_message_deliveries ${ownerThreadId === undefined ? sql`` : sql`WHERE owner_thread_id = ${ownerThreadId}`}`,\n );\n\n const decoded = yield* Schema.decodeUnknownEffect(Schema.Array(Deadline))(rows).pipe(\n Effect.mapError((cause) => corrupt(\"next-deadline\", cause)),\n );\n\n return decoded[0]?.deadline ?? null;\n }),\n });\n});\n\n/** Add the pending-only index within the adapter's format transaction. */\nexport const createMessageDeliveryPendingIndex = Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n\n yield* sql`CREATE INDEX effect_agent_message_deliveries_pending ON effect_agent_message_deliveries(owner_thread_id, message_id) WHERE state NOT IN ('processed', 'refused')`;\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"SqlMessageDeliveryStore.mjs","names":[],"sources":["../../src/durable/SqlMessageDeliveryStore.ts"],"sourcesContent":["import { Context, Effect, Schema } from \"effect\";\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\";\nimport type { SqlError } from \"effect/unstable/sql/SqlError\";\n\nimport { ThreadId } from \"../core/Identifiers.ts\";\nimport {\n applyMessageDeliveryChange,\n defaultMessageDeliveryStoreLimits,\n MessageDeliveryChange,\n MessageDeliveryError,\n type MessageDeliveryFailure,\n MessageDeliveryFailpoint,\n MessageDeliveryKey,\n MessageDeliveryPageRequest,\n MessageDeliveryRecord,\n MessageDeliveryStore,\n MessageDeliveryStoreLimits,\n messageDeliveryDeadline,\n isWorkerUpdateDelivery,\n messageDeliveryCapacity,\n sameMessageDeliveryIdentity,\n validateMessageDelivery,\n} from \"./MessageDelivery.ts\";\nimport { ScheduleInstant } from \"./Schedule.ts\";\nimport { IdempotencyKey } from \"./SubmissionLedger.ts\";\n\n/** The adapter owns the atomic transaction and any associated native wake/alarm update. */\nexport class SqlMessageDeliveryTransaction extends Context.Service<\n SqlMessageDeliveryTransaction,\n {\n readonly run: <A>(\n body: Effect.Effect<A, MessageDeliveryFailure>,\n ) => Effect.Effect<A, MessageDeliveryFailure>;\n }\n>()(\"@effect-agent/thread/SqlMessageDeliveryTransaction\") {}\n\nexport interface SqlMessageDeliveryStoreOptions {\n /** UTF-8 bound on the complete persisted record, including a processed Settlement. */\n readonly maxStoredValueBytes?: number;\n}\n\nconst Row = Schema.Struct({\n owner_thread_id: ThreadId,\n message_id: IdempotencyKey,\n version: Schema.Int,\n state: Schema.String,\n deadline_at_millis: Schema.NullOr(ScheduleInstant),\n record_json: Schema.String,\n});\n\nconst Count = Schema.Struct({ retained: Schema.Natural, pending: Schema.Natural });\nconst Deadline = Schema.Struct({ deadline: Schema.NullOr(ScheduleInstant) });\n\nconst Scan = Schema.Struct({\n nowMillis: ScheduleInstant,\n limit: Schema.Int.check(Schema.isGreaterThan(0), Schema.isLessThanOrEqualTo(100)),\n ownerThreadId: Schema.optionalKey(ThreadId),\n});\n\nconst codec = Schema.fromJsonString(MessageDeliveryRecord);\nconst bytes = (text: string): number => new TextEncoder().encode(text).byteLength;\n\nconst storage = (operation: string, cause?: unknown) =>\n MessageDeliveryError.make({\n reason: \"storage\",\n operation,\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst corrupt = (operation: string, cause?: unknown) =>\n MessageDeliveryError.make({\n reason: \"corrupt\",\n operation,\n ...(cause === undefined ? {} : { cause }),\n });\n\nconst query = <A>(operation: string, effect: Effect.Effect<A, SqlError>) =>\n effect.pipe(Effect.mapError((cause) => storage(operation, cause)));\n\n/**\n * Shared SQL implementation over the adapter-owned effect_agent_message_deliveries table.\n * Required columns: owner_thread_id, message_id (composite primary key), version, state,\n * deadline_at_millis (nullable effective wake deadline), record_json. Index non-null deadlines\n * by (deadline_at_millis, owner_thread_id, message_id). No source/receiver ledger joins.\n * Before failpoints precede the atomic transaction; after failpoints run after its commit.\n */\nexport const makeSqlMessageDeliveryStore = Effect.fn(\"SqlMessageDeliveryStore.make\")(function* (\n limits: MessageDeliveryStoreLimits = defaultMessageDeliveryStoreLimits,\n options: SqlMessageDeliveryStoreOptions = {},\n) {\n const config = yield* validateMessageDelivery(MessageDeliveryStoreLimits, limits, \"limits\");\n\n const maxStoredValueBytes = yield* validateMessageDelivery(\n Schema.Int.check(Schema.isGreaterThan(0)),\n options.maxStoredValueBytes ?? 16 * 1_024 * 1_024,\n \"stored-value-limit\",\n );\n\n const sql = yield* SqlClient.SqlClient;\n const transaction = yield* SqlMessageDeliveryTransaction;\n const failpoint = yield* MessageDeliveryFailpoint;\n\n const encode = Effect.fn(\"SqlMessageDeliveryStore.encode\")(function* (\n record: MessageDeliveryRecord,\n ) {\n const text = yield* Schema.encodeEffect(codec)(record).pipe(\n Effect.mapError((cause) => corrupt(\"encode\", cause)),\n );\n\n if (bytes(text) > maxStoredValueBytes)\n return yield* MessageDeliveryError.make({\n reason: \"capacity\",\n operation: \"stored-value-bytes\",\n });\n\n return text;\n });\n\n const decode = Effect.fn(\"SqlMessageDeliveryStore.decode\")(function* (row: typeof Row.Type) {\n if (bytes(row.record_json) > maxStoredValueBytes) return yield* corrupt(\"stored-value-bytes\");\n\n const record = yield* Schema.decodeEffect(codec)(row.record_json).pipe(\n Effect.mapError((cause) => corrupt(\"decode\", cause)),\n );\n\n if (\n record.key.ownerThreadId !== row.owner_thread_id ||\n record.key.messageId !== row.message_id ||\n record.version !== row.version ||\n record.status !== row.state ||\n messageDeliveryDeadline(record) !== row.deadline_at_millis\n ) {\n return yield* corrupt(\"row-metadata\");\n }\n\n return record;\n });\n\n const decodeRows = (rows: unknown) =>\n Schema.decodeUnknownEffect(Schema.Array(Row))(rows).pipe(\n Effect.mapError((cause) => corrupt(\"rows\", cause)),\n Effect.flatMap((rows) => Effect.forEach(rows, decode)),\n );\n\n const get: MessageDeliveryStore[\"Service\"][\"get\"] = Effect.fn(\"SqlMessageDeliveryStore.get\")(\n function* (key) {\n const input = yield* validateMessageDelivery(MessageDeliveryKey, key, \"get\");\n\n const rows = yield* query(\n \"get\",\n sql`SELECT owner_thread_id, message_id, version, state, deadline_at_millis, record_json FROM effect_agent_message_deliveries WHERE owner_thread_id = ${input.ownerThreadId} AND message_id = ${input.messageId}`,\n );\n\n return (yield* decodeRows(rows))[0] ?? null;\n },\n );\n\n const insert: MessageDeliveryStore[\"Service\"][\"insert\"] = Effect.fn(\n \"SqlMessageDeliveryStore.insert\",\n )(function* (record) {\n const text = yield* encode(record);\n\n const input = yield* Schema.decodeEffect(codec)(text).pipe(\n Effect.mapError((cause) => corrupt(\"insert\", cause)),\n );\n\n if (\n input.version !== 1 ||\n input.status !== \"pending\" ||\n input.leaseUntilMillis !== null ||\n input.retry.attempts !== 0 ||\n input.retry.generation !== 0 ||\n input.retry.automaticAttempts !== 0 ||\n input.retry.nextAttemptAtMillis !== input.createdAtMillis ||\n input.retry.lastAttemptAtMillis !== null ||\n input.retry.lastFailure !== null ||\n input.deadlineAtMillis !== input.initialDeadlineAtMillis\n ) {\n return yield* MessageDeliveryError.make({ reason: \"validation\", operation: \"insert-state\" });\n }\n if (bytes(JSON.stringify(input.envelope)) > config.maxEnvelopeBytes)\n return yield* MessageDeliveryError.make({ reason: \"capacity\", operation: \"envelope-bytes\" });\n yield* failpoint.hit(\"message-delivery:insert:before\");\n\n const result = yield* transaction.run(\n Effect.gen(function* () {\n const existing = yield* get(input.key);\n\n if (existing !== null) {\n if (!sameMessageDeliveryIdentity(existing, input))\n return yield* MessageDeliveryError.make({ reason: \"conflict\", operation: \"insert\" });\n\n return existing;\n }\n\n const update = isWorkerUpdateDelivery(input);\n const capacity = messageDeliveryCapacity(config, update);\n\n const counts = yield* query(\n \"count\",\n sql`SELECT COUNT(*) AS retained, COALESCE(SUM(CASE WHEN state IN ('pending', 'accepted', 'parked') THEN 1 ELSE 0 END), 0) AS pending FROM effect_agent_message_deliveries WHERE owner_thread_id = ${input.key.ownerThreadId} AND COALESCE(json_extract(record_json, '$.envelope.messageAdmission._tag'), '') ${update ? sql`= 'WorkerUpdate'` : sql`<> 'WorkerUpdate'`}`,\n );\n\n const count = (yield* Schema.decodeUnknownEffect(Schema.Array(Count))(counts).pipe(\n Effect.mapError((cause) => corrupt(\"count\", cause)),\n ))[0];\n\n if (count === undefined) return yield* corrupt(\"count\");\n if (count.retained >= capacity.retained || count.pending >= capacity.pending)\n return yield* MessageDeliveryError.make({ reason: \"capacity\", operation: \"insert\" });\n yield* query(\n \"insert\",\n sql`INSERT INTO effect_agent_message_deliveries (owner_thread_id, message_id, version, state, deadline_at_millis, record_json) VALUES (${input.key.ownerThreadId}, ${input.key.messageId}, ${input.version}, ${input.status}, ${messageDeliveryDeadline(input)}, ${text})`,\n );\n\n return input;\n }),\n );\n\n yield* failpoint.hit(\"message-delivery:insert:after\");\n\n return result;\n });\n\n const change: MessageDeliveryStore[\"Service\"][\"change\"] = Effect.fn(\n \"SqlMessageDeliveryStore.change\",\n )(function* (key, change) {\n const decodedKey = yield* validateMessageDelivery(MessageDeliveryKey, key, \"change\");\n const input = yield* validateMessageDelivery(MessageDeliveryChange, change, \"change\");\n const point = `message-delivery:${input._tag.toLowerCase()}`;\n\n yield* failpoint.hit(`${point}:before`);\n\n const result = yield* transaction.run(\n Effect.gen(function* () {\n const current = yield* get(decodedKey);\n\n if (current === null)\n return yield* MessageDeliveryError.make({ reason: \"not-found\", operation: \"change\" });\n const next = yield* Effect.fromResult(applyMessageDeliveryChange(current, input));\n const text = yield* encode(next);\n\n const updated = yield* query(\n \"change\",\n sql`UPDATE effect_agent_message_deliveries SET version = ${next.version}, state = ${next.status}, deadline_at_millis = ${messageDeliveryDeadline(next)}, record_json = ${text} WHERE owner_thread_id = ${decodedKey.ownerThreadId} AND message_id = ${decodedKey.messageId} AND version = ${input.expectedVersion} RETURNING owner_thread_id, message_id, version, state, deadline_at_millis, record_json`,\n );\n\n const rows = yield* decodeRows(updated);\n\n if (rows.length !== 1 || rows[0] === undefined)\n return yield* MessageDeliveryError.make({ reason: \"conflict\", operation: \"change\" });\n\n return rows[0];\n }),\n );\n\n yield* failpoint.hit(`${point}:after`);\n\n return result;\n });\n\n return MessageDeliveryStore.of({\n limits: config,\n maxStoredValueBytes,\n insert,\n get,\n change,\n list: Effect.fn(\"SqlMessageDeliveryStore.list\")(function* (request) {\n const input = yield* validateMessageDelivery(MessageDeliveryPageRequest, request, \"list\");\n\n const rows = yield* query(\n \"list\",\n sql`SELECT owner_thread_id, message_id, version, state, deadline_at_millis, record_json FROM effect_agent_message_deliveries WHERE owner_thread_id = ${input.ownerThreadId} ${input.after === undefined ? sql`` : sql`AND message_id > ${input.after}`} ${input.pendingOnly ? sql`AND state NOT IN ('processed', 'refused')` : sql``}\n ${\n input.workerStarts === undefined\n ? sql``\n : sql`AND json_extract(record_json, '$.envelope.workerAdmission.origin.worker.delegationId') = ${input.workerStarts.delegationId}\n AND json_extract(record_json, '$.envelope.workerAdmission.origin.worker.targetAgentId') = ${input.workerStarts.targetAgentId}\n AND message_id = json_extract(record_json, '$.envelope.workerAdmission.origin.firstMessageId')`\n }\n ${\n input.pendingWorker === undefined\n ? sql``\n : sql`AND json_extract(record_json, '$.envelope.workerAdmission.origin.worker.threadId') = ${input.pendingWorker}\n AND state IN ('pending', 'parked') AND json_extract(record_json, '$.receipt') IS NULL`\n }\n ORDER BY message_id LIMIT ${input.limit + 1}`,\n );\n\n const records = yield* decodeRows(rows);\n const items = records.slice(0, input.limit);\n\n return {\n items,\n next: records.length > input.limit ? (items.at(-1)?.key.messageId ?? null) : null,\n };\n }),\n due: Effect.fn(\"SqlMessageDeliveryStore.due\")(function* (nowMillis, limit, ownerThreadId) {\n const input = yield* validateMessageDelivery(\n Scan,\n { nowMillis, limit, ...(ownerThreadId === undefined ? {} : { ownerThreadId }) },\n \"due\",\n );\n\n const rows = yield* query(\n \"due\",\n sql`SELECT owner_thread_id, message_id, version, state, deadline_at_millis, record_json FROM effect_agent_message_deliveries WHERE deadline_at_millis IS NOT NULL AND deadline_at_millis <= ${input.nowMillis} ${input.ownerThreadId === undefined ? sql`` : sql`AND owner_thread_id = ${input.ownerThreadId}`} ORDER BY deadline_at_millis, owner_thread_id, message_id LIMIT ${input.limit}`,\n );\n\n return (yield* decodeRows(rows)).map((record) => record.key);\n }),\n nextDeadline: Effect.fn(\"SqlMessageDeliveryStore.nextDeadline\")(function* (ownerThreadId) {\n if (ownerThreadId !== undefined)\n yield* validateMessageDelivery(ThreadId, ownerThreadId, \"nextDeadline\");\n\n const rows = yield* query(\n \"next-deadline\",\n sql`SELECT MIN(deadline_at_millis) AS deadline FROM effect_agent_message_deliveries ${ownerThreadId === undefined ? sql`` : sql`WHERE owner_thread_id = ${ownerThreadId}`}`,\n );\n\n const decoded = yield* Schema.decodeUnknownEffect(Schema.Array(Deadline))(rows).pipe(\n Effect.mapError((cause) => corrupt(\"next-deadline\", cause)),\n );\n\n return decoded[0]?.deadline ?? null;\n }),\n });\n});\n\n/** Add the pending-only index within the adapter's format transaction. */\nexport const createMessageDeliveryPendingIndex = Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n\n yield* sql`CREATE INDEX effect_agent_message_deliveries_pending ON effect_agent_message_deliveries(owner_thread_id, message_id) WHERE state NOT IN ('processed', 'refused')`;\n});\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { d as ScheduleFailpointError } from "../Schedule-DGPyXBzK.mjs";
2
- import { g as SubscriptionFailpointError } from "../Subscription-B9VszlF9.mjs";
1
+ import { d as ScheduleFailpointError } from "../Schedule-krSnBcbU.mjs";
2
+ import { g as SubscriptionFailpointError } from "../Subscription-Xnwd42Sm.mjs";
3
3
  import { Effect, Schema } from "effect";
4
4
  import * as SqlClient from "effect/unstable/sql/SqlClient";
5
5
  //#region src/durable/SqlStorageV2Upgrade.d.ts
@@ -1,5 +1,5 @@
1
- import { _ as Digest } from "../Records-BtxMy8xD.mjs";
2
- import { C as SubscriptionScanCursors, O as SubscriptionStoreFailure, S as SubscriptionRetentionPolicy, _ as SubscriptionKey, b as SubscriptionRecord, d as SubscriptionDelivery, f as SubscriptionDeliveryKey, g as SubscriptionFailpointError, l as SubscriptionChange, m as SubscriptionError, n as DeliveryChange, o as SourcePartition, t as AcceptedEvent, v as SubscriptionLimits } from "../Subscription-B9VszlF9.mjs";
1
+ import { _ as Digest } from "../Records-Byeb70tt.mjs";
2
+ import { C as SubscriptionScanCursors, O as SubscriptionStoreFailure, S as SubscriptionRetentionPolicy, _ as SubscriptionKey, b as SubscriptionRecord, d as SubscriptionDelivery, f as SubscriptionDeliveryKey, g as SubscriptionFailpointError, l as SubscriptionChange, m as SubscriptionError, n as DeliveryChange, o as SourcePartition, t as AcceptedEvent, v as SubscriptionLimits } from "../Subscription-Xnwd42Sm.mjs";
3
3
  import { Context, Effect } from "effect";
4
4
  import * as SqlClientService from "effect/unstable/sql/SqlClient";
5
5
  //#region src/durable/SqlSubscriptionStore.d.ts
@@ -1,4 +1,4 @@
1
- import { cn as ThreadNotMaterialized, fn as ThreadPeerCountRequest, j as RecordEnvelope, l as CanonicalRecordEnvelope, xn as ThreadStoreError } from "../Records-BtxMy8xD.mjs";
1
+ import { Sn as ThreadStoreError, j as RecordEnvelope, l as CanonicalRecordEnvelope, ln as ThreadNotMaterialized, pn as ThreadPeerCountRequest } from "../Records-Byeb70tt.mjs";
2
2
  import { Effect, Schema } from "effect";
3
3
  import * as SqlClient from "effect/unstable/sql/SqlClient";
4
4
  declare namespace SqlThreadNativeReads_d_exports {
@@ -31,6 +31,10 @@ export declare const makeSelectedReads: (envelope: (row: typeof Row.Type) => Eff
31
31
  readonly _tag: "Outstanding";
32
32
  readonly expectedTailSequence: number & import("effect/Brand").Brand<"@effect-agent/thread/CanonicalSequence">;
33
33
  readonly expectedTailDigest: string & import("effect/Brand").Brand<"@effect-agent/thread/Digest">;
34
+ } | {
35
+ readonly _tag: "WorkerExecution";
36
+ readonly expectedTailSequence: number & import("effect/Brand").Brand<"@effect-agent/thread/CanonicalSequence">;
37
+ readonly expectedTailDigest: string & import("effect/Brand").Brand<"@effect-agent/thread/Digest">;
34
38
  } | {
35
39
  readonly _tag: "WorkerState";
36
40
  readonly expectedTailSequence: number & import("effect/Brand").Brand<"@effect-agent/thread/CanonicalSequence">;
@@ -116,6 +116,12 @@ const makeSelectedReads = Effect.fnUntraced(function* (envelope) {
116
116
  case "Outstanding":
117
117
  rows = yield* sql`SELECT thread_id, sequence, record_id, batch_id, record_json, outstanding FROM effect_agent_canonical_records WHERE thread_id = ${request.threadId} AND outstanding <> 0 AND sequence > ${after} ORDER BY sequence LIMIT ${request.page.limit}`;
118
118
  break;
119
+ case "WorkerExecution":
120
+ rows = (yield* Effect.forEach(["UserInputRecorded", "RunStarted"], (tag) => sql`SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records
121
+ WHERE thread_id = ${request.threadId} AND json_extract(record_json, '$.payload._tag') = ${tag}
122
+ AND json_extract(record_json, '$.payload.runId') IS NOT NULL
123
+ ORDER BY sequence DESC LIMIT 1`)).flat().filter((row) => Number(row.sequence) > after).sort((a, b) => Number(a.sequence) - Number(b.sequence)).slice(0, request.page.limit);
124
+ break;
119
125
  case "WorkerState": {
120
126
  const runId = selection.sourceSubmissionId === void 0 ? null : runIdForSubmission(selection.sourceSubmissionId);
121
127
  rows = yield* sql`
@@ -1 +1 @@
1
- {"version":3,"file":"SqlThreadNativeReads.mjs","names":[],"sources":["../../src/durable/SqlThreadNativeReads.ts"],"sourcesContent":["import { Effect, Schema } from \"effect\";\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\";\n\nimport {\n CanonicalRecord,\n CanonicalRecordEnvelope,\n CanonicalSequence,\n Digest,\n RecordId,\n} from \"./Records.ts\";\nimport { runIdForSubmission } from \"./RunJournal.ts\";\nimport type { ThreadStore } from \"./ThreadStore.ts\";\nimport {\n SelectedThreadRead,\n ThreadPeerCountRequest,\n ThreadNotMaterialized,\n ThreadStoreError,\n} from \"./ThreadStore.ts\";\n\nconst failure = (operation: string, cause?: unknown) =>\n ThreadStoreError.make({\n operation,\n message: \"Native canonical read is incomplete or corrupt\",\n ...(cause === undefined ? {} : { cause }),\n });\n\n/** Adapter-owned metadata on canonical rows, never a second copy of execution records. */\nexport const createNativeReadIndexes = Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n\n yield* sql`ALTER TABLE effect_agent_canonical_records ADD COLUMN outstanding INTEGER NOT NULL DEFAULT 0`;\n yield* sql`CREATE INDEX effect_agent_records_outstanding ON effect_agent_canonical_records(thread_id, sequence) WHERE outstanding <> 0`;\n yield* sql`CREATE INDEX effect_agent_records_call ON effect_agent_canonical_records(thread_id, json_extract(record_json, '$.payload._tag'), json_extract(record_json, '$.payload.runId'), json_extract(record_json, '$.payload.toolCallId'))`;\n yield* sql`CREATE INDEX effect_agent_records_run_input ON effect_agent_canonical_records(thread_id, json_extract(record_json, '$.payload.runId')) WHERE json_extract(record_json, '$.payload._tag') = 'UserInputRecorded' AND json_extract(record_json, '$.payload.kind') = 'user'`;\n yield* sql`CREATE INDEX effect_agent_records_subtree ON effect_agent_canonical_records(thread_id, json_extract(record_json, '$.payload.sourceSubmissionId'), sequence) WHERE json_extract(record_json, '$.payload._tag') = 'SubtreeBudgetReserved'`;\n yield* sql`CREATE INDEX effect_agent_records_worker_input ON effect_agent_canonical_records(thread_id, json_extract(record_json, '$.payload.admission.messageId')) WHERE json_extract(record_json, '$.payload._tag') = 'WorkerInputRequested'`;\n});\n\n/** Must run in the canonical append/upgrade transaction, after inserting this record. */\nexport const indexCanonicalRecord = Effect.fnUntraced(function* (\n threadId: string,\n record: CanonicalRecord,\n) {\n const sql = yield* SqlClient.SqlClient;\n const payload = record.payload;\n\n switch (payload._tag) {\n case \"ToolCallPrepared\":\n case \"ToolCallUnknown\": {\n if (payload._tag === \"ToolCallUnknown\")\n yield* sql`\n UPDATE effect_agent_canonical_records SET outstanding = 0\n WHERE thread_id = ${threadId} AND json_extract(record_json, '$.payload._tag') = 'ToolCallPrepared'\n AND json_extract(record_json, '$.payload.runId') = ${payload.runId}\n AND json_extract(record_json, '$.payload.toolCallId') = ${payload.toolCallId}`;\n yield* sql`UPDATE effect_agent_canonical_records SET outstanding = ${payload._tag === \"ToolCallPrepared\" ? 1 : 2}\n WHERE thread_id = ${threadId} AND record_id = ${record.recordId}`;\n break;\n }\n case \"ToolCallSettled\":\n for (const tag of [\"ToolCallPrepared\", \"ToolCallUnknown\"])\n yield* sql`\n UPDATE effect_agent_canonical_records SET outstanding = 0\n WHERE thread_id = ${threadId} AND json_extract(record_json, '$.payload._tag') = ${tag}\n AND json_extract(record_json, '$.payload.runId') = ${payload.runId}\n AND json_extract(record_json, '$.payload.toolCallId') = ${payload.toolCallId}`;\n break;\n case \"WorkerInputRequested\":\n yield* sql`UPDATE effect_agent_canonical_records SET outstanding = 3 WHERE thread_id = ${threadId} AND record_id = ${record.recordId}`;\n break;\n case \"WorkerInputCompleted\":\n yield* sql`\n UPDATE effect_agent_canonical_records SET outstanding = ${payload.effectsResolved ? 0 : 4}\n WHERE thread_id = ${threadId} AND json_extract(record_json, '$.payload._tag') = 'WorkerInputRequested'\n AND json_extract(record_json, '$.payload.admission.messageId') = ${payload.messageId}`;\n break;\n }\n});\n\n/** One-time native index construction during the atomic supported-format upgrade. */\nexport const seedNativeReadIndexes = Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n\n // This is the one supported-format upgrade, in the adapter transaction. Decode in\n // bounded pages; malformed rows or gaps roll back both metadata and version.\n const gaps =\n yield* sql`SELECT t.thread_id FROM effect_agent_threads t LEFT JOIN effect_agent_canonical_records r ON r.thread_id = t.thread_id\n GROUP BY t.thread_id HAVING count(r.sequence) <> t.tail_sequence OR coalesce(max(r.sequence), 0) <> t.tail_sequence\n UNION ALL SELECT r.thread_id FROM effect_agent_canonical_records r LEFT JOIN effect_agent_threads t ON t.thread_id = r.thread_id WHERE t.thread_id IS NULL LIMIT 1`;\n\n if (gaps.length > 0) return yield* failure(\"native index upgrade canonical gap\");\n let afterThread = \"\";\n let afterSequence = 0;\n\n while (true) {\n const rows = yield* sql<{\n thread_id: string;\n record_id: string;\n sequence: number;\n record_json: string;\n }>`SELECT thread_id, record_id, sequence, record_json FROM effect_agent_canonical_records\n WHERE (thread_id, sequence) > (${afterThread}, ${afterSequence}) ORDER BY thread_id, sequence LIMIT 100`;\n\n if (rows.length === 0) break;\n for (const row of rows) {\n const record = yield* Schema.decodeEffect(Schema.fromJsonString(CanonicalRecord))(\n row.record_json,\n );\n\n if (\n record.recordId !== row.record_id ||\n row.sequence !== (row.thread_id === afterThread ? afterSequence : 0) + 1\n )\n return yield* failure(\"native index upgrade canonical identity\");\n yield* indexCanonicalRecord(row.thread_id, record);\n afterThread = row.thread_id;\n afterSequence = row.sequence;\n }\n }\n});\n\nconst Row = Schema.Struct({\n thread_id: SelectedThreadRead.fields.threadId,\n sequence: CanonicalSequence,\n record_id: RecordId,\n batch_id: CanonicalRecordEnvelope.fields.batchId,\n record_json: Schema.String,\n outstanding: Schema.optionalKey(Schema.Int),\n});\n\nexport const makeSelectedReads = Effect.fnUntraced(function* (\n envelope: (row: typeof Row.Type) => Effect.Effect<CanonicalRecordEnvelope, ThreadStoreError>,\n) {\n const sql = yield* SqlClient.SqlClient;\n\n const requireThread = Effect.fnUntraced(function* (threadId: SelectedThreadRead[\"threadId\"]) {\n const rows =\n yield* sql`SELECT tail_sequence, tail_digest FROM effect_agent_threads WHERE thread_id = ${threadId}`;\n\n if (rows.length === 0) return yield* ThreadNotMaterialized.make({ threadId });\n\n const decoded = yield* Schema.decodeUnknownEffect(\n Schema.Array(Schema.Struct({ tail_sequence: CanonicalSequence, tail_digest: Digest })),\n )(rows);\n\n if (decoded.length !== 1 || decoded[0] === undefined)\n return yield* failure(\"native thread tail\");\n\n return decoded[0];\n });\n\n const read = Effect.fnUntraced(\n function* (request: SelectedThreadRead) {\n return yield* sql.withTransaction(\n Effect.gen(function* () {\n const tail = yield* requireThread(request.threadId);\n const selection = request.selection;\n\n if (\n \"expectedTailSequence\" in selection &&\n (tail.tail_sequence !== selection.expectedTailSequence ||\n tail.tail_digest !== selection.expectedTailDigest)\n )\n return yield* failure(\"selected read tail changed\");\n const after = request.page.afterSequence ?? 0;\n let rows: unknown;\n\n switch (selection._tag) {\n case \"RecordId\":\n rows =\n yield* sql`SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records WHERE thread_id = ${request.threadId} AND record_id = ${selection.recordId} AND sequence > ${after}`;\n break;\n case \"RunInput\":\n rows =\n yield* sql`SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records WHERE thread_id = ${request.threadId} AND json_extract(record_json, '$.payload._tag') = 'UserInputRecorded' AND json_extract(record_json, '$.payload.kind') = 'user' AND json_extract(record_json, '$.payload.runId') = ${selection.runId} LIMIT 2`;\n break;\n case \"Outstanding\":\n rows =\n yield* sql`SELECT thread_id, sequence, record_id, batch_id, record_json, outstanding FROM effect_agent_canonical_records WHERE thread_id = ${request.threadId} AND outstanding <> 0 AND sequence > ${after} ORDER BY sequence LIMIT ${request.page.limit}`;\n break;\n case \"WorkerState\": {\n const runId =\n selection.sourceSubmissionId === undefined\n ? null\n : runIdForSubmission(selection.sourceSubmissionId);\n\n rows = yield* sql`\n SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId} AND sequence > ${after} AND json_extract(record_json, '$.payload._tag') IN ('ThreadCreated', 'WorkerOriginRecorded', 'SubagentLineageRecorded', 'WorkerInputRequested', 'WorkerInputCompleted')\n UNION ALL\n SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId} AND sequence > ${after} AND json_extract(record_json, '$.payload._tag') = 'SubtreeBudgetReserved' AND json_extract(record_json, '$.payload.sourceSubmissionId') IS ${selection.sourceSubmissionId ?? null}\n UNION ALL\n SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId} AND sequence > ${after} AND json_extract(record_json, '$.payload._tag') = 'SubagentJoined' AND json_extract(record_json, '$.payload.runId') = ${runId}\n ORDER BY sequence LIMIT ${request.page.limit}`;\n break;\n }\n }\n const decoded = yield* Schema.decodeUnknownEffect(Schema.Array(Row))(rows);\n\n if (selection._tag === \"RunInput\" && decoded.length > 1)\n return yield* failure(\"ambiguous original Run input\");\n\n return yield* Effect.forEach(\n decoded.filter((row) => row.sequence > after),\n (row) =>\n Effect.gen(function* () {\n const value = yield* envelope(row);\n\n if (\n value.record.recordId !== row.record_id ||\n row.thread_id !== request.threadId ||\n (selection._tag === \"Outstanding\" &&\n !(\n (row.outstanding === 1 && value.record.payload._tag === \"ToolCallPrepared\") ||\n (row.outstanding === 2 && value.record.payload._tag === \"ToolCallUnknown\") ||\n (row.outstanding === 3 &&\n value.record.payload._tag === \"WorkerInputRequested\")\n ))\n )\n return yield* failure(\"selected record incomplete or corrupt\");\n\n return value;\n }),\n );\n }),\n );\n },\n Effect.mapError((cause) =>\n cause._tag === \"ThreadNotMaterialized\" || cause._tag === \"ThreadStoreError\"\n ? cause\n : failure(\"selected read\", cause),\n ),\n );\n\n const countPeerMessages: NonNullable<ThreadStore[\"Service\"][\"countPeerMessages\"]> =\n Effect.fnUntraced(\n function* (request) {\n yield* Schema.decodeEffect(ThreadPeerCountRequest)(request);\n yield* requireThread(request.threadId);\n\n const rows =\n yield* sql`SELECT 1 FROM effect_agent_canonical_records WHERE thread_id = ${request.threadId} AND json_extract(record_json, '$.payload._tag') = 'PeerMessagePrepared' LIMIT ${request.limit}`;\n\n return rows.length;\n },\n Effect.mapError((cause) =>\n cause._tag === \"ThreadNotMaterialized\" || cause._tag === \"ThreadStoreError\"\n ? cause\n : failure(\"countPeerMessages\", cause),\n ),\n );\n\n return { read, countPeerMessages };\n});\n"],"mappings":";;;;;;;;;;;;;AAmBA,MAAM,WAAW,WAAmB,UAClC,iBAAiB,KAAK;CACpB;CACA,SAAS;CACT,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;AACzC,CAAC;;AAGH,MAAa,0BAA0B,OAAO,IAAI,aAAa;CAC7D,MAAM,MAAM,OAAO,UAAU;CAE7B,OAAO,GAAG;CACV,OAAO,GAAG;CACV,OAAO,GAAG;CACV,OAAO,GAAG;CACV,OAAO,GAAG;CACV,OAAO,GAAG;AACZ,CAAC;;AAGD,MAAa,uBAAuB,OAAO,WAAW,WACpD,UACA,QACA;CACA,MAAM,MAAM,OAAO,UAAU;CAC7B,MAAM,UAAU,OAAO;CAEvB,QAAQ,QAAQ,MAAhB;EACE,KAAK;EACL,KAAK;GACH,IAAI,QAAQ,SAAS,mBACnB,OAAO,GAAG;;4BAEU,SAAS;+DAC0B,QAAQ,MAAM;oEACT,QAAQ;GACtE,OAAO,GAAG,2DAA2D,QAAQ,SAAS,qBAAqB,IAAI,EAAE;4BAC3F,SAAS,mBAAmB,OAAO;GACzD;EAEF,KAAK;GACH,KAAK,MAAM,OAAO,CAAC,oBAAoB,iBAAiB,GACtD,OAAO,GAAG;;4BAEU,SAAS,qDAAqD,IAAI;+DAC/B,QAAQ,MAAM;oEACT,QAAQ;GACtE;EACF,KAAK;GACH,OAAO,GAAG,+EAA+E,SAAS,mBAAmB,OAAO;GAC5H;EACF,KAAK,wBACH,OAAO,GAAG;kEACkD,QAAQ,kBAAkB,IAAI,EAAE;4BACtE,SAAS;6EACwC,QAAQ;CAEnF;AACF,CAAC;;AAGD,MAAa,wBAAwB,OAAO,IAAI,aAAa;CAC3D,MAAM,MAAM,OAAO,UAAU;CAS7B,KAAI,OAJK,GAAG;;wKAIJ,CAAC,SAAS,GAAG,OAAO,OAAO,QAAQ,oCAAoC;CAC/E,IAAI,cAAc;CAClB,IAAI,gBAAgB;CAEpB,OAAO,MAAM;EACX,MAAM,OAAO,OAAO,GAKlB;uCACiC,YAAY,IAAI,cAAc;EAEjE,IAAI,KAAK,WAAW,GAAG;EACvB,KAAK,MAAM,OAAO,MAAM;GACtB,MAAM,SAAS,OAAO,OAAO,aAAa,OAAO,eAAe,eAAe,CAAC,CAAC,CAC/E,IAAI,WACN;GAEA,IACE,OAAO,aAAa,IAAI,aACxB,IAAI,cAAc,IAAI,cAAc,cAAc,gBAAgB,KAAK,GAEvE,OAAO,OAAO,QAAQ,yCAAyC;GACjE,OAAO,qBAAqB,IAAI,WAAW,MAAM;GACjD,cAAc,IAAI;GAClB,gBAAgB,IAAI;EACtB;CACF;AACF,CAAC;AAED,MAAM,MAAM,OAAO,OAAO;CACxB,WAAW,mBAAmB,OAAO;CACrC,UAAU;CACV,WAAW;CACX,UAAU,wBAAwB,OAAO;CACzC,aAAa,OAAO;CACpB,aAAa,OAAO,YAAY,OAAO,GAAG;AAC5C,CAAC;AAED,MAAa,oBAAoB,OAAO,WAAW,WACjD,UACA;CACA,MAAM,MAAM,OAAO,UAAU;CAE7B,MAAM,gBAAgB,OAAO,WAAW,WAAW,UAA0C;EAC3F,MAAM,OACJ,OAAO,GAAG,iFAAiF;EAE7F,IAAI,KAAK,WAAW,GAAG,OAAO,OAAO,sBAAsB,KAAK,EAAE,SAAS,CAAC;EAE5E,MAAM,UAAU,OAAO,OAAO,oBAC5B,OAAO,MAAM,OAAO,OAAO;GAAE,eAAe;GAAmB,aAAa;EAAO,CAAC,CAAC,CACvF,CAAC,CAAC,IAAI;EAEN,IAAI,QAAQ,WAAW,KAAK,QAAQ,OAAO,KAAA,GACzC,OAAO,OAAO,QAAQ,oBAAoB;EAE5C,OAAO,QAAQ;CACjB,CAAC;CAyGD,OAAO;EAAE,MAvGI,OAAO,WAClB,WAAW,SAA6B;GACtC,OAAO,OAAO,IAAI,gBAChB,OAAO,IAAI,aAAa;IACtB,MAAM,OAAO,OAAO,cAAc,QAAQ,QAAQ;IAClD,MAAM,YAAY,QAAQ;IAE1B,IACE,0BAA0B,cACzB,KAAK,kBAAkB,UAAU,wBAChC,KAAK,gBAAgB,UAAU,qBAEjC,OAAO,OAAO,QAAQ,4BAA4B;IACpD,MAAM,QAAQ,QAAQ,KAAK,iBAAiB;IAC5C,IAAI;IAEJ,QAAQ,UAAU,MAAlB;KACE,KAAK;MACH,OACE,OAAO,GAAG,sHAAsH,QAAQ,SAAS,mBAAmB,UAAU,SAAS,kBAAkB;MAC3M;KACF,KAAK;MACH,OACE,OAAO,GAAG,sHAAsH,QAAQ,SAAS,qLAAqL,UAAU,MAAM;MACxV;KACF,KAAK;MACH,OACE,OAAO,GAAG,mIAAmI,QAAQ,SAAS,uCAAuC,MAAM,2BAA2B,QAAQ,KAAK;MACrP;KACF,KAAK,eAAe;MAClB,MAAM,QACJ,UAAU,uBAAuB,KAAA,IAC7B,OACA,mBAAmB,UAAU,kBAAkB;MAErD,OAAO,OAAO,GAAG;;gCAEC,QAAQ,SAAS,kBAAkB,MAAM;;;gCAGzC,QAAQ,SAAS,kBAAkB,MAAM,8IAA8I,UAAU,sBAAsB,KAAK;;;gCAG5N,QAAQ,SAAS,kBAAkB,MAAM,yHAAyH,MAAM;sCAClK,QAAQ,KAAK;MACrC;KACF;IACF;IACA,MAAM,UAAU,OAAO,OAAO,oBAAoB,OAAO,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI;IAEzE,IAAI,UAAU,SAAS,cAAc,QAAQ,SAAS,GACpD,OAAO,OAAO,QAAQ,8BAA8B;IAEtD,OAAO,OAAO,OAAO,QACnB,QAAQ,QAAQ,QAAQ,IAAI,WAAW,KAAK,IAC3C,QACC,OAAO,IAAI,aAAa;KACtB,MAAM,QAAQ,OAAO,SAAS,GAAG;KAEjC,IACE,MAAM,OAAO,aAAa,IAAI,aAC9B,IAAI,cAAc,QAAQ,YACzB,UAAU,SAAS,iBAClB,EACG,IAAI,gBAAgB,KAAK,MAAM,OAAO,QAAQ,SAAS,sBACvD,IAAI,gBAAgB,KAAK,MAAM,OAAO,QAAQ,SAAS,qBACvD,IAAI,gBAAgB,KACnB,MAAM,OAAO,QAAQ,SAAS,yBAGpC,OAAO,OAAO,QAAQ,uCAAuC;KAE/D,OAAO;IACT,CAAC,CACL;GACF,CAAC,CACH;EACF,GACA,OAAO,UAAU,UACf,MAAM,SAAS,2BAA2B,MAAM,SAAS,qBACrD,QACA,QAAQ,iBAAiB,KAAK,CACpC,CAqBU;EAAG,mBAjBb,OAAO,WACL,WAAW,SAAS;GAClB,OAAO,OAAO,aAAa,sBAAsB,CAAC,CAAC,OAAO;GAC1D,OAAO,cAAc,QAAQ,QAAQ;GAKrC,QAAO,OAFE,GAAG,kEAAkE,QAAQ,SAAS,iFAAiF,QAAQ,QAAA,CAE5K;EACd,GACA,OAAO,UAAU,UACf,MAAM,SAAS,2BAA2B,MAAM,SAAS,qBACrD,QACA,QAAQ,qBAAqB,KAAK,CACxC,CAG2B;CAAE;AACnC,CAAC"}
1
+ {"version":3,"file":"SqlThreadNativeReads.mjs","names":[],"sources":["../../src/durable/SqlThreadNativeReads.ts"],"sourcesContent":["import { Effect, Schema } from \"effect\";\nimport * as SqlClient from \"effect/unstable/sql/SqlClient\";\n\nimport {\n CanonicalRecord,\n CanonicalRecordEnvelope,\n CanonicalSequence,\n Digest,\n RecordId,\n} from \"./Records.ts\";\nimport { runIdForSubmission } from \"./RunJournal.ts\";\nimport type { ThreadStore } from \"./ThreadStore.ts\";\nimport {\n SelectedThreadRead,\n ThreadPeerCountRequest,\n ThreadNotMaterialized,\n ThreadStoreError,\n} from \"./ThreadStore.ts\";\n\nconst failure = (operation: string, cause?: unknown) =>\n ThreadStoreError.make({\n operation,\n message: \"Native canonical read is incomplete or corrupt\",\n ...(cause === undefined ? {} : { cause }),\n });\n\n/** Adapter-owned metadata on canonical rows, never a second copy of execution records. */\nexport const createNativeReadIndexes = Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n\n yield* sql`ALTER TABLE effect_agent_canonical_records ADD COLUMN outstanding INTEGER NOT NULL DEFAULT 0`;\n yield* sql`CREATE INDEX effect_agent_records_outstanding ON effect_agent_canonical_records(thread_id, sequence) WHERE outstanding <> 0`;\n yield* sql`CREATE INDEX effect_agent_records_call ON effect_agent_canonical_records(thread_id, json_extract(record_json, '$.payload._tag'), json_extract(record_json, '$.payload.runId'), json_extract(record_json, '$.payload.toolCallId'))`;\n yield* sql`CREATE INDEX effect_agent_records_run_input ON effect_agent_canonical_records(thread_id, json_extract(record_json, '$.payload.runId')) WHERE json_extract(record_json, '$.payload._tag') = 'UserInputRecorded' AND json_extract(record_json, '$.payload.kind') = 'user'`;\n yield* sql`CREATE INDEX effect_agent_records_subtree ON effect_agent_canonical_records(thread_id, json_extract(record_json, '$.payload.sourceSubmissionId'), sequence) WHERE json_extract(record_json, '$.payload._tag') = 'SubtreeBudgetReserved'`;\n yield* sql`CREATE INDEX effect_agent_records_worker_input ON effect_agent_canonical_records(thread_id, json_extract(record_json, '$.payload.admission.messageId')) WHERE json_extract(record_json, '$.payload._tag') = 'WorkerInputRequested'`;\n});\n\n/** Must run in the canonical append/upgrade transaction, after inserting this record. */\nexport const indexCanonicalRecord = Effect.fnUntraced(function* (\n threadId: string,\n record: CanonicalRecord,\n) {\n const sql = yield* SqlClient.SqlClient;\n const payload = record.payload;\n\n switch (payload._tag) {\n case \"ToolCallPrepared\":\n case \"ToolCallUnknown\": {\n if (payload._tag === \"ToolCallUnknown\")\n yield* sql`\n UPDATE effect_agent_canonical_records SET outstanding = 0\n WHERE thread_id = ${threadId} AND json_extract(record_json, '$.payload._tag') = 'ToolCallPrepared'\n AND json_extract(record_json, '$.payload.runId') = ${payload.runId}\n AND json_extract(record_json, '$.payload.toolCallId') = ${payload.toolCallId}`;\n yield* sql`UPDATE effect_agent_canonical_records SET outstanding = ${payload._tag === \"ToolCallPrepared\" ? 1 : 2}\n WHERE thread_id = ${threadId} AND record_id = ${record.recordId}`;\n break;\n }\n case \"ToolCallSettled\":\n for (const tag of [\"ToolCallPrepared\", \"ToolCallUnknown\"])\n yield* sql`\n UPDATE effect_agent_canonical_records SET outstanding = 0\n WHERE thread_id = ${threadId} AND json_extract(record_json, '$.payload._tag') = ${tag}\n AND json_extract(record_json, '$.payload.runId') = ${payload.runId}\n AND json_extract(record_json, '$.payload.toolCallId') = ${payload.toolCallId}`;\n break;\n case \"WorkerInputRequested\":\n yield* sql`UPDATE effect_agent_canonical_records SET outstanding = 3 WHERE thread_id = ${threadId} AND record_id = ${record.recordId}`;\n break;\n case \"WorkerInputCompleted\":\n yield* sql`\n UPDATE effect_agent_canonical_records SET outstanding = ${payload.effectsResolved ? 0 : 4}\n WHERE thread_id = ${threadId} AND json_extract(record_json, '$.payload._tag') = 'WorkerInputRequested'\n AND json_extract(record_json, '$.payload.admission.messageId') = ${payload.messageId}`;\n break;\n }\n});\n\n/** One-time native index construction during the atomic supported-format upgrade. */\nexport const seedNativeReadIndexes = Effect.gen(function* () {\n const sql = yield* SqlClient.SqlClient;\n\n // This is the one supported-format upgrade, in the adapter transaction. Decode in\n // bounded pages; malformed rows or gaps roll back both metadata and version.\n const gaps =\n yield* sql`SELECT t.thread_id FROM effect_agent_threads t LEFT JOIN effect_agent_canonical_records r ON r.thread_id = t.thread_id\n GROUP BY t.thread_id HAVING count(r.sequence) <> t.tail_sequence OR coalesce(max(r.sequence), 0) <> t.tail_sequence\n UNION ALL SELECT r.thread_id FROM effect_agent_canonical_records r LEFT JOIN effect_agent_threads t ON t.thread_id = r.thread_id WHERE t.thread_id IS NULL LIMIT 1`;\n\n if (gaps.length > 0) return yield* failure(\"native index upgrade canonical gap\");\n let afterThread = \"\";\n let afterSequence = 0;\n\n while (true) {\n const rows = yield* sql<{\n thread_id: string;\n record_id: string;\n sequence: number;\n record_json: string;\n }>`SELECT thread_id, record_id, sequence, record_json FROM effect_agent_canonical_records\n WHERE (thread_id, sequence) > (${afterThread}, ${afterSequence}) ORDER BY thread_id, sequence LIMIT 100`;\n\n if (rows.length === 0) break;\n for (const row of rows) {\n const record = yield* Schema.decodeEffect(Schema.fromJsonString(CanonicalRecord))(\n row.record_json,\n );\n\n if (\n record.recordId !== row.record_id ||\n row.sequence !== (row.thread_id === afterThread ? afterSequence : 0) + 1\n )\n return yield* failure(\"native index upgrade canonical identity\");\n yield* indexCanonicalRecord(row.thread_id, record);\n afterThread = row.thread_id;\n afterSequence = row.sequence;\n }\n }\n});\n\nconst Row = Schema.Struct({\n thread_id: SelectedThreadRead.fields.threadId,\n sequence: CanonicalSequence,\n record_id: RecordId,\n batch_id: CanonicalRecordEnvelope.fields.batchId,\n record_json: Schema.String,\n outstanding: Schema.optionalKey(Schema.Int),\n});\n\nexport const makeSelectedReads = Effect.fnUntraced(function* (\n envelope: (row: typeof Row.Type) => Effect.Effect<CanonicalRecordEnvelope, ThreadStoreError>,\n) {\n const sql = yield* SqlClient.SqlClient;\n\n const requireThread = Effect.fnUntraced(function* (threadId: SelectedThreadRead[\"threadId\"]) {\n const rows =\n yield* sql`SELECT tail_sequence, tail_digest FROM effect_agent_threads WHERE thread_id = ${threadId}`;\n\n if (rows.length === 0) return yield* ThreadNotMaterialized.make({ threadId });\n\n const decoded = yield* Schema.decodeUnknownEffect(\n Schema.Array(Schema.Struct({ tail_sequence: CanonicalSequence, tail_digest: Digest })),\n )(rows);\n\n if (decoded.length !== 1 || decoded[0] === undefined)\n return yield* failure(\"native thread tail\");\n\n return decoded[0];\n });\n\n const read = Effect.fnUntraced(\n function* (request: SelectedThreadRead) {\n return yield* sql.withTransaction(\n Effect.gen(function* () {\n const tail = yield* requireThread(request.threadId);\n const selection = request.selection;\n\n if (\n \"expectedTailSequence\" in selection &&\n (tail.tail_sequence !== selection.expectedTailSequence ||\n tail.tail_digest !== selection.expectedTailDigest)\n )\n return yield* failure(\"selected read tail changed\");\n const after = request.page.afterSequence ?? 0;\n let rows: unknown;\n\n switch (selection._tag) {\n case \"RecordId\":\n rows =\n yield* sql`SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records WHERE thread_id = ${request.threadId} AND record_id = ${selection.recordId} AND sequence > ${after}`;\n break;\n case \"RunInput\":\n rows =\n yield* sql`SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records WHERE thread_id = ${request.threadId} AND json_extract(record_json, '$.payload._tag') = 'UserInputRecorded' AND json_extract(record_json, '$.payload.kind') = 'user' AND json_extract(record_json, '$.payload.runId') = ${selection.runId} LIMIT 2`;\n break;\n case \"Outstanding\":\n rows =\n yield* sql`SELECT thread_id, sequence, record_id, batch_id, record_json, outstanding FROM effect_agent_canonical_records WHERE thread_id = ${request.threadId} AND outstanding <> 0 AND sequence > ${after} ORDER BY sequence LIMIT ${request.page.limit}`;\n break;\n case \"WorkerExecution\":\n rows = (yield* Effect.forEach(\n [\"UserInputRecorded\", \"RunStarted\"],\n (tag) =>\n sql`SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId} AND json_extract(record_json, '$.payload._tag') = ${tag}\n AND json_extract(record_json, '$.payload.runId') IS NOT NULL\n ORDER BY sequence DESC LIMIT 1`,\n ))\n .flat()\n .filter((row) => Number(row.sequence) > after)\n .sort((a, b) => Number(a.sequence) - Number(b.sequence))\n .slice(0, request.page.limit);\n break;\n case \"WorkerState\": {\n const runId =\n selection.sourceSubmissionId === undefined\n ? null\n : runIdForSubmission(selection.sourceSubmissionId);\n\n rows = yield* sql`\n SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId} AND sequence > ${after} AND json_extract(record_json, '$.payload._tag') IN ('ThreadCreated', 'WorkerOriginRecorded', 'SubagentLineageRecorded', 'WorkerInputRequested', 'WorkerInputCompleted')\n UNION ALL\n SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId} AND sequence > ${after} AND json_extract(record_json, '$.payload._tag') = 'SubtreeBudgetReserved' AND json_extract(record_json, '$.payload.sourceSubmissionId') IS ${selection.sourceSubmissionId ?? null}\n UNION ALL\n SELECT thread_id, sequence, record_id, batch_id, record_json FROM effect_agent_canonical_records\n WHERE thread_id = ${request.threadId} AND sequence > ${after} AND json_extract(record_json, '$.payload._tag') = 'SubagentJoined' AND json_extract(record_json, '$.payload.runId') = ${runId}\n ORDER BY sequence LIMIT ${request.page.limit}`;\n break;\n }\n }\n const decoded = yield* Schema.decodeUnknownEffect(Schema.Array(Row))(rows);\n\n if (selection._tag === \"RunInput\" && decoded.length > 1)\n return yield* failure(\"ambiguous original Run input\");\n\n return yield* Effect.forEach(\n decoded.filter((row) => row.sequence > after),\n (row) =>\n Effect.gen(function* () {\n const value = yield* envelope(row);\n\n if (\n value.record.recordId !== row.record_id ||\n row.thread_id !== request.threadId ||\n (selection._tag === \"Outstanding\" &&\n !(\n (row.outstanding === 1 && value.record.payload._tag === \"ToolCallPrepared\") ||\n (row.outstanding === 2 && value.record.payload._tag === \"ToolCallUnknown\") ||\n (row.outstanding === 3 &&\n value.record.payload._tag === \"WorkerInputRequested\")\n ))\n )\n return yield* failure(\"selected record incomplete or corrupt\");\n\n return value;\n }),\n );\n }),\n );\n },\n Effect.mapError((cause) =>\n cause._tag === \"ThreadNotMaterialized\" || cause._tag === \"ThreadStoreError\"\n ? cause\n : failure(\"selected read\", cause),\n ),\n );\n\n const countPeerMessages: NonNullable<ThreadStore[\"Service\"][\"countPeerMessages\"]> =\n Effect.fnUntraced(\n function* (request) {\n yield* Schema.decodeEffect(ThreadPeerCountRequest)(request);\n yield* requireThread(request.threadId);\n\n const rows =\n yield* sql`SELECT 1 FROM effect_agent_canonical_records WHERE thread_id = ${request.threadId} AND json_extract(record_json, '$.payload._tag') = 'PeerMessagePrepared' LIMIT ${request.limit}`;\n\n return rows.length;\n },\n Effect.mapError((cause) =>\n cause._tag === \"ThreadNotMaterialized\" || cause._tag === \"ThreadStoreError\"\n ? cause\n : failure(\"countPeerMessages\", cause),\n ),\n );\n\n return { read, countPeerMessages };\n});\n"],"mappings":";;;;;;;;;;;;;AAmBA,MAAM,WAAW,WAAmB,UAClC,iBAAiB,KAAK;CACpB;CACA,SAAS;CACT,GAAI,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,MAAM;AACzC,CAAC;;AAGH,MAAa,0BAA0B,OAAO,IAAI,aAAa;CAC7D,MAAM,MAAM,OAAO,UAAU;CAE7B,OAAO,GAAG;CACV,OAAO,GAAG;CACV,OAAO,GAAG;CACV,OAAO,GAAG;CACV,OAAO,GAAG;CACV,OAAO,GAAG;AACZ,CAAC;;AAGD,MAAa,uBAAuB,OAAO,WAAW,WACpD,UACA,QACA;CACA,MAAM,MAAM,OAAO,UAAU;CAC7B,MAAM,UAAU,OAAO;CAEvB,QAAQ,QAAQ,MAAhB;EACE,KAAK;EACL,KAAK;GACH,IAAI,QAAQ,SAAS,mBACnB,OAAO,GAAG;;4BAEU,SAAS;+DAC0B,QAAQ,MAAM;oEACT,QAAQ;GACtE,OAAO,GAAG,2DAA2D,QAAQ,SAAS,qBAAqB,IAAI,EAAE;4BAC3F,SAAS,mBAAmB,OAAO;GACzD;EAEF,KAAK;GACH,KAAK,MAAM,OAAO,CAAC,oBAAoB,iBAAiB,GACtD,OAAO,GAAG;;4BAEU,SAAS,qDAAqD,IAAI;+DAC/B,QAAQ,MAAM;oEACT,QAAQ;GACtE;EACF,KAAK;GACH,OAAO,GAAG,+EAA+E,SAAS,mBAAmB,OAAO;GAC5H;EACF,KAAK,wBACH,OAAO,GAAG;kEACkD,QAAQ,kBAAkB,IAAI,EAAE;4BACtE,SAAS;6EACwC,QAAQ;CAEnF;AACF,CAAC;;AAGD,MAAa,wBAAwB,OAAO,IAAI,aAAa;CAC3D,MAAM,MAAM,OAAO,UAAU;CAS7B,KAAI,OAJK,GAAG;;wKAIJ,CAAC,SAAS,GAAG,OAAO,OAAO,QAAQ,oCAAoC;CAC/E,IAAI,cAAc;CAClB,IAAI,gBAAgB;CAEpB,OAAO,MAAM;EACX,MAAM,OAAO,OAAO,GAKlB;uCACiC,YAAY,IAAI,cAAc;EAEjE,IAAI,KAAK,WAAW,GAAG;EACvB,KAAK,MAAM,OAAO,MAAM;GACtB,MAAM,SAAS,OAAO,OAAO,aAAa,OAAO,eAAe,eAAe,CAAC,CAAC,CAC/E,IAAI,WACN;GAEA,IACE,OAAO,aAAa,IAAI,aACxB,IAAI,cAAc,IAAI,cAAc,cAAc,gBAAgB,KAAK,GAEvE,OAAO,OAAO,QAAQ,yCAAyC;GACjE,OAAO,qBAAqB,IAAI,WAAW,MAAM;GACjD,cAAc,IAAI;GAClB,gBAAgB,IAAI;EACtB;CACF;AACF,CAAC;AAED,MAAM,MAAM,OAAO,OAAO;CACxB,WAAW,mBAAmB,OAAO;CACrC,UAAU;CACV,WAAW;CACX,UAAU,wBAAwB,OAAO;CACzC,aAAa,OAAO;CACpB,aAAa,OAAO,YAAY,OAAO,GAAG;AAC5C,CAAC;AAED,MAAa,oBAAoB,OAAO,WAAW,WACjD,UACA;CACA,MAAM,MAAM,OAAO,UAAU;CAE7B,MAAM,gBAAgB,OAAO,WAAW,WAAW,UAA0C;EAC3F,MAAM,OACJ,OAAO,GAAG,iFAAiF;EAE7F,IAAI,KAAK,WAAW,GAAG,OAAO,OAAO,sBAAsB,KAAK,EAAE,SAAS,CAAC;EAE5E,MAAM,UAAU,OAAO,OAAO,oBAC5B,OAAO,MAAM,OAAO,OAAO;GAAE,eAAe;GAAmB,aAAa;EAAO,CAAC,CAAC,CACvF,CAAC,CAAC,IAAI;EAEN,IAAI,QAAQ,WAAW,KAAK,QAAQ,OAAO,KAAA,GACzC,OAAO,OAAO,QAAQ,oBAAoB;EAE5C,OAAO,QAAQ;CACjB,CAAC;CAuHD,OAAO;EAAE,MArHI,OAAO,WAClB,WAAW,SAA6B;GACtC,OAAO,OAAO,IAAI,gBAChB,OAAO,IAAI,aAAa;IACtB,MAAM,OAAO,OAAO,cAAc,QAAQ,QAAQ;IAClD,MAAM,YAAY,QAAQ;IAE1B,IACE,0BAA0B,cACzB,KAAK,kBAAkB,UAAU,wBAChC,KAAK,gBAAgB,UAAU,qBAEjC,OAAO,OAAO,QAAQ,4BAA4B;IACpD,MAAM,QAAQ,QAAQ,KAAK,iBAAiB;IAC5C,IAAI;IAEJ,QAAQ,UAAU,MAAlB;KACE,KAAK;MACH,OACE,OAAO,GAAG,sHAAsH,QAAQ,SAAS,mBAAmB,UAAU,SAAS,kBAAkB;MAC3M;KACF,KAAK;MACH,OACE,OAAO,GAAG,sHAAsH,QAAQ,SAAS,qLAAqL,UAAU,MAAM;MACxV;KACF,KAAK;MACH,OACE,OAAO,GAAG,mIAAmI,QAAQ,SAAS,uCAAuC,MAAM,2BAA2B,QAAQ,KAAK;MACrP;KACF,KAAK;MACH,QAAQ,OAAO,OAAO,QACpB,CAAC,qBAAqB,YAAY,IACjC,QACC,GAAG;sCACiB,QAAQ,SAAS,qDAAqD,IAAI;;iDAGlG,EAAA,CACG,KAAK,CAAC,CACN,QAAQ,QAAQ,OAAO,IAAI,QAAQ,IAAI,KAAK,CAAC,CAC7C,MAAM,GAAG,MAAM,OAAO,EAAE,QAAQ,IAAI,OAAO,EAAE,QAAQ,CAAC,CAAC,CACvD,MAAM,GAAG,QAAQ,KAAK,KAAK;MAC9B;KACF,KAAK,eAAe;MAClB,MAAM,QACJ,UAAU,uBAAuB,KAAA,IAC7B,OACA,mBAAmB,UAAU,kBAAkB;MAErD,OAAO,OAAO,GAAG;;gCAEC,QAAQ,SAAS,kBAAkB,MAAM;;;gCAGzC,QAAQ,SAAS,kBAAkB,MAAM,8IAA8I,UAAU,sBAAsB,KAAK;;;gCAG5N,QAAQ,SAAS,kBAAkB,MAAM,yHAAyH,MAAM;sCAClK,QAAQ,KAAK;MACrC;KACF;IACF;IACA,MAAM,UAAU,OAAO,OAAO,oBAAoB,OAAO,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI;IAEzE,IAAI,UAAU,SAAS,cAAc,QAAQ,SAAS,GACpD,OAAO,OAAO,QAAQ,8BAA8B;IAEtD,OAAO,OAAO,OAAO,QACnB,QAAQ,QAAQ,QAAQ,IAAI,WAAW,KAAK,IAC3C,QACC,OAAO,IAAI,aAAa;KACtB,MAAM,QAAQ,OAAO,SAAS,GAAG;KAEjC,IACE,MAAM,OAAO,aAAa,IAAI,aAC9B,IAAI,cAAc,QAAQ,YACzB,UAAU,SAAS,iBAClB,EACG,IAAI,gBAAgB,KAAK,MAAM,OAAO,QAAQ,SAAS,sBACvD,IAAI,gBAAgB,KAAK,MAAM,OAAO,QAAQ,SAAS,qBACvD,IAAI,gBAAgB,KACnB,MAAM,OAAO,QAAQ,SAAS,yBAGpC,OAAO,OAAO,QAAQ,uCAAuC;KAE/D,OAAO;IACT,CAAC,CACL;GACF,CAAC,CACH;EACF,GACA,OAAO,UAAU,UACf,MAAM,SAAS,2BAA2B,MAAM,SAAS,qBACrD,QACA,QAAQ,iBAAiB,KAAK,CACpC,CAqBU;EAAG,mBAjBb,OAAO,WACL,WAAW,SAAS;GAClB,OAAO,OAAO,aAAa,sBAAsB,CAAC,CAAC,OAAO;GAC1D,OAAO,cAAc,QAAQ,QAAQ;GAKrC,QAAO,OAFE,GAAG,kEAAkE,QAAQ,SAAS,iFAAiF,QAAQ,QAAA,CAE5K;EACd,GACA,OAAO,UAAU,UACf,MAAM,SAAS,2BAA2B,MAAM,SAAS,qBACrD,QACA,QAAQ,qBAAqB,KAAK,CACxC,CAG2B;CAAE;AACnC,CAAC"}
@@ -1,3 +1,3 @@
1
1
  import { i as QueueSequence, n as JoinedToHost, r as Principal, t as IdempotencyKey } from "../Receipt-BAHyigAF.mjs";
2
- import { $a as OwnershipSnapshot, Aa as ChildAttachmentSnapshot, Ao as SuspensionOutcome, Ba as ClaimRequest, Bo as submissionAbortBatchId, Ca as AdmissionResult, Co as SubmissionLookup, Da as ApprovalPendingSuspension, Do as SubmissionState, Ea as ApprovalDecisionIntent, Eo as SubmissionSnapshot, Fa as ChildReservationStatus, Fo as UnknownResolutionConflict, Ga as LedgerCapabilities, Go as submissionSettlementId, Ha as InputAppliedMarker, Ho as submissionInputBatchId, Ia as ChildSettledNotification, Io as UnknownResolutionIntent, Ja as MarkJoinedRequest, Ka as LedgerError, Ko as submissionSettlementRecordId, La as ChildSettledOutcome, Lo as WaitingChild, Ma as ChildBudgetReservationSnapshot, Mo as SuspensionSnapshot, Na as ChildReservationConflict, No as UnknownResolution, Oa as AttachChildToReservationRequest, Oo as SubmissionWorkItem, Pa as ChildReservationId, Po as UnknownResolutionCommand, Qa as OwnershipRenewal, Ra as Claim, Ro as WaitingForChildSuspension, Sa as AdmissionResolution, Ta as ApprovalDecisionCommand, To as SubmissionLookupByKey, Ua as JoinSnapshot, Uo as submissionInputRecordId, Va as DEFAULT_OWNERSHIP_LEASE_DURATION, Vo as submissionAbortRecordId, Wa as JoiningClaim, Wo as submissionSettlementBatchId, Xa as MarkUnknownRequest, Ya as MarkReadyRequest, Za as OwnershipLost, _a as AdmissionGroup, _o as SettlementReservation, ao as ReleaseOwnershipRequest, ba as AdmissionPolicyError, bo as SubmissionLedger, co as ReservedSettlement, da as AbortCommand, do as ResolutionNeverHappened, eo as OwnershipToken, fa as AbortIntent, fo as ResolutionSafeToRetry, ga as AdmissionFence, go as SettlementFinalization, ha as AdmissionConflict, ho as SettlementConflict, io as ReleaseChildBudgetRequest, ja as ChildBudgetReservationRequest, jo as SuspensionReason, ka as BeginChildBudgetReleaseRequest, ko as SuspendRequest, lo as ResolutionAbortSubmission, ma as AdmissionAdmitted, mo as Settlement, no as RecoverySnapshot, oo as RenewOwnershipRequest, pa as AbortIntentRequest, po as RevertJoiningRequest, qa as MarkInputAppliedRequest, ro as RecoverySnapshotRequest, so as ReservedChildBudget, to as ParentLinkage, uo as ResolutionCompletedWithResult, va as AdmissionIndeterminate, vo as SettlementReservationSnapshot, wa as ApprovalConflict, wo as SubmissionLookupById, xa as AdmissionRequest, xo as SubmissionLedgerFailure, ya as AdmissionNotAdmitted, yo as SubmissionAdmissionFence, za as ClaimJoiningRequest, zo as settlementFailureFromRecord } from "../Records-BtxMy8xD.mjs";
3
- export { AbortCommand, AbortIntent, AbortIntentRequest, AdmissionAdmitted, AdmissionConflict, AdmissionFence, AdmissionGroup, AdmissionIndeterminate, AdmissionNotAdmitted, AdmissionPolicyError, AdmissionRequest, AdmissionResolution, AdmissionResult, ApprovalConflict, ApprovalDecisionCommand, ApprovalDecisionIntent, ApprovalPendingSuspension, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, ChildAttachmentSnapshot, ChildBudgetReservationRequest, ChildBudgetReservationSnapshot, ChildReservationConflict, ChildReservationId, ChildReservationStatus, ChildSettledNotification, ChildSettledOutcome, Claim, ClaimJoiningRequest, ClaimRequest, DEFAULT_OWNERSHIP_LEASE_DURATION, IdempotencyKey, InputAppliedMarker, JoinSnapshot, JoinedToHost, JoiningClaim, LedgerCapabilities, LedgerError, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, OwnershipLost, OwnershipRenewal, OwnershipSnapshot, OwnershipToken, ParentLinkage, Principal, QueueSequence, RecoverySnapshot, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, ReservedChildBudget, ReservedSettlement, ResolutionAbortSubmission, ResolutionCompletedWithResult, ResolutionNeverHappened, ResolutionSafeToRetry, RevertJoiningRequest, Settlement, SettlementConflict, SettlementFinalization, SettlementReservation, SettlementReservationSnapshot, SubmissionAdmissionFence, SubmissionLedger, SubmissionLedgerFailure, SubmissionLookup, SubmissionLookupById, SubmissionLookupByKey, SubmissionSnapshot, SubmissionState, SubmissionWorkItem, SuspendRequest, SuspensionOutcome, SuspensionReason, SuspensionSnapshot, UnknownResolution, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, WaitingChild, WaitingForChildSuspension, settlementFailureFromRecord, submissionAbortBatchId, submissionAbortRecordId, submissionInputBatchId, submissionInputRecordId, submissionSettlementBatchId, submissionSettlementId, submissionSettlementRecordId };
2
+ import { $a as OwnershipRenewal, Aa as BeginChildBudgetReleaseRequest, Ao as SuspendRequest, Ba as ClaimJoiningRequest, Bo as WorkerLedgerState, Ca as AdmissionResolution, Da as ApprovalDecisionIntent, Do as SubmissionSnapshot, Ea as ApprovalDecisionCommand, Eo as SubmissionLookupByKey, Fa as ChildReservationId, Fo as UnknownResolutionCommand, Ga as JoiningClaim, Go as submissionInputBatchId, Ha as DEFAULT_OWNERSHIP_LEASE_DURATION, Ho as settlementFailureFromRecord, Ia as ChildReservationStatus, Io as UnknownResolutionConflict, Ja as MarkInputAppliedRequest, Jo as submissionSettlementId, Ka as LedgerCapabilities, Ko as submissionInputRecordId, La as ChildSettledNotification, Lo as UnknownResolutionIntent, Ma as ChildBudgetReservationRequest, Mo as SuspensionReason, Na as ChildBudgetReservationSnapshot, No as SuspensionSnapshot, Oa as ApprovalPendingSuspension, Oo as SubmissionState, Pa as ChildReservationConflict, Po as UnknownResolution, Qa as OwnershipLost, Ra as ChildSettledOutcome, Ro as WaitingChild, Sa as AdmissionRequest, So as SubmissionLedgerFailure, Ta as ApprovalConflict, To as SubmissionLookupById, Ua as InputAppliedMarker, Uo as submissionAbortBatchId, Va as ClaimRequest, Vo as WorkerStopCommand, Wa as JoinSnapshot, Wo as submissionAbortRecordId, Xa as MarkReadyRequest, Xo as workerTerminalFromRecord, Ya as MarkJoinedRequest, Yo as submissionSettlementRecordId, Za as MarkUnknownRequest, _a as AdmissionFence, _o as SettlementFinalization, ao as ReleaseChildBudgetRequest, ba as AdmissionNotAdmitted, bo as SubmissionAdmissionFence, co as ReservedChildBudget, do as ResolutionCompletedWithResult, eo as OwnershipSnapshot, fa as AbortCommand, fo as ResolutionNeverHappened, ga as AdmissionConflict, go as SettlementConflict, ha as AdmissionAdmitted, ho as Settlement, io as RecoverySnapshotRequest, ja as ChildAttachmentSnapshot, jo as SuspensionOutcome, ka as AttachChildToReservationRequest, ko as SubmissionWorkItem, lo as ReservedSettlement, ma as AbortIntentRequest, mo as RevertJoiningRequest, no as ParentLinkage, oo as ReleaseOwnershipRequest, pa as AbortIntent, po as ResolutionSafeToRetry, qa as LedgerError, qo as submissionSettlementBatchId, ro as RecoverySnapshot, so as RenewOwnershipRequest, to as OwnershipToken, uo as ResolutionAbortSubmission, va as AdmissionGroup, vo as SettlementReservation, wa as AdmissionResult, wo as SubmissionLookup, xa as AdmissionPolicyError, xo as SubmissionLedger, ya as AdmissionIndeterminate, yo as SettlementReservationSnapshot, za as Claim, zo as WaitingForChildSuspension } from "../Records-Byeb70tt.mjs";
3
+ export { AbortCommand, AbortIntent, AbortIntentRequest, AdmissionAdmitted, AdmissionConflict, AdmissionFence, AdmissionGroup, AdmissionIndeterminate, AdmissionNotAdmitted, AdmissionPolicyError, AdmissionRequest, AdmissionResolution, AdmissionResult, ApprovalConflict, ApprovalDecisionCommand, ApprovalDecisionIntent, ApprovalPendingSuspension, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, ChildAttachmentSnapshot, ChildBudgetReservationRequest, ChildBudgetReservationSnapshot, ChildReservationConflict, ChildReservationId, ChildReservationStatus, ChildSettledNotification, ChildSettledOutcome, Claim, ClaimJoiningRequest, ClaimRequest, DEFAULT_OWNERSHIP_LEASE_DURATION, IdempotencyKey, InputAppliedMarker, JoinSnapshot, JoinedToHost, JoiningClaim, LedgerCapabilities, LedgerError, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, OwnershipLost, OwnershipRenewal, OwnershipSnapshot, OwnershipToken, ParentLinkage, Principal, QueueSequence, RecoverySnapshot, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, ReservedChildBudget, ReservedSettlement, ResolutionAbortSubmission, ResolutionCompletedWithResult, ResolutionNeverHappened, ResolutionSafeToRetry, RevertJoiningRequest, Settlement, SettlementConflict, SettlementFinalization, SettlementReservation, SettlementReservationSnapshot, SubmissionAdmissionFence, SubmissionLedger, SubmissionLedgerFailure, SubmissionLookup, SubmissionLookupById, SubmissionLookupByKey, SubmissionSnapshot, SubmissionState, SubmissionWorkItem, SuspendRequest, SuspensionOutcome, SuspensionReason, SuspensionSnapshot, UnknownResolution, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, WaitingChild, WaitingForChildSuspension, WorkerLedgerState, WorkerStopCommand, settlementFailureFromRecord, submissionAbortBatchId, submissionAbortRecordId, submissionInputBatchId, submissionInputRecordId, submissionSettlementBatchId, submissionSettlementId, submissionSettlementRecordId, workerTerminalFromRecord };
@@ -3,7 +3,8 @@ import { AgentId, AttemptId, ReceiptId, SettlementId, SubmissionId, ThreadId, To
3
3
  import { IdempotencyKey, JoinedToHost, Principal, QueueSequence } from "../core/Receipt.mjs";
4
4
  import { o as Value } from "../FailureDiagnostic-BElLOoED.mjs";
5
5
  import { RunUsageSummary } from "../core/Usage.mjs";
6
- import { l as InputMessage } from "../MessagingHost-D89X7ma8.mjs";
6
+ import { n as AssignmentTerminal } from "../Worker-CfwzMZEK.mjs";
7
+ import { l as InputMessage } from "../MessagingHost-DfsbMPvq.mjs";
7
8
  import { AbortRequested, ApprovalDecision, BatchId, CanonicalSequence, DefinitionDigests, DeploymentId, Digest, PersistedJson, ProducerEpoch, ProducerId, RecordEnvelope, RecordId, SettlementFailureDiagnostic, SettlementOutcome, ToolApprovalDecided, ToolCallResolved, ToolCallUnknown, WorkerAdmission } from "./Records.mjs";
8
9
  import { Context, Duration, Effect, Schema } from "effect";
9
10
  //#region src/durable/SubmissionLedger.ts
@@ -92,6 +93,8 @@ var SubmissionLedger_exports = /* @__PURE__ */ __exportAll({
92
93
  UnknownResolutionIntent: () => UnknownResolutionIntent,
93
94
  WaitingChild: () => WaitingChild,
94
95
  WaitingForChildSuspension: () => WaitingForChildSuspension,
96
+ WorkerLedgerState: () => WorkerLedgerState,
97
+ WorkerStopCommand: () => WorkerStopCommand,
95
98
  settlementFailureFromRecord: () => settlementFailureFromRecord,
96
99
  submissionAbortBatchId: () => submissionAbortBatchId,
97
100
  submissionAbortRecordId: () => submissionAbortRecordId,
@@ -99,7 +102,8 @@ var SubmissionLedger_exports = /* @__PURE__ */ __exportAll({
99
102
  submissionInputRecordId: () => submissionInputRecordId,
100
103
  submissionSettlementBatchId: () => submissionSettlementBatchId,
101
104
  submissionSettlementId: () => submissionSettlementId,
102
- submissionSettlementRecordId: () => submissionSettlementRecordId
105
+ submissionSettlementRecordId: () => submissionSettlementRecordId,
106
+ workerTerminalFromRecord: () => workerTerminalFromRecord
103
107
  });
104
108
  const identifier = (name) => Schema.NonEmptyString.check(Schema.isMaxLength(256)).pipe(Schema.brand(`@effect-agent/thread/${name}`));
105
109
  /**
@@ -260,6 +264,13 @@ var SubmissionSnapshot = class extends Schema.Class("@effect-agent/thread/Submis
260
264
  workerAdmission: Schema.optionalKey(WorkerAdmission),
261
265
  messageAdmission: Schema.optionalKey(InputMessage)
262
266
  }) {};
267
+ /** Bounded native control facts. Canonical input/Run records remain ThreadStore-owned. */
268
+ const WorkerLedgerState = Schema.Struct({
269
+ latest: Schema.NullOr(SubmissionSnapshot),
270
+ active: Schema.NullOr(SubmissionSnapshot),
271
+ stopped: Schema.Boolean,
272
+ terminal: Schema.optionalKey(AssignmentTerminal)
273
+ }).check(Schema.makeFilter((state) => state.terminal === void 0 || state.stopped));
263
274
  /** The authoritative store proves the scoped idempotency key was never admitted (SUB-031). */
264
275
  var AdmissionNotAdmitted = class extends Schema.TaggedClass("@effect-agent/thread/AdmissionNotAdmitted")("NotAdmitted", {}) {};
265
276
  /** The scoped idempotency key was admitted; the full Submission snapshot is authoritative. */
@@ -381,6 +392,24 @@ const settlementFailureFromRecord = (record) => {
381
392
  return payload._tag === "SubmissionSettled" && payload.outcome === "failed" ? payload.result : void 0;
382
393
  };
383
394
  /**
395
+ * Assignment intent derived only from frozen admission and exact settlement evidence.
396
+ * Joined receipts and cancellation before a Run starts do not finish an assignment.
397
+ * Adapters suppress completed intent when newer accepted input remains unapplied, then
398
+ * install the first seal and outstanding abort intents atomically before releasing the lane.
399
+ */
400
+ const workerTerminalFromRecord = (submission, record) => {
401
+ const payload = record.payload;
402
+ if (submission.workerAdmission?.origin.lifecycle !== "assignment" || payload._tag !== "SubmissionSettled" || payload.runId !== void 0 && payload.runId !== `run:${submission.submissionId}`) return void 0;
403
+ if (payload.outcome === "failed" || payload.finishReason === "budget-exhausted") return "failed";
404
+ if (payload.outcome === "aborted") return payload.runId === void 0 ? void 0 : "cancelled";
405
+ return payload.runDisposition === "completed" ? "completed" : void 0;
406
+ };
407
+ /** Destination-owned permanent inbox seal; recorded atomically with all outstanding abort intents. */
408
+ const WorkerStopCommand = Schema.Struct({
409
+ threadId: ThreadId,
410
+ author: Principal
411
+ });
412
+ /**
384
413
  * A durable abort command (durability §13). Field bounds are exactly those of the canonical
385
414
  * `AbortRequested` payload so the intent can become canonical without re-validation.
386
415
  */
@@ -812,7 +841,8 @@ var LedgerError = class extends Schema.TaggedError()("LedgerError", {
812
841
  * recovery settles aborted never-claimed queued work immediately, without waiting for it to
813
842
  * head the lane. Both exceptions are outcome- and state-narrow; everything else stays fenced.
814
843
  * - `finalizeSettlement` — idempotent terminal transition (state → settled) after the reserved
815
- * record is canonical; releases the lane so the next `queueSequence` becomes claimable. It
844
+ * record is canonical. Native adapters seal opted-in worker assignments atomically before
845
+ * releasing the lane. Otherwise the next `queueSequence` becomes claimable. It
816
846
  * requires no ownership token: canonical history authorizes finalization (DUR-015). A
817
847
  * finalization that disagrees with the recorded outcome fails with `SettlementConflict`.
818
848
  * - `requestAbort` — durable, idempotent by `submissionId`: repeating returns the recorded
@@ -924,6 +954,6 @@ const SubmissionAdmissionFence = Context.Reference("@effect-agent/thread/Submiss
924
954
  code: "unsupported-policy"
925
955
  }) }) });
926
956
  //#endregion
927
- export { AbortCommand, AbortIntent, AbortIntentRequest, AdmissionAdmitted, AdmissionConflict, AdmissionFence, AdmissionGroup, AdmissionIndeterminate, AdmissionNotAdmitted, AdmissionPolicyError, AdmissionRequest, AdmissionResolution, AdmissionResult, ApprovalConflict, ApprovalDecisionCommand, ApprovalDecisionIntent, ApprovalPendingSuspension, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, ChildAttachmentSnapshot, ChildBudgetReservationRequest, ChildBudgetReservationSnapshot, ChildReservationConflict, ChildReservationId, ChildReservationStatus, ChildSettledNotification, ChildSettledOutcome, Claim, ClaimJoiningRequest, ClaimRequest, DEFAULT_OWNERSHIP_LEASE_DURATION, IdempotencyKey, InputAppliedMarker, JoinSnapshot, JoinedToHost, JoiningClaim, LedgerCapabilities, LedgerError, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, OwnershipLost, OwnershipRenewal, OwnershipSnapshot, OwnershipToken, ParentLinkage, Principal, QueueSequence, RecoverySnapshot, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, ReservedChildBudget, ReservedSettlement, ResolutionAbortSubmission, ResolutionCompletedWithResult, ResolutionNeverHappened, ResolutionSafeToRetry, RevertJoiningRequest, Settlement, SettlementConflict, SettlementFinalization, SettlementReservation, SettlementReservationSnapshot, SubmissionAdmissionFence, SubmissionLedger, SubmissionLookup, SubmissionLookupById, SubmissionLookupByKey, SubmissionSnapshot, SubmissionState, SubmissionWorkItem, SuspendRequest, SuspensionOutcome, SuspensionReason, SuspensionSnapshot, UnknownResolution, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, WaitingChild, WaitingForChildSuspension, settlementFailureFromRecord, submissionAbortBatchId, submissionAbortRecordId, submissionInputBatchId, submissionInputRecordId, submissionSettlementBatchId, submissionSettlementId, submissionSettlementRecordId, SubmissionLedger_exports as t };
957
+ export { AbortCommand, AbortIntent, AbortIntentRequest, AdmissionAdmitted, AdmissionConflict, AdmissionFence, AdmissionGroup, AdmissionIndeterminate, AdmissionNotAdmitted, AdmissionPolicyError, AdmissionRequest, AdmissionResolution, AdmissionResult, ApprovalConflict, ApprovalDecisionCommand, ApprovalDecisionIntent, ApprovalPendingSuspension, AttachChildToReservationRequest, BeginChildBudgetReleaseRequest, ChildAttachmentSnapshot, ChildBudgetReservationRequest, ChildBudgetReservationSnapshot, ChildReservationConflict, ChildReservationId, ChildReservationStatus, ChildSettledNotification, ChildSettledOutcome, Claim, ClaimJoiningRequest, ClaimRequest, DEFAULT_OWNERSHIP_LEASE_DURATION, IdempotencyKey, InputAppliedMarker, JoinSnapshot, JoinedToHost, JoiningClaim, LedgerCapabilities, LedgerError, MarkInputAppliedRequest, MarkJoinedRequest, MarkReadyRequest, MarkUnknownRequest, OwnershipLost, OwnershipRenewal, OwnershipSnapshot, OwnershipToken, ParentLinkage, Principal, QueueSequence, RecoverySnapshot, RecoverySnapshotRequest, ReleaseChildBudgetRequest, ReleaseOwnershipRequest, RenewOwnershipRequest, ReservedChildBudget, ReservedSettlement, ResolutionAbortSubmission, ResolutionCompletedWithResult, ResolutionNeverHappened, ResolutionSafeToRetry, RevertJoiningRequest, Settlement, SettlementConflict, SettlementFinalization, SettlementReservation, SettlementReservationSnapshot, SubmissionAdmissionFence, SubmissionLedger, SubmissionLookup, SubmissionLookupById, SubmissionLookupByKey, SubmissionSnapshot, SubmissionState, SubmissionWorkItem, SuspendRequest, SuspensionOutcome, SuspensionReason, SuspensionSnapshot, UnknownResolution, UnknownResolutionCommand, UnknownResolutionConflict, UnknownResolutionIntent, WaitingChild, WaitingForChildSuspension, WorkerLedgerState, WorkerStopCommand, settlementFailureFromRecord, submissionAbortBatchId, submissionAbortRecordId, submissionInputBatchId, submissionInputRecordId, submissionSettlementBatchId, submissionSettlementId, submissionSettlementRecordId, SubmissionLedger_exports as t, workerTerminalFromRecord };
928
958
 
929
959
  //# sourceMappingURL=SubmissionLedger.mjs.map