@effect-agent/storage-cloudflare 0.1.0-beta.12 → 0.1.0-beta.121
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/DoMemoryStore.d.mts +29 -0
- package/dist/DoMemoryStore.mjs +55 -0
- package/dist/DoMemoryStore.mjs.map +1 -0
- package/dist/DoMessageDeliveryStore.d.mts +17 -0
- package/dist/DoMessageDeliveryStore.mjs +32 -0
- package/dist/DoMessageDeliveryStore.mjs.map +1 -0
- package/dist/DoScheduleStore.d.mts +36 -0
- package/dist/DoScheduleStore.mjs +388 -0
- package/dist/DoScheduleStore.mjs.map +1 -0
- package/dist/DoStorageConfig.d.mts +45 -0
- package/dist/DoStorageConfig.mjs +52 -0
- package/dist/DoStorageConfig.mjs.map +1 -0
- package/dist/DoStorageError-DjpuLHmX.d.mts +101 -0
- package/dist/DoStorageError.d.mts +2 -0
- package/dist/DoStorageError.mjs +167 -0
- package/dist/DoStorageError.mjs.map +1 -0
- package/dist/DoStorageFailpoint.d.mts +17 -0
- package/dist/DoStorageFailpoint.mjs +14 -0
- package/dist/DoStorageFailpoint.mjs.map +1 -0
- package/dist/DoStorageFailpointTesting.d.mts +33 -0
- package/dist/DoStorageFailpointTesting.mjs +35 -0
- package/dist/DoStorageFailpointTesting.mjs.map +1 -0
- package/dist/DoStorageVersion-DJwZzqel.d.mts +12 -0
- package/dist/DoStorageVersion.d.mts +2 -0
- package/dist/DoStorageVersion.mjs +8 -0
- package/dist/DoStorageVersion.mjs.map +1 -0
- package/dist/DoSubmissionLedger.d.mts +23 -0
- package/dist/DoSubmissionLedger.mjs +1939 -0
- package/dist/DoSubmissionLedger.mjs.map +1 -0
- package/dist/DoSubscriptionStore.d.mts +25 -0
- package/dist/DoSubscriptionStore.mjs +183 -0
- package/dist/DoSubscriptionStore.mjs.map +1 -0
- package/dist/DoThreadStore.d.mts +59 -0
- package/dist/DoThreadStore.mjs +499 -0
- package/dist/DoThreadStore.mjs.map +1 -0
- package/dist/MemoryProtocol.d.mts +38160 -0
- package/dist/MemoryProtocol.mjs +219 -0
- package/dist/MemoryProtocol.mjs.map +1 -0
- package/dist/PortProtocol.d.mts +5521 -0
- package/dist/PortProtocol.mjs +206 -0
- package/dist/PortProtocol.mjs.map +1 -0
- package/dist/PortRouting.d.mts +86 -0
- package/dist/PortRouting.mjs +461 -0
- package/dist/PortRouting.mjs.map +1 -0
- package/dist/do-journal-D65Iuln6.mjs +1119 -0
- package/dist/do-journal-D65Iuln6.mjs.map +1 -0
- package/dist/index.d.mts +14 -1525
- package/dist/index.mjs +14 -3695
- package/dist/migrations-Br6QqMIf.mjs +306 -0
- package/dist/migrations-Br6QqMIf.mjs.map +1 -0
- package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
- package/package.json +1 -45
- package/src/DoMemoryStore.ts +56 -0
- package/src/DoMessageDeliveryStore.ts +53 -0
- package/src/DoScheduleStore.ts +622 -0
- package/src/{errors.ts → DoStorageError.ts} +13 -3
- package/src/DoStorageFailpoint.ts +20 -0
- package/src/{do-storage-failpoint.ts → DoStorageFailpointTesting.ts} +5 -18
- package/src/DoStorageVersion.ts +2 -0
- package/src/{do-ledger.ts → DoSubmissionLedger.ts} +1119 -262
- package/src/DoSubscriptionStore.ts +329 -0
- package/src/DoThreadStore.ts +1064 -0
- package/src/MemoryProtocol.ts +351 -0
- package/src/{port-protocol.ts → PortProtocol.ts} +103 -38
- package/src/{routing.ts → PortRouting.ts} +440 -264
- package/src/index.ts +13 -32
- package/src/internal/do-journal.ts +1789 -0
- package/src/internal/message-delivery-schema.ts +24 -0
- package/src/{migrations.ts → internal/migrations.ts} +72 -35
- package/src/internal/recovery-checkpoint-schema.ts +17 -0
- package/dist/index.mjs.map +0 -1
- package/src/do-conversation-store.ts +0 -850
- package/src/do-journal.ts +0 -1078
- /package/src/{do-storage-config.ts → DoStorageConfig.ts} +0 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { Clock, Context, Effect, Schema } from "effect";
|
|
2
|
+
import * as MemoryNamespace from "effect-agent/memory-namespace";
|
|
3
|
+
import { MemoryLookup, MemoryRecallError, MemoryRecallLimits } from "effect-agent/memory-reference";
|
|
4
|
+
import { MemoryAccess, revalidateMemoryLookup } from "effect-agent/memory-revalidation";
|
|
5
|
+
import {
|
|
6
|
+
MemoryKey,
|
|
7
|
+
MemoryReader,
|
|
8
|
+
MemoryConflict,
|
|
9
|
+
MemoryDocument,
|
|
10
|
+
MemoryMutationFailure,
|
|
11
|
+
MemoryOperationConflict,
|
|
12
|
+
MemoryStorageError,
|
|
13
|
+
MemoryWithdrawn,
|
|
14
|
+
MemoryWrite,
|
|
15
|
+
MemoryWriter,
|
|
16
|
+
} from "effect-agent/memory-store";
|
|
17
|
+
import {
|
|
18
|
+
MemoryIndexSearch,
|
|
19
|
+
MemoryIndexError,
|
|
20
|
+
SemanticMemoryProfile,
|
|
21
|
+
} from "effect-agent/semantic-memory-index";
|
|
22
|
+
import {
|
|
23
|
+
SemanticMemoryError,
|
|
24
|
+
SemanticCandidateLimits,
|
|
25
|
+
SemanticCandidateResult,
|
|
26
|
+
revalidateSemanticMemoryCandidates,
|
|
27
|
+
} from "effect-agent/semantic-memory-revalidation";
|
|
28
|
+
import { Principal } from "effect-agent/submission-ledger";
|
|
29
|
+
|
|
30
|
+
export class MemoryRpcError extends Schema.TaggedError<MemoryRpcError>()("MemoryRpcError", {
|
|
31
|
+
reason: Schema.Literals(["denied", "protocol", "budget", "timeout", "unavailable"]),
|
|
32
|
+
}) {}
|
|
33
|
+
|
|
34
|
+
export class MemoryRpcLimits extends Schema.Class<MemoryRpcLimits>(
|
|
35
|
+
"@effect-agent/storage-cloudflare/MemoryRpcLimits",
|
|
36
|
+
)({
|
|
37
|
+
maxRequestBytes: Schema.Int.check(Schema.isBetween({ minimum: 256, maximum: 4_194_304 })),
|
|
38
|
+
maxResponseBytes: Schema.Int.check(Schema.isBetween({ minimum: 256, maximum: 16_777_216 })),
|
|
39
|
+
maxSourceBytes: Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: 67_108_864 })),
|
|
40
|
+
maxSources: MemoryRecallLimits.fields.maxSources,
|
|
41
|
+
timeoutMillis: MemoryRecallLimits.fields.timeoutMillis,
|
|
42
|
+
}) {}
|
|
43
|
+
|
|
44
|
+
export const defaultMemoryRpcLimits = MemoryRpcLimits.make({
|
|
45
|
+
maxRequestBytes: 1_048_576,
|
|
46
|
+
maxResponseBytes: 4_194_304,
|
|
47
|
+
maxSourceBytes: 16_777_216,
|
|
48
|
+
maxSources: 16,
|
|
49
|
+
timeoutMillis: 10_000,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const RequestFields = {
|
|
53
|
+
version: Schema.Literal(1),
|
|
54
|
+
access: MemoryAccess.Wire,
|
|
55
|
+
/** Host-authenticated identity, never copied from model input. The owner still authorizes it. */
|
|
56
|
+
principal: Principal,
|
|
57
|
+
deadlineMillis: Schema.Finite.check(Schema.isGreaterThanOrEqualTo(0)),
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const RevalidateRequest = Schema.TaggedStruct("Revalidate", {
|
|
61
|
+
...RequestFields,
|
|
62
|
+
lookup: MemoryLookup,
|
|
63
|
+
limits: MemoryRecallLimits,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const ChangeRequest = Schema.TaggedStruct("Change", { ...RequestFields, write: MemoryWrite.Wire });
|
|
67
|
+
|
|
68
|
+
const GetRequest = Schema.TaggedStruct("Get", { ...RequestFields, key: MemoryKey.Wire });
|
|
69
|
+
|
|
70
|
+
const SemanticRequest: Schema.TaggedStruct<
|
|
71
|
+
"RevalidateSemantic",
|
|
72
|
+
typeof RequestFields & {
|
|
73
|
+
readonly found: typeof MemoryIndexSearch.Wire;
|
|
74
|
+
readonly profile: typeof SemanticMemoryProfile;
|
|
75
|
+
readonly limits: typeof SemanticCandidateLimits;
|
|
76
|
+
}
|
|
77
|
+
> = Schema.TaggedStruct("RevalidateSemantic", {
|
|
78
|
+
...RequestFields,
|
|
79
|
+
found: MemoryIndexSearch.Wire,
|
|
80
|
+
profile: SemanticMemoryProfile,
|
|
81
|
+
limits: SemanticCandidateLimits,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export const MemoryOwnerRequest: Schema.Union<
|
|
85
|
+
[typeof RevalidateRequest, typeof ChangeRequest, typeof SemanticRequest, typeof GetRequest]
|
|
86
|
+
> = Schema.Union([RevalidateRequest, ChangeRequest, SemanticRequest, GetRequest]);
|
|
87
|
+
|
|
88
|
+
export type MemoryOwnerRequest = typeof MemoryOwnerRequest.Type;
|
|
89
|
+
|
|
90
|
+
export const MemoryOwnerFailure = Schema.Union([
|
|
91
|
+
MemoryRpcError,
|
|
92
|
+
MemoryStorageError,
|
|
93
|
+
MemoryRecallError,
|
|
94
|
+
MemoryConflict,
|
|
95
|
+
MemoryWithdrawn,
|
|
96
|
+
MemoryOperationConflict,
|
|
97
|
+
MemoryMutationFailure,
|
|
98
|
+
MemoryIndexError,
|
|
99
|
+
SemanticMemoryError,
|
|
100
|
+
]);
|
|
101
|
+
|
|
102
|
+
export type MemoryOwnerFailure = typeof MemoryOwnerFailure.Type;
|
|
103
|
+
|
|
104
|
+
const LookupResponse = Schema.TaggedStruct("Lookup", {
|
|
105
|
+
access: MemoryAccess.Wire,
|
|
106
|
+
lookup: MemoryLookup,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
const ChangedResponse = Schema.TaggedStruct("Changed", {
|
|
110
|
+
access: MemoryAccess.Wire,
|
|
111
|
+
document: MemoryDocument.Wire,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const SemanticResponse = Schema.TaggedStruct("Semantic", {
|
|
115
|
+
access: MemoryAccess.Wire,
|
|
116
|
+
result: SemanticCandidateResult,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const DocumentResponse = Schema.TaggedStruct("Document", {
|
|
120
|
+
access: MemoryAccess.Wire,
|
|
121
|
+
key: MemoryKey.Wire,
|
|
122
|
+
document: Schema.NullOr(MemoryDocument.Wire),
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const FailedResponse = Schema.TaggedStruct("Failed", { failure: MemoryOwnerFailure });
|
|
126
|
+
|
|
127
|
+
export const MemoryOwnerResponse: Schema.Union<
|
|
128
|
+
[
|
|
129
|
+
typeof LookupResponse,
|
|
130
|
+
typeof ChangedResponse,
|
|
131
|
+
typeof SemanticResponse,
|
|
132
|
+
typeof DocumentResponse,
|
|
133
|
+
typeof FailedResponse,
|
|
134
|
+
]
|
|
135
|
+
> = Schema.Union([
|
|
136
|
+
LookupResponse,
|
|
137
|
+
ChangedResponse,
|
|
138
|
+
SemanticResponse,
|
|
139
|
+
DocumentResponse,
|
|
140
|
+
FailedResponse,
|
|
141
|
+
]);
|
|
142
|
+
|
|
143
|
+
export type MemoryOwnerResponse = typeof MemoryOwnerResponse.Type;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Fail-closed application policy. Authorize the namespace, principal, scope, and full command.
|
|
147
|
+
* Get requires exact-key authority, including application source/provenance checks where needed.
|
|
148
|
+
* Possession of a key or scope is not authorization, including for absent or withdrawn documents.
|
|
149
|
+
*/
|
|
150
|
+
export class MemoryOwnerAuthorizer extends Context.Service<
|
|
151
|
+
MemoryOwnerAuthorizer,
|
|
152
|
+
{
|
|
153
|
+
readonly authorize: (request: MemoryOwnerRequest) => Effect.Effect<void, MemoryRpcError>;
|
|
154
|
+
}
|
|
155
|
+
>()("@effect-agent/storage-cloudflare/MemoryOwnerAuthorizer") {}
|
|
156
|
+
|
|
157
|
+
/** Canonical namespace derived from this object's idFromName identity, never its request. */
|
|
158
|
+
export class MemoryOwnerIdentity extends Context.Service<
|
|
159
|
+
MemoryOwnerIdentity,
|
|
160
|
+
{
|
|
161
|
+
readonly namespace: MemoryNamespace.Any;
|
|
162
|
+
}
|
|
163
|
+
>()("@effect-agent/storage-cloudflare/MemoryOwnerIdentity") {}
|
|
164
|
+
|
|
165
|
+
export const memoryWireBytes = (text: string): number => new TextEncoder().encode(text).byteLength;
|
|
166
|
+
|
|
167
|
+
export const decodeMemoryWire = Effect.fn("decodeMemoryWire")(function* <A, I>(
|
|
168
|
+
schema: Schema.Codec<A, I, never>,
|
|
169
|
+
raw: unknown,
|
|
170
|
+
maxBytes: number,
|
|
171
|
+
) {
|
|
172
|
+
const text = yield* Schema.decodeUnknownEffect(Schema.String)(raw).pipe(
|
|
173
|
+
Effect.mapError(() => MemoryRpcError.make({ reason: "protocol" })),
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
if (text.length > maxBytes || memoryWireBytes(text) > maxBytes)
|
|
177
|
+
return yield* MemoryRpcError.make({ reason: "budget" });
|
|
178
|
+
|
|
179
|
+
return yield* Schema.decodeEffect(Schema.fromJsonString(schema))(text).pipe(
|
|
180
|
+
Effect.mapError(() => MemoryRpcError.make({ reason: "protocol" })),
|
|
181
|
+
);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
export const encodeMemoryWire = Effect.fn("encodeMemoryWire")(function* <A, I>(
|
|
185
|
+
schema: Schema.Codec<A, I, never, never>,
|
|
186
|
+
value: A,
|
|
187
|
+
maxBytes: number,
|
|
188
|
+
) {
|
|
189
|
+
const encoded = yield* Schema.encodeEffect(Schema.fromJsonString(schema))(value).pipe(
|
|
190
|
+
Effect.mapError(() => MemoryRpcError.make({ reason: "protocol" })),
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
if (encoded.length > maxBytes || memoryWireBytes(encoded) > maxBytes)
|
|
194
|
+
return yield* MemoryRpcError.make({ reason: "budget" });
|
|
195
|
+
|
|
196
|
+
return encoded;
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
/** One local read for Get, or per distinct candidate source. No discovery or background work. */
|
|
200
|
+
export const handleMemoryOwnerRequest = Effect.fn("MemoryOwner.handleRequest")(function* (
|
|
201
|
+
raw: unknown,
|
|
202
|
+
limits: MemoryRpcLimits = defaultMemoryRpcLimits,
|
|
203
|
+
): Effect.fn.Return<
|
|
204
|
+
string,
|
|
205
|
+
never,
|
|
206
|
+
MemoryOwnerIdentity | MemoryOwnerAuthorizer | MemoryReader | MemoryWriter
|
|
207
|
+
> {
|
|
208
|
+
const result = yield* Effect.gen(function* (): Effect.fn.Return<
|
|
209
|
+
MemoryOwnerResponse,
|
|
210
|
+
MemoryOwnerFailure,
|
|
211
|
+
MemoryOwnerIdentity | MemoryOwnerAuthorizer | MemoryReader | MemoryWriter
|
|
212
|
+
> {
|
|
213
|
+
limits = yield* Schema.decodeEffect(MemoryRpcLimits)(limits).pipe(
|
|
214
|
+
Effect.mapError(() => MemoryRpcError.make({ reason: "protocol" })),
|
|
215
|
+
);
|
|
216
|
+
const request = yield* decodeMemoryWire(MemoryOwnerRequest, raw, limits.maxRequestBytes);
|
|
217
|
+
const { namespace } = yield* MemoryOwnerIdentity;
|
|
218
|
+
|
|
219
|
+
if (
|
|
220
|
+
!MemoryNamespace.equals(namespace, request.access.namespace) ||
|
|
221
|
+
(request._tag === "Get" && !MemoryNamespace.equals(namespace, request.key.namespace)) ||
|
|
222
|
+
(request._tag === "Change" &&
|
|
223
|
+
!MemoryNamespace.equals(namespace, request.write.key.namespace)) ||
|
|
224
|
+
(request._tag === "RevalidateSemantic" &&
|
|
225
|
+
request.found.candidates.some(
|
|
226
|
+
(candidate) => !MemoryNamespace.equals(namespace, candidate.key.namespace),
|
|
227
|
+
))
|
|
228
|
+
)
|
|
229
|
+
return yield* MemoryRpcError.make({ reason: "denied" });
|
|
230
|
+
|
|
231
|
+
const remaining = Math.min(
|
|
232
|
+
limits.timeoutMillis,
|
|
233
|
+
request.deadlineMillis - (yield* Clock.currentTimeMillis),
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
if (remaining <= 0) return yield* MemoryRpcError.make({ reason: "timeout" });
|
|
237
|
+
|
|
238
|
+
return yield* Effect.gen(function* (): Effect.fn.Return<
|
|
239
|
+
MemoryOwnerResponse,
|
|
240
|
+
MemoryOwnerFailure,
|
|
241
|
+
MemoryOwnerAuthorizer | MemoryReader | MemoryWriter
|
|
242
|
+
> {
|
|
243
|
+
const authorizer = yield* MemoryOwnerAuthorizer;
|
|
244
|
+
|
|
245
|
+
yield* authorizer.authorize(request);
|
|
246
|
+
if (request._tag === "Get") {
|
|
247
|
+
const reader = yield* MemoryReader;
|
|
248
|
+
const current = yield* reader.get(request.key);
|
|
249
|
+
|
|
250
|
+
const document =
|
|
251
|
+
current === null ? null : yield* MemoryDocument.restore(namespace, current);
|
|
252
|
+
|
|
253
|
+
if (document !== null) {
|
|
254
|
+
if (document.key.id !== request.key.id || document.source.id !== request.key.id)
|
|
255
|
+
return yield* MemoryStorageError.make({
|
|
256
|
+
operation: "validate memory read identity",
|
|
257
|
+
reason: "corrupt",
|
|
258
|
+
});
|
|
259
|
+
if (
|
|
260
|
+
document._tag === "ActiveMemoryDocument" &&
|
|
261
|
+
!document.scopes.includes(request.access.scope)
|
|
262
|
+
)
|
|
263
|
+
return yield* MemoryRpcError.make({ reason: "denied" });
|
|
264
|
+
|
|
265
|
+
yield* encodeMemoryWire(MemoryDocument.Wire, document, limits.maxSourceBytes);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return { _tag: "Document", access: request.access, key: request.key, document };
|
|
269
|
+
}
|
|
270
|
+
if (request._tag === "Change") {
|
|
271
|
+
const writer = yield* MemoryWriter;
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
_tag: "Changed",
|
|
275
|
+
access: request.access,
|
|
276
|
+
document: yield* writer.change(request.write),
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
if (request._tag === "RevalidateSemantic") {
|
|
280
|
+
if (
|
|
281
|
+
new Set(request.found.candidates.map((candidate) => candidate.key.id)).size >
|
|
282
|
+
limits.maxSources
|
|
283
|
+
)
|
|
284
|
+
return yield* MemoryRpcError.make({ reason: "budget" });
|
|
285
|
+
|
|
286
|
+
const result = yield* revalidateSemanticMemoryCandidates(
|
|
287
|
+
request.found,
|
|
288
|
+
request.access,
|
|
289
|
+
request.profile,
|
|
290
|
+
{
|
|
291
|
+
...request.limits,
|
|
292
|
+
maxSourceBytes: Math.min(
|
|
293
|
+
limits.maxSourceBytes,
|
|
294
|
+
request.limits.maxSourceBytes ?? 16_777_216,
|
|
295
|
+
),
|
|
296
|
+
maxOutputBytes: Math.min(
|
|
297
|
+
limits.maxResponseBytes,
|
|
298
|
+
request.limits.maxOutputBytes ?? 16_777_216,
|
|
299
|
+
),
|
|
300
|
+
},
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
return { _tag: "Semantic", access: request.access, result };
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const count =
|
|
307
|
+
request.lookup._tag === "Found"
|
|
308
|
+
? new Set(request.lookup.passages.map((passage) => passage.source.id)).size
|
|
309
|
+
: 0;
|
|
310
|
+
|
|
311
|
+
if (count > Math.min(limits.maxSources, request.limits.maxSources))
|
|
312
|
+
return yield* MemoryRpcError.make({ reason: "budget" });
|
|
313
|
+
|
|
314
|
+
const lookup = yield* revalidateMemoryLookup(request.lookup, request.access, {
|
|
315
|
+
maxSourceBytes: limits.maxSourceBytes,
|
|
316
|
+
maxInputBytes: Math.min(limits.maxSourceBytes, request.limits.maxInputBytes ?? 16_777_216),
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
return { _tag: "Lookup", access: request.access, lookup };
|
|
320
|
+
}).pipe(
|
|
321
|
+
Effect.scoped,
|
|
322
|
+
Effect.timeoutOrElse({
|
|
323
|
+
duration: remaining,
|
|
324
|
+
orElse: () => Effect.fail(MemoryRpcError.make({ reason: "timeout" })),
|
|
325
|
+
}),
|
|
326
|
+
);
|
|
327
|
+
}).pipe(
|
|
328
|
+
Effect.flatMap((response) =>
|
|
329
|
+
encodeMemoryWire(MemoryOwnerResponse, response, limits.maxResponseBytes),
|
|
330
|
+
),
|
|
331
|
+
Effect.result,
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
if (result._tag === "Success") return result.success;
|
|
335
|
+
|
|
336
|
+
return yield* encodeMemoryWire(
|
|
337
|
+
MemoryOwnerResponse,
|
|
338
|
+
{
|
|
339
|
+
_tag: "Failed",
|
|
340
|
+
failure: result.failure,
|
|
341
|
+
},
|
|
342
|
+
limits.maxResponseBytes,
|
|
343
|
+
).pipe(
|
|
344
|
+
Effect.catch(() =>
|
|
345
|
+
Schema.encodeEffect(Schema.fromJsonString(MemoryOwnerResponse))({
|
|
346
|
+
_tag: "Failed",
|
|
347
|
+
failure: MemoryRpcError.make({ reason: "budget" }),
|
|
348
|
+
}).pipe(Effect.orDie),
|
|
349
|
+
),
|
|
350
|
+
);
|
|
351
|
+
});
|
|
@@ -1,25 +1,23 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { ThreadId } from "effect-agent/identifiers";
|
|
3
|
+
import {
|
|
4
|
+
MessageDeliveryError,
|
|
5
|
+
MessageDeliveryPageRequest,
|
|
6
|
+
MessageDeliveryPage,
|
|
7
|
+
} from "effect-agent/message-delivery";
|
|
8
|
+
import { CanonicalRecordEnvelope } from "effect-agent/records";
|
|
1
9
|
import {
|
|
2
10
|
AbortCommand,
|
|
11
|
+
WorkerStopCommand,
|
|
12
|
+
WorkerLedgerState,
|
|
3
13
|
AbortIntent,
|
|
4
14
|
AdmissionConflict,
|
|
15
|
+
AdmissionPolicyError,
|
|
5
16
|
AdmissionRequest,
|
|
6
17
|
AdmissionResolution,
|
|
7
18
|
AdmissionResult,
|
|
8
|
-
AppendConflict,
|
|
9
|
-
AppendResult,
|
|
10
|
-
CanonicalRecordEnvelope,
|
|
11
19
|
ChildSettledNotification,
|
|
12
20
|
ChildSettledOutcome,
|
|
13
|
-
ConversationExport,
|
|
14
|
-
ConversationExportRequest,
|
|
15
|
-
ConversationMaterialization,
|
|
16
|
-
ConversationNotMaterialized,
|
|
17
|
-
ConversationRead,
|
|
18
|
-
ConversationStoreError,
|
|
19
|
-
ConversationTail,
|
|
20
|
-
ConversationTailRequest,
|
|
21
|
-
FenceRejected,
|
|
22
|
-
FencedAppendRequest,
|
|
23
21
|
JoinedToHost,
|
|
24
22
|
LedgerError,
|
|
25
23
|
MarkReadyRequest,
|
|
@@ -27,33 +25,47 @@ import {
|
|
|
27
25
|
SubmissionLookup,
|
|
28
26
|
SubmissionLookupByKey,
|
|
29
27
|
SubmissionSnapshot,
|
|
30
|
-
} from "
|
|
31
|
-
import {
|
|
28
|
+
} from "effect-agent/submission-ledger";
|
|
29
|
+
import {
|
|
30
|
+
AppendConflict,
|
|
31
|
+
AppendResult,
|
|
32
|
+
ThreadExport,
|
|
33
|
+
ThreadPeerCountRequest,
|
|
34
|
+
ThreadExportRequest,
|
|
35
|
+
ThreadMaterialization,
|
|
36
|
+
ThreadNotMaterialized,
|
|
37
|
+
ThreadReadRequest,
|
|
38
|
+
ThreadStoreError,
|
|
39
|
+
ThreadTail,
|
|
40
|
+
ThreadTailRequest,
|
|
41
|
+
FenceRejected,
|
|
42
|
+
FencedAppendRequest,
|
|
43
|
+
} from "effect-agent/thread-store";
|
|
32
44
|
|
|
33
45
|
/**
|
|
34
46
|
* The cross-Durable-Object port protocol (plan §1.3, D-P6-3): Schema request/response/error
|
|
35
|
-
* envelopes for the CLOSED route-capable subset of the
|
|
36
|
-
* Durable Object executes another
|
|
47
|
+
* envelopes for the CLOSED route-capable subset of the thread ports. One Thread's
|
|
48
|
+
* Durable Object executes another Thread's request against its OWN local facets; the
|
|
37
49
|
* envelopes here are the only values that cross the Object boundary, and they are
|
|
38
50
|
* transport-agnostic — native Durable Object JS RPC is the shipped carrier, fetch-with-JSON
|
|
39
51
|
* the documented fallback, and both move the same Schema-encoded JSON.
|
|
40
52
|
*
|
|
41
53
|
* The closed subset is exactly the set of operations the durable coordinator performs against
|
|
42
|
-
* a FOREIGN
|
|
43
|
-
* child-settlement notification, and the child-
|
|
54
|
+
* a FOREIGN Thread (parent/child establishment, status checks, abort propagation,
|
|
55
|
+
* child-settlement notification, and the child-thread store operations used by
|
|
44
56
|
* establishment, `verifySettledChild`, and result projection):
|
|
45
57
|
*
|
|
46
58
|
* - ledger: `admit`, `markReady`, `lookup`, `resolveAdmission`, `requestAbort`,
|
|
47
59
|
* `recordChildSettled`;
|
|
48
60
|
* - store: `materialize`, `append`, `read` (one page), `inspectTail`, `export`.
|
|
49
61
|
*
|
|
50
|
-
* Every other port operation is lane-local
|
|
51
|
-
*
|
|
52
|
-
* instead of
|
|
62
|
+
* Every other port operation is lane-local and has no envelope. A foreign disposable
|
|
63
|
+
* recovery-cache load returns a miss so the caller can replay canonical history. Other
|
|
64
|
+
* foreign operations fail fast and typed instead of widening the distributed surface.
|
|
53
65
|
*
|
|
54
66
|
* Failures cross the boundary as the `PortFailure` union and re-decode on the caller side to
|
|
55
67
|
* the SAME tagged error types the local facet would have produced, so routed calls keep
|
|
56
|
-
* error-tag fidelity. `cause` chains inside `LedgerError`/`
|
|
68
|
+
* error-tag fidelity. `cause` chains inside `LedgerError`/`ThreadStoreError` travel as
|
|
57
69
|
* Schema defects and do not claim instance fidelity across Objects (plan §2.8).
|
|
58
70
|
*/
|
|
59
71
|
|
|
@@ -71,7 +83,7 @@ export const boundPortDiagnostic = (value: string): string =>
|
|
|
71
83
|
/**
|
|
72
84
|
* The envelope itself could not be honored: the receiving Object could not decode the
|
|
73
85
|
* request, or a response could not be encoded/decoded. It never carries port semantics —
|
|
74
|
-
* callers fold it into the operation's base error (`LedgerError`/`
|
|
86
|
+
* callers fold it into the operation's base error (`LedgerError`/`ThreadStoreError`),
|
|
75
87
|
* except `resolveAdmission`, which folds it into `AdmissionIndeterminate` because a
|
|
76
88
|
* non-answer is never proof of absence (SUB-031).
|
|
77
89
|
*/
|
|
@@ -114,6 +126,26 @@ export class LedgerResolveAdmissionCall extends Schema.TaggedClass<LedgerResolve
|
|
|
114
126
|
request: SubmissionLookupByKey,
|
|
115
127
|
}) {}
|
|
116
128
|
|
|
129
|
+
export class LedgerInspectWorkerCall extends Schema.TaggedClass<LedgerInspectWorkerCall>()(
|
|
130
|
+
"LedgerInspectWorker",
|
|
131
|
+
{ request: Schema.Struct({ threadId: ThreadId }) },
|
|
132
|
+
) {}
|
|
133
|
+
|
|
134
|
+
export class LedgerInspectWorkerResult extends Schema.TaggedClass<LedgerInspectWorkerResult>()(
|
|
135
|
+
"LedgerInspectWorkerResult",
|
|
136
|
+
{ state: WorkerLedgerState },
|
|
137
|
+
) {}
|
|
138
|
+
|
|
139
|
+
export class LedgerStopWorkerCall extends Schema.TaggedClass<LedgerStopWorkerCall>()(
|
|
140
|
+
"LedgerStopWorker",
|
|
141
|
+
{ request: WorkerStopCommand },
|
|
142
|
+
) {}
|
|
143
|
+
|
|
144
|
+
export class LedgerStopWorkerResult extends Schema.TaggedClass<LedgerStopWorkerResult>()(
|
|
145
|
+
"LedgerStopWorkerResult",
|
|
146
|
+
{ owned: Schema.Natural },
|
|
147
|
+
) {}
|
|
148
|
+
|
|
117
149
|
/** Routed `SubmissionLedger.requestAbort` — abort propagation across Objects. */
|
|
118
150
|
export class LedgerRequestAbortCall extends Schema.TaggedClass<LedgerRequestAbortCall>(
|
|
119
151
|
"@effect-agent/storage-cloudflare/LedgerRequestAbortCall",
|
|
@@ -128,55 +160,70 @@ export class LedgerRecordChildSettledCall extends Schema.TaggedClass<LedgerRecor
|
|
|
128
160
|
request: ChildSettledNotification,
|
|
129
161
|
}) {}
|
|
130
162
|
|
|
131
|
-
/** Routed `
|
|
163
|
+
/** Routed `ThreadStore.materialize` against the owning Object. */
|
|
132
164
|
export class StoreMaterializeCall extends Schema.TaggedClass<StoreMaterializeCall>(
|
|
133
165
|
"@effect-agent/storage-cloudflare/StoreMaterializeCall",
|
|
134
166
|
)("StoreMaterialize", {
|
|
135
|
-
request:
|
|
167
|
+
request: ThreadMaterialization,
|
|
136
168
|
}) {}
|
|
137
169
|
|
|
138
|
-
/** Routed `
|
|
170
|
+
/** Routed `ThreadStore.append` against the owning Object. */
|
|
139
171
|
export class StoreAppendCall extends Schema.TaggedClass<StoreAppendCall>(
|
|
140
172
|
"@effect-agent/storage-cloudflare/StoreAppendCall",
|
|
141
173
|
)("StoreAppend", {
|
|
142
174
|
request: FencedAppendRequest,
|
|
143
175
|
}) {}
|
|
144
176
|
|
|
145
|
-
/** Routed one-page `
|
|
177
|
+
/** Routed one-page `ThreadStore.read`; the page bound is the request's own `limit`. */
|
|
146
178
|
export class StoreReadPageCall extends Schema.TaggedClass<StoreReadPageCall>(
|
|
147
179
|
"@effect-agent/storage-cloudflare/StoreReadPageCall",
|
|
148
180
|
)("StoreReadPage", {
|
|
149
|
-
request:
|
|
181
|
+
request: ThreadReadRequest,
|
|
150
182
|
}) {}
|
|
151
183
|
|
|
152
|
-
/** Routed `
|
|
184
|
+
/** Routed `ThreadStore.inspectTail` against the owning Object. */
|
|
153
185
|
export class StoreInspectTailCall extends Schema.TaggedClass<StoreInspectTailCall>(
|
|
154
186
|
"@effect-agent/storage-cloudflare/StoreInspectTailCall",
|
|
155
187
|
)("StoreInspectTail", {
|
|
156
|
-
request:
|
|
188
|
+
request: ThreadTailRequest,
|
|
157
189
|
}) {}
|
|
158
190
|
|
|
159
|
-
/** Routed `
|
|
191
|
+
/** Routed `ThreadStore.export` against the owning Object. */
|
|
160
192
|
export class StoreExportCall extends Schema.TaggedClass<StoreExportCall>(
|
|
161
193
|
"@effect-agent/storage-cloudflare/StoreExportCall",
|
|
162
194
|
)("StoreExport", {
|
|
163
|
-
request:
|
|
195
|
+
request: ThreadExportRequest,
|
|
164
196
|
}) {}
|
|
165
197
|
|
|
198
|
+
export class StoreCountPeerMessagesCall extends Schema.TaggedClass<StoreCountPeerMessagesCall>()(
|
|
199
|
+
"StoreCountPeerMessages",
|
|
200
|
+
{ request: ThreadPeerCountRequest },
|
|
201
|
+
) {}
|
|
202
|
+
|
|
203
|
+
export class MessageDeliveryListCall extends Schema.TaggedClass<MessageDeliveryListCall>()(
|
|
204
|
+
"MessageDeliveryList",
|
|
205
|
+
{ request: MessageDeliveryPageRequest },
|
|
206
|
+
) {}
|
|
207
|
+
|
|
166
208
|
/** Every request that may cross a Durable Object boundary — the CLOSED route-capable subset. */
|
|
167
209
|
export const PortRequest = Schema.Union([
|
|
210
|
+
MessageDeliveryListCall,
|
|
168
211
|
LedgerAdmitCall,
|
|
169
212
|
LedgerMarkReadyCall,
|
|
170
213
|
LedgerLookupCall,
|
|
171
214
|
LedgerResolveAdmissionCall,
|
|
172
215
|
LedgerRequestAbortCall,
|
|
216
|
+
LedgerStopWorkerCall,
|
|
217
|
+
LedgerInspectWorkerCall,
|
|
173
218
|
LedgerRecordChildSettledCall,
|
|
174
219
|
StoreMaterializeCall,
|
|
175
220
|
StoreAppendCall,
|
|
176
221
|
StoreReadPageCall,
|
|
177
222
|
StoreInspectTailCall,
|
|
178
223
|
StoreExportCall,
|
|
224
|
+
StoreCountPeerMessagesCall,
|
|
179
225
|
]);
|
|
226
|
+
|
|
180
227
|
export type PortRequest = typeof PortRequest.Type;
|
|
181
228
|
|
|
182
229
|
/** The wire form of one port request (what a transport actually carries). */
|
|
@@ -241,29 +288,44 @@ export class StoreReadPageResult extends Schema.TaggedClass<StoreReadPageResult>
|
|
|
241
288
|
export class StoreInspectTailResult extends Schema.TaggedClass<StoreInspectTailResult>(
|
|
242
289
|
"@effect-agent/storage-cloudflare/StoreInspectTailResult",
|
|
243
290
|
)("StoreInspectTailResult", {
|
|
244
|
-
tail:
|
|
291
|
+
tail: ThreadTail,
|
|
245
292
|
}) {}
|
|
246
293
|
|
|
247
294
|
export class StoreExportResult extends Schema.TaggedClass<StoreExportResult>(
|
|
248
295
|
"@effect-agent/storage-cloudflare/StoreExportResult",
|
|
249
296
|
)("StoreExportResult", {
|
|
250
|
-
export:
|
|
297
|
+
export: ThreadExport,
|
|
251
298
|
}) {}
|
|
252
299
|
|
|
300
|
+
export class StoreCountPeerMessagesResult extends Schema.TaggedClass<StoreCountPeerMessagesResult>()(
|
|
301
|
+
"StoreCountPeerMessagesResult",
|
|
302
|
+
{ count: Schema.Int.check(Schema.isBetween({ minimum: 0, maximum: 1000 })) },
|
|
303
|
+
) {}
|
|
304
|
+
|
|
305
|
+
export class MessageDeliveryListResult extends Schema.TaggedClass<MessageDeliveryListResult>()(
|
|
306
|
+
"MessageDeliveryListResult",
|
|
307
|
+
{ page: MessageDeliveryPage },
|
|
308
|
+
) {}
|
|
309
|
+
|
|
253
310
|
/** Every successful routed result. Callers narrow by the tag their request implies. */
|
|
254
311
|
export const PortResult = Schema.Union([
|
|
312
|
+
MessageDeliveryListResult,
|
|
255
313
|
LedgerAdmitResult,
|
|
256
314
|
LedgerMarkReadyResult,
|
|
257
315
|
LedgerLookupResult,
|
|
258
316
|
LedgerResolveAdmissionResult,
|
|
259
317
|
LedgerRequestAbortResult,
|
|
318
|
+
LedgerStopWorkerResult,
|
|
319
|
+
LedgerInspectWorkerResult,
|
|
260
320
|
LedgerRecordChildSettledResult,
|
|
261
321
|
StoreMaterializeResult,
|
|
262
322
|
StoreAppendResult,
|
|
263
323
|
StoreReadPageResult,
|
|
264
324
|
StoreInspectTailResult,
|
|
265
325
|
StoreExportResult,
|
|
326
|
+
StoreCountPeerMessagesResult,
|
|
266
327
|
]);
|
|
328
|
+
|
|
267
329
|
export type PortResult = typeof PortResult.Type;
|
|
268
330
|
|
|
269
331
|
// ---------------------------------------------------------------------------
|
|
@@ -273,19 +335,22 @@ export type PortResult = typeof PortResult.Type;
|
|
|
273
335
|
/**
|
|
274
336
|
* Every typed failure a route-capable operation can produce on its owning Object, plus the
|
|
275
337
|
* protocol's own `PortProtocolError`. Members re-decode to the SAME tagged classes the
|
|
276
|
-
*
|
|
338
|
+
* thread ports declare, so a routed caller observes identical error tags and fields.
|
|
277
339
|
*/
|
|
278
340
|
export const PortFailure = Schema.Union([
|
|
341
|
+
MessageDeliveryError,
|
|
279
342
|
AdmissionConflict,
|
|
343
|
+
AdmissionPolicyError,
|
|
280
344
|
SettlementConflict,
|
|
281
345
|
JoinedToHost,
|
|
282
346
|
LedgerError,
|
|
283
|
-
|
|
284
|
-
|
|
347
|
+
ThreadStoreError,
|
|
348
|
+
ThreadNotMaterialized,
|
|
285
349
|
AppendConflict,
|
|
286
350
|
FenceRejected,
|
|
287
351
|
PortProtocolError,
|
|
288
352
|
]);
|
|
353
|
+
|
|
289
354
|
export type PortFailure = typeof PortFailure.Type;
|
|
290
355
|
|
|
291
356
|
/** The routed operation succeeded on its owning Object. */
|