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.
- package/dist/Agent-1DMSO_Fl.mjs.map +1 -1
- package/dist/{Agent-DriBcXBN.d.mts → Agent-D9cXqfF3.d.mts} +9 -2
- package/dist/{AgentRuntime-DLwPoEVH.mjs → AgentRuntime-Cp1hAb-W.mjs} +8 -4
- package/dist/AgentRuntime-Cp1hAb-W.mjs.map +1 -0
- package/dist/{AgentRuntime-CWkHuzyt.d.mts → AgentRuntime-DyZv8uu2.d.mts} +6 -6
- package/dist/{DurableAgentRuntime-BIrgxwRl.mjs → DurableAgentRuntime-tNrkJZNo.mjs} +254 -162
- package/dist/DurableAgentRuntime-tNrkJZNo.mjs.map +1 -0
- package/dist/{DurableFailpoint-mx3-nsxU.d.mts → DurableFailpoint-Cnr3wx1L.d.mts} +3 -3
- package/dist/{EventSource-ARs56eBq.d.mts → EventSource-DPRdlvhV.d.mts} +3 -3
- package/dist/{Messaging-DaZDlBqh.d.mts → Messaging-JYYN3oYS.d.mts} +3 -3
- package/dist/{MessagingHost-e1Sbzfao.d.mts → MessagingHost-CqzpxbGz.d.mts} +3 -3
- package/dist/{MessagingHost-D89X7ma8.mjs → MessagingHost-DfsbMPvq.mjs} +2 -2
- package/dist/{MessagingHost-D89X7ma8.mjs.map → MessagingHost-DfsbMPvq.mjs.map} +1 -1
- package/dist/{Output-CAFJTAbP.d.mts → Output-V-6YL1_Z.d.mts} +2 -2
- package/dist/{PreparedInputAdmission-_WYg-D0f.d.mts → PreparedInputAdmission-DqQUjA9k.d.mts} +4 -4
- package/dist/{Records-BtxMy8xD.d.mts → Records-Byeb70tt.d.mts} +89 -31
- package/dist/{RunOptions-BoESJrxw.d.mts → RunOptions-CSBsSj0X.d.mts} +3 -3
- package/dist/{Schedule-DGPyXBzK.d.mts → Schedule-krSnBcbU.d.mts} +2 -2
- package/dist/{Subagent-D9eYdGTl.mjs → Subagent-Di8EEjWZ.mjs} +67 -105
- package/dist/Subagent-Di8EEjWZ.mjs.map +1 -0
- package/dist/{Subagent-F72tuaxy.d.mts → Subagent-gw9KD6eb.d.mts} +310 -35
- package/dist/{SubagentHost-CmiNTOBZ.d.mts → SubagentHost-P9zB_TfV.d.mts} +24 -18
- package/dist/{Subscription-B9VszlF9.d.mts → Subscription-Xnwd42Sm.d.mts} +6 -3
- package/dist/{SubscriptionInput-BJWZqCWP.d.mts → SubscriptionInput-CqtJ58vl.d.mts} +3 -3
- package/dist/{Worker-T_3RbaKc.mjs → Worker-CfwzMZEK.mjs} +66 -5
- package/dist/Worker-CfwzMZEK.mjs.map +1 -0
- package/dist/{Worker-Du9dhVnp.d.mts → Worker-fwWkBg12.d.mts} +199 -6
- package/dist/{agent-registration-B5CI-Ygk.mjs → agent-registration-CKNsrpwo.mjs} +7 -7
- package/dist/agent-registration-CKNsrpwo.mjs.map +1 -0
- package/dist/capabilities/Commands.d.mts +1 -1
- package/dist/capabilities/Messaging.d.mts +1 -1
- package/dist/capabilities/Messaging.mjs +2 -2
- package/dist/capabilities/RunHooks.d.mts +1 -1
- package/dist/capabilities/Subagent.d.mts +3 -3
- package/dist/capabilities/Subagent.mjs +3 -3
- package/dist/core/Agent.d.mts +1 -1
- package/dist/core/Worker.d.mts +2 -2
- package/dist/core/Worker.mjs +2 -2
- package/dist/durable/ActivityStore.d.mts +1 -1
- package/dist/durable/Admin.d.mts +1 -1
- package/dist/durable/AgentRegistration.d.mts +1 -1
- package/dist/durable/AgentRegistration.mjs +1 -1
- package/dist/durable/Certification.d.mts +2 -2
- package/dist/durable/CommittedActivity.d.mts +1 -1
- package/dist/durable/Digest.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.d.mts +1 -1
- package/dist/durable/DurableAgentRuntime.mjs +1 -1
- package/dist/durable/DurableFailpoint.d.mts +1 -1
- package/dist/durable/DurableFailpoint.mjs +4 -0
- package/dist/durable/DurableFailpoint.mjs.map +1 -1
- package/dist/durable/DurableFailpointTestControl.d.mts +1 -1
- package/dist/durable/EventSource.d.mts +1 -1
- package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
- package/dist/durable/MessageDelivery.d.mts +20 -3
- package/dist/durable/MessageDelivery.mjs +12 -4
- package/dist/durable/MessageDelivery.mjs.map +1 -1
- package/dist/durable/MessageDeliveryStoreConformance.d.mts +41 -39
- package/dist/durable/MessageDeliveryStoreConformance.mjs +1 -1
- package/dist/durable/PersistentHistory.d.mts +1 -1
- package/dist/durable/PreparedInputAdmission.d.mts +1 -1
- package/dist/durable/Records.d.mts +2 -2
- package/dist/durable/Records.mjs +12 -5
- package/dist/durable/Records.mjs.map +1 -1
- package/dist/durable/Recovery.d.mts +1 -1
- package/dist/durable/RunJournal.d.mts +1 -1
- package/dist/durable/Schedule.d.mts +1 -1
- package/dist/durable/ScheduleStoreConformance.d.mts +1 -1
- package/dist/durable/ScheduleTransition.d.mts +1 -1
- package/dist/durable/Scheduling.d.mts +2 -2
- package/dist/durable/SqlMessageDeliveryStore.mjs +7 -1
- package/dist/durable/SqlMessageDeliveryStore.mjs.map +1 -1
- package/dist/durable/SqlStorageV2Upgrade.d.mts +2 -2
- package/dist/durable/SqlSubscriptionStore.d.mts +2 -2
- package/dist/durable/SqlThreadNativeReads.d.mts +5 -1
- package/dist/durable/SqlThreadNativeReads.mjs +6 -0
- package/dist/durable/SqlThreadNativeReads.mjs.map +1 -1
- package/dist/durable/SubmissionLedger.d.mts +2 -2
- package/dist/durable/SubmissionLedger.mjs +34 -4
- package/dist/durable/SubmissionLedger.mjs.map +1 -1
- package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
- package/dist/durable/SubmissionLedgerConformance.mjs +899 -706
- package/dist/durable/SubmissionLedgerConformance.mjs.map +1 -1
- package/dist/durable/SubmissionStatus.d.mts +1 -1
- package/dist/durable/Subscription.d.mts +1 -1
- package/dist/durable/Subscription.mjs +1 -1
- package/dist/durable/SubscriptionInput.d.mts +1 -1
- package/dist/durable/SubscriptionInput.mjs +1 -1
- package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
- package/dist/durable/SubscriptionTools.d.mts +3 -3
- package/dist/durable/SubscriptionTransition.d.mts +1 -1
- package/dist/durable/Subscriptions.d.mts +5 -5
- package/dist/durable/ThreadContextHistory.d.mts +1 -1
- package/dist/durable/ThreadContextHistoryProjection.d.mts +1 -1
- package/dist/durable/ThreadInvariants.d.mts +1 -1
- package/dist/durable/ThreadProjection.d.mts +1 -1
- package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
- package/dist/durable/ThreadStore.d.mts +1 -1
- package/dist/durable/ThreadStore.mjs +5 -0
- package/dist/durable/ThreadStore.mjs.map +1 -1
- package/dist/durable/ThreadStoreConformance.d.mts +1 -1
- package/dist/durable/WorkerHost.d.mts +3 -3
- package/dist/durable/WorkerHost.mjs +1 -1
- package/dist/engine/AgentRuntime.d.mts +1 -1
- package/dist/engine/AgentRuntime.mjs +1 -1
- package/dist/engine/MessagingHost.d.mts +1 -1
- package/dist/engine/MessagingHost.mjs +1 -1
- package/dist/engine/Output.d.mts +1 -1
- package/dist/engine/RunOptions.d.mts +1 -1
- package/dist/engine/SubagentHost.d.mts +2 -2
- package/dist/engine/SubagentHost.mjs +5 -1
- package/dist/engine/SubagentHost.mjs.map +1 -1
- package/dist/index.d.mts +16 -16
- package/dist/index.mjs +5 -5
- package/package.json +1 -1
- package/src/capabilities/Subagent.ts +2 -1
- package/src/capabilities/internal/subagent-background.ts +86 -57
- package/src/capabilities/internal/subagent-reporting.ts +3 -128
- package/src/core/Agent.ts +8 -1
- package/src/core/Worker.ts +58 -2
- package/src/durable/DurableAgentRuntime.ts +2 -0
- package/src/durable/DurableFailpoint.ts +4 -0
- package/src/durable/MessageDelivery.ts +17 -2
- package/src/durable/Records.ts +12 -2
- package/src/durable/SqlMessageDeliveryStore.ts +15 -1
- package/src/durable/SqlThreadNativeReads.ts +14 -0
- package/src/durable/SubmissionLedger.ts +48 -1
- package/src/durable/SubmissionLedgerConformance.ts +260 -42
- package/src/durable/ThreadStore.ts +5 -0
- package/src/durable/internal/agent-registration.ts +13 -48
- package/src/durable/internal/worker-host.ts +490 -341
- package/src/engine/SubagentHost.ts +37 -13
- package/src/engine/internal/agent-runtime.ts +17 -2
- package/dist/AgentRuntime-DLwPoEVH.mjs.map +0 -1
- package/dist/DurableAgentRuntime-BIrgxwRl.mjs.map +0 -1
- package/dist/Subagent-D9eYdGTl.mjs.map +0 -1
- package/dist/Worker-T_3RbaKc.mjs.map +0 -1
- 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``}
|
|
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-
|
|
2
|
-
import { g as SubscriptionFailpointError } from "../Subscription-
|
|
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-
|
|
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-
|
|
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 {
|
|
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":"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"}
|
|
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":"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"}
|
|
@@ -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
|
|
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 {
|
|
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
|
|
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
|