@effect-agent/storage-cloudflare 0.1.0-beta.12 → 0.1.0-beta.120

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 (74) hide show
  1. package/dist/DoMemoryStore.d.mts +29 -0
  2. package/dist/DoMemoryStore.mjs +55 -0
  3. package/dist/DoMemoryStore.mjs.map +1 -0
  4. package/dist/DoMessageDeliveryStore.d.mts +17 -0
  5. package/dist/DoMessageDeliveryStore.mjs +32 -0
  6. package/dist/DoMessageDeliveryStore.mjs.map +1 -0
  7. package/dist/DoScheduleStore.d.mts +36 -0
  8. package/dist/DoScheduleStore.mjs +388 -0
  9. package/dist/DoScheduleStore.mjs.map +1 -0
  10. package/dist/DoStorageConfig.d.mts +45 -0
  11. package/dist/DoStorageConfig.mjs +52 -0
  12. package/dist/DoStorageConfig.mjs.map +1 -0
  13. package/dist/DoStorageError-DjpuLHmX.d.mts +101 -0
  14. package/dist/DoStorageError.d.mts +2 -0
  15. package/dist/DoStorageError.mjs +167 -0
  16. package/dist/DoStorageError.mjs.map +1 -0
  17. package/dist/DoStorageFailpoint.d.mts +17 -0
  18. package/dist/DoStorageFailpoint.mjs +14 -0
  19. package/dist/DoStorageFailpoint.mjs.map +1 -0
  20. package/dist/DoStorageFailpointTesting.d.mts +33 -0
  21. package/dist/DoStorageFailpointTesting.mjs +35 -0
  22. package/dist/DoStorageFailpointTesting.mjs.map +1 -0
  23. package/dist/DoStorageVersion-DJwZzqel.d.mts +12 -0
  24. package/dist/DoStorageVersion.d.mts +2 -0
  25. package/dist/DoStorageVersion.mjs +8 -0
  26. package/dist/DoStorageVersion.mjs.map +1 -0
  27. package/dist/DoSubmissionLedger.d.mts +23 -0
  28. package/dist/DoSubmissionLedger.mjs +1939 -0
  29. package/dist/DoSubmissionLedger.mjs.map +1 -0
  30. package/dist/DoSubscriptionStore.d.mts +25 -0
  31. package/dist/DoSubscriptionStore.mjs +183 -0
  32. package/dist/DoSubscriptionStore.mjs.map +1 -0
  33. package/dist/DoThreadStore.d.mts +59 -0
  34. package/dist/DoThreadStore.mjs +499 -0
  35. package/dist/DoThreadStore.mjs.map +1 -0
  36. package/dist/MemoryProtocol.d.mts +38160 -0
  37. package/dist/MemoryProtocol.mjs +219 -0
  38. package/dist/MemoryProtocol.mjs.map +1 -0
  39. package/dist/PortProtocol.d.mts +5521 -0
  40. package/dist/PortProtocol.mjs +206 -0
  41. package/dist/PortProtocol.mjs.map +1 -0
  42. package/dist/PortRouting.d.mts +86 -0
  43. package/dist/PortRouting.mjs +461 -0
  44. package/dist/PortRouting.mjs.map +1 -0
  45. package/dist/do-journal-D65Iuln6.mjs +1119 -0
  46. package/dist/do-journal-D65Iuln6.mjs.map +1 -0
  47. package/dist/index.d.mts +14 -1525
  48. package/dist/index.mjs +14 -3695
  49. package/dist/migrations-Br6QqMIf.mjs +306 -0
  50. package/dist/migrations-Br6QqMIf.mjs.map +1 -0
  51. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  52. package/package.json +1 -45
  53. package/src/DoMemoryStore.ts +56 -0
  54. package/src/DoMessageDeliveryStore.ts +53 -0
  55. package/src/DoScheduleStore.ts +622 -0
  56. package/src/{errors.ts → DoStorageError.ts} +13 -3
  57. package/src/DoStorageFailpoint.ts +20 -0
  58. package/src/{do-storage-failpoint.ts → DoStorageFailpointTesting.ts} +5 -18
  59. package/src/DoStorageVersion.ts +2 -0
  60. package/src/{do-ledger.ts → DoSubmissionLedger.ts} +1119 -262
  61. package/src/DoSubscriptionStore.ts +329 -0
  62. package/src/DoThreadStore.ts +1064 -0
  63. package/src/MemoryProtocol.ts +351 -0
  64. package/src/{port-protocol.ts → PortProtocol.ts} +103 -38
  65. package/src/{routing.ts → PortRouting.ts} +440 -264
  66. package/src/index.ts +13 -32
  67. package/src/internal/do-journal.ts +1789 -0
  68. package/src/internal/message-delivery-schema.ts +24 -0
  69. package/src/{migrations.ts → internal/migrations.ts} +72 -35
  70. package/src/internal/recovery-checkpoint-schema.ts +17 -0
  71. package/dist/index.mjs.map +0 -1
  72. package/src/do-conversation-store.ts +0 -850
  73. package/src/do-journal.ts +0 -1078
  74. /package/src/{do-storage-config.ts → DoStorageConfig.ts} +0 -0
@@ -0,0 +1,24 @@
1
+ import { Effect } from "effect";
2
+ import * as SqlClient from "effect/unstable/sql/SqlClient";
3
+
4
+ /** Additive storage owned by this adapter; creation participates in its version transaction. */
5
+ export const createMessageDeliveryTables = Effect.gen(function* () {
6
+ const sql = yield* SqlClient.SqlClient;
7
+
8
+ yield* sql`
9
+ CREATE TABLE effect_agent_message_deliveries (
10
+ owner_thread_id TEXT NOT NULL,
11
+ message_id TEXT NOT NULL,
12
+ version INTEGER NOT NULL,
13
+ state TEXT NOT NULL,
14
+ deadline_at_millis INTEGER,
15
+ record_json TEXT NOT NULL,
16
+ PRIMARY KEY (owner_thread_id, message_id)
17
+ )
18
+ `.withoutTransform;
19
+ yield* sql`
20
+ CREATE INDEX effect_agent_message_deliveries_due
21
+ ON effect_agent_message_deliveries (deadline_at_millis, owner_thread_id, message_id)
22
+ WHERE deadline_at_millis IS NOT NULL
23
+ `.withoutTransform;
24
+ });
@@ -1,36 +1,58 @@
1
1
  import { SqliteMigrator } from "@effect/sql-sqlite-do";
2
2
  import { Effect } from "effect";
3
+ import { createMessageDeliveryPendingIndex } from "effect-agent/sql-message-delivery-store";
4
+ import { createNativeReadIndexes } from "effect-agent/sql-thread-native-reads";
3
5
  import * as SqlClient from "effect/unstable/sql/SqlClient";
4
6
 
5
- /**
6
- * The exact-or-fresh storage version recorded in `effect_agent_meta`. Cloudflare is a fresh
7
- * platform, so there is exactly ONE migration carrying the complete current schema — no
8
- * v1→v4 history to replay (deployment spec §9: no rolling data-version promise during
9
- * private development).
10
- */
11
- export const CurrentDoStorageVersion = 1;
7
+ import { createMessageDeliveryTables } from "./message-delivery-schema.ts";
8
+ import { createRecoveryCheckpointTable } from "./recovery-checkpoint-schema.ts";
9
+
10
+ /** The current storage version recorded in `effect_agent_meta`. */
11
+ export const CurrentDoStorageVersion = 9;
12
+
13
+ /** One permanent destination inbox fence, including workers stopped before admission. */
14
+ export const createWorkerStops = Effect.gen(function* () {
15
+ const sql = yield* SqlClient.SqlClient;
16
+
17
+ yield* sql`CREATE TABLE effect_agent_worker_stops (thread_id TEXT PRIMARY KEY NOT NULL, terminal TEXT)`;
18
+ yield* sql`CREATE INDEX effect_agent_worker_starts ON effect_agent_message_deliveries(owner_thread_id,
19
+ json_extract(record_json, '$.envelope.workerAdmission.origin.worker.delegationId'),
20
+ json_extract(record_json, '$.envelope.workerAdmission.origin.worker.targetAgentId'), message_id)
21
+ WHERE message_id = json_extract(record_json, '$.envelope.workerAdmission.origin.firstMessageId')`;
22
+ yield* sql`CREATE INDEX effect_agent_worker_pending ON effect_agent_message_deliveries(owner_thread_id,
23
+ json_extract(record_json, '$.envelope.workerAdmission.origin.worker.threadId'), message_id)
24
+ WHERE state IN ('pending', 'parked') AND json_extract(record_json, '$.receipt') IS NULL`;
25
+ yield* sql`CREATE INDEX effect_agent_worker_execution ON effect_agent_canonical_records(thread_id,
26
+ json_extract(record_json, '$.payload._tag'), sequence) WHERE json_extract(record_json, '$.payload.runId') IS NOT NULL`;
27
+ });
28
+
29
+ /** Index only outstanding obligations, ordered by the recovery scan's stable cursor. */
30
+ export const createNonterminalIndex = Effect.gen(function* () {
31
+ const sql = yield* SqlClient.SqlClient;
32
+
33
+ yield* sql`CREATE INDEX effect_agent_submissions_nonterminal ON effect_agent_submissions (thread_id, queue_sequence) WHERE state <> 'settled'`
34
+ .withoutTransform;
35
+ });
12
36
 
13
37
  /**
14
- * The Conversation Durable Object schema. Table names and columns mirror the Node/SQLite v4
15
- * schema byte-for-byte (`packages/storage-sqlite/src/migrations.ts`, migrations 1–4 collapsed
16
- * into their final shape) so the shared conformance suites and crash-matrix rows address
17
- * identical durable state. Two DC-specific additions:
38
+ * The Thread Durable Object schema shares its thread and ledger tables with Node/SQLite.
39
+ * Schedules and subscriptions use separate Durable Objects. Two DC-specific additions:
18
40
  *
19
41
  * 1. `effect_agent_meta` replaces `PRAGMA user_version` as the exact-or-fresh version gate —
20
42
  * a meta table is portable regardless of which PRAGMAs Durable Object SQL storage allows.
21
43
  * 2. `effect_agent_child_settlements` is the durable cross-store notification marker the
22
44
  * SubmissionLedger port contract mandates for cross-store adapters (`suspend`'s covering
23
- * check and `recordChildSettled`'s wake both consult it): parent and child Conversations
45
+ * check and `recordChildSettled`'s wake both consult it): parent and child Threads
24
46
  * live in different Durable Objects, so a child settlement reported before the parent's
25
47
  * suspend commits must be observable from the PARENT's own storage.
26
48
  */
27
49
  export const doMigrations = SqliteMigrator.fromRecord({
28
- "1_current_cloudflare_conversation_object": Effect.gen(function* () {
50
+ "1_current_cloudflare_thread_object": Effect.gen(function* () {
29
51
  const sql = yield* SqlClient.SqlClient;
30
52
 
31
53
  yield* sql`
32
- CREATE TABLE effect_agent_conversations (
33
- conversation_id TEXT PRIMARY KEY NOT NULL,
54
+ CREATE TABLE effect_agent_threads (
55
+ thread_id TEXT PRIMARY KEY NOT NULL,
34
56
  created_at TEXT NOT NULL,
35
57
  tail_sequence INTEGER NOT NULL,
36
58
  tail_digest TEXT NOT NULL,
@@ -40,59 +62,59 @@ export const doMigrations = SqliteMigrator.fromRecord({
40
62
 
41
63
  yield* sql`
42
64
  CREATE TABLE effect_agent_canonical_batches (
43
- conversation_id TEXT NOT NULL,
65
+ thread_id TEXT NOT NULL,
44
66
  batch_id TEXT NOT NULL,
45
67
  first_sequence INTEGER NOT NULL,
46
68
  last_sequence INTEGER NOT NULL,
47
69
  batch_digest TEXT NOT NULL,
48
70
  tail_digest TEXT NOT NULL,
49
71
  batch_json TEXT NOT NULL,
50
- PRIMARY KEY (conversation_id, batch_id),
51
- FOREIGN KEY (conversation_id)
52
- REFERENCES effect_agent_conversations(conversation_id)
72
+ PRIMARY KEY (thread_id, batch_id),
73
+ FOREIGN KEY (thread_id)
74
+ REFERENCES effect_agent_threads(thread_id)
53
75
  ON DELETE RESTRICT
54
76
  )
55
77
  `.withoutTransform;
56
78
 
57
79
  yield* sql`
58
80
  CREATE TABLE effect_agent_canonical_records (
59
- conversation_id TEXT NOT NULL,
81
+ thread_id TEXT NOT NULL,
60
82
  sequence INTEGER NOT NULL,
61
83
  record_id TEXT NOT NULL,
62
84
  batch_id TEXT NOT NULL,
63
85
  record_json TEXT NOT NULL,
64
- PRIMARY KEY (conversation_id, sequence),
65
- UNIQUE (conversation_id, record_id),
66
- FOREIGN KEY (conversation_id, batch_id)
67
- REFERENCES effect_agent_canonical_batches(conversation_id, batch_id)
86
+ PRIMARY KEY (thread_id, sequence),
87
+ UNIQUE (thread_id, record_id),
88
+ FOREIGN KEY (thread_id, batch_id)
89
+ REFERENCES effect_agent_canonical_batches(thread_id, batch_id)
68
90
  ON DELETE RESTRICT
69
91
  )
70
92
  `.withoutTransform;
71
93
 
72
94
  yield* sql`
73
95
  CREATE INDEX effect_agent_canonical_records_batch
74
- ON effect_agent_canonical_records (conversation_id, batch_id, sequence)
96
+ ON effect_agent_canonical_records (thread_id, batch_id, sequence)
75
97
  `.withoutTransform;
76
98
 
77
99
  yield* sql`
78
100
  CREATE TABLE effect_agent_checkpoints (
79
- conversation_id TEXT NOT NULL,
101
+ thread_id TEXT NOT NULL,
80
102
  through_sequence INTEGER NOT NULL,
81
103
  tail_digest TEXT NOT NULL,
82
104
  checkpoint_json TEXT NOT NULL,
83
- PRIMARY KEY (conversation_id, through_sequence),
84
- FOREIGN KEY (conversation_id)
85
- REFERENCES effect_agent_conversations(conversation_id)
105
+ PRIMARY KEY (thread_id, through_sequence),
106
+ FOREIGN KEY (thread_id)
107
+ REFERENCES effect_agent_threads(thread_id)
86
108
  ON DELETE RESTRICT
87
109
  )
88
110
  `.withoutTransform;
89
111
 
90
- // Admission rows exist before Conversation materialization (durability §4), so
91
- // conversation_id intentionally carries no foreign key into effect_agent_conversations.
112
+ // Admission rows exist before Thread materialization (durability §4), so
113
+ // thread_id intentionally carries no foreign key into effect_agent_threads.
92
114
  yield* sql`
93
115
  CREATE TABLE effect_agent_submissions (
94
116
  submission_id TEXT PRIMARY KEY NOT NULL,
95
- conversation_id TEXT NOT NULL,
117
+ thread_id TEXT NOT NULL,
96
118
  queue_sequence INTEGER NOT NULL,
97
119
  principal TEXT NOT NULL,
98
120
  idempotency_key TEXT NOT NULL,
@@ -115,8 +137,12 @@ export const doMigrations = SqliteMigrator.fromRecord({
115
137
  unknown_tool_call_ids_json TEXT,
116
138
  parent_submission_id TEXT,
117
139
  parent_tool_call_id TEXT,
118
- UNIQUE (conversation_id, principal, idempotency_key),
119
- UNIQUE (conversation_id, queue_sequence)
140
+ admission_group TEXT,
141
+ admission_fence_json TEXT,
142
+ worker_admission_json TEXT,
143
+ message_admission_json TEXT,
144
+ UNIQUE (thread_id, principal, idempotency_key),
145
+ UNIQUE (thread_id, queue_sequence)
120
146
  )
121
147
  `.withoutTransform;
122
148
 
@@ -130,6 +156,11 @@ export const doMigrations = SqliteMigrator.fromRecord({
130
156
  ON effect_agent_submissions (parent_submission_id)
131
157
  `.withoutTransform;
132
158
 
159
+ yield* sql`
160
+ CREATE INDEX effect_agent_submissions_group
161
+ ON effect_agent_submissions (thread_id, admission_group, state)
162
+ `.withoutTransform;
163
+
133
164
  yield* sql`
134
165
  CREATE TABLE effect_agent_submission_ownership (
135
166
  submission_id TEXT PRIMARY KEY NOT NULL,
@@ -148,7 +179,7 @@ export const doMigrations = SqliteMigrator.fromRecord({
148
179
  CREATE TABLE effect_agent_attempts (
149
180
  attempt_id TEXT PRIMARY KEY NOT NULL,
150
181
  submission_id TEXT NOT NULL,
151
- conversation_id TEXT NOT NULL,
182
+ thread_id TEXT NOT NULL,
152
183
  owner_producer_id TEXT NOT NULL,
153
184
  producer_epoch INTEGER NOT NULL,
154
185
  claimed_at TEXT NOT NULL,
@@ -252,6 +283,12 @@ export const doMigrations = SqliteMigrator.fromRecord({
252
283
  )
253
284
  `.withoutTransform;
254
285
 
286
+ yield* createNativeReadIndexes;
287
+ yield* createNonterminalIndex;
288
+ yield* createMessageDeliveryTables;
289
+ yield* createMessageDeliveryPendingIndex;
290
+ yield* createRecoveryCheckpointTable;
291
+ yield* createWorkerStops;
255
292
  yield* sql`
256
293
  CREATE TABLE effect_agent_meta (
257
294
  key TEXT PRIMARY KEY NOT NULL,
@@ -0,0 +1,17 @@
1
+ import { Effect } from "effect";
2
+ import * as SqlClient from "effect/unstable/sql/SqlClient";
3
+
4
+ /** One disposable recovery snapshot per Thread, independent of generic projections. */
5
+ export const createRecoveryCheckpointTable = Effect.gen(function* () {
6
+ const sql = yield* SqlClient.SqlClient;
7
+
8
+ yield* sql`
9
+ CREATE TABLE effect_agent_recovery_checkpoints (
10
+ thread_id TEXT PRIMARY KEY NOT NULL,
11
+ through_sequence INTEGER NOT NULL,
12
+ tail_digest TEXT NOT NULL,
13
+ checkpoint_json TEXT NOT NULL,
14
+ FOREIGN KEY (thread_id) REFERENCES effect_agent_threads(thread_id) ON DELETE RESTRICT
15
+ )
16
+ `.withoutTransform;
17
+ });