@effect-agent/platform-cloudflare 0.1.0-beta.42 → 0.1.0-beta.45

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 (47) hide show
  1. package/dist/browser-quick-action.mjs.map +1 -1
  2. package/dist/browser-rest-capture.mjs.map +1 -1
  3. package/dist/browser-rest-crawl.mjs.map +1 -1
  4. package/dist/browser-session-lifecycle-DqntvG-Y.d.mts +21 -0
  5. package/dist/browser-session-lifecycle-ZGgb3pnK.mjs +84 -0
  6. package/dist/browser-session-lifecycle-ZGgb3pnK.mjs.map +1 -0
  7. package/dist/index.d.mts +47 -34
  8. package/dist/index.mjs +3 -3
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/interactive-browser.d.mts +1 -18
  11. package/dist/interactive-browser.mjs +2 -81
  12. package/dist/interactive-browser.mjs.map +1 -1
  13. package/dist/{prepared-admission-BKp_Upw2.mjs → prepared-admission-BhW2eT_a.mjs} +3 -3
  14. package/dist/prepared-admission-BhW2eT_a.mjs.map +1 -0
  15. package/dist/protected-browser.d.mts +62 -0
  16. package/dist/protected-browser.mjs +714 -0
  17. package/dist/protected-browser.mjs.map +1 -0
  18. package/dist/scheduling.mjs +1 -1
  19. package/dist/scheduling.mjs.map +1 -1
  20. package/dist/subscriptions.mjs +1 -1
  21. package/dist/subscriptions.mjs.map +1 -1
  22. package/package.json +1 -81
  23. package/src/alarm.ts +277 -242
  24. package/src/bindings.ts +5 -0
  25. package/src/boundary.ts +4 -0
  26. package/src/browser-quick-action.ts +52 -0
  27. package/src/browser-rest-capture.ts +30 -0
  28. package/src/browser-rest-crawl.ts +43 -0
  29. package/src/browser-session-lifecycle.ts +18 -0
  30. package/src/client.ts +40 -0
  31. package/src/code-mode-executor.ts +50 -0
  32. package/src/interactive-browser.ts +176 -0
  33. package/src/layers.ts +13 -3
  34. package/src/memory.ts +42 -3
  35. package/src/prepared-admission.ts +1 -0
  36. package/src/progress-wait.ts +14 -0
  37. package/src/protected-browser/binding.ts +185 -0
  38. package/src/protected-browser/inspect-frame.ts +82 -0
  39. package/src/protected-browser/native.ts +384 -0
  40. package/src/protected-browser/policy.ts +594 -0
  41. package/src/protected-browser.ts +2 -0
  42. package/src/scheduling.ts +34 -0
  43. package/src/subscriptions.ts +50 -0
  44. package/src/thread-object.ts +55 -1
  45. package/src/transport.ts +1 -0
  46. package/src/wake-scheduler.ts +1 -0
  47. package/dist/prepared-admission-BKp_Upw2.mjs.map +0 -1
@@ -47,6 +47,7 @@ const BoundedJobId = Schema.NonEmptyString.check(Schema.isMaxLength(256));
47
47
  const BoundedCursorString = Schema.NonEmptyString.check(Schema.isMaxLength(MAX_CURSOR_LENGTH));
48
48
  // The generated API response Schema says string; the current product example returns a number.
49
49
  const ProviderCursor = Schema.Union([BoundedCursorString, Schema.Natural]);
50
+
50
51
  const ProviderJobStatus = Schema.Literals([
51
52
  "running",
52
53
  "completed",
@@ -55,6 +56,7 @@ const ProviderJobStatus = Schema.Literals([
55
56
  "cancelled_due_to_timeout",
56
57
  "cancelled_due_to_limits",
57
58
  ]);
59
+
58
60
  const ProviderResult = Schema.Struct({
59
61
  id: BoundedJobId,
60
62
  status: ProviderJobStatus,
@@ -65,14 +67,17 @@ const ProviderResult = Schema.Struct({
65
67
  records: Schema.Array(PageCrawlRecord).check(Schema.isMaxLength(MAX_RECORDS_PER_RESPONSE)),
66
68
  cursor: Schema.optionalKey(ProviderCursor),
67
69
  });
70
+
68
71
  const CreateEnvelope = Schema.Struct({
69
72
  success: Schema.Literal(true),
70
73
  result: BoundedJobId,
71
74
  });
75
+
72
76
  const ResultEnvelope = Schema.Struct({
73
77
  success: Schema.Literal(true),
74
78
  result: ProviderResult,
75
79
  });
80
+
76
81
  const DeleteEnvelope = Schema.Struct({
77
82
  success: Schema.Literal(true),
78
83
  result: Schema.Struct({
@@ -91,8 +96,10 @@ const boundedDiagnostic = (message: string): string => message.slice(0, MAX_DIAG
91
96
 
92
97
  const privateCause = (value: unknown, apiToken: Redacted.Redacted<string>): Error | undefined => {
93
98
  const raw = boundedDiagnostic(String(value));
99
+
94
100
  if (raw.length === 0) return undefined;
95
101
  const token = Redacted.value(apiToken);
102
+
96
103
  return new Error(token.length === 0 ? raw : raw.replaceAll(token, "[REDACTED]"));
97
104
  };
98
105
 
@@ -116,6 +123,7 @@ const limitError = (
116
123
  : limit === "total-bytes"
117
124
  ? request.limits.maxTotalBytes
118
125
  : request.limits.deadlineMillis;
126
+
119
127
  return PageCrawlLimitError.make({
120
128
  implementation: browserRestCrawlImplementation,
121
129
  limit,
@@ -129,15 +137,19 @@ const retryAfterMillis = (
129
137
  headers: Readonly<Record<string, string | undefined>>,
130
138
  ): number | undefined => {
131
139
  const seconds = Number(headers["retry-after"]);
140
+
132
141
  if (!Number.isSafeInteger(seconds) || seconds < 0) return undefined;
133
142
  const millis = seconds * 1_000;
143
+
134
144
  return Number.isSafeInteger(millis) ? millis : undefined;
135
145
  };
136
146
 
137
147
  const isJsonResponse = (headers: Readonly<Record<string, string | undefined>>): boolean => {
138
148
  const contentType = headers["content-type"];
149
+
139
150
  if (contentType === undefined) return false;
140
151
  const mediaType = contentType.split(";", 1)[0]?.trim().toLowerCase();
152
+
141
153
  return mediaType === "application/json" || mediaType?.endsWith("+json") === true;
142
154
  };
143
155
 
@@ -153,6 +165,7 @@ const readBoundedResponse = Effect.fn("BrowserRestCrawl.readBoundedResponse")(fu
153
165
  maximum: number,
154
166
  ): Effect.fn.Return<string, PageCrawlProtocolError> {
155
167
  const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: false });
168
+
156
169
  const state = yield* Stream.runFoldEffect<
157
170
  Uint8Array,
158
171
  HttpClientError.HttpClientError,
@@ -165,6 +178,7 @@ const readBoundedResponse = Effect.fn("BrowserRestCrawl.readBoundedResponse")(fu
165
178
  () => ({ observed: 0, text: "" }),
166
179
  (current, chunk) => {
167
180
  const observed = current.observed + chunk.byteLength;
181
+
168
182
  if (observed > maximum) {
169
183
  return Effect.fail(
170
184
  protocolError(
@@ -172,6 +186,7 @@ const readBoundedResponse = Effect.fn("BrowserRestCrawl.readBoundedResponse")(fu
172
186
  ),
173
187
  );
174
188
  }
189
+
175
190
  return Effect.try({
176
191
  try: () => ({ observed, text: current.text + decoder.decode(chunk, { stream: true }) }),
177
192
  catch: (cause) => protocolError("Decoding the Browser Run crawl response failed", cause),
@@ -184,6 +199,7 @@ const readBoundedResponse = Effect.fn("BrowserRestCrawl.readBoundedResponse")(fu
184
199
  : protocolError("Reading the Browser Run crawl response failed", cause),
185
200
  ),
186
201
  );
202
+
187
203
  return yield* Effect.try({
188
204
  try: () => state.text + decoder.decode(),
189
205
  catch: (cause) => protocolError("Decoding the Browser Run crawl response failed", cause),
@@ -195,6 +211,7 @@ const deadlineFailure = Effect.fn("BrowserRestCrawl.deadlineFailure")(function*
195
211
  startedAt: number,
196
212
  ) {
197
213
  const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);
214
+
198
215
  return yield* limitError(request, "deadline", Math.max(0, now - startedAt));
199
216
  });
200
217
 
@@ -206,7 +223,9 @@ const withinDeadline = Effect.fn("BrowserRestCrawl.withinDeadline")(function* <A
206
223
  const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);
207
224
  const elapsed = Math.max(0, now - startedAt);
208
225
  const remaining = request.limits.deadlineMillis - elapsed;
226
+
209
227
  if (remaining <= 0) return yield* limitError(request, "deadline", elapsed);
228
+
210
229
  return yield* effect.pipe(
211
230
  Effect.timeoutOrElse({
212
231
  duration: Duration.millis(remaining),
@@ -221,6 +240,7 @@ const checkDeadline = Effect.fn("BrowserRestCrawl.checkDeadline")(function* (
221
240
  ) {
222
241
  const now = yield* Effect.clockWith((clock) => clock.currentTimeMillis);
223
242
  const elapsed = Math.max(0, now - startedAt);
243
+
224
244
  if (elapsed >= request.limits.deadlineMillis) {
225
245
  return yield* limitError(request, "deadline", elapsed);
226
246
  }
@@ -254,6 +274,7 @@ const makeCrawl =
254
274
  const authorized = HttpClientRequest.bearerToken(request, options.apiToken).pipe(
255
275
  HttpClientRequest.acceptJson,
256
276
  );
277
+
257
278
  const response = yield* client
258
279
  .execute(authorized)
259
280
  .pipe(
@@ -264,9 +285,12 @@ const makeCrawl =
264
285
  ),
265
286
  ),
266
287
  );
288
+
267
289
  const bodyText = yield* readBoundedResponse(response, maximum);
290
+
268
291
  if (response.status === 429) {
269
292
  const reason = isQuotaMessage(bodyText) ? "quota" : "rate";
293
+
270
294
  return yield* PageCrawlRateLimitedError.make({
271
295
  implementation: browserRestCrawlImplementation,
272
296
  reason,
@@ -294,6 +318,7 @@ const makeCrawl =
294
318
  privateCause(bodyText, options.apiToken),
295
319
  );
296
320
  }
321
+
297
322
  return yield* Schema.decodeUnknownEffect(Schema.fromJsonString(schema))(bodyText).pipe(
298
323
  Effect.mapError((cause) =>
299
324
  protocolError(
@@ -322,11 +347,13 @@ const makeCrawl =
322
347
  protocolError("Encoding the Browser Run crawl request failed", cause),
323
348
  ),
324
349
  );
350
+
325
351
  const created = yield* withinDeadline(
326
352
  executeJson(requestWithBody, CreateEnvelope, MAX_CONTROL_RESPONSE_BYTES),
327
353
  input,
328
354
  startedAt,
329
355
  );
356
+
330
357
  return created.result;
331
358
  });
332
359
 
@@ -344,6 +371,7 @@ const makeCrawl =
344
371
  ).pipe(
345
372
  Effect.flatMap((shouldCancel) => {
346
373
  if (!shouldCancel) return Effect.void;
374
+
347
375
  const cancellation = executeJson(
348
376
  HttpClientRequest.delete(endpoint(options, id)),
349
377
  DeleteEnvelope,
@@ -355,6 +383,7 @@ const makeCrawl =
355
383
  : protocolError("Browser Run cancelled a different crawl job"),
356
384
  ),
357
385
  );
386
+
358
387
  return cancellation.pipe(
359
388
  Effect.timeoutOrElse({
360
389
  duration: CANCEL_TIMEOUT,
@@ -373,6 +402,7 @@ const makeCrawl =
373
402
  ),
374
403
  ),
375
404
  );
405
+
376
406
  return { id, state } as const;
377
407
  }),
378
408
  ),
@@ -384,19 +414,23 @@ const makeCrawl =
384
414
  statusOnly: boolean,
385
415
  ) {
386
416
  let request = HttpClientRequest.get(endpoint(options, job.id));
417
+
387
418
  if (statusOnly) request = HttpClientRequest.setUrlParam(request, "limit", "1");
388
419
  if (Option.isSome(cursor)) {
389
420
  request = HttpClientRequest.setUrlParam(request, "cursor", cursor.value);
390
421
  }
422
+
391
423
  // `limit=1` still permits one complete record, so poll GETs use the bounded result cap.
392
424
  const envelope = yield* withinDeadline(
393
425
  executeJson(request, ResultEnvelope, MAX_RESULTS_RESPONSE_BYTES),
394
426
  input,
395
427
  startedAt,
396
428
  );
429
+
397
430
  if (envelope.result.id !== job.id) {
398
431
  return yield* protocolError("Browser Run returned a different crawl job identity");
399
432
  }
433
+
400
434
  return envelope.result;
401
435
  });
402
436
 
@@ -412,6 +446,7 @@ const makeCrawl =
412
446
  ),
413
447
  ).pipe(Effect.tap(() => Ref.set(job.state, "terminal"))),
414
448
  );
449
+
415
450
  if (terminal.status === "running") {
416
451
  return yield* protocolError("Browser Run polling stopped before a terminal status");
417
452
  }
@@ -428,6 +463,7 @@ const makeCrawl =
428
463
  (state) =>
429
464
  Effect.gen(function* () {
430
465
  const result = yield* fetchResult(state.cursor, false);
466
+
431
467
  if (result.status !== "completed") {
432
468
  return yield* protocolError(
433
469
  "Browser Run changed crawl status during result pagination",
@@ -437,12 +473,14 @@ const makeCrawl =
437
473
  return [result.records, Option.none()] as const;
438
474
  }
439
475
  const cursor = normalizedCursor(result.cursor);
476
+
440
477
  if (state.seen.includes(cursor)) {
441
478
  return yield* protocolError("Browser Run repeated a crawl result cursor");
442
479
  }
443
480
  if (state.seen.length >= input.limits.maxPages) {
444
481
  return yield* protocolError("Browser Run returned too many crawl result cursors");
445
482
  }
483
+
446
484
  return [
447
485
  result.records,
448
486
  Option.some({ cursor: Option.some(cursor), seen: [...state.seen, cursor] }),
@@ -458,6 +496,7 @@ const makeCrawl =
458
496
  Effect.gen(function* () {
459
497
  yield* checkDeadline(input, startedAt);
460
498
  const pages = state.pages + 1;
499
+
461
500
  if (pages > input.limits.maxPages) {
462
501
  return yield* limitError(input, "pages", pages);
463
502
  }
@@ -467,17 +506,21 @@ const makeCrawl =
467
506
  if (record.metadata !== undefined && !sameHost(startHost, record.metadata.url)) {
468
507
  return yield* protocolError("Browser Run returned off-host crawl metadata");
469
508
  }
509
+
470
510
  const pageBytes =
471
511
  record.markdown === undefined
472
512
  ? 0
473
513
  : new TextEncoder().encode(record.markdown).byteLength;
514
+
474
515
  if (pageBytes > input.limits.maxPageBytes) {
475
516
  return yield* limitError(input, "page-bytes", pageBytes);
476
517
  }
477
518
  const totalBytes = state.totalBytes + pageBytes;
519
+
478
520
  if (totalBytes > input.limits.maxTotalBytes) {
479
521
  return yield* limitError(input, "total-bytes", totalBytes);
480
522
  }
523
+
481
524
  return [{ pages, totalBytes }, [record]] as const;
482
525
  }),
483
526
  ),
@@ -49,11 +49,13 @@ export class BrowserRunSessionLifecycle extends Context.Service<
49
49
  return yield* new BrowserRunCleanupError({ reason: "configuration" });
50
50
  }
51
51
  const client = yield* HttpClient.HttpClient;
52
+
52
53
  const request = Effect.fn("BrowserRunSessionLifecycle.request")(function* (
53
54
  method: "GET" | "DELETE",
54
55
  sessionId: string,
55
56
  ) {
56
57
  const path = method === "DELETE" ? "browser" : "session";
58
+
57
59
  const response = yield* client
58
60
  .execute(
59
61
  HttpClientRequest.make(method)(
@@ -65,6 +67,7 @@ export class BrowserRunSessionLifecycle extends Context.Service<
65
67
  Effect.provideService(FetchHttpClient.RequestInit, { redirect: "manual" }),
66
68
  Effect.mapError(() => new BrowserRunCleanupError({ reason: "provider" })),
67
69
  );
70
+
68
71
  if (response.status === 401 || response.status === 403)
69
72
  return yield* new BrowserRunCleanupError({
70
73
  reason: "authorization",
@@ -82,6 +85,7 @@ export class BrowserRunSessionLifecycle extends Context.Service<
82
85
  });
83
86
  if (response.headers["content-type"]?.split(";", 1)[0]?.trim() !== "application/json")
84
87
  return yield* new BrowserRunCleanupError({ reason: "malformed" });
88
+
85
89
  const bytes = yield* Stream.runFoldEffect(
86
90
  response.stream,
87
91
  () => new Uint8Array(),
@@ -89,44 +93,57 @@ export class BrowserRunSessionLifecycle extends Context.Service<
89
93
  if (body.byteLength + chunk.byteLength > 16_384)
90
94
  return Effect.fail(new BrowserRunCleanupError({ reason: "malformed" }));
91
95
  const combined = new Uint8Array(body.byteLength + chunk.byteLength);
96
+
92
97
  combined.set(body);
93
98
  combined.set(chunk, body.byteLength);
99
+
94
100
  return Effect.succeed(combined);
95
101
  },
96
102
  ).pipe(Effect.mapError(() => new BrowserRunCleanupError({ reason: "malformed" })));
103
+
97
104
  const body = yield* Effect.try({
98
105
  try: () => new TextDecoder("utf-8", { fatal: true, ignoreBOM: false }).decode(bytes),
99
106
  catch: () => new BrowserRunCleanupError({ reason: "malformed" }),
100
107
  });
108
+
101
109
  if (response.status === 404) {
102
110
  const absent = Schema.decodeUnknownOption(Schema.fromJsonString(Absent))(body, {
103
111
  onExcessProperty: "error",
104
112
  });
113
+
105
114
  if (Option.isSome(absent)) return true;
115
+
106
116
  return yield* new BrowserRunCleanupError({ reason: "malformed" });
107
117
  }
108
118
  if (method === "DELETE") {
109
119
  const result = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(Closed))(
110
120
  body,
111
121
  ).pipe(Effect.mapError(() => new BrowserRunCleanupError({ reason: "malformed" })));
122
+
112
123
  return result.status === "closed";
113
124
  }
125
+
114
126
  const result = yield* Schema.decodeUnknownEffect(Schema.fromJsonString(Metadata))(
115
127
  body,
116
128
  ).pipe(Effect.mapError(() => new BrowserRunCleanupError({ reason: "malformed" })));
129
+
117
130
  if (result.sessionId !== sessionId)
118
131
  return yield* new BrowserRunCleanupError({ reason: "malformed" });
132
+
119
133
  return result.endTime !== undefined && result.endTime > 0;
120
134
  });
135
+
121
136
  const close = Effect.fn("BrowserRunSessionLifecycle.close")(
122
137
  function* (sessionId: Redacted.Redacted<string>) {
123
138
  const id = yield* Schema.decodeUnknownEffect(Identity)(Redacted.value(sessionId)).pipe(
124
139
  Effect.mapError(() => new BrowserRunCleanupError({ reason: "configuration" })),
125
140
  );
141
+
126
142
  if (yield* request("DELETE", id)) return;
127
143
  for (let read = 0; read < 2; read++) {
128
144
  if (yield* request("GET", id)) return;
129
145
  }
146
+
130
147
  return yield* new BrowserRunCleanupError({ reason: "pending" });
131
148
  },
132
149
  Effect.timeoutOrElse({
@@ -135,6 +152,7 @@ export class BrowserRunSessionLifecycle extends Context.Service<
135
152
  }),
136
153
  Effect.withTracerEnabled(false),
137
154
  );
155
+
138
156
  return { close };
139
157
  }),
140
158
  );
package/src/client.ts CHANGED
@@ -156,6 +156,7 @@ export const HostFailure = Schema.Union([
156
156
  OperationDenied,
157
157
  HostProtocolError,
158
158
  ]);
159
+
159
160
  export type HostFailure = typeof HostFailure.Type;
160
161
 
161
162
  export class SubmitSucceeded extends Schema.TaggedClass<SubmitSucceeded>(
@@ -222,6 +223,7 @@ export const HostResponse = Schema.Union([
222
223
  UnknownResolutionRecorded,
223
224
  HostFailed,
224
225
  ]);
226
+
225
227
  export type HostResponse = typeof HostResponse.Type;
226
228
 
227
229
  // ---------------------------------------------------------------------------
@@ -266,18 +268,21 @@ const ClientSubmitHostFailure = Schema.Union([
266
268
  DurableAlarmError,
267
269
  HostProtocolError,
268
270
  ]);
271
+
269
272
  const ClientAwaitHostFailure = Schema.Union([
270
273
  LedgerError,
271
274
  SettlementConflict,
272
275
  OperationDenied,
273
276
  HostProtocolError,
274
277
  ]);
278
+
275
279
  const ClientObserveHostFailure = Schema.Union([
276
280
  ThreadStoreError,
277
281
  ThreadNotMaterialized,
278
282
  OperationDenied,
279
283
  HostProtocolError,
280
284
  ]);
285
+
281
286
  const ClientAbortHostFailure = Schema.Union([
282
287
  OperationDenied,
283
288
  LedgerError,
@@ -287,6 +292,7 @@ const ClientAbortHostFailure = Schema.Union([
287
292
  DurableAlarmError,
288
293
  HostProtocolError,
289
294
  ]);
295
+
290
296
  const ClientApprovalHostFailure = Schema.Union([
291
297
  LedgerError,
292
298
  SettlementConflict,
@@ -295,6 +301,7 @@ const ClientApprovalHostFailure = Schema.Union([
295
301
  DurableAlarmError,
296
302
  HostProtocolError,
297
303
  ]);
304
+
298
305
  const ClientUnknownHostFailure = Schema.Union([
299
306
  LedgerError,
300
307
  SettlementConflict,
@@ -420,9 +427,11 @@ export class CloudflareThreadClient extends Context.Service<
420
427
  // Empty arguments preserve native arity. Passing `undefined` still adds an argument.
421
428
  const traceArgs =
422
429
  rpcTracing === undefined ? [] : yield* RpcTracing.withRpcTraceContext([]);
430
+
423
431
  const raw = yield* Effect.tryPromise({
424
432
  try: () => {
425
433
  const stub = namespace.get(namespace.idFromName(threadId));
434
+
426
435
  return stub[hostRpcMethods[operation]](encoded, ...traceArgs);
427
436
  },
428
437
  catch: (cause) =>
@@ -438,6 +447,7 @@ export class CloudflareThreadClient extends Context.Service<
438
447
  ...cloudflareFailureSignals(cause),
439
448
  }),
440
449
  });
450
+
441
451
  return yield* decodeHostResponse(raw).pipe(
442
452
  Effect.mapError((error): HostProtocolError =>
443
453
  HostProtocolError.make({
@@ -464,11 +474,13 @@ export class CloudflareThreadClient extends Context.Service<
464
474
  ) => {
465
475
  const isExpectedResult = Schema.is(resultSchema);
466
476
  const isExpectedFailure = Schema.is(failureSchema);
477
+
467
478
  return (
468
479
  response: HostResponse,
469
480
  ): Effect.Effect<ResultSchema["Type"], FailureSchema["Type"] | ThreadClientError> => {
470
481
  if (response._tag === "HostFailed") {
471
482
  const failure = response.failure;
483
+
472
484
  return isExpectedFailure(failure)
473
485
  ? Effect.fail(failure)
474
486
  : Effect.fail(outOfContract(threadId, operation, `failure ${failure._tag}`));
@@ -476,6 +488,7 @@ export class CloudflareThreadClient extends Context.Service<
476
488
  if (!isExpectedResult(response)) {
477
489
  return Effect.fail(outOfContract(threadId, operation, `result ${response._tag}`));
478
490
  }
491
+
479
492
  return Effect.succeed(response);
480
493
  };
481
494
  };
@@ -494,6 +507,7 @@ export class CloudflareThreadClient extends Context.Service<
494
507
  : { afterSequence: options.afterSequence }),
495
508
  limit: options?.limit ?? 256,
496
509
  });
510
+
497
511
  const encoded = yield* encodeObservePageRequest(request).pipe(
498
512
  Effect.mapError((error) =>
499
513
  HostProtocolError.make({
@@ -501,13 +515,16 @@ export class CloudflareThreadClient extends Context.Service<
501
515
  }),
502
516
  ),
503
517
  );
518
+
504
519
  const response = yield* call(threadId, "observePage", encoded);
520
+
505
521
  const page = yield* expect(
506
522
  threadId,
507
523
  "observePage",
508
524
  ObservedPage,
509
525
  ClientObserveHostFailure,
510
526
  )(response);
527
+
511
528
  return page.records;
512
529
  });
513
530
 
@@ -533,6 +550,7 @@ export class CloudflareThreadClient extends Context.Service<
533
550
  AgentInputError.make({ message: `Unable to encode Agent input: ${cause.message}` }),
534
551
  ),
535
552
  );
553
+
536
554
  const inputPayload = yield* Schema.decodeUnknownEffect(PersistedJson)(
537
555
  encodedInput,
538
556
  ).pipe(
@@ -542,6 +560,7 @@ export class CloudflareThreadClient extends Context.Service<
542
560
  }),
543
561
  ),
544
562
  );
563
+
545
564
  const request = SubmitRequest.make({
546
565
  agentId: agent.definition.id,
547
566
  principal: options.principal,
@@ -549,6 +568,7 @@ export class CloudflareThreadClient extends Context.Service<
549
568
  definitions: options.definitions,
550
569
  inputPayload,
551
570
  });
571
+
552
572
  const encoded = yield* encodeSubmitRequest(request).pipe(
553
573
  Effect.mapError((error) =>
554
574
  HostProtocolError.make({
@@ -556,13 +576,16 @@ export class CloudflareThreadClient extends Context.Service<
556
576
  }),
557
577
  ),
558
578
  );
579
+
559
580
  const response = yield* call(options.threadId, "submit", encoded);
581
+
560
582
  const succeeded = yield* expect(
561
583
  options.threadId,
562
584
  "submit",
563
585
  SubmitSucceeded,
564
586
  ClientSubmitHostFailure,
565
587
  )(response);
588
+
566
589
  return succeeded.receipt;
567
590
  }),
568
591
 
@@ -575,13 +598,16 @@ export class CloudflareThreadClient extends Context.Service<
575
598
  }),
576
599
  ),
577
600
  );
601
+
578
602
  const response = yield* call(receipt.threadId, "awaitSettlement", encoded);
603
+
579
604
  const settled = yield* expect(
580
605
  receipt.threadId,
581
606
  "awaitSettlement",
582
607
  SettlementReached,
583
608
  ClientAwaitHostFailure,
584
609
  )(response);
610
+
585
611
  return settled.settlement;
586
612
  }),
587
613
 
@@ -596,7 +622,9 @@ export class CloudflareThreadClient extends Context.Service<
596
622
  }),
597
623
  ),
598
624
  );
625
+
599
626
  const request = AwaitProgressRequest.make({ afterSequence, waiterId });
627
+
600
628
  const encoded = yield* encodeAwaitProgressRequest(request).pipe(
601
629
  Effect.mapError((error) =>
602
630
  HostProtocolError.make({
@@ -631,10 +659,13 @@ export class CloudflareThreadClient extends Context.Service<
631
659
  Effect.gen(function* () {
632
660
  const all: Array<CanonicalRecordEnvelope> = [];
633
661
  let after: CanonicalSequence | undefined;
662
+
634
663
  for (;;) {
635
664
  const page = yield* readPage(threadId, { afterSequence: after, limit: 1_024 });
665
+
636
666
  all.push(...page);
637
667
  const last = page.at(-1);
668
+
638
669
  if (page.length < 1_024 || last === undefined) return all;
639
670
  after = last.sequence;
640
671
  }
@@ -649,13 +680,16 @@ export class CloudflareThreadClient extends Context.Service<
649
680
  }),
650
681
  ),
651
682
  );
683
+
652
684
  const response = yield* call(threadId, "abort", encoded);
685
+
653
686
  const recorded = yield* expect(
654
687
  threadId,
655
688
  "abort",
656
689
  AbortRecorded,
657
690
  ClientAbortHostFailure,
658
691
  )(response);
692
+
659
693
  return recorded.intent;
660
694
  }),
661
695
 
@@ -668,13 +702,16 @@ export class CloudflareThreadClient extends Context.Service<
668
702
  }),
669
703
  ),
670
704
  );
705
+
671
706
  const response = yield* call(threadId, "resolveApproval", encoded);
707
+
672
708
  const recorded = yield* expect(
673
709
  threadId,
674
710
  "resolveApproval",
675
711
  ApprovalRecorded,
676
712
  ClientApprovalHostFailure,
677
713
  )(response);
714
+
678
715
  return recorded.intent;
679
716
  }),
680
717
 
@@ -689,13 +726,16 @@ export class CloudflareThreadClient extends Context.Service<
689
726
  }),
690
727
  ),
691
728
  );
729
+
692
730
  const response = yield* call(threadId, "resolveUnknown", encoded);
731
+
693
732
  const recorded = yield* expect(
694
733
  threadId,
695
734
  "resolveUnknown",
696
735
  UnknownResolutionRecorded,
697
736
  ClientUnknownHostFailure,
698
737
  )(response);
738
+
699
739
  return recorded.intent;
700
740
  }),
701
741
  });