@yielded/agent-platform-cloudflare 0.1.0-beta.173 → 0.1.0-beta.175
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/{Alarm-BMEAZo3p.mjs → Alarm-B44efvB1.mjs} +162 -103
- package/dist/Alarm-B44efvB1.mjs.map +1 -0
- package/dist/Alarm.d.mts +2 -0
- package/dist/Alarm.mjs +1 -1
- package/dist/BrowserRestCapture.mjs.map +1 -1
- package/dist/BrowserRestCrawl.mjs.map +1 -1
- package/dist/{BrowserSession-Bx0V1-6_.d.mts → BrowserSession-Cojp7nth.d.mts} +3 -2
- package/dist/{BrowserSession-BfNmyayH.mjs → BrowserSession-aovMjfL4.mjs} +14 -14
- package/dist/BrowserSession-aovMjfL4.mjs.map +1 -0
- package/dist/BrowserSession.d.mts +1 -1
- package/dist/BrowserSession.mjs +2 -2
- package/dist/BrowserUse.d.mts +40 -64
- package/dist/BrowserUse.mjs +223 -2
- package/dist/BrowserUse.mjs.map +1 -0
- package/dist/CloudflareBrowser-Vt8qTdYW.mjs.map +1 -1
- package/dist/CloudflareCodeMode.mjs.map +1 -1
- package/dist/CloudflareScheduling.mjs +9 -9
- package/dist/CloudflareScheduling.mjs.map +1 -1
- package/dist/CloudflareSubscriptions.mjs +15 -15
- package/dist/CloudflareSubscriptions.mjs.map +1 -1
- package/dist/{CloudflareThreadClient-DgZVrZzF.mjs → CloudflareThreadClient-Ai3MTs3X.mjs} +43 -40
- package/dist/CloudflareThreadClient-Ai3MTs3X.mjs.map +1 -0
- package/dist/CloudflareThreadClient.mjs +1 -1
- package/dist/{InteractiveBrowser-LdKzQeLR.mjs → InteractiveBrowser-BHNlwjZL.mjs} +40 -31
- package/dist/InteractiveBrowser-BHNlwjZL.mjs.map +1 -0
- package/dist/InteractiveBrowser.mjs +1 -1
- package/dist/{ThreadObject-CRbLbdXM.d.mts → ThreadObject-CxNlhoPL.d.mts} +3 -3
- package/dist/{ThreadObject-CGIaz6Jv.mjs → ThreadObject-DGvlHWYi.mjs} +50 -52
- package/dist/ThreadObject-DGvlHWYi.mjs.map +1 -0
- package/dist/ThreadObject.d.mts +1 -1
- package/dist/ThreadObject.mjs +1 -1
- package/dist/WakeScheduler.d.mts +1 -1
- package/dist/WakeScheduler.mjs +8 -3
- package/dist/WakeScheduler.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +5 -5
- package/dist/{prepared-admission-CSdzFM_v.mjs → prepared-admission-DYdffQ8K.mjs} +2 -2
- package/dist/{prepared-admission-CSdzFM_v.mjs.map → prepared-admission-DYdffQ8K.mjs.map} +1 -1
- package/package.json +1 -1
- package/src/Alarm.ts +293 -155
- package/src/BrowserRestCapture.ts +1 -0
- package/src/BrowserRestCrawl.ts +1 -0
- package/src/BrowserSession.ts +3 -2
- package/src/BrowserUse.ts +287 -1504
- package/src/CloudflareCodeMode.ts +6 -0
- package/src/CloudflareScheduling.ts +103 -103
- package/src/CloudflareSubscriptions.ts +192 -199
- package/src/CloudflareThreadClient.ts +258 -269
- package/src/InteractiveBrowser.ts +43 -17
- package/src/ThreadObject.ts +51 -45
- package/src/WakeScheduler.ts +12 -9
- package/src/internal/browser-binding.ts +8 -0
- package/src/internal/browser-credentials.ts +18 -13
- package/src/internal/browser-file-selection.ts +13 -2
- package/src/internal/browser-quick-action.ts +1 -0
- package/src/internal/browser-session-lifecycle.ts +32 -36
- package/src/internal/due-queue.ts +38 -19
- package/src/internal/layers.ts +108 -87
- package/src/internal/message-delivery.ts +61 -37
- package/dist/Alarm-BMEAZo3p.mjs.map +0 -1
- package/dist/BrowserSession-BfNmyayH.mjs.map +0 -1
- package/dist/BrowserUse-Bc2JdLW2.mjs +0 -1528
- package/dist/BrowserUse-Bc2JdLW2.mjs.map +0 -1
- package/dist/CloudflareThreadClient-DgZVrZzF.mjs.map +0 -1
- package/dist/InteractiveBrowser-LdKzQeLR.mjs.map +0 -1
- package/dist/ThreadObject-CGIaz6Jv.mjs.map +0 -1
- package/dist/page-function-CmUCcyNP.mjs +0 -11
- package/dist/page-function-CmUCcyNP.mjs.map +0 -1
- package/src/internal/browser-dom.ts +0 -886
- package/src/internal/browser-jev-dom.ts +0 -362
|
@@ -386,23 +386,24 @@ const liveTextProtocolFailure = () =>
|
|
|
386
386
|
message: "Provisional text is incomplete or invalid; discard drafts and read canonical records",
|
|
387
387
|
});
|
|
388
388
|
|
|
389
|
+
const decodeLiveTextFrame = Schema.decodeUnknownSync(Schema.fromJsonString(LiveTextFrame));
|
|
390
|
+
|
|
389
391
|
const decodeLiveText = (
|
|
390
392
|
threadId: ThreadId,
|
|
391
393
|
source: ReadableStream<unknown>,
|
|
392
394
|
): Stream.Stream<LiveTextFrame, HostProtocolError | ThreadClientError> =>
|
|
393
395
|
Stream.suspend(() => {
|
|
394
396
|
const decoder = new TextDecoder("utf-8", { fatal: true, ignoreBOM: false });
|
|
395
|
-
const decode = Schema.decodeUnknownSync(Schema.fromJsonString(LiveTextFrame));
|
|
396
397
|
let pending = "";
|
|
397
398
|
let pendingBytes = 0;
|
|
398
399
|
let expected = 0;
|
|
399
400
|
let streamId: string | undefined;
|
|
400
401
|
const models = new Map<string, { attemptId: string; parts: Set<string> }>();
|
|
401
402
|
|
|
402
|
-
const accept = (frame: LiveTextFrame)
|
|
403
|
+
const accept = Effect.fnUntraced(function* (frame: LiveTextFrame) {
|
|
403
404
|
if (frame._tag === "Reset") {
|
|
404
405
|
if (frame.streamId === streamId || frame.threadId !== threadId)
|
|
405
|
-
|
|
406
|
+
return yield* liveTextProtocolFailure();
|
|
406
407
|
streamId = frame.streamId;
|
|
407
408
|
expected = 1;
|
|
408
409
|
models.clear();
|
|
@@ -416,7 +417,7 @@ const decodeLiveText = (
|
|
|
416
417
|
frame.event.threadId !== threadId ||
|
|
417
418
|
!isBoundedEvent(frame.event)
|
|
418
419
|
)
|
|
419
|
-
|
|
420
|
+
return yield* liveTextProtocolFailure();
|
|
420
421
|
const event = frame.event;
|
|
421
422
|
|
|
422
423
|
if (event._tag === "AttemptEnded") {
|
|
@@ -435,12 +436,12 @@ const decodeLiveText = (
|
|
|
435
436
|
let model = models.get(key);
|
|
436
437
|
|
|
437
438
|
if (event.part.type === "text-start") {
|
|
438
|
-
if (model?.parts.has(event.part.id))
|
|
439
|
+
if (model?.parts.has(event.part.id)) return yield* liveTextProtocolFailure();
|
|
439
440
|
if (
|
|
440
441
|
[...models.values()].reduce((size, value) => size + value.parts.size, 0) >=
|
|
441
442
|
MAX_DRAFT_PARTS
|
|
442
443
|
)
|
|
443
|
-
|
|
444
|
+
return yield* liveTextProtocolFailure();
|
|
444
445
|
if (model === undefined) {
|
|
445
446
|
model = { attemptId: event.attemptId, parts: new Set() };
|
|
446
447
|
models.set(key, model);
|
|
@@ -449,14 +450,14 @@ const decodeLiveText = (
|
|
|
449
450
|
|
|
450
451
|
return true;
|
|
451
452
|
}
|
|
452
|
-
if (!model?.parts.has(event.part.id))
|
|
453
|
+
if (!model?.parts.has(event.part.id)) return yield* liveTextProtocolFailure();
|
|
453
454
|
if (event.part.type === "text-end") {
|
|
454
455
|
model.parts.delete(event.part.id);
|
|
455
456
|
if (model.parts.size === 0) models.delete(key);
|
|
456
457
|
}
|
|
457
458
|
|
|
458
459
|
return true;
|
|
459
|
-
};
|
|
460
|
+
});
|
|
460
461
|
|
|
461
462
|
return Stream.fromReadableStream({
|
|
462
463
|
evaluate: () => source,
|
|
@@ -469,31 +470,35 @@ const decodeLiveText = (
|
|
|
469
470
|
cause,
|
|
470
471
|
}),
|
|
471
472
|
}).pipe(
|
|
472
|
-
Stream.mapEffect(
|
|
473
|
-
Effect.
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
473
|
+
Stream.mapEffect(
|
|
474
|
+
Effect.fnUntraced(function* (chunk) {
|
|
475
|
+
if (!(chunk instanceof Uint8Array)) return yield* liveTextProtocolFailure();
|
|
476
|
+
const frames: LiveTextFrame[] = [];
|
|
477
|
+
|
|
478
|
+
for (let offset = 0; offset < chunk.byteLength;) {
|
|
479
|
+
const newline = chunk.indexOf(10, offset);
|
|
480
|
+
const end = newline < 0 ? chunk.byteLength : newline;
|
|
481
|
+
|
|
482
|
+
pendingBytes += end - offset;
|
|
483
|
+
if (pendingBytes > MAX_FRAME_BYTES) return yield* liveTextProtocolFailure();
|
|
484
|
+
pending += yield* Effect.try({
|
|
485
|
+
try: () => decoder.decode(chunk.subarray(offset, end), { stream: newline < 0 }),
|
|
486
|
+
catch: liveTextProtocolFailure,
|
|
487
|
+
});
|
|
488
|
+
offset = end + 1;
|
|
489
|
+
if (newline < 0) break;
|
|
490
|
+
|
|
491
|
+
const frame = yield* Effect.try({
|
|
492
|
+
try: () => decodeLiveTextFrame(pending),
|
|
493
|
+
catch: liveTextProtocolFailure,
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
pending = "";
|
|
497
|
+
pendingBytes = 0;
|
|
498
|
+
if (yield* accept(frame)) frames.push(frame);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return frames;
|
|
497
502
|
}),
|
|
498
503
|
),
|
|
499
504
|
Stream.flatMap(Stream.fromArray),
|
|
@@ -702,40 +707,37 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
702
707
|
};
|
|
703
708
|
};
|
|
704
709
|
|
|
705
|
-
const readPage = (
|
|
710
|
+
const readPage = Effect.fnUntraced(function* (
|
|
706
711
|
threadId: ThreadId,
|
|
707
712
|
options?: {
|
|
708
713
|
readonly afterSequence?: CanonicalSequence | undefined;
|
|
709
714
|
readonly limit?: number | undefined;
|
|
710
715
|
},
|
|
711
|
-
)
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
: { afterSequence: options.afterSequence }),
|
|
717
|
-
limit: options?.limit ?? 256,
|
|
718
|
-
});
|
|
716
|
+
) {
|
|
717
|
+
const request = ObservePageRequest.make({
|
|
718
|
+
...(options?.afterSequence === undefined ? {} : { afterSequence: options.afterSequence }),
|
|
719
|
+
limit: options?.limit ?? 256,
|
|
720
|
+
});
|
|
719
721
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
722
|
+
const encoded = yield* encodeObservePageRequest(request).pipe(
|
|
723
|
+
Effect.mapError((error) =>
|
|
724
|
+
HostProtocolError.make({
|
|
725
|
+
message: boundHostDiagnostic(`observePage request encode failed: ${error.message}`),
|
|
726
|
+
}),
|
|
727
|
+
),
|
|
728
|
+
);
|
|
727
729
|
|
|
728
|
-
|
|
730
|
+
const response = yield* call(threadId, "observePage", encoded);
|
|
729
731
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
732
|
+
const page = yield* expect(
|
|
733
|
+
threadId,
|
|
734
|
+
"observePage",
|
|
735
|
+
ObservedPage,
|
|
736
|
+
ClientObserveHostFailure,
|
|
737
|
+
)(response);
|
|
736
738
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
+
return page.records;
|
|
740
|
+
});
|
|
739
741
|
|
|
740
742
|
const cancelProgress = (threadId: ThreadId, waiterId: string): Effect.Effect<void> =>
|
|
741
743
|
encodeCancelProgressRequest(CancelProgressRequest.make({ waiterId })).pipe(
|
|
@@ -779,156 +781,149 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
779
781
|
});
|
|
780
782
|
|
|
781
783
|
return CloudflareThreadClient.of({
|
|
782
|
-
submit: <InputSchema extends Schema.Top>(
|
|
784
|
+
submit: Effect.fnUntraced(function* <InputSchema extends Schema.Top>(
|
|
783
785
|
agent: DurableSubmitAgent<InputSchema>,
|
|
784
786
|
input: InputSchema["Type"],
|
|
785
787
|
options: DurableSubmitOptions,
|
|
786
|
-
)
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
);
|
|
788
|
+
) {
|
|
789
|
+
// Client-side half of `DurableAgentRuntime.submit`'s input boundary: encode
|
|
790
|
+
// through the Agent's input schema and prove the canonical persistence bounds.
|
|
791
|
+
const encodedInput = yield* Schema.encodeEffect(agent.definition.input)(input).pipe(
|
|
792
|
+
Effect.mapError((cause) =>
|
|
793
|
+
AgentInputError.make({ message: `Unable to encode Agent input: ${cause.message}` }),
|
|
794
|
+
),
|
|
795
|
+
);
|
|
795
796
|
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
),
|
|
804
|
-
);
|
|
797
|
+
const inputPayload = yield* Schema.decodeUnknownEffect(PersistedJson)(encodedInput).pipe(
|
|
798
|
+
Effect.mapError(() =>
|
|
799
|
+
AgentInputError.make({
|
|
800
|
+
message: "Agent input does not satisfy the canonical persistence bounds",
|
|
801
|
+
}),
|
|
802
|
+
),
|
|
803
|
+
);
|
|
805
804
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
805
|
+
const request = SubmitRequest.make({
|
|
806
|
+
agentId: agent.definition.id,
|
|
807
|
+
principal: options.principal,
|
|
808
|
+
idempotencyKey: options.idempotencyKey,
|
|
809
|
+
...(options.admissionGroup === undefined
|
|
810
|
+
? {}
|
|
811
|
+
: { admissionGroup: options.admissionGroup }),
|
|
812
|
+
...(options.admissionFence === undefined
|
|
813
|
+
? {}
|
|
814
|
+
: { admissionFence: options.admissionFence }),
|
|
815
|
+
...(options.workerAdmission === undefined
|
|
816
|
+
? {}
|
|
817
|
+
: { workerAdmission: options.workerAdmission }),
|
|
818
|
+
...(options.messageAdmission === undefined
|
|
819
|
+
? {}
|
|
820
|
+
: { messageAdmission: options.messageAdmission }),
|
|
821
|
+
definitions: options.definitions,
|
|
822
|
+
inputPayload,
|
|
823
|
+
});
|
|
825
824
|
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
825
|
+
const encoded = yield* encodeSubmitRequest(request).pipe(
|
|
826
|
+
Effect.mapError((error) =>
|
|
827
|
+
HostProtocolError.make({
|
|
828
|
+
message: boundHostDiagnostic(`submit request encode failed: ${error.message}`),
|
|
829
|
+
}),
|
|
830
|
+
),
|
|
831
|
+
);
|
|
832
|
+
|
|
833
|
+
const response = yield* call(options.threadId, "submit", encoded);
|
|
834
|
+
|
|
835
|
+
const succeeded = yield* expect(
|
|
836
|
+
options.threadId,
|
|
837
|
+
"submit",
|
|
838
|
+
SubmitSucceeded,
|
|
839
|
+
ClientSubmitHostFailure,
|
|
840
|
+
)(response);
|
|
833
841
|
|
|
834
|
-
|
|
842
|
+
return succeeded.receipt;
|
|
843
|
+
}),
|
|
835
844
|
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
ClientSubmitHostFailure,
|
|
841
|
-
)(response);
|
|
845
|
+
submissionStatus: Effect.fnUntraced(function* (receipt) {
|
|
846
|
+
const encoded = yield* encodeReceipt(receipt).pipe(
|
|
847
|
+
Effect.mapError(() => HostProtocolError.make({ message: "Invalid receipt" })),
|
|
848
|
+
);
|
|
842
849
|
|
|
843
|
-
|
|
844
|
-
}),
|
|
850
|
+
const response = yield* call(receipt.threadId, "submissionStatus", encoded);
|
|
845
851
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
852
|
+
const result = yield* expect(
|
|
853
|
+
receipt.threadId,
|
|
854
|
+
"submissionStatus",
|
|
855
|
+
SubmissionStatusResponse,
|
|
856
|
+
ClientAwaitHostFailure,
|
|
857
|
+
)(response);
|
|
851
858
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
awaitSettlement: (receipt) =>
|
|
864
|
-
Effect.gen(function* () {
|
|
865
|
-
const response = yield* awaitSettlementCall(receipt, "awaitSettlement");
|
|
866
|
-
|
|
867
|
-
const settled = yield* expect(
|
|
868
|
-
receipt.threadId,
|
|
869
|
-
"awaitSettlement",
|
|
870
|
-
SettlementReached,
|
|
871
|
-
ClientAwaitHostFailure,
|
|
872
|
-
)(response);
|
|
873
|
-
|
|
874
|
-
return settled.settlement;
|
|
875
|
-
}),
|
|
876
|
-
|
|
877
|
-
awaitSettlementRecord: (receipt) =>
|
|
878
|
-
Effect.gen(function* () {
|
|
879
|
-
const response = yield* awaitSettlementCall(receipt, "awaitSettlementRecord");
|
|
880
|
-
|
|
881
|
-
const settled = yield* expect(
|
|
882
|
-
receipt.threadId,
|
|
883
|
-
"awaitSettlementRecord",
|
|
884
|
-
SettlementRecordReached,
|
|
885
|
-
ClientAwaitHostFailure,
|
|
886
|
-
)(response);
|
|
887
|
-
|
|
888
|
-
return settled.record;
|
|
889
|
-
}),
|
|
890
|
-
|
|
891
|
-
awaitProgress: (threadId, afterSequence) =>
|
|
892
|
-
Effect.gen(function* () {
|
|
893
|
-
const waiterId = yield* crypto.randomUUIDv4().pipe(
|
|
894
|
-
Effect.mapError((error) =>
|
|
895
|
-
HostProtocolError.make({
|
|
896
|
-
message: boundHostDiagnostic(
|
|
897
|
-
`awaitProgress cancellation identity generation failed: ${error.message}`,
|
|
898
|
-
),
|
|
899
|
-
}),
|
|
900
|
-
),
|
|
901
|
-
);
|
|
859
|
+
return result.status;
|
|
860
|
+
}),
|
|
861
|
+
awaitSettlement: Effect.fnUntraced(function* (receipt) {
|
|
862
|
+
const response = yield* awaitSettlementCall(receipt, "awaitSettlement");
|
|
863
|
+
|
|
864
|
+
const settled = yield* expect(
|
|
865
|
+
receipt.threadId,
|
|
866
|
+
"awaitSettlement",
|
|
867
|
+
SettlementReached,
|
|
868
|
+
ClientAwaitHostFailure,
|
|
869
|
+
)(response);
|
|
902
870
|
|
|
903
|
-
|
|
871
|
+
return settled.settlement;
|
|
872
|
+
}),
|
|
904
873
|
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
874
|
+
awaitSettlementRecord: Effect.fnUntraced(function* (receipt) {
|
|
875
|
+
const response = yield* awaitSettlementCall(receipt, "awaitSettlementRecord");
|
|
876
|
+
|
|
877
|
+
const settled = yield* expect(
|
|
878
|
+
receipt.threadId,
|
|
879
|
+
"awaitSettlementRecord",
|
|
880
|
+
SettlementRecordReached,
|
|
881
|
+
ClientAwaitHostFailure,
|
|
882
|
+
)(response);
|
|
914
883
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
884
|
+
return settled.record;
|
|
885
|
+
}),
|
|
886
|
+
|
|
887
|
+
awaitProgress: Effect.fnUntraced(function* (threadId, afterSequence) {
|
|
888
|
+
const waiterId = yield* crypto.randomUUIDv4().pipe(
|
|
889
|
+
Effect.mapError((error) =>
|
|
890
|
+
HostProtocolError.make({
|
|
891
|
+
message: boundHostDiagnostic(
|
|
892
|
+
`awaitProgress cancellation identity generation failed: ${error.message}`,
|
|
919
893
|
),
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
894
|
+
}),
|
|
895
|
+
),
|
|
896
|
+
);
|
|
897
|
+
|
|
898
|
+
const request = AwaitProgressRequest.make({ afterSequence, waiterId });
|
|
899
|
+
|
|
900
|
+
const encoded = yield* encodeAwaitProgressRequest(request).pipe(
|
|
901
|
+
Effect.mapError((error) =>
|
|
902
|
+
HostProtocolError.make({
|
|
903
|
+
message: boundHostDiagnostic(
|
|
904
|
+
`awaitProgress request encode failed: ${error.message}`,
|
|
927
905
|
),
|
|
928
|
-
)
|
|
906
|
+
}),
|
|
907
|
+
),
|
|
908
|
+
);
|
|
929
909
|
|
|
930
|
-
|
|
931
|
-
|
|
910
|
+
const attempt = (retry: number): Effect.Effect<void, ClientProgressFailure> =>
|
|
911
|
+
call(threadId, "awaitProgress", encoded).pipe(
|
|
912
|
+
Effect.flatMap(
|
|
913
|
+
expect(threadId, "awaitProgress", ProgressObserved, ClientObserveHostFailure),
|
|
914
|
+
),
|
|
915
|
+
Effect.asVoid,
|
|
916
|
+
Effect.catchTag("ThreadClientError", (error) =>
|
|
917
|
+
error.retryable === true && error.overloaded !== true && retry < 5
|
|
918
|
+
? Effect.sleep(Duration.millis(10 * 2 ** retry)).pipe(
|
|
919
|
+
Effect.andThen(attempt(retry + 1)),
|
|
920
|
+
)
|
|
921
|
+
: Effect.fail(error),
|
|
922
|
+
),
|
|
923
|
+
);
|
|
924
|
+
|
|
925
|
+
yield* attempt(0).pipe(Effect.onInterrupt(() => cancelProgress(threadId, waiterId)));
|
|
926
|
+
}),
|
|
932
927
|
|
|
933
928
|
watchText: (threadId) =>
|
|
934
929
|
Stream.unwrap(
|
|
@@ -1027,89 +1022,83 @@ export class CloudflareThreadClient extends Context.Service<
|
|
|
1027
1022
|
|
|
1028
1023
|
readPage,
|
|
1029
1024
|
|
|
1030
|
-
readAll: (threadId)
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
let after: CanonicalSequence | undefined;
|
|
1034
|
-
|
|
1035
|
-
for (;;) {
|
|
1036
|
-
const page = yield* readPage(threadId, { afterSequence: after, limit: 1_024 });
|
|
1037
|
-
|
|
1038
|
-
all.push(...page);
|
|
1039
|
-
const last = page.at(-1);
|
|
1040
|
-
|
|
1041
|
-
if (page.length < 1_024 || last === undefined) return all;
|
|
1042
|
-
after = last.sequence;
|
|
1043
|
-
}
|
|
1044
|
-
}),
|
|
1045
|
-
|
|
1046
|
-
abort: (threadId, command) =>
|
|
1047
|
-
Effect.gen(function* () {
|
|
1048
|
-
const encoded = yield* encodeAbortCommand(command).pipe(
|
|
1049
|
-
Effect.mapError((error) =>
|
|
1050
|
-
HostProtocolError.make({
|
|
1051
|
-
message: boundHostDiagnostic(`abort command encode failed: ${error.message}`),
|
|
1052
|
-
}),
|
|
1053
|
-
),
|
|
1054
|
-
);
|
|
1025
|
+
readAll: Effect.fnUntraced(function* (threadId) {
|
|
1026
|
+
const all: Array<CanonicalRecordEnvelope> = [];
|
|
1027
|
+
let after: CanonicalSequence | undefined;
|
|
1055
1028
|
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
const recorded = yield* expect(
|
|
1059
|
-
threadId,
|
|
1060
|
-
"abort",
|
|
1061
|
-
AbortRecorded,
|
|
1062
|
-
ClientAbortHostFailure,
|
|
1063
|
-
)(response);
|
|
1064
|
-
|
|
1065
|
-
return recorded.intent;
|
|
1066
|
-
}),
|
|
1067
|
-
|
|
1068
|
-
resolveApproval: (threadId, command) =>
|
|
1069
|
-
Effect.gen(function* () {
|
|
1070
|
-
const encoded = yield* encodeApprovalDecisionCommand(command).pipe(
|
|
1071
|
-
Effect.mapError((error) =>
|
|
1072
|
-
HostProtocolError.make({
|
|
1073
|
-
message: boundHostDiagnostic(`approval command encode failed: ${error.message}`),
|
|
1074
|
-
}),
|
|
1075
|
-
),
|
|
1076
|
-
);
|
|
1029
|
+
for (;;) {
|
|
1030
|
+
const page = yield* readPage(threadId, { afterSequence: after, limit: 1_024 });
|
|
1077
1031
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
const recorded = yield* expect(
|
|
1081
|
-
threadId,
|
|
1082
|
-
"resolveApproval",
|
|
1083
|
-
ApprovalRecorded,
|
|
1084
|
-
ClientApprovalHostFailure,
|
|
1085
|
-
)(response);
|
|
1086
|
-
|
|
1087
|
-
return recorded.intent;
|
|
1088
|
-
}),
|
|
1089
|
-
|
|
1090
|
-
resolveUnknown: (threadId, command) =>
|
|
1091
|
-
Effect.gen(function* () {
|
|
1092
|
-
const encoded = yield* encodeUnknownResolutionCommand(command).pipe(
|
|
1093
|
-
Effect.mapError((error) =>
|
|
1094
|
-
HostProtocolError.make({
|
|
1095
|
-
message: boundHostDiagnostic(
|
|
1096
|
-
`resolution command encode failed: ${error.message}`,
|
|
1097
|
-
),
|
|
1098
|
-
}),
|
|
1099
|
-
),
|
|
1100
|
-
);
|
|
1032
|
+
all.push(...page);
|
|
1033
|
+
const last = page.at(-1);
|
|
1101
1034
|
|
|
1102
|
-
|
|
1035
|
+
if (page.length < 1_024 || last === undefined) return all;
|
|
1036
|
+
after = last.sequence;
|
|
1037
|
+
}
|
|
1038
|
+
}),
|
|
1103
1039
|
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1040
|
+
abort: Effect.fnUntraced(function* (threadId, command) {
|
|
1041
|
+
const encoded = yield* encodeAbortCommand(command).pipe(
|
|
1042
|
+
Effect.mapError((error) =>
|
|
1043
|
+
HostProtocolError.make({
|
|
1044
|
+
message: boundHostDiagnostic(`abort command encode failed: ${error.message}`),
|
|
1045
|
+
}),
|
|
1046
|
+
),
|
|
1047
|
+
);
|
|
1048
|
+
|
|
1049
|
+
const response = yield* call(threadId, "abort", encoded);
|
|
1050
|
+
|
|
1051
|
+
const recorded = yield* expect(
|
|
1052
|
+
threadId,
|
|
1053
|
+
"abort",
|
|
1054
|
+
AbortRecorded,
|
|
1055
|
+
ClientAbortHostFailure,
|
|
1056
|
+
)(response);
|
|
1057
|
+
|
|
1058
|
+
return recorded.intent;
|
|
1059
|
+
}),
|
|
1060
|
+
|
|
1061
|
+
resolveApproval: Effect.fnUntraced(function* (threadId, command) {
|
|
1062
|
+
const encoded = yield* encodeApprovalDecisionCommand(command).pipe(
|
|
1063
|
+
Effect.mapError((error) =>
|
|
1064
|
+
HostProtocolError.make({
|
|
1065
|
+
message: boundHostDiagnostic(`approval command encode failed: ${error.message}`),
|
|
1066
|
+
}),
|
|
1067
|
+
),
|
|
1068
|
+
);
|
|
1069
|
+
|
|
1070
|
+
const response = yield* call(threadId, "resolveApproval", encoded);
|
|
1110
1071
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1072
|
+
const recorded = yield* expect(
|
|
1073
|
+
threadId,
|
|
1074
|
+
"resolveApproval",
|
|
1075
|
+
ApprovalRecorded,
|
|
1076
|
+
ClientApprovalHostFailure,
|
|
1077
|
+
)(response);
|
|
1078
|
+
|
|
1079
|
+
return recorded.intent;
|
|
1080
|
+
}),
|
|
1081
|
+
|
|
1082
|
+
resolveUnknown: Effect.fnUntraced(function* (threadId, command) {
|
|
1083
|
+
const encoded = yield* encodeUnknownResolutionCommand(command).pipe(
|
|
1084
|
+
Effect.mapError((error) =>
|
|
1085
|
+
HostProtocolError.make({
|
|
1086
|
+
message: boundHostDiagnostic(`resolution command encode failed: ${error.message}`),
|
|
1087
|
+
}),
|
|
1088
|
+
),
|
|
1089
|
+
);
|
|
1090
|
+
|
|
1091
|
+
const response = yield* call(threadId, "resolveUnknown", encoded);
|
|
1092
|
+
|
|
1093
|
+
const recorded = yield* expect(
|
|
1094
|
+
threadId,
|
|
1095
|
+
"resolveUnknown",
|
|
1096
|
+
UnknownResolutionRecorded,
|
|
1097
|
+
ClientUnknownHostFailure,
|
|
1098
|
+
)(response);
|
|
1099
|
+
|
|
1100
|
+
return recorded.intent;
|
|
1101
|
+
}),
|
|
1113
1102
|
});
|
|
1114
1103
|
}),
|
|
1115
1104
|
);
|