eve 0.58.1 → 0.59.0
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/CHANGELOG.md +21 -0
- package/dist/src/channel/session.d.ts +2 -0
- package/dist/src/channel/session.js +1 -1
- package/dist/src/channel/types.d.ts +8 -1
- package/dist/src/chunks/{use-eve-agent-X0asmJg-.js → use-eve-agent-Dmc6sX4d.js} +558 -233
- package/dist/src/chunks/{use-eve-agent-CxWcZCsU.js → use-eve-agent-jSR8P4nK.js} +565 -235
- package/dist/src/cli/dev/tui/runner.d.ts +4 -0
- package/dist/src/cli/dev/tui/runner.js +1 -1
- package/dist/src/cli/dev/tui/terminal-renderer.js +12 -12
- package/dist/src/client/eve-agent-projection.d.ts +10 -0
- package/dist/src/client/eve-agent-projection.js +1 -0
- package/dist/src/client/eve-agent-store-helpers.d.ts +6 -2
- package/dist/src/client/eve-agent-store-helpers.js +2 -2
- package/dist/src/client/eve-agent-store-state.d.ts +54 -1
- package/dist/src/client/eve-agent-store.d.ts +12 -82
- package/dist/src/client/eve-agent-store.js +1 -1
- package/dist/src/client/index.d.ts +2 -2
- package/dist/src/client/index.js +1 -1
- package/dist/src/client/message-response.d.ts +5 -1
- package/dist/src/client/message-response.js +1 -1
- package/dist/src/client/ndjson.d.ts +1 -0
- package/dist/src/client/ndjson.js +2 -2
- package/dist/src/client/open-stream.d.ts +4 -1
- package/dist/src/client/open-stream.js +1 -1
- package/dist/src/client/session-event-stream.d.ts +30 -0
- package/dist/src/client/session-event-stream.js +1 -0
- package/dist/src/client/session-utils.d.ts +2 -1
- package/dist/src/client/session-utils.js +1 -1
- package/dist/src/client/session.d.ts +14 -1
- package/dist/src/client/session.js +1 -1
- package/dist/src/client/sessions.d.ts +8 -2
- package/dist/src/client/sessions.js +1 -1
- package/dist/src/client/types.d.ts +7 -0
- package/dist/src/compiled/.vendor-stamp.json +2 -3
- package/dist/src/compiled/@vercel/sandbox/api-client/api-client.d.ts +88 -1
- package/dist/src/compiled/@vercel/sandbox/api-client/index.d.ts +1 -1
- package/dist/src/compiled/@vercel/sandbox/api-client/validators.d.ts +41 -1
- package/dist/src/compiled/@vercel/sandbox/constants.d.ts +3 -3
- package/dist/src/compiled/@vercel/{sandbox-drives → sandbox}/drive.d.ts +13 -2
- package/dist/src/compiled/@vercel/sandbox/index.d.ts +3 -2
- package/dist/src/compiled/@vercel/sandbox/index.js +15 -9
- package/dist/src/compiled/@vercel/sandbox/sandbox.d.ts +40 -5
- package/dist/src/compiled/_chunks/node/auth-DDrvYko5.js +2 -0
- package/dist/src/compiled/_chunks/node/version-C__MqbLM.js +1 -0
- package/dist/src/compiler/extension-compatibility.d.ts +14 -14
- package/dist/src/compiler/extension-compatibility.js +1 -1
- package/dist/src/context/build-dynamic-tools.js +1 -1
- package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
- package/dist/src/context/memory-tools.js +1 -1
- package/dist/src/evals/context.d.ts +1 -1
- package/dist/src/evals/context.js +1 -1
- package/dist/src/evals/define-eval.d.ts +1 -1
- package/dist/src/evals/define-eval.js +1 -1
- package/dist/src/evals/index.js +1 -1
- package/dist/src/evals/judge.d.ts +1 -1
- package/dist/src/evals/runner/execute-task.d.ts +1 -1
- package/dist/src/evals/runner/execute-task.js +1 -1
- package/dist/src/evals/session-manager.d.ts +27 -0
- package/dist/src/evals/session-manager.js +1 -0
- package/dist/src/evals/session.d.ts +8 -28
- package/dist/src/evals/session.js +2 -1
- package/dist/src/evals/target.d.ts +1 -1
- package/dist/src/evals/target.js +1 -1
- package/dist/src/evals/types.d.ts +19 -15
- package/dist/src/eve-channel/create-request.d.ts +24 -0
- package/dist/src/eve-channel/create-request.js +1 -0
- package/dist/src/eve-channel/index.js +1 -1
- package/dist/src/eve-channel/request.d.ts +3 -12
- package/dist/src/eve-channel/request.js +2 -2
- package/dist/src/eve-channel/types.d.ts +4 -2
- package/dist/src/execution/dynamic-workflow/tool.js +1 -1
- package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
- package/dist/src/execution/runtime-context.js +1 -1
- package/dist/src/execution/sandbox/bindings/vercel-lifecycle.d.ts +3 -3
- package/dist/src/execution/sandbox/bindings/vercel-lifecycle.js +1 -1
- package/dist/src/execution/sandbox/bindings/vercel-sdk-types.d.ts +1 -4
- package/dist/src/execution/sandbox/bindings/vercel.d.ts +1 -2
- package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
- package/dist/src/execution/session/entry.js +1 -1
- package/dist/src/execution/session/handoff-steps.js +1 -1
- package/dist/src/execution/session/program.d.ts +2 -0
- package/dist/src/execution/session/program.js +1 -1
- package/dist/src/execution/session/turn-step.js +1 -1
- package/dist/src/execution/session/turn.js +1 -1
- package/dist/src/execution/session-inbox/protocol.js +1 -1
- package/dist/src/execution/tools/connection-search.js +1 -1
- package/dist/src/execution/tools/sleep-workflow.js +1 -1
- package/dist/src/execution/workflow-runtime.js +1 -1
- package/dist/src/experimental/evaluate/auto-model.js +2 -2
- package/dist/src/experimental/evaluate/evaluate.d.ts +7 -0
- package/dist/src/experimental/evaluate/evaluate.js +1 -0
- package/dist/src/harness/compaction.d.ts +3 -3
- package/dist/src/harness/compaction.js +1 -1
- package/dist/src/harness/request-envelope.d.ts +11 -0
- package/dist/src/harness/request-envelope.js +1 -0
- package/dist/src/harness/tool-loop.js +2 -2
- package/dist/src/instrumentation/prepare-trace-context.d.ts +2 -1
- package/dist/src/instrumentation/prepare-trace-context.js +1 -1
- package/dist/src/internal/application/package.js +1 -1
- package/dist/src/internal/authored-module-loader.d.ts +4 -1
- package/dist/src/internal/authored-module-loader.js +1 -1
- package/dist/src/internal/bundler/nitro-rolldown.d.ts +2 -0
- package/dist/src/internal/nitro/host/build-extension.js +1 -1
- package/dist/src/internal/nitro/host/extension-capability-requirements.d.ts +1 -0
- package/dist/src/internal/nitro/host/extension-capability-requirements.js +1 -1
- package/dist/src/internal/nitro/host/extension-distribution.d.ts +1 -1
- package/dist/src/internal/nitro/host/extension-distribution.js +1 -1
- package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +1 -1
- package/dist/src/public/experimental/evaluate/index.d.ts +1 -0
- package/dist/src/public/experimental/evaluate/index.js +1 -1
- package/dist/src/public/sandbox/vercel-sandbox.d.ts +1 -1
- package/dist/src/public/sandbox/vercel.d.ts +1 -1
- package/dist/src/public/sandbox/vercel.js +1 -1
- package/dist/src/public/tools/index.d.ts +1 -0
- package/dist/src/public/tools/index.js +1 -1
- package/dist/src/react/use-eve-agent.d.ts +4 -0
- package/dist/src/react/use-eve-agent.js +1 -1
- package/dist/src/setup/scaffold/create/project.js +1 -1
- package/dist/src/subagents/handle-dispatch.js +1 -1
- package/dist/src/svelte/index.js +1 -1
- package/dist/src/svelte/use-eve-agent.d.ts +4 -0
- package/dist/src/svelte/use-eve-agent.js +1 -1
- package/dist/src/tools/definition.d.ts +2 -0
- package/dist/src/tools/definition.js +1 -1
- package/dist/src/tools/durable-callbacks.d.ts +8 -2
- package/dist/src/tools/durable-callbacks.js +1 -1
- package/dist/src/tools/durable-schema.d.ts +16 -0
- package/dist/src/tools/durable-schema.js +1 -0
- package/dist/src/vue/index.js +1 -1
- package/dist/src/vue/use-eve-agent.d.ts +4 -0
- package/dist/src/vue/use-eve-agent.js +1 -1
- package/docs/channels/eve.mdx +20 -10
- package/docs/concepts/context-control.md +4 -0
- package/docs/concepts/sessions-runs-and-streaming.md +18 -3
- package/docs/evals/assertions.mdx +6 -6
- package/docs/evals/cases.mdx +59 -23
- package/docs/evals/judge.mdx +10 -8
- package/docs/evals/overview.mdx +6 -6
- package/docs/evals/reporters.mdx +1 -1
- package/docs/evals/targets.mdx +5 -0
- package/docs/guides/client/messages.mdx +5 -5
- package/docs/guides/client/overview.mdx +15 -1
- package/docs/guides/dynamic-capabilities.md +22 -0
- package/docs/guides/evaluate.md +53 -3
- package/docs/guides/frontend/overview.mdx +54 -5
- package/docs/guides/frontend/use-eve-agent-svelte.mdx +13 -8
- package/docs/guides/frontend/use-eve-agent-vue.mdx +13 -8
- package/docs/reference/typescript-api.md +38 -37
- package/package.json +2 -3
- package/dist/src/compiled/@vercel/sandbox-drives/LICENSE +0 -201
- package/dist/src/compiled/@vercel/sandbox-drives/_async-retry.d.ts +0 -8
- package/dist/src/compiled/@vercel/sandbox-drives/_workflow-serde.d.ts +0 -5
- package/dist/src/compiled/@vercel/sandbox-drives/api-client/api-client.d.ts +0 -1815
- package/dist/src/compiled/@vercel/sandbox-drives/api-client/api-error.d.ts +0 -29
- package/dist/src/compiled/@vercel/sandbox-drives/api-client/base-client.d.ts +0 -39
- package/dist/src/compiled/@vercel/sandbox-drives/api-client/file-writer.d.ts +0 -66
- package/dist/src/compiled/@vercel/sandbox-drives/api-client/index.d.ts +0 -2
- package/dist/src/compiled/@vercel/sandbox-drives/api-client/validators.d.ts +0 -932
- package/dist/src/compiled/@vercel/sandbox-drives/api-client/with-retry.d.ts +0 -10
- package/dist/src/compiled/@vercel/sandbox-drives/auth/error.d.ts +0 -15
- package/dist/src/compiled/@vercel/sandbox-drives/auth/file.d.ts +0 -18
- package/dist/src/compiled/@vercel/sandbox-drives/auth/index.d.ts +0 -6
- package/dist/src/compiled/@vercel/sandbox-drives/auth/oauth.d.ts +0 -111
- package/dist/src/compiled/@vercel/sandbox-drives/auth/poll-for-token.d.ts +0 -28
- package/dist/src/compiled/@vercel/sandbox-drives/auth/project.d.ts +0 -40
- package/dist/src/compiled/@vercel/sandbox-drives/command.d.ts +0 -292
- package/dist/src/compiled/@vercel/sandbox-drives/constants.d.ts +0 -15
- package/dist/src/compiled/@vercel/sandbox-drives/execution-context.d.ts +0 -116
- package/dist/src/compiled/@vercel/sandbox-drives/filesystem.d.ts +0 -258
- package/dist/src/compiled/@vercel/sandbox-drives/index.d.ts +0 -14
- package/dist/src/compiled/@vercel/sandbox-drives/index.js +0 -9
- package/dist/src/compiled/@vercel/sandbox-drives/network-policy.d.ts +0 -169
- package/dist/src/compiled/@vercel/sandbox-drives/proxy.d.ts +0 -55
- package/dist/src/compiled/@vercel/sandbox-drives/sandbox-user.d.ts +0 -211
- package/dist/src/compiled/@vercel/sandbox-drives/sandbox.d.ts +0 -1287
- package/dist/src/compiled/@vercel/sandbox-drives/session.d.ts +0 -435
- package/dist/src/compiled/@vercel/sandbox-drives/snapshot.d.ts +0 -238
- package/dist/src/compiled/@vercel/sandbox-drives/utils/get-credentials.d.ts +0 -21
- package/dist/src/compiled/@vercel/sandbox-drives/utils/paginator.d.ts +0 -16
- package/dist/src/compiled/@vercel/sandbox-drives/utils/resolveSignal.d.ts +0 -15
- package/dist/src/compiled/@vercel/sandbox-drives/utils/sandbox-snapshot.d.ts +0 -11
- package/dist/src/compiled/@vercel/sandbox-drives/utils/types.d.ts +0 -11
- package/dist/src/compiled/_chunks/node/auth-8aQozzfi.js +0 -2
- package/dist/src/compiled/_chunks/node/auth-Bvv0xGTY.js +0 -2
- package/dist/src/compiled/_chunks/node/esm-Fqlolk7e.js +0 -7
- package/dist/src/compiled/_chunks/node/version-BC6t2Txc.js +0 -1
- package/dist/src/compiled/_chunks/node/version-DSQqVZ5T.js +0 -1
- package/dist/src/compiled/_chunks/node/xdg-app-paths-F-QHrdza.js +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { onMount } from "svelte";
|
|
1
2
|
import { createSubscriber } from "svelte/reactivity";
|
|
2
3
|
import { z } from "#compiled/zod/index.js";
|
|
3
4
|
import { asSchema } from "ai";
|
|
@@ -686,17 +687,6 @@ function isTurnFailureEvent(event) {
|
|
|
686
687
|
return event.type === "session.failed" || event.type === "step.failed" || event.type === "turn.failed";
|
|
687
688
|
}
|
|
688
689
|
|
|
689
|
-
//#endregion
|
|
690
|
-
//#region src/client/output-schema.ts
|
|
691
|
-
function extractCompletedResult(events) {
|
|
692
|
-
let result;
|
|
693
|
-
for (const event of events) if (isResultCompletedEvent(event)) result = event.data.result;
|
|
694
|
-
return result;
|
|
695
|
-
}
|
|
696
|
-
function isResultCompletedEvent(event) {
|
|
697
|
-
return event.type === "result.completed";
|
|
698
|
-
}
|
|
699
|
-
|
|
700
690
|
//#endregion
|
|
701
691
|
//#region src/client/session-utils.ts
|
|
702
692
|
function summarizeTurnEvents(events) {
|
|
@@ -725,9 +715,25 @@ function summarizeTurnEvents(events) {
|
|
|
725
715
|
function isFinalMessageCompleted(event) {
|
|
726
716
|
return event.type === "message.completed" && event.data.finishReason !== "tool-calls";
|
|
727
717
|
}
|
|
718
|
+
function updatePendingAuthorizations(pending, event) {
|
|
719
|
+
if (event.type === "authorization.required" && event.data.webhookUrl !== void 0) pending.add(event.data.name);
|
|
720
|
+
else if (event.type === "authorization.completed") pending.delete(event.data.name);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
//#endregion
|
|
724
|
+
//#region src/client/output-schema.ts
|
|
725
|
+
function extractCompletedResult(events) {
|
|
726
|
+
let result;
|
|
727
|
+
for (const event of events) if (isResultCompletedEvent(event)) result = event.data.result;
|
|
728
|
+
return result;
|
|
729
|
+
}
|
|
730
|
+
function isResultCompletedEvent(event) {
|
|
731
|
+
return event.type === "result.completed";
|
|
732
|
+
}
|
|
728
733
|
|
|
729
734
|
//#endregion
|
|
730
735
|
//#region src/client/message-response.ts
|
|
736
|
+
const consumeResponse = Symbol("consumeMessageResponse");
|
|
731
737
|
var MessageResponse = class {
|
|
732
738
|
sessionId;
|
|
733
739
|
#cancelTurn;
|
|
@@ -765,13 +771,16 @@ var MessageResponse = class {
|
|
|
765
771
|
};
|
|
766
772
|
}
|
|
767
773
|
[Symbol.asyncIterator]() {
|
|
774
|
+
return this[consumeResponse]();
|
|
775
|
+
}
|
|
776
|
+
[consumeResponse](source) {
|
|
768
777
|
if (this.#consumed) throw new Error("MessageResponse has already been consumed.");
|
|
769
778
|
this.#consumed = true;
|
|
770
|
-
return this.#observeStream();
|
|
779
|
+
return this.#observeStream(source);
|
|
771
780
|
}
|
|
772
|
-
async *#observeStream() {
|
|
781
|
+
async *#observeStream(source) {
|
|
773
782
|
try {
|
|
774
|
-
for await (const event of this.#createStream()) {
|
|
783
|
+
for await (const event of this.#createStream(source)) {
|
|
775
784
|
if (event.type === "turn.started") this.#turnId.resolve(event.data.turnId);
|
|
776
785
|
else if (isCurrentTurnBoundaryEvent(event)) {
|
|
777
786
|
this.#settled = true;
|
|
@@ -784,6 +793,9 @@ var MessageResponse = class {
|
|
|
784
793
|
}
|
|
785
794
|
}
|
|
786
795
|
};
|
|
796
|
+
function consumeMessageResponse(response, source) {
|
|
797
|
+
return response[consumeResponse](source);
|
|
798
|
+
}
|
|
787
799
|
|
|
788
800
|
//#endregion
|
|
789
801
|
//#region src/protocol/message-version.ts
|
|
@@ -893,9 +905,15 @@ async function* readNdjsonStream(body, options) {
|
|
|
893
905
|
const decoder = new TextDecoder();
|
|
894
906
|
let buffer = "";
|
|
895
907
|
let reachedEof = false;
|
|
908
|
+
const abort = () => {
|
|
909
|
+
reader.cancel().catch(() => {});
|
|
910
|
+
};
|
|
911
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
896
912
|
try {
|
|
897
913
|
while (true) {
|
|
914
|
+
options.signal?.throwIfAborted();
|
|
898
915
|
const result = await readWithIdleTimeout(reader, options?.idleTimeoutMs);
|
|
916
|
+
options.signal?.throwIfAborted();
|
|
899
917
|
if (result.done) {
|
|
900
918
|
reachedEof = true;
|
|
901
919
|
buffer += decoder.decode();
|
|
@@ -921,6 +939,7 @@ async function* readNdjsonStream(body, options) {
|
|
|
921
939
|
else yield parseMessageStreamEvent(value, options.streamVersion);
|
|
922
940
|
}
|
|
923
941
|
} finally {
|
|
942
|
+
options.signal?.removeEventListener("abort", abort);
|
|
924
943
|
if (!reachedEof) reader.cancel().catch(() => {});
|
|
925
944
|
reader.releaseLock();
|
|
926
945
|
}
|
|
@@ -1065,45 +1084,56 @@ function resolveRetryPolicy(policy, defaults) {
|
|
|
1065
1084
|
...policy
|
|
1066
1085
|
};
|
|
1067
1086
|
}
|
|
1068
|
-
function resolveStreamReconnectPolicy(policy) {
|
|
1087
|
+
function resolveStreamReconnectPolicy(policy, keepAlive = false) {
|
|
1069
1088
|
if (policy && "reconnect" in policy && policy.reconnect === false) return NO_STREAM_RECONNECT_POLICY;
|
|
1070
1089
|
const configured = policy;
|
|
1071
1090
|
return {
|
|
1072
1091
|
retryableErrorStatuses: configured?.retryableErrorStatuses ? new Set(configured.retryableErrorStatuses) : DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses,
|
|
1073
|
-
streamIdleReconnectPolicy: resolveRetryPolicy(configured?.streamIdleReconnectPolicy,
|
|
1092
|
+
streamIdleReconnectPolicy: resolveRetryPolicy(configured?.streamIdleReconnectPolicy, {
|
|
1093
|
+
...DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy,
|
|
1094
|
+
maxAttempts: keepAlive ? Infinity : DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy.maxAttempts
|
|
1095
|
+
}),
|
|
1074
1096
|
streamOpenReconnectPolicy: resolveRetryPolicy(configured?.streamOpenReconnectPolicy, DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy)
|
|
1075
1097
|
};
|
|
1076
1098
|
}
|
|
1077
1099
|
async function* followStreamIterable(input) {
|
|
1078
1100
|
if (input.follow === false && input.startIndex < 0) throw new Error("stream({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.");
|
|
1079
|
-
const
|
|
1080
|
-
|
|
1101
|
+
const resolvePolicy = () => resolveStreamReconnectPolicy(input.resolveReconnectPolicy === void 0 ? input.streamReconnectPolicy : input.resolveReconnectPolicy(), input.keepAlive);
|
|
1102
|
+
let retryPolicy = resolvePolicy();
|
|
1103
|
+
let idleRetryPolicy = retryPolicy.streamIdleReconnectPolicy;
|
|
1081
1104
|
let startIndex = input.startIndex;
|
|
1082
1105
|
let reconnectDelayMs = idleRetryPolicy.baseDelayMs;
|
|
1083
1106
|
let idleReconnects = 0;
|
|
1084
1107
|
let initialConnection = true;
|
|
1085
1108
|
let tailIndex;
|
|
1109
|
+
let caughtUp = false;
|
|
1086
1110
|
while (true) {
|
|
1111
|
+
retryPolicy = resolvePolicy();
|
|
1112
|
+
idleRetryPolicy = retryPolicy.streamIdleReconnectPolicy;
|
|
1087
1113
|
let connection;
|
|
1088
1114
|
try {
|
|
1089
1115
|
connection = await openStreamBody({
|
|
1090
1116
|
...input,
|
|
1091
1117
|
retryPolicy,
|
|
1092
1118
|
startIndex,
|
|
1093
|
-
requestTailIndex: input.follow === false && tailIndex === void 0
|
|
1119
|
+
requestTailIndex: (input.follow === false || input.onCaughtUp !== void 0) && tailIndex === void 0
|
|
1094
1120
|
});
|
|
1095
1121
|
} catch (error) {
|
|
1096
1122
|
if (input.signal?.aborted) return;
|
|
1097
1123
|
throw error;
|
|
1098
1124
|
}
|
|
1099
|
-
if (input.follow === false && tailIndex === void 0) {
|
|
1125
|
+
if ((input.follow === false || input.onCaughtUp !== void 0) && tailIndex === void 0) {
|
|
1100
1126
|
tailIndex = connection.tailIndex;
|
|
1101
1127
|
if (tailIndex === void 0) {
|
|
1102
1128
|
connection.close();
|
|
1103
1129
|
throw new Error(`stream({ follow: false }) requires the server to report the ${EVE_STREAM_TAIL_INDEX_HEADER} header. The agent may be running an older eve version.`);
|
|
1104
1130
|
}
|
|
1105
1131
|
}
|
|
1106
|
-
if (tailIndex !== void 0 && startIndex > tailIndex) {
|
|
1132
|
+
if (!caughtUp && tailIndex !== void 0 && startIndex > tailIndex) {
|
|
1133
|
+
caughtUp = true;
|
|
1134
|
+
input.onCaughtUp?.();
|
|
1135
|
+
}
|
|
1136
|
+
if (input.follow === false && tailIndex !== void 0 && startIndex > tailIndex) {
|
|
1107
1137
|
connection.close();
|
|
1108
1138
|
return;
|
|
1109
1139
|
}
|
|
@@ -1111,6 +1141,7 @@ async function* followStreamIterable(input) {
|
|
|
1111
1141
|
let leaseEnded = false;
|
|
1112
1142
|
try {
|
|
1113
1143
|
for await (const event of readNdjsonStream(connection.body, {
|
|
1144
|
+
signal: input.signal,
|
|
1114
1145
|
controlVersion: connection.controlVersion,
|
|
1115
1146
|
idleTimeoutMs: input.streamReadIdleTimeoutMs ?? DEFAULT_STREAM_READ_IDLE_TIMEOUT_MS,
|
|
1116
1147
|
onLeaseEnded: () => {
|
|
@@ -1123,16 +1154,21 @@ async function* followStreamIterable(input) {
|
|
|
1123
1154
|
reconnectDelayMs = idleRetryPolicy.baseDelayMs;
|
|
1124
1155
|
idleReconnects = 0;
|
|
1125
1156
|
yield event;
|
|
1126
|
-
if (tailIndex !== void 0 && startIndex > tailIndex)
|
|
1157
|
+
if (!caughtUp && tailIndex !== void 0 && startIndex > tailIndex) {
|
|
1158
|
+
caughtUp = true;
|
|
1159
|
+
input.onCaughtUp?.();
|
|
1160
|
+
}
|
|
1161
|
+
if (input.follow === false && tailIndex !== void 0 && startIndex > tailIndex) return;
|
|
1127
1162
|
}
|
|
1128
1163
|
} catch (error) {
|
|
1129
1164
|
if (!isStreamDisconnectError(error)) throw error;
|
|
1130
1165
|
} finally {
|
|
1131
1166
|
connection.close();
|
|
1132
1167
|
}
|
|
1168
|
+
idleRetryPolicy = resolvePolicy().streamIdleReconnectPolicy;
|
|
1133
1169
|
if (input.signal?.aborted || input.startIndex < 0 || idleRetryPolicy.maxAttempts === 0) return;
|
|
1134
1170
|
if (leaseEnded) continue;
|
|
1135
|
-
if (
|
|
1171
|
+
if (!deliveredEvent && !initialConnection && (idleReconnects += 1) >= idleRetryPolicy.maxAttempts) return;
|
|
1136
1172
|
initialConnection = false;
|
|
1137
1173
|
await sleep(reconnectDelayMs, input.signal);
|
|
1138
1174
|
if (input.signal?.aborted) return;
|
|
@@ -1140,7 +1176,7 @@ async function* followStreamIterable(input) {
|
|
|
1140
1176
|
}
|
|
1141
1177
|
}
|
|
1142
1178
|
async function openStreamBody(input) {
|
|
1143
|
-
const retryPolicy = input.retryPolicy ?? resolveStreamReconnectPolicy(input.streamReconnectPolicy);
|
|
1179
|
+
const retryPolicy = input.retryPolicy ?? resolveStreamReconnectPolicy(input.streamReconnectPolicy, input.keepAlive);
|
|
1144
1180
|
const openRetryPolicy = retryPolicy.streamOpenReconnectPolicy;
|
|
1145
1181
|
let lastStatus;
|
|
1146
1182
|
let lastBody;
|
|
@@ -1152,8 +1188,10 @@ async function openStreamBody(input) {
|
|
|
1152
1188
|
if (input.startIndex !== 0) searchParams.startIndex = String(input.startIndex);
|
|
1153
1189
|
if (input.requestTailIndex === true) searchParams.includeTailIndex = "1";
|
|
1154
1190
|
for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
|
|
1191
|
+
input.signal?.throwIfAborted();
|
|
1155
1192
|
const url = createClientUrl(input.host, createEveSessionStreamRoutePath(input.sessionId), Object.keys(searchParams).length > 0 ? searchParams : void 0);
|
|
1156
1193
|
const headers = await input.resolveHeaders();
|
|
1194
|
+
input.signal?.throwIfAborted();
|
|
1157
1195
|
const connectionController = new AbortController();
|
|
1158
1196
|
const signal = input.signal ? AbortSignal.any([input.signal, connectionController.signal]) : connectionController.signal;
|
|
1159
1197
|
let response;
|
|
@@ -1434,8 +1472,10 @@ function getStandardSchemaProperties(value) {
|
|
|
1434
1472
|
|
|
1435
1473
|
//#endregion
|
|
1436
1474
|
//#region src/client/session.ts
|
|
1437
|
-
const SESSION_SEND_RETRY_COUNT = 3;
|
|
1438
1475
|
const SESSION_SEND_RETRY_BASE_DELAY_MS = 250;
|
|
1476
|
+
const SESSION_SEND_RETRY_MAX_DELAY_MS = 2e3;
|
|
1477
|
+
const SESSION_SEND_READY_TIMEOUT_MS = 2e4;
|
|
1478
|
+
const followSession = Symbol("followClientSession");
|
|
1439
1479
|
var ClientSession = class ClientSession {
|
|
1440
1480
|
#context;
|
|
1441
1481
|
#state;
|
|
@@ -1455,6 +1495,13 @@ var ClientSession = class ClientSession {
|
|
|
1455
1495
|
session
|
|
1456
1496
|
};
|
|
1457
1497
|
}
|
|
1498
|
+
static async prewarm(context, options = {}) {
|
|
1499
|
+
const { sessionId } = await readAcceptedMessage(await postCreateSession(context, options));
|
|
1500
|
+
return new ClientSession(context, {
|
|
1501
|
+
sessionId,
|
|
1502
|
+
streamIndex: 0
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1458
1505
|
get state() {
|
|
1459
1506
|
return this.#state;
|
|
1460
1507
|
}
|
|
@@ -1488,10 +1535,10 @@ var ClientSession = class ClientSession {
|
|
|
1488
1535
|
inputResponses
|
|
1489
1536
|
}, false);
|
|
1490
1537
|
}
|
|
1491
|
-
async #send(input,
|
|
1538
|
+
async #send(input, retrySessionNotReady) {
|
|
1492
1539
|
const initialStreamIndex = this.#state.streamIndex;
|
|
1493
1540
|
const path = createEveSessionRoutePath(this.#state.sessionId);
|
|
1494
|
-
const response =
|
|
1541
|
+
const response = retrySessionNotReady ? await postSessionSend(this.#context, path, input) : await postTurn(this.#context, path, input, false);
|
|
1495
1542
|
const { sessionId: responseSessionId, deliveryId } = await readAcceptedMessage(response, this.#state.sessionId);
|
|
1496
1543
|
if (responseSessionId !== this.#state.sessionId) throw new Error("Message route returned a different session id.");
|
|
1497
1544
|
if (input.message !== void 0 && deliveryId === void 0) throw new Error("Message route did not return a delivery id. Update the server before sending with this client.");
|
|
@@ -1527,23 +1574,29 @@ var ClientSession = class ClientSession {
|
|
|
1527
1574
|
if (options?.follow === false && (options.startIndex ?? this.#state.streamIndex) < 0) throw new Error("stream({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.");
|
|
1528
1575
|
return this.#streamAndAdvance(options);
|
|
1529
1576
|
}
|
|
1577
|
+
[followSession](options) {
|
|
1578
|
+
return this.#streamAndAdvance({
|
|
1579
|
+
...options,
|
|
1580
|
+
keepAlive: true
|
|
1581
|
+
});
|
|
1582
|
+
}
|
|
1530
1583
|
#messageResponse(response, input, initialStreamIndex, deliveryId) {
|
|
1531
1584
|
response.body?.cancel().catch(() => {});
|
|
1532
1585
|
return new MessageResponse({
|
|
1533
1586
|
cancelTurn: async (turnId) => await this.cancel({ turnId }),
|
|
1534
|
-
createStream: () => this.#createEventStream(initialStreamIndex, input, deliveryId),
|
|
1587
|
+
createStream: (source) => this.#createEventStream(initialStreamIndex, input, deliveryId, source),
|
|
1535
1588
|
sessionId: this.#state.sessionId
|
|
1536
1589
|
});
|
|
1537
1590
|
}
|
|
1538
|
-
async *#createEventStream(initialStreamIndex, input, deliveryId) {
|
|
1591
|
+
async *#createEventStream(initialStreamIndex, input, deliveryId, source) {
|
|
1539
1592
|
let eventCount = 0;
|
|
1540
1593
|
let started = deliveryId === void 0;
|
|
1541
1594
|
let reachedBoundary = false;
|
|
1542
1595
|
const pendingAuthorizations = /* @__PURE__ */ new Set();
|
|
1543
1596
|
try {
|
|
1544
|
-
for await (const event of this.#readStream({
|
|
1597
|
+
for await (const event of source ?? this.#readStream({
|
|
1545
1598
|
headers: input.headers,
|
|
1546
|
-
keepAlive:
|
|
1599
|
+
keepAlive: true,
|
|
1547
1600
|
signal: input.signal,
|
|
1548
1601
|
startIndex: initialStreamIndex,
|
|
1549
1602
|
streamReconnectPolicy: input.streamReconnectPolicy
|
|
@@ -1557,73 +1610,92 @@ var ClientSession = class ClientSession {
|
|
|
1557
1610
|
if (!terminal && event.meta?.deliveryIds !== void 0 && !matches) continue;
|
|
1558
1611
|
started = true;
|
|
1559
1612
|
}
|
|
1560
|
-
|
|
1561
|
-
else if (event.type === "authorization.completed") pendingAuthorizations.delete(event.data.name);
|
|
1613
|
+
updatePendingAuthorizations(pendingAuthorizations, event);
|
|
1562
1614
|
reachedBoundary = isCurrentTurnBoundaryEvent(event) && (event.type !== "session.waiting" || pendingAuthorizations.size === 0);
|
|
1563
1615
|
yield event;
|
|
1564
1616
|
if (reachedBoundary) break;
|
|
1565
1617
|
}
|
|
1566
1618
|
if (deliveryId !== void 0 && !reachedBoundary && !input.signal?.aborted) throw new Error("The response stream ended before the accepted message reached its turn boundary.");
|
|
1567
1619
|
} finally {
|
|
1568
|
-
this.#
|
|
1569
|
-
sessionId: this.#state.sessionId,
|
|
1570
|
-
streamIndex: Math.max(this.#state.streamIndex, initialStreamIndex + eventCount)
|
|
1571
|
-
};
|
|
1620
|
+
this.#advanceStreamIndex(initialStreamIndex + eventCount);
|
|
1572
1621
|
}
|
|
1573
1622
|
}
|
|
1574
1623
|
async *#streamAndAdvance(options) {
|
|
1575
1624
|
const startIndex = options?.startIndex ?? this.#state.streamIndex;
|
|
1576
1625
|
let eventCount = 0;
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
};
|
|
1626
|
+
for await (const event of this.#readStream({
|
|
1627
|
+
follow: options?.follow,
|
|
1628
|
+
headers: options?.headers,
|
|
1629
|
+
keepAlive: options?.keepAlive,
|
|
1630
|
+
onCaughtUp: options?.onCaughtUp,
|
|
1631
|
+
resolveHeaders: options?.resolveHeaders,
|
|
1632
|
+
resolveReconnectPolicy: options?.resolveReconnectPolicy,
|
|
1633
|
+
signal: options?.signal,
|
|
1634
|
+
startIndex,
|
|
1635
|
+
streamReconnectPolicy: options?.streamReconnectPolicy
|
|
1636
|
+
})) {
|
|
1637
|
+
eventCount += 1;
|
|
1638
|
+
if (startIndex >= 0) this.#advanceStreamIndex(startIndex + eventCount);
|
|
1639
|
+
yield event;
|
|
1592
1640
|
}
|
|
1593
1641
|
}
|
|
1642
|
+
#advanceStreamIndex(streamIndex) {
|
|
1643
|
+
this.#state = {
|
|
1644
|
+
sessionId: this.#state.sessionId,
|
|
1645
|
+
streamIndex: Math.max(this.#state.streamIndex, streamIndex)
|
|
1646
|
+
};
|
|
1647
|
+
}
|
|
1594
1648
|
#readStream(input) {
|
|
1595
1649
|
return followStreamIterable({
|
|
1650
|
+
onCaughtUp: input.onCaughtUp,
|
|
1596
1651
|
follow: input.follow,
|
|
1597
1652
|
host: this.#context.host,
|
|
1598
1653
|
keepAlive: input.keepAlive,
|
|
1599
|
-
resolveHeaders: () => this.#context.resolveHeaders(input.headers),
|
|
1654
|
+
resolveHeaders: () => this.#context.resolveHeaders(input.resolveHeaders?.() ?? input.headers),
|
|
1600
1655
|
redirect: this.#context.redirect,
|
|
1601
1656
|
sessionId: this.#state.sessionId,
|
|
1602
1657
|
signal: input.signal,
|
|
1603
1658
|
startIndex: input.startIndex,
|
|
1604
|
-
streamReconnectPolicy: input.streamReconnectPolicy
|
|
1659
|
+
streamReconnectPolicy: input.streamReconnectPolicy,
|
|
1660
|
+
resolveReconnectPolicy: input.resolveReconnectPolicy
|
|
1605
1661
|
});
|
|
1606
1662
|
}
|
|
1607
1663
|
};
|
|
1664
|
+
function followClientSession(session, options) {
|
|
1665
|
+
return session[followSession](options);
|
|
1666
|
+
}
|
|
1608
1667
|
async function postSessionSend(context, path, input) {
|
|
1668
|
+
const readyDeadline = Date.now() + SESSION_SEND_READY_TIMEOUT_MS;
|
|
1609
1669
|
let retryDelayMs = SESSION_SEND_RETRY_BASE_DELAY_MS;
|
|
1610
|
-
for (
|
|
1670
|
+
for (;;) {
|
|
1611
1671
|
try {
|
|
1612
1672
|
return await postTurn(context, path, input, false);
|
|
1613
1673
|
} catch (error) {
|
|
1614
|
-
if (!
|
|
1674
|
+
if (!isSessionNotReady(error)) throw error;
|
|
1675
|
+
const remainingMs = readyDeadline - Date.now();
|
|
1676
|
+
if (remainingMs <= 0) throw error;
|
|
1677
|
+
await sleep(Math.min(retryDelayMs, remainingMs), input.signal);
|
|
1615
1678
|
}
|
|
1616
|
-
await sleep(retryDelayMs, input.signal);
|
|
1617
1679
|
input.signal?.throwIfAborted();
|
|
1618
|
-
retryDelayMs
|
|
1680
|
+
retryDelayMs = Math.min(retryDelayMs * 2, SESSION_SEND_RETRY_MAX_DELAY_MS);
|
|
1619
1681
|
}
|
|
1620
1682
|
}
|
|
1621
|
-
function
|
|
1622
|
-
|
|
1683
|
+
async function postCreateSession(context, options) {
|
|
1684
|
+
const headers = await context.resolveHeaders(options.headers);
|
|
1685
|
+
const response = await fetch(createClientUrl(context.host, EVE_SESSION_ROUTE_PATH), {
|
|
1686
|
+
headers,
|
|
1687
|
+
method: "POST",
|
|
1688
|
+
redirect: context.redirect,
|
|
1689
|
+
signal: options.signal ?? null
|
|
1690
|
+
});
|
|
1691
|
+
if (!response.ok) {
|
|
1692
|
+
const responseBody = await response.text();
|
|
1693
|
+
throw new ClientError(response.status, responseBody, response.headers);
|
|
1694
|
+
}
|
|
1695
|
+
return response;
|
|
1623
1696
|
}
|
|
1624
|
-
function
|
|
1625
|
-
|
|
1626
|
-
return policy?.streamIdleReconnectPolicy?.maxAttempts === void 0;
|
|
1697
|
+
function isSessionNotReady(error) {
|
|
1698
|
+
return error instanceof ClientError && error.status === 409 && error.code === "session_not_ready";
|
|
1627
1699
|
}
|
|
1628
1700
|
async function postTurn(context, path, input, requireMessage) {
|
|
1629
1701
|
const body = createMessageBody(input, requireMessage);
|
|
@@ -1672,8 +1744,9 @@ var ClientSessions = class {
|
|
|
1672
1744
|
constructor(context) {
|
|
1673
1745
|
this.#context = context;
|
|
1674
1746
|
}
|
|
1675
|
-
async create(input) {
|
|
1676
|
-
return await ClientSession.create(this.#context, input);
|
|
1747
|
+
async create(input = {}) {
|
|
1748
|
+
if ("message" in input) return await ClientSession.create(this.#context, input);
|
|
1749
|
+
return { session: await ClientSession.prewarm(this.#context, input) };
|
|
1677
1750
|
}
|
|
1678
1751
|
attach(sessionId, options) {
|
|
1679
1752
|
if (sessionId.length === 0) throw new Error("sessionId must be a non-empty string.");
|
|
@@ -1803,6 +1876,151 @@ function withRedirectPolicy(init, redirect) {
|
|
|
1803
1876
|
};
|
|
1804
1877
|
}
|
|
1805
1878
|
|
|
1879
|
+
//#endregion
|
|
1880
|
+
//#region src/client/session-event-stream.ts
|
|
1881
|
+
var SessionEventStream = class {
|
|
1882
|
+
#controller = new AbortController();
|
|
1883
|
+
#readers = /* @__PURE__ */ new Set();
|
|
1884
|
+
#caughtUp = Promise.withResolvers();
|
|
1885
|
+
caughtUp = this.#caughtUp.promise;
|
|
1886
|
+
#ended = false;
|
|
1887
|
+
#error;
|
|
1888
|
+
#headers;
|
|
1889
|
+
#reconnectPolicy;
|
|
1890
|
+
constructor(session, options) {
|
|
1891
|
+
this.setOptions(options);
|
|
1892
|
+
this.caughtUp.catch(() => {});
|
|
1893
|
+
if (!options.catchUp) this.#caughtUp.resolve();
|
|
1894
|
+
(async () => {
|
|
1895
|
+
try {
|
|
1896
|
+
for await (const event of followClientSession(session, {
|
|
1897
|
+
signal: this.#controller.signal,
|
|
1898
|
+
resolveHeaders: () => this.#headers,
|
|
1899
|
+
resolveReconnectPolicy: () => this.#reconnectPolicy,
|
|
1900
|
+
startIndex: options.startIndex,
|
|
1901
|
+
onCaughtUp: options.catchUp ? () => this.#caughtUp.resolve() : void 0
|
|
1902
|
+
})) {
|
|
1903
|
+
if (this.#controller.signal.aborted) return;
|
|
1904
|
+
options.onEvent(event);
|
|
1905
|
+
for (const reader of this.#readers) reader.push(event);
|
|
1906
|
+
if (event.type === "session.completed" || event.type === "session.failed") break;
|
|
1907
|
+
}
|
|
1908
|
+
this.#caughtUp.resolve();
|
|
1909
|
+
this.#finish();
|
|
1910
|
+
} catch (error) {
|
|
1911
|
+
this.#caughtUp.reject(error);
|
|
1912
|
+
this.#finish(error);
|
|
1913
|
+
if (!this.#controller.signal.aborted) options.onError(error);
|
|
1914
|
+
}
|
|
1915
|
+
})();
|
|
1916
|
+
}
|
|
1917
|
+
subscribe(signal) {
|
|
1918
|
+
const reader = new SessionEventReader(() => this.#readers.delete(reader), signal);
|
|
1919
|
+
if (this.#ended) reader.end(this.#error);
|
|
1920
|
+
else this.#readers.add(reader);
|
|
1921
|
+
return reader;
|
|
1922
|
+
}
|
|
1923
|
+
get ended() {
|
|
1924
|
+
return this.#ended;
|
|
1925
|
+
}
|
|
1926
|
+
setOptions(options) {
|
|
1927
|
+
if ("headers" in options) this.#headers = options.headers;
|
|
1928
|
+
if ("streamReconnectPolicy" in options) this.#reconnectPolicy = options.streamReconnectPolicy;
|
|
1929
|
+
}
|
|
1930
|
+
close() {
|
|
1931
|
+
const error = new DOMException("Session stream was detached.", "AbortError");
|
|
1932
|
+
this.#controller.abort(error);
|
|
1933
|
+
this.#caughtUp.reject(error);
|
|
1934
|
+
this.#finish(error);
|
|
1935
|
+
}
|
|
1936
|
+
#finish(error) {
|
|
1937
|
+
if (this.#ended) return;
|
|
1938
|
+
this.#ended = true;
|
|
1939
|
+
this.#error = error;
|
|
1940
|
+
for (const reader of this.#readers) reader.end(error);
|
|
1941
|
+
}
|
|
1942
|
+
};
|
|
1943
|
+
var SessionEventReader = class {
|
|
1944
|
+
#events = [];
|
|
1945
|
+
#wake = Promise.withResolvers();
|
|
1946
|
+
#ended = false;
|
|
1947
|
+
#error;
|
|
1948
|
+
#dispose;
|
|
1949
|
+
constructor(unsubscribe, signal) {
|
|
1950
|
+
const abort = () => this.end(signal?.reason);
|
|
1951
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
1952
|
+
this.#dispose = () => {
|
|
1953
|
+
signal?.removeEventListener("abort", abort);
|
|
1954
|
+
unsubscribe();
|
|
1955
|
+
};
|
|
1956
|
+
if (signal?.aborted) abort();
|
|
1957
|
+
}
|
|
1958
|
+
push(event) {
|
|
1959
|
+
if (this.#ended) return;
|
|
1960
|
+
this.#events.push(event);
|
|
1961
|
+
this.#wake.resolve();
|
|
1962
|
+
}
|
|
1963
|
+
end(error) {
|
|
1964
|
+
if (this.#ended) return;
|
|
1965
|
+
this.#ended = true;
|
|
1966
|
+
this.#error = error;
|
|
1967
|
+
this.#wake.resolve();
|
|
1968
|
+
}
|
|
1969
|
+
[Symbol.dispose]() {
|
|
1970
|
+
this.end();
|
|
1971
|
+
this.#events = [];
|
|
1972
|
+
this.#dispose();
|
|
1973
|
+
}
|
|
1974
|
+
discard() {
|
|
1975
|
+
this.#events = [];
|
|
1976
|
+
}
|
|
1977
|
+
async *[Symbol.asyncIterator]() {
|
|
1978
|
+
for (;;) {
|
|
1979
|
+
while (this.#events.length > 0) yield this.#events.shift();
|
|
1980
|
+
if (this.#ended) {
|
|
1981
|
+
if (this.#error !== void 0) throw this.#error;
|
|
1982
|
+
return;
|
|
1983
|
+
}
|
|
1984
|
+
this.#wake = Promise.withResolvers();
|
|
1985
|
+
await this.#wake.promise;
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
};
|
|
1989
|
+
|
|
1990
|
+
//#endregion
|
|
1991
|
+
//#region src/client/eve-agent-projection.ts
|
|
1992
|
+
var EveAgentProjection = class {
|
|
1993
|
+
#reducer;
|
|
1994
|
+
#events;
|
|
1995
|
+
#data;
|
|
1996
|
+
constructor(reducer, events) {
|
|
1997
|
+
this.#reducer = reducer;
|
|
1998
|
+
this.#events = events;
|
|
1999
|
+
this.#data = this.#reduce();
|
|
2000
|
+
}
|
|
2001
|
+
get data() {
|
|
2002
|
+
return this.#data;
|
|
2003
|
+
}
|
|
2004
|
+
reset() {
|
|
2005
|
+
this.#events = [];
|
|
2006
|
+
this.#data = this.#reducer.initial();
|
|
2007
|
+
}
|
|
2008
|
+
append(event) {
|
|
2009
|
+
this.#events = [...this.#events, event];
|
|
2010
|
+
this.#data = this.#reducer.reduce(this.#data, event);
|
|
2011
|
+
}
|
|
2012
|
+
replace(predicate, replacement) {
|
|
2013
|
+
const index = this.#events.findIndex(predicate);
|
|
2014
|
+
this.#events = index === -1 ? [...this.#events, replacement] : this.#events.map((event, i) => i === index ? replacement : event);
|
|
2015
|
+
this.#data = this.#reduce();
|
|
2016
|
+
}
|
|
2017
|
+
#reduce() {
|
|
2018
|
+
let data = this.#reducer.initial();
|
|
2019
|
+
for (const event of this.#events) data = this.#reducer.reduce(data, event);
|
|
2020
|
+
return data;
|
|
2021
|
+
}
|
|
2022
|
+
};
|
|
2023
|
+
|
|
1806
2024
|
//#endregion
|
|
1807
2025
|
//#region src/protocol/event-dedupe.ts
|
|
1808
2026
|
function createEventDeduper() {
|
|
@@ -1832,10 +2050,6 @@ function collectPendingAuthorizations(events) {
|
|
|
1832
2050
|
for (const event of events) updatePendingAuthorizations(pending, event);
|
|
1833
2051
|
return pending;
|
|
1834
2052
|
}
|
|
1835
|
-
function updatePendingAuthorizations(pending, event) {
|
|
1836
|
-
if (event.type === "authorization.required" && event.data.webhookUrl !== void 0) pending.add(event.data.name);
|
|
1837
|
-
else if (event.type === "authorization.completed") pending.delete(event.data.name);
|
|
1838
|
-
}
|
|
1839
2053
|
function assertExclusiveTurnInput(input) {
|
|
1840
2054
|
if (input.message !== void 0 === (input.inputResponses !== void 0)) throw new Error("A turn requires exactly one of message or inputResponses.");
|
|
1841
2055
|
}
|
|
@@ -1865,29 +2079,78 @@ function toTerminalStreamFailureError(event) {
|
|
|
1865
2079
|
error.name = event.data.code;
|
|
1866
2080
|
return error;
|
|
1867
2081
|
}
|
|
2082
|
+
function createActiveTurn(cancel) {
|
|
2083
|
+
const response = Promise.withResolvers();
|
|
2084
|
+
const completion = Promise.withResolvers();
|
|
2085
|
+
const turn = {
|
|
2086
|
+
abortController: new AbortController(),
|
|
2087
|
+
acceptedFollowUps: 0,
|
|
2088
|
+
cancel: () => cancel(turn),
|
|
2089
|
+
completion: completion.promise,
|
|
2090
|
+
followUpDispatches: /* @__PURE__ */ new Set(),
|
|
2091
|
+
receivedFollowUps: 0,
|
|
2092
|
+
receivedFollowUpEvents: /* @__PURE__ */ new Set(),
|
|
2093
|
+
followUpSubmissionIds: /* @__PURE__ */ new Set(),
|
|
2094
|
+
resolveCompletion: completion.resolve,
|
|
2095
|
+
response: response.promise,
|
|
2096
|
+
resolveResponse: response.resolve
|
|
2097
|
+
};
|
|
2098
|
+
return turn;
|
|
2099
|
+
}
|
|
2100
|
+
async function followSteeredTurns(turn, events, isActive) {
|
|
2101
|
+
while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
|
|
2102
|
+
if (turn.receivedFollowUps >= turn.acceptedFollowUps) return;
|
|
2103
|
+
for await (const event of events) {
|
|
2104
|
+
if (!isActive()) return;
|
|
2105
|
+
if (turn.receivedFollowUpEvents.delete(event)) turn.receivedFollowUps += 1;
|
|
2106
|
+
if (isCurrentTurnBoundaryEvent(event)) {
|
|
2107
|
+
while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
|
|
2108
|
+
if (turn.receivedFollowUps >= turn.acceptedFollowUps) return;
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
}
|
|
2112
|
+
async function waitWithSignal(promise, signal) {
|
|
2113
|
+
if (signal === void 0) return await promise;
|
|
2114
|
+
const aborted = Promise.withResolvers();
|
|
2115
|
+
const onAbort = () => aborted.reject(signal.reason);
|
|
2116
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2117
|
+
if (signal.aborted) onAbort();
|
|
2118
|
+
try {
|
|
2119
|
+
return await Promise.race([aborted.promise, promise]);
|
|
2120
|
+
} finally {
|
|
2121
|
+
signal.removeEventListener("abort", onAbort);
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
1868
2124
|
|
|
1869
2125
|
//#endregion
|
|
1870
2126
|
//#region src/client/eve-agent-store.ts
|
|
1871
2127
|
const detachStore = Symbol("detachEveAgentStore");
|
|
2128
|
+
const attachStore = Symbol("attachEveAgentStore");
|
|
1872
2129
|
var EveAgentStore = class {
|
|
1873
2130
|
#client;
|
|
2131
|
+
#autoPrewarm;
|
|
2132
|
+
#attached = false;
|
|
2133
|
+
#stream;
|
|
2134
|
+
#pendingAuthorizations = /* @__PURE__ */ new Set();
|
|
1874
2135
|
#externalSession;
|
|
1875
2136
|
#optimistic;
|
|
1876
|
-
#
|
|
2137
|
+
#projection;
|
|
1877
2138
|
#subscribers = /* @__PURE__ */ new Set();
|
|
1878
2139
|
#seenEvents = createEventDeduper();
|
|
1879
2140
|
#activeTurn;
|
|
1880
2141
|
#callbacks = {};
|
|
1881
|
-
#data;
|
|
1882
2142
|
#error;
|
|
1883
2143
|
#events;
|
|
1884
2144
|
#pendingMessageSubmissions = [];
|
|
1885
|
-
#
|
|
2145
|
+
#prewarmGeneration = 0;
|
|
2146
|
+
#prewarmPromise;
|
|
2147
|
+
#prewarmController;
|
|
1886
2148
|
#resumePromise;
|
|
1887
2149
|
#session;
|
|
1888
2150
|
#snapshot;
|
|
1889
2151
|
#status = "ready";
|
|
1890
2152
|
constructor(init) {
|
|
2153
|
+
this.#autoPrewarm = init.prewarm ?? false;
|
|
1891
2154
|
this.#externalSession = init.session !== void 0;
|
|
1892
2155
|
this.#client = this.#externalSession ? void 0 : new Client({
|
|
1893
2156
|
auth: init.auth,
|
|
@@ -1895,13 +2158,14 @@ var EveAgentStore = class {
|
|
|
1895
2158
|
host: init.host ?? ""
|
|
1896
2159
|
});
|
|
1897
2160
|
const initialEvents = [];
|
|
1898
|
-
for (const event of init.initialEvents ?? [])
|
|
2161
|
+
for (const event of init.initialEvents ?? []) {
|
|
2162
|
+
if (this.#seenEvents.admit(event)) initialEvents.push(event);
|
|
2163
|
+
updatePendingAuthorizations(this.#pendingAuthorizations, event);
|
|
2164
|
+
}
|
|
1899
2165
|
this.#events = initialEvents;
|
|
1900
|
-
this.#
|
|
2166
|
+
this.#projection = new EveAgentProjection(init.reducer, this.#events);
|
|
1901
2167
|
this.#optimistic = init.optimistic ?? true;
|
|
1902
|
-
this.#reducer = init.reducer;
|
|
1903
2168
|
this.#session = init.session ?? (init.initialSession === void 0 ? void 0 : this.#client?.sessions.attach(init.initialSession.sessionId, { streamIndex: init.initialSession.streamIndex }));
|
|
1904
|
-
this.#data = this.#reduceProjectionEvents(this.#projectionEvents);
|
|
1905
2169
|
this.#snapshot = this.#createSnapshot();
|
|
1906
2170
|
}
|
|
1907
2171
|
get snapshot() {
|
|
@@ -1916,31 +2180,63 @@ var EveAgentStore = class {
|
|
|
1916
2180
|
this.#subscribers.delete(callback);
|
|
1917
2181
|
};
|
|
1918
2182
|
}
|
|
2183
|
+
prewarm() {
|
|
2184
|
+
if (this.#prewarmPromise !== void 0) return this.#prewarmPromise;
|
|
2185
|
+
if (this.#session !== void 0 || this.#externalSession) return Promise.resolve();
|
|
2186
|
+
if (this.#activeTurn !== void 0) return this.#activeTurn.response.then((response) => {
|
|
2187
|
+
if (response === void 0) throw this.#error ?? new DOMException("Session creation was aborted.", "AbortError");
|
|
2188
|
+
});
|
|
2189
|
+
const client = this.#client;
|
|
2190
|
+
if (client === void 0) return Promise.reject(/* @__PURE__ */ new Error("This eve agent store does not own a session client."));
|
|
2191
|
+
const generation = this.#prewarmGeneration;
|
|
2192
|
+
const controller = new AbortController();
|
|
2193
|
+
this.#prewarmController = controller;
|
|
2194
|
+
const promise = (async () => {
|
|
2195
|
+
try {
|
|
2196
|
+
const created = await client.sessions.create({ signal: controller.signal });
|
|
2197
|
+
if (generation !== this.#prewarmGeneration) return;
|
|
2198
|
+
this.#session = created.session;
|
|
2199
|
+
this.#error = void 0;
|
|
2200
|
+
if (this.#status === "error") this.#status = "ready";
|
|
2201
|
+
this.#callbacks.onSessionChange?.(created.session.state);
|
|
2202
|
+
this.#publish();
|
|
2203
|
+
this.#ensureStream();
|
|
2204
|
+
} catch (error) {
|
|
2205
|
+
if (generation === this.#prewarmGeneration && this.#activeTurn === void 0 && this.#error === void 0) {
|
|
2206
|
+
this.#error = toError(error);
|
|
2207
|
+
this.#status = "error";
|
|
2208
|
+
this.#callbacks.onError?.(this.#error);
|
|
2209
|
+
this.#publish();
|
|
2210
|
+
}
|
|
2211
|
+
throw error;
|
|
2212
|
+
}
|
|
2213
|
+
})();
|
|
2214
|
+
this.#prewarmPromise = promise;
|
|
2215
|
+
const clear = () => {
|
|
2216
|
+
if (this.#prewarmPromise === promise) {
|
|
2217
|
+
this.#prewarmPromise = void 0;
|
|
2218
|
+
this.#prewarmController = void 0;
|
|
2219
|
+
}
|
|
2220
|
+
};
|
|
2221
|
+
promise.then(clear, clear);
|
|
2222
|
+
return promise;
|
|
2223
|
+
}
|
|
1919
2224
|
async send(input) {
|
|
2225
|
+
return await this.#submit(input, this.#callbacks.prepareSend);
|
|
2226
|
+
}
|
|
2227
|
+
async #submit(input, prepareSend) {
|
|
1920
2228
|
if (this.#activeTurn !== void 0) {
|
|
1921
2229
|
if (this.#status === "resuming") throw new Error("eve session is resuming.");
|
|
1922
|
-
return await this.#sendFollowUp(this.#activeTurn, input);
|
|
2230
|
+
return await this.#sendFollowUp(this.#activeTurn, input, prepareSend);
|
|
1923
2231
|
}
|
|
1924
|
-
const
|
|
1925
|
-
const completion = Promise.withResolvers();
|
|
1926
|
-
const turn = {
|
|
1927
|
-
abortController: new AbortController(),
|
|
1928
|
-
acceptedFollowUps: 0,
|
|
1929
|
-
cancel: () => turn.acceptedFollowUps > 0 && this.#session !== void 0 ? this.#session.cancel() : response.promise.then((messageResponse) => messageResponse === void 0 ? { status: "no_active_turn" } : messageResponse.cancel()),
|
|
1930
|
-
completion: completion.promise,
|
|
1931
|
-
followUpDispatches: /* @__PURE__ */ new Set(),
|
|
1932
|
-
receivedFollowUps: 0,
|
|
1933
|
-
followUpSubmissionIds: /* @__PURE__ */ new Set(),
|
|
1934
|
-
resolveCompletion: completion.resolve,
|
|
1935
|
-
response: response.promise,
|
|
1936
|
-
resolveResponse: response.resolve
|
|
1937
|
-
};
|
|
2232
|
+
const turn = createActiveTurn((turn) => turn.acceptedFollowUps > 0 && this.#session !== void 0 ? this.#session.cancel() : turn.response.then((response) => response === void 0 ? { status: "no_active_turn" } : response.cancel()));
|
|
1938
2233
|
this.#activeTurn = turn;
|
|
1939
2234
|
this.#error = void 0;
|
|
1940
2235
|
this.#status = "submitted";
|
|
1941
2236
|
this.#publish();
|
|
2237
|
+
let reader;
|
|
1942
2238
|
try {
|
|
1943
|
-
const preparedInput = await
|
|
2239
|
+
const preparedInput = await (prepareSend === void 0 ? input : waitWithSignal(Promise.resolve(prepareSend(input)), createAbortSignal(input.signal, turn.abortController.signal)));
|
|
1944
2240
|
assertExclusiveTurnInput(preparedInput);
|
|
1945
2241
|
if (!this.#isActiveTurn(turn)) return;
|
|
1946
2242
|
this.#projectOptimisticMessage(preparedInput);
|
|
@@ -1950,15 +2246,17 @@ var EveAgentStore = class {
|
|
|
1950
2246
|
...preparedInput,
|
|
1951
2247
|
signal: createAbortSignal(preparedInput.signal, turn.abortController.signal)
|
|
1952
2248
|
};
|
|
1953
|
-
const
|
|
2249
|
+
const dispatched = await this.#dispatchTurn(turnInput);
|
|
2250
|
+
const response = dispatched.response;
|
|
2251
|
+
reader = dispatched.reader;
|
|
1954
2252
|
if (!this.#isActiveTurn(turn)) return;
|
|
1955
2253
|
turn.resolveResponse(response);
|
|
1956
|
-
for await (const event of response) {
|
|
2254
|
+
for await (const event of consumeMessageResponse(response, reader)) {
|
|
1957
2255
|
if (!this.#isActiveTurn(turn)) return;
|
|
1958
|
-
|
|
2256
|
+
if (turn.receivedFollowUpEvents.delete(event)) turn.receivedFollowUps += 1;
|
|
1959
2257
|
}
|
|
1960
2258
|
if (!this.#isActiveTurn(turn)) return;
|
|
1961
|
-
await this.#
|
|
2259
|
+
await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
|
|
1962
2260
|
if (!this.#isActiveTurn(turn)) return;
|
|
1963
2261
|
this.#status = this.#error === void 0 ? "ready" : "error";
|
|
1964
2262
|
} catch (error) {
|
|
@@ -1967,20 +2265,15 @@ var EveAgentStore = class {
|
|
|
1967
2265
|
this.#status = "ready";
|
|
1968
2266
|
this.#failPendingMessageSubmission(toError(error));
|
|
1969
2267
|
} else {
|
|
1970
|
-
this.#error
|
|
2268
|
+
const reported = this.#error !== void 0;
|
|
2269
|
+
this.#error ??= toError(error);
|
|
1971
2270
|
this.#status = "error";
|
|
1972
2271
|
this.#failPendingMessageSubmission(this.#error);
|
|
1973
|
-
this.#callbacks.onError?.(this.#error);
|
|
2272
|
+
if (!reported) this.#callbacks.onError?.(this.#error);
|
|
1974
2273
|
}
|
|
1975
2274
|
} finally {
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
this.#activeTurn = void 0;
|
|
1979
|
-
this.#callbacks.onSessionChange?.(this.#session?.state);
|
|
1980
|
-
this.#publish();
|
|
1981
|
-
this.#callbacks.onFinish?.(this.#snapshot);
|
|
1982
|
-
turn.resolveCompletion();
|
|
1983
|
-
}
|
|
2275
|
+
reader?.[Symbol.dispose]();
|
|
2276
|
+
this.#finishTurn(turn);
|
|
1984
2277
|
}
|
|
1985
2278
|
}
|
|
1986
2279
|
resume() {
|
|
@@ -1996,70 +2289,34 @@ var EveAgentStore = class {
|
|
|
1996
2289
|
async #resume() {
|
|
1997
2290
|
if (this.#status === "resuming" || this.#status === "streaming" || this.#status === "submitted") throw new Error("eve session is already processing a turn.");
|
|
1998
2291
|
if (this.#session === void 0) throw new Error("An eve session is required before resuming.");
|
|
1999
|
-
const response = Promise.withResolvers();
|
|
2000
|
-
const completion = Promise.withResolvers();
|
|
2001
2292
|
const session = this.#session;
|
|
2002
|
-
const turn =
|
|
2003
|
-
abortController: new AbortController(),
|
|
2004
|
-
acceptedFollowUps: 0,
|
|
2005
|
-
cancel: () => session.cancel(),
|
|
2006
|
-
completion: completion.promise,
|
|
2007
|
-
followUpDispatches: /* @__PURE__ */ new Set(),
|
|
2008
|
-
receivedFollowUps: 0,
|
|
2009
|
-
followUpSubmissionIds: /* @__PURE__ */ new Set(),
|
|
2010
|
-
resolveCompletion: completion.resolve,
|
|
2011
|
-
response: response.promise,
|
|
2012
|
-
resolveResponse: response.resolve
|
|
2013
|
-
};
|
|
2293
|
+
const turn = createActiveTurn(() => session.cancel());
|
|
2014
2294
|
this.#activeTurn = turn;
|
|
2015
2295
|
turn.resolveResponse(void 0);
|
|
2016
2296
|
this.#error = void 0;
|
|
2017
2297
|
this.#status = "resuming";
|
|
2018
2298
|
this.#publish();
|
|
2019
2299
|
try {
|
|
2020
|
-
const
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
})) {
|
|
2027
|
-
if (!this.#isActiveTurn(turn)) return;
|
|
2028
|
-
replayed.push(event);
|
|
2029
|
-
this.#acceptServerEvent(event, {
|
|
2030
|
-
publish: false,
|
|
2031
|
-
transitionToStreaming: false
|
|
2032
|
-
});
|
|
2033
|
-
}
|
|
2300
|
+
const stream = this.#ensureStream({
|
|
2301
|
+
catchUp: true,
|
|
2302
|
+
startIndex: this.#events.length === session.state.streamIndex ? session.state.streamIndex : 0
|
|
2303
|
+
});
|
|
2304
|
+
using reader = stream.subscribe(turn.abortController.signal);
|
|
2305
|
+
await stream.caughtUp;
|
|
2034
2306
|
if (!this.#isActiveTurn(turn)) return;
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
if (this.#error === void 0 && (
|
|
2039
|
-
|
|
2040
|
-
if (!replaySettled) this.#status = "streaming";
|
|
2307
|
+
reader.discard();
|
|
2308
|
+
const tail = this.#events.at(-1);
|
|
2309
|
+
if (tail !== void 0) this.#applyTerminalStreamFailure(tail);
|
|
2310
|
+
if (tail !== void 0 && this.#error === void 0 && !isSettledSessionTail(this.#events)) {
|
|
2311
|
+
this.#status = "streaming";
|
|
2041
2312
|
this.#publish();
|
|
2042
|
-
|
|
2043
|
-
for (;;) {
|
|
2044
|
-
for await (const event of session.stream({
|
|
2045
|
-
follow: followLive ? void 0 : false,
|
|
2046
|
-
signal: turn.abortController.signal
|
|
2047
|
-
})) {
|
|
2048
|
-
if (!this.#isActiveTurn(turn)) return;
|
|
2049
|
-
replayed.push(event);
|
|
2050
|
-
this.#acceptServerEvent(event);
|
|
2051
|
-
updatePendingAuthorizations(pendingAuthorizations, event);
|
|
2052
|
-
if (followLive && isCurrentTurnBoundaryEvent(event) && (event.type !== "session.waiting" || pendingAuthorizations.size === 0)) break;
|
|
2053
|
-
}
|
|
2313
|
+
for await (const event of reader) {
|
|
2054
2314
|
if (!this.#isActiveTurn(turn)) return;
|
|
2055
|
-
if (
|
|
2056
|
-
|
|
2315
|
+
if (turn.receivedFollowUpEvents.delete(event)) turn.receivedFollowUps += 1;
|
|
2316
|
+
if (isCurrentTurnBoundaryEvent(event) && this.#pendingAuthorizations.size === 0) break;
|
|
2057
2317
|
}
|
|
2058
|
-
} else {
|
|
2059
|
-
this.#status = this.#error === void 0 ? "ready" : "error";
|
|
2060
|
-
this.#publish();
|
|
2061
2318
|
}
|
|
2062
|
-
await this.#
|
|
2319
|
+
await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
|
|
2063
2320
|
if (this.#isActiveTurn(turn)) this.#status = this.#error === void 0 ? "ready" : "error";
|
|
2064
2321
|
} catch (error) {
|
|
2065
2322
|
if (!this.#isActiveTurn(turn)) return;
|
|
@@ -2070,61 +2327,81 @@ var EveAgentStore = class {
|
|
|
2070
2327
|
this.#callbacks.onError?.(this.#error);
|
|
2071
2328
|
}
|
|
2072
2329
|
} finally {
|
|
2073
|
-
|
|
2074
|
-
turn.resolveResponse(void 0);
|
|
2075
|
-
this.#activeTurn = void 0;
|
|
2076
|
-
this.#callbacks.onSessionChange?.(session.state);
|
|
2077
|
-
this.#publish();
|
|
2078
|
-
this.#callbacks.onFinish?.(this.#snapshot);
|
|
2079
|
-
turn.resolveCompletion();
|
|
2080
|
-
}
|
|
2330
|
+
this.#finishTurn(turn);
|
|
2081
2331
|
}
|
|
2082
2332
|
}
|
|
2083
2333
|
cancel() {
|
|
2084
2334
|
const turn = this.#activeTurn;
|
|
2085
|
-
if (turn === void 0) return Promise.resolve({ status: "no_active_turn" });
|
|
2335
|
+
if (turn === void 0) return this.#status === "streaming" && this.#session !== void 0 ? this.#session.cancel() : Promise.resolve({ status: "no_active_turn" });
|
|
2086
2336
|
return turn.cancel();
|
|
2087
2337
|
}
|
|
2338
|
+
[attachStore]() {
|
|
2339
|
+
this.#attached = true;
|
|
2340
|
+
if (this.#autoPrewarm && this.#session === void 0) this.prewarm().catch(() => {});
|
|
2341
|
+
}
|
|
2088
2342
|
[detachStore]() {
|
|
2343
|
+
this.#attached = false;
|
|
2344
|
+
this.#stream?.close();
|
|
2345
|
+
this.#stream = void 0;
|
|
2089
2346
|
this.#activeTurn?.abortController.abort();
|
|
2347
|
+
this.#resetPrewarm();
|
|
2348
|
+
this.#resumePromise = void 0;
|
|
2090
2349
|
}
|
|
2091
2350
|
reset() {
|
|
2351
|
+
this.#stream?.close();
|
|
2352
|
+
this.#stream = void 0;
|
|
2353
|
+
this.#pendingAuthorizations.clear();
|
|
2092
2354
|
const turn = this.#activeTurn;
|
|
2093
2355
|
this.#activeTurn = void 0;
|
|
2094
2356
|
turn?.resolveResponse(void 0);
|
|
2095
2357
|
turn?.resolveCompletion();
|
|
2096
2358
|
turn?.abortController.abort();
|
|
2359
|
+
this.#resetPrewarm();
|
|
2360
|
+
this.#resumePromise = void 0;
|
|
2097
2361
|
if (!this.#externalSession) this.#session = void 0;
|
|
2098
2362
|
this.#events = [];
|
|
2099
2363
|
this.#seenEvents = createEventDeduper();
|
|
2100
2364
|
this.#pendingMessageSubmissions = [];
|
|
2101
|
-
this.#
|
|
2102
|
-
this.#data = this.#reducer.initial();
|
|
2365
|
+
this.#projection.reset();
|
|
2103
2366
|
this.#error = void 0;
|
|
2104
2367
|
this.#status = "ready";
|
|
2105
2368
|
this.#callbacks.onSessionChange?.(this.#session?.state);
|
|
2106
2369
|
this.#publish();
|
|
2370
|
+
if (this.#autoPrewarm && this.#attached) this.prewarm().catch(() => {});
|
|
2107
2371
|
}
|
|
2108
|
-
async #sendFollowUp(turn, input) {
|
|
2372
|
+
async #sendFollowUp(turn, input, prepareSend) {
|
|
2109
2373
|
if (input.message === void 0 || input.turnPolicy !== "steer") throw new Error("eve session is already processing a turn. Send a message with turnPolicy: \"steer\" to guide it at the next boundary.");
|
|
2110
|
-
const
|
|
2374
|
+
const generation = this.#prewarmGeneration;
|
|
2375
|
+
const signal = createAbortSignal(input.signal, turn.abortController.signal);
|
|
2376
|
+
const preparedInput = await waitWithSignal(Promise.resolve(prepareSend?.(input)), signal) ?? input;
|
|
2377
|
+
if (generation !== this.#prewarmGeneration) return;
|
|
2111
2378
|
assertExclusiveTurnInput(preparedInput);
|
|
2112
2379
|
if (preparedInput.message === void 0 || preparedInput.turnPolicy !== "steer") throw new Error("An in-flight follow-up requires a message with turnPolicy: \"steer\".");
|
|
2113
|
-
if (!this.#isActiveTurn(turn)) return await this
|
|
2380
|
+
if (!this.#isActiveTurn(turn)) return await this.#submit(preparedInput);
|
|
2114
2381
|
const submissionId = this.#projectOptimisticMessage(preparedInput);
|
|
2115
2382
|
if (submissionId !== void 0) turn.followUpSubmissionIds.add(submissionId);
|
|
2116
2383
|
this.#publish();
|
|
2384
|
+
this.#ensureStream({
|
|
2385
|
+
headers: preparedInput.headers,
|
|
2386
|
+
streamReconnectPolicy: preparedInput.streamReconnectPolicy
|
|
2387
|
+
});
|
|
2117
2388
|
let dispatch;
|
|
2118
2389
|
dispatch = (async () => {
|
|
2119
2390
|
try {
|
|
2120
|
-
|
|
2391
|
+
const signal = createAbortSignal(preparedInput.signal, turn.abortController.signal);
|
|
2392
|
+
await waitWithSignal(turn.response, signal);
|
|
2121
2393
|
if (!this.#isActiveTurn(turn) || this.#session === void 0) throw new Error("The active eve turn ended before the follow-up could be sent.");
|
|
2122
2394
|
const { message, ...options } = preparedInput;
|
|
2123
|
-
await this.#session.send(message,
|
|
2395
|
+
await this.#session.send(message, {
|
|
2396
|
+
...options,
|
|
2397
|
+
signal
|
|
2398
|
+
});
|
|
2124
2399
|
turn.acceptedFollowUps += 1;
|
|
2125
2400
|
} catch (error) {
|
|
2126
|
-
this.#
|
|
2127
|
-
|
|
2401
|
+
if (this.#isActiveTurn(turn)) {
|
|
2402
|
+
this.#failPendingMessageSubmission(toError(error), submissionId);
|
|
2403
|
+
this.#publish();
|
|
2404
|
+
}
|
|
2128
2405
|
throw error;
|
|
2129
2406
|
} finally {
|
|
2130
2407
|
turn.followUpDispatches.delete(dispatch);
|
|
@@ -2134,38 +2411,94 @@ var EveAgentStore = class {
|
|
|
2134
2411
|
await dispatch;
|
|
2135
2412
|
await turn.completion;
|
|
2136
2413
|
}
|
|
2137
|
-
async #
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2414
|
+
async #dispatchTurn(input) {
|
|
2415
|
+
const streamOptions = {
|
|
2416
|
+
headers: input.headers,
|
|
2417
|
+
streamReconnectPolicy: input.streamReconnectPolicy
|
|
2418
|
+
};
|
|
2419
|
+
if (this.#prewarmPromise !== void 0) {
|
|
2420
|
+
await waitWithSignal(this.#prewarmPromise.catch((error) => {
|
|
2421
|
+
if (this.#session !== void 0) throw error;
|
|
2422
|
+
}), input.signal);
|
|
2423
|
+
input.signal?.throwIfAborted();
|
|
2424
|
+
}
|
|
2425
|
+
if (this.#session === void 0) {
|
|
2426
|
+
if (this.#client === void 0) throw new Error("An external eve session is required before sending.");
|
|
2427
|
+
if (input.message === void 0) throw new Error("Cannot answer an input request before the session starts.");
|
|
2428
|
+
const created = await this.#client.sessions.create({
|
|
2429
|
+
...input,
|
|
2430
|
+
message: input.message
|
|
2431
|
+
});
|
|
2432
|
+
input.signal?.throwIfAborted();
|
|
2433
|
+
this.#session = created.session;
|
|
2434
|
+
this.#callbacks.onSessionChange?.(created.session.state);
|
|
2435
|
+
this.#publish();
|
|
2436
|
+
return {
|
|
2437
|
+
response: created.response,
|
|
2438
|
+
reader: this.#ensureStream(streamOptions).subscribe(input.signal)
|
|
2439
|
+
};
|
|
2440
|
+
}
|
|
2441
|
+
const reader = this.#ensureStream(streamOptions).subscribe(input.signal);
|
|
2442
|
+
try {
|
|
2443
|
+
if (input.inputResponses === void 0) {
|
|
2444
|
+
const { message, ...options } = input;
|
|
2445
|
+
return {
|
|
2446
|
+
response: await this.#session.send(message, options),
|
|
2447
|
+
reader
|
|
2448
|
+
};
|
|
2146
2449
|
}
|
|
2450
|
+
const { inputResponses, ...options } = input;
|
|
2451
|
+
return {
|
|
2452
|
+
response: await this.#session.respond(inputResponses, options),
|
|
2453
|
+
reader
|
|
2454
|
+
};
|
|
2455
|
+
} catch (error) {
|
|
2456
|
+
reader[Symbol.dispose]();
|
|
2457
|
+
throw error;
|
|
2147
2458
|
}
|
|
2148
2459
|
}
|
|
2149
|
-
|
|
2150
|
-
if (this.#
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2460
|
+
#ensureStream(options = {}) {
|
|
2461
|
+
if (this.#stream !== void 0 && !this.#stream.ended) {
|
|
2462
|
+
this.#stream.setOptions(options);
|
|
2463
|
+
return this.#stream;
|
|
2464
|
+
}
|
|
2465
|
+
if (this.#session === void 0) throw new Error("A session is required before opening its stream.");
|
|
2466
|
+
const session = this.#session;
|
|
2467
|
+
const generation = this.#prewarmGeneration;
|
|
2468
|
+
this.#stream = new SessionEventStream(session, {
|
|
2469
|
+
...options,
|
|
2470
|
+
onEvent: (event) => {
|
|
2471
|
+
if (generation === this.#prewarmGeneration) this.#acceptServerEvent(event);
|
|
2472
|
+
},
|
|
2473
|
+
onError: (error) => {
|
|
2474
|
+
if (generation !== this.#prewarmGeneration) return;
|
|
2475
|
+
this.#stream = void 0;
|
|
2476
|
+
if (this.#activeTurn !== void 0) return;
|
|
2477
|
+
this.#error = toError(error);
|
|
2478
|
+
this.#status = "error";
|
|
2479
|
+
this.#callbacks.onError?.(this.#error);
|
|
2480
|
+
this.#publish();
|
|
2481
|
+
}
|
|
2155
2482
|
});
|
|
2156
|
-
this.#
|
|
2157
|
-
this.#callbacks.onSessionChange?.(created.session.state);
|
|
2158
|
-
this.#publish();
|
|
2159
|
-
return created.response;
|
|
2483
|
+
return this.#stream;
|
|
2160
2484
|
}
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2485
|
+
#resetPrewarm() {
|
|
2486
|
+
this.#prewarmGeneration += 1;
|
|
2487
|
+
this.#prewarmController?.abort();
|
|
2488
|
+
this.#prewarmController = void 0;
|
|
2489
|
+
this.#prewarmPromise = void 0;
|
|
2490
|
+
}
|
|
2491
|
+
#finishTurn(turn) {
|
|
2492
|
+
if (!this.#isActiveTurn(turn)) return;
|
|
2493
|
+
turn.resolveResponse(void 0);
|
|
2494
|
+
this.#activeTurn = void 0;
|
|
2495
|
+
try {
|
|
2496
|
+
this.#callbacks.onSessionChange?.(this.#session?.state);
|
|
2497
|
+
this.#publish();
|
|
2498
|
+
this.#callbacks.onFinish?.(this.#snapshot);
|
|
2499
|
+
} finally {
|
|
2500
|
+
turn.resolveCompletion();
|
|
2166
2501
|
}
|
|
2167
|
-
const { inputResponses, ...options } = input;
|
|
2168
|
-
return await this.#session.respond(inputResponses, options);
|
|
2169
2502
|
}
|
|
2170
2503
|
#isActiveTurn(turn) {
|
|
2171
2504
|
return this.#activeTurn === turn;
|
|
@@ -2179,7 +2512,7 @@ var EveAgentStore = class {
|
|
|
2179
2512
|
message: summarizeUserContent(input.message)
|
|
2180
2513
|
};
|
|
2181
2514
|
this.#pendingMessageSubmissions = [...this.#pendingMessageSubmissions, pending];
|
|
2182
|
-
if (this.#optimistic) this.#
|
|
2515
|
+
if (this.#optimistic) this.#projection.append({
|
|
2183
2516
|
data: {
|
|
2184
2517
|
createdAt: pending.createdAt,
|
|
2185
2518
|
message: pending.message,
|
|
@@ -2191,7 +2524,7 @@ var EveAgentStore = class {
|
|
|
2191
2524
|
}
|
|
2192
2525
|
#projectInputResponses(input) {
|
|
2193
2526
|
if (input.inputResponses === void 0 || input.inputResponses.length === 0) return;
|
|
2194
|
-
this.#
|
|
2527
|
+
this.#projection.append({
|
|
2195
2528
|
data: {
|
|
2196
2529
|
createdAt: Date.now(),
|
|
2197
2530
|
responses: input.inputResponses
|
|
@@ -2199,25 +2532,33 @@ var EveAgentStore = class {
|
|
|
2199
2532
|
type: "client.input.responded"
|
|
2200
2533
|
});
|
|
2201
2534
|
}
|
|
2202
|
-
#acceptServerEvent(event
|
|
2535
|
+
#acceptServerEvent(event) {
|
|
2203
2536
|
if (!this.#seenEvents.admit(event)) return;
|
|
2537
|
+
const wasStreaming = this.#status === "streaming";
|
|
2538
|
+
updatePendingAuthorizations(this.#pendingAuthorizations, event);
|
|
2204
2539
|
this.#events = [...this.#events, event];
|
|
2205
2540
|
this.#applyServerEvent(event);
|
|
2206
2541
|
this.#callbacks.onEvent?.(event);
|
|
2207
|
-
if (options.transitionToStreaming ?? true) this.#status = "streaming";
|
|
2208
2542
|
this.#applyTerminalStreamFailure(event);
|
|
2209
|
-
|
|
2543
|
+
const settled = isCurrentTurnBoundaryEvent(event) && this.#pendingAuthorizations.size === 0;
|
|
2544
|
+
if (this.#status !== "resuming" && this.#error === void 0) {
|
|
2545
|
+
if ("data" in event && "turnId" in event.data) this.#status = "streaming";
|
|
2546
|
+
if (this.#activeTurn === void 0 && settled) this.#status = "ready";
|
|
2547
|
+
}
|
|
2548
|
+
this.#callbacks.onSessionChange?.(this.#session?.state);
|
|
2549
|
+
this.#publish();
|
|
2550
|
+
if (this.#activeTurn === void 0 && wasStreaming && settled) this.#callbacks.onFinish?.(this.#snapshot);
|
|
2210
2551
|
}
|
|
2211
2552
|
#applyServerEvent(event) {
|
|
2212
2553
|
const pendingSubmission = this.#pendingMessageSubmissions[0];
|
|
2213
2554
|
if (event.type === "message.received" && pendingSubmission !== void 0) {
|
|
2214
2555
|
const submissionId = pendingSubmission.id;
|
|
2215
|
-
if (this.#activeTurn?.followUpSubmissionIds.delete(submissionId)) this.#activeTurn.
|
|
2556
|
+
if (this.#activeTurn?.followUpSubmissionIds.delete(submissionId)) this.#activeTurn.receivedFollowUpEvents.add(event);
|
|
2216
2557
|
this.#pendingMessageSubmissions = this.#pendingMessageSubmissions.slice(1);
|
|
2217
|
-
this.#
|
|
2558
|
+
this.#projection.replace((candidate) => candidate.type === "client.message.submitted" && candidate.data.submissionId === submissionId, event);
|
|
2218
2559
|
return;
|
|
2219
2560
|
}
|
|
2220
|
-
this.#
|
|
2561
|
+
this.#projection.append(event);
|
|
2221
2562
|
}
|
|
2222
2563
|
#applyTerminalStreamFailure(event) {
|
|
2223
2564
|
const error = toTerminalStreamFailureError(event);
|
|
@@ -2233,7 +2574,7 @@ var EveAgentStore = class {
|
|
|
2233
2574
|
const pending = submissionId === void 0 ? this.#pendingMessageSubmissions[0] : this.#pendingMessageSubmissions.find((candidate) => candidate.id === submissionId);
|
|
2234
2575
|
if (pending === void 0) return;
|
|
2235
2576
|
this.#pendingMessageSubmissions = this.#pendingMessageSubmissions.filter((candidate) => candidate.id !== pending.id);
|
|
2236
|
-
this.#
|
|
2577
|
+
this.#projection.replace((event) => event.type === "client.message.submitted" && event.data.submissionId === pending.id, {
|
|
2237
2578
|
data: {
|
|
2238
2579
|
createdAt: pending.createdAt,
|
|
2239
2580
|
error: { message: error.message },
|
|
@@ -2243,30 +2584,9 @@ var EveAgentStore = class {
|
|
|
2243
2584
|
type: "client.message.failed"
|
|
2244
2585
|
});
|
|
2245
2586
|
}
|
|
2246
|
-
#appendProjectionEvent(event) {
|
|
2247
|
-
this.#projectionEvents = [...this.#projectionEvents, event];
|
|
2248
|
-
this.#data = this.#reducer.reduce(this.#data, event);
|
|
2249
|
-
}
|
|
2250
|
-
#replaceProjectionEvent(predicate, replacement) {
|
|
2251
|
-
let replaced = false;
|
|
2252
|
-
this.#projectionEvents = this.#projectionEvents.map((event) => {
|
|
2253
|
-
if (!replaced && predicate(event)) {
|
|
2254
|
-
replaced = true;
|
|
2255
|
-
return replacement;
|
|
2256
|
-
}
|
|
2257
|
-
return event;
|
|
2258
|
-
});
|
|
2259
|
-
if (!replaced) this.#projectionEvents = [...this.#projectionEvents, replacement];
|
|
2260
|
-
this.#data = this.#reduceProjectionEvents(this.#projectionEvents);
|
|
2261
|
-
}
|
|
2262
|
-
#reduceProjectionEvents(events) {
|
|
2263
|
-
let data = this.#reducer.initial();
|
|
2264
|
-
for (const event of events) data = this.#reducer.reduce(data, event);
|
|
2265
|
-
return data;
|
|
2266
|
-
}
|
|
2267
2587
|
#createSnapshot() {
|
|
2268
2588
|
return {
|
|
2269
|
-
data: this.#data,
|
|
2589
|
+
data: this.#projection.data,
|
|
2270
2590
|
error: this.#error,
|
|
2271
2591
|
events: this.#events,
|
|
2272
2592
|
session: this.#session?.state,
|
|
@@ -2281,6 +2601,9 @@ var EveAgentStore = class {
|
|
|
2281
2601
|
function detachEveAgentStore(store) {
|
|
2282
2602
|
store[detachStore]();
|
|
2283
2603
|
}
|
|
2604
|
+
function attachEveAgentStore(store) {
|
|
2605
|
+
store[attachStore]();
|
|
2606
|
+
}
|
|
2284
2607
|
|
|
2285
2608
|
//#endregion
|
|
2286
2609
|
//#region src/client/agent-host.ts
|
|
@@ -2937,7 +3260,6 @@ var SvelteEveAgent = class {
|
|
|
2937
3260
|
});
|
|
2938
3261
|
return () => {
|
|
2939
3262
|
unsubscribe();
|
|
2940
|
-
detachEveAgentStore(store);
|
|
2941
3263
|
};
|
|
2942
3264
|
});
|
|
2943
3265
|
}
|
|
@@ -2967,6 +3289,9 @@ var SvelteEveAgent = class {
|
|
|
2967
3289
|
reset = () => {
|
|
2968
3290
|
this.#store.reset();
|
|
2969
3291
|
};
|
|
3292
|
+
prewarm = () => {
|
|
3293
|
+
return this.#store.prewarm();
|
|
3294
|
+
};
|
|
2970
3295
|
resume = () => {
|
|
2971
3296
|
return this.#store.resume();
|
|
2972
3297
|
};
|
|
@@ -2996,6 +3321,7 @@ function useEveAgent(options = {}) {
|
|
|
2996
3321
|
initialEvents: options.initialEvents,
|
|
2997
3322
|
initialSession: options.initialSession,
|
|
2998
3323
|
optimistic: options.optimistic,
|
|
3324
|
+
prewarm: options.prewarm,
|
|
2999
3325
|
reducer,
|
|
3000
3326
|
session: options.session
|
|
3001
3327
|
});
|
|
@@ -3006,7 +3332,11 @@ function useEveAgent(options = {}) {
|
|
|
3006
3332
|
onSessionChange: options.onSessionChange,
|
|
3007
3333
|
prepareSend: options.prepareSend
|
|
3008
3334
|
});
|
|
3009
|
-
if ("window" in globalThis
|
|
3335
|
+
if ("window" in globalThis) onMount(() => {
|
|
3336
|
+
attachEveAgentStore(store);
|
|
3337
|
+
if (options.resume) store.resume();
|
|
3338
|
+
return () => detachEveAgentStore(store);
|
|
3339
|
+
});
|
|
3010
3340
|
return new SvelteEveAgent(store);
|
|
3011
3341
|
}
|
|
3012
3342
|
|