@finalai/agents 0.4.4 → 0.6.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/HOSTING.md +3 -3
- package/dist/modules/agent-client/build.d.mts +11 -1
- package/dist/modules/agent-client/build.mjs +1 -1
- package/dist/modules/agent-client/build.mjs.map +2 -2
- package/dist/modules/agent-client/client.d.mts +10 -22
- package/dist/modules/agent-client/client.mjs +10 -40
- package/dist/modules/agent-client/client.mjs.map +2 -2
- package/dist/modules/agent-client/collection-events.d.mts +1 -1
- package/dist/modules/agent-client/collection-events.mjs.map +1 -1
- package/dist/modules/agent-client/context.d.mts +1 -2
- package/dist/modules/agent-client/context.mjs +0 -1
- package/dist/modules/agent-client/context.mjs.map +2 -2
- package/dist/modules/agent-client/conversations.d.mts +35 -10
- package/dist/modules/agent-client/conversations.mjs +46 -42
- package/dist/modules/agent-client/conversations.mjs.map +2 -2
- package/dist/modules/agent-client/errors.d.mts +14 -14
- package/dist/modules/agent-client/errors.mjs +15 -15
- package/dist/modules/agent-client/errors.mjs.map +3 -3
- package/dist/modules/agent-client/frame-stream.d.mts +8 -8
- package/dist/modules/agent-client/frame-stream.mjs +36 -36
- package/dist/modules/agent-client/frame-stream.mjs.map +2 -2
- package/dist/modules/agent-client/http.d.mts +2 -2
- package/dist/modules/agent-client/http.mjs +10 -10
- package/dist/modules/agent-client/http.mjs.map +2 -2
- package/dist/modules/agent-client/index.d.mts +2 -2
- package/dist/modules/agent-client/index.mjs +6 -6
- package/dist/modules/agent-client/index.mjs.map +2 -2
- package/dist/modules/agent-client/sessions.d.mts +9 -8
- package/dist/modules/agent-client/sessions.mjs +13 -13
- package/dist/modules/agent-client/sessions.mjs.map +2 -2
- package/dist/modules/cli/cli.mjs +2 -2
- package/dist/modules/cli/cli.mjs.map +2 -2
- package/examples/release-scout/README.md +1 -1
- package/examples/release-scout/client.ts +2 -2
- package/package.json +5 -5
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
2
|
var AgentClientErrorName = /* @__PURE__ */ ((AgentClientErrorName2) => {
|
|
3
3
|
AgentClientErrorName2["Client"] = "ClientError";
|
|
4
|
-
AgentClientErrorName2["
|
|
4
|
+
AgentClientErrorName2["Decision"] = "DecisionError";
|
|
5
5
|
AgentClientErrorName2["TurnRejected"] = "TurnRejectedError";
|
|
6
6
|
AgentClientErrorName2["RealtimeSubscription"] = "RealtimeSubscriptionError";
|
|
7
7
|
return AgentClientErrorName2;
|
|
8
8
|
})(AgentClientErrorName || {});
|
|
9
|
-
var
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return
|
|
15
|
-
})(
|
|
9
|
+
var DecisionErrorReason = /* @__PURE__ */ ((DecisionErrorReason2) => {
|
|
10
|
+
DecisionErrorReason2["NotFound"] = "not_found";
|
|
11
|
+
DecisionErrorReason2["NotInAudience"] = "not_in_audience";
|
|
12
|
+
DecisionErrorReason2["AlreadyResolved"] = "already_resolved";
|
|
13
|
+
DecisionErrorReason2["Expired"] = "expired";
|
|
14
|
+
return DecisionErrorReason2;
|
|
15
|
+
})(DecisionErrorReason || {});
|
|
16
16
|
var ClientErrorCode = /* @__PURE__ */ ((ClientErrorCode2) => {
|
|
17
17
|
ClientErrorCode2["Network"] = "network_error";
|
|
18
18
|
ClientErrorCode2["InvalidRequest"] = "invalid_request";
|
|
@@ -31,12 +31,12 @@ const clientError = (args) => Object.assign(baseError(args), {
|
|
|
31
31
|
code: args.code,
|
|
32
32
|
body: args.body ?? null
|
|
33
33
|
});
|
|
34
|
-
const
|
|
35
|
-
name: "
|
|
34
|
+
const decisionError = (args) => Object.assign(baseError(args), {
|
|
35
|
+
name: "DecisionError" /* Decision */,
|
|
36
36
|
status: args.status,
|
|
37
37
|
code: args.code,
|
|
38
38
|
body: args.body ?? null,
|
|
39
|
-
|
|
39
|
+
decisionId: args.decisionId,
|
|
40
40
|
reason: args.reason
|
|
41
41
|
});
|
|
42
42
|
const turnRejectedError = (args) => Object.assign(baseError(args), {
|
|
@@ -72,22 +72,22 @@ const errorNameOf = (cause) => {
|
|
|
72
72
|
return parsed.success ? parsed.data.name : null;
|
|
73
73
|
};
|
|
74
74
|
const isClientError = (cause) => errorNameOf(cause) != null;
|
|
75
|
-
const
|
|
75
|
+
const isDecisionError = (cause) => errorNameOf(cause) === "DecisionError" /* Decision */;
|
|
76
76
|
const isTurnRejectedError = (cause) => errorNameOf(cause) === "TurnRejectedError" /* TurnRejected */;
|
|
77
77
|
const isRealtimeSubscriptionError = (cause) => errorNameOf(cause) === "RealtimeSubscriptionError" /* RealtimeSubscription */;
|
|
78
78
|
const isRetryableClientError = (cause) => isClientError(cause) && (cause.code === "network_error" /* Network */ || cause.status === 429 || cause.status >= 500);
|
|
79
79
|
export {
|
|
80
80
|
AgentClientErrorName,
|
|
81
81
|
ClientErrorCode,
|
|
82
|
-
|
|
82
|
+
DecisionErrorReason,
|
|
83
83
|
clientError,
|
|
84
|
+
decisionError,
|
|
84
85
|
isClientError,
|
|
85
|
-
|
|
86
|
+
isDecisionError,
|
|
86
87
|
isRealtimeSubscriptionError,
|
|
87
88
|
isRetryableClientError,
|
|
88
89
|
isTerminalRealtimeError,
|
|
89
90
|
isTurnRejectedError,
|
|
90
|
-
pendingRequestError,
|
|
91
91
|
realtimeSubscriptionError,
|
|
92
92
|
turnRejectedError
|
|
93
93
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/agent-client/errors.ts"],
|
|
4
|
-
"sourcesContent": ["import type { JsonValue } from '@finalai/agent-protocol';\nimport * as z from 'zod';\n\n// Errors are plain `Error` objects with a discriminating `name` (no classes):\n// narrow with the `is*Error` guards, never `instanceof`.\n\nexport enum AgentClientErrorName {\n Client = 'ClientError',\n
|
|
5
|
-
"mappings": "AACA,YAAY,OAAO;AAKZ,IAAK,uBAAL,kBAAKA,0BAAL;AACL,EAAAA,sBAAA,YAAS;AACT,EAAAA,sBAAA,
|
|
6
|
-
"names": ["AgentClientErrorName", "
|
|
4
|
+
"sourcesContent": ["import type { JsonValue } from '@finalai/agent-protocol';\nimport * as z from 'zod';\n\n// Errors are plain `Error` objects with a discriminating `name` (no classes):\n// narrow with the `is*Error` guards, never `instanceof`.\n\nexport enum AgentClientErrorName {\n Client = 'ClientError',\n Decision = 'DecisionError',\n TurnRejected = 'TurnRejectedError',\n RealtimeSubscription = 'RealtimeSubscriptionError',\n}\n\nexport enum DecisionErrorReason {\n NotFound = 'not_found',\n NotInAudience = 'not_in_audience',\n AlreadyResolved = 'already_resolved',\n Expired = 'expired',\n}\n\n/** Codes the SDK itself assigns when no HTTP error body applies. */\nexport enum ClientErrorCode {\n Network = 'network_error',\n InvalidRequest = 'invalid_request',\n InvalidResponse = 'invalid_response',\n UploadFailed = 'upload_failed',\n NotFound = 'not_found',\n Closed = 'client_closed',\n /** The runtime's fetch cannot stream a response body (Streamable HTTP). */\n StreamUnsupported = 'stream_unsupported',\n Unknown = 'unknown',\n}\n\ninterface ErrorFieldsIface {\n /** HTTP status; 0 when no response arrived or the SDK rejected the call locally. */\n status: number;\n code: string;\n body: JsonValue | null;\n}\n\nexport interface ClientErrorIface extends Error, ErrorFieldsIface {\n name: AgentClientErrorName.Client;\n}\n\n/** Answering a decision outside your audience, already resolved, expired, or unknown. */\nexport interface DecisionErrorIface extends Error, ErrorFieldsIface {\n name: AgentClientErrorName.Decision;\n decisionId: string | null;\n reason: DecisionErrorReason;\n}\n\n/** The session is not accepting prompts; `state` is its ACP/session state. */\nexport interface TurnRejectedErrorIface extends Error, ErrorFieldsIface {\n name: AgentClientErrorName.TurnRejected;\n sessionId: string | null;\n state: string | null;\n}\n\n/** The realtime gateway refused a topic for good (no access, unknown topic, subscription limit). */\nexport interface RealtimeSubscriptionErrorIface extends Error, ErrorFieldsIface {\n name: AgentClientErrorName.RealtimeSubscription;\n topic: string;\n}\n\nexport type AgentClientError =\n | ClientErrorIface\n | DecisionErrorIface\n | TurnRejectedErrorIface\n | RealtimeSubscriptionErrorIface;\n\ntype ErrorBaseKey = 'message' | 'stack' | 'cause';\n\nexport interface ClientErrorArgsIface {\n message: string;\n status: number;\n code: string;\n body?: JsonValue | null;\n cause?: unknown;\n}\n\nconst baseError = (args: ClientErrorArgsIface): Error =>\n args.cause === undefined\n ? new Error(args.message)\n : new Error(args.message, { cause: args.cause });\n\nexport const clientError = (args: ClientErrorArgsIface): ClientErrorIface =>\n Object.assign(baseError(args), {\n name: AgentClientErrorName.Client,\n status: args.status,\n code: args.code,\n body: args.body ?? null,\n } satisfies Omit<ClientErrorIface, ErrorBaseKey>);\n\nexport const decisionError = (\n args: ClientErrorArgsIface & { decisionId: string | null; reason: DecisionErrorReason },\n): DecisionErrorIface =>\n Object.assign(baseError(args), {\n name: AgentClientErrorName.Decision,\n status: args.status,\n code: args.code,\n body: args.body ?? null,\n decisionId: args.decisionId,\n reason: args.reason,\n } satisfies Omit<DecisionErrorIface, ErrorBaseKey>);\n\nexport const turnRejectedError = (\n args: ClientErrorArgsIface & { sessionId: string | null; state: string | null },\n): TurnRejectedErrorIface =>\n Object.assign(baseError(args), {\n name: AgentClientErrorName.TurnRejected,\n status: args.status,\n code: args.code,\n body: args.body ?? null,\n sessionId: args.sessionId,\n state: args.state,\n } satisfies Omit<TurnRejectedErrorIface, ErrorBaseKey>);\n\n// Gateway codes map onto the HTTP statuses callers already branch on.\nconst realtimeStatusByCode = new Map<string, number>([\n ['unauthorized', 401],\n ['forbidden', 403],\n ['not_found', 404],\n ['too_many_subscriptions', 429],\n]);\n\nexport const realtimeSubscriptionError = (args: {\n topic: string;\n code: string;\n message: string;\n}): RealtimeSubscriptionErrorIface =>\n Object.assign(new Error(args.message), {\n name: AgentClientErrorName.RealtimeSubscription,\n status: realtimeStatusByCode.get(args.code) ?? 0,\n code: args.code,\n body: null,\n topic: args.topic,\n } satisfies Omit<RealtimeSubscriptionErrorIface, ErrorBaseKey>);\n\n/** Whether a realtime error frame ends the subscription: explicit, or by a known terminal code. */\nexport const isTerminalRealtimeError = (frame: {\n code: string | null;\n retryable: boolean | null;\n}): boolean =>\n frame.retryable === false ||\n (frame.retryable == null && realtimeStatusByCode.has(frame.code ?? ''));\n\nconst errorIdentitySchema = z.object({\n name: z.nativeEnum(AgentClientErrorName),\n status: z.number(),\n code: z.string(),\n message: z.string(),\n});\n\nconst errorNameOf = (cause: unknown): AgentClientErrorName | null => {\n const parsed = errorIdentitySchema.safeParse(cause);\n return parsed.success ? parsed.data.name : null;\n};\n\n/** True for every SDK error (ClientError, DecisionError, TurnRejectedError). */\nexport const isClientError = (cause: unknown): cause is AgentClientError =>\n errorNameOf(cause) != null;\n\nexport const isDecisionError = (cause: unknown): cause is DecisionErrorIface =>\n errorNameOf(cause) === AgentClientErrorName.Decision;\n\nexport const isTurnRejectedError = (cause: unknown): cause is TurnRejectedErrorIface =>\n errorNameOf(cause) === AgentClientErrorName.TurnRejected;\n\nexport const isRealtimeSubscriptionError = (\n cause: unknown,\n): cause is RealtimeSubscriptionErrorIface =>\n errorNameOf(cause) === AgentClientErrorName.RealtimeSubscription;\n\nexport const isRetryableClientError = (cause: unknown): boolean =>\n isClientError(cause) &&\n (cause.code === ClientErrorCode.Network || cause.status === 429 || cause.status >= 500);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["AgentClientErrorName", "DecisionErrorReason", "ClientErrorCode"]
|
|
7
7
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AcpFrameEventIface, type
|
|
1
|
+
import { type AcpFrameEventIface, type DecisionRecordIface, type SessionFramesPageIface } from '@finalai/agent-protocol/agent-platform';
|
|
2
2
|
import type { RealtimeTransportIface } from "./realtime.mjs";
|
|
3
3
|
export interface StreamTimingIface {
|
|
4
4
|
sleep: (ms: number) => Promise<void>;
|
|
@@ -10,10 +10,10 @@ export interface StreamTimingIface {
|
|
|
10
10
|
conversationPollIntervalMs: number;
|
|
11
11
|
replayPageSize: number;
|
|
12
12
|
/**
|
|
13
|
-
* How long a live request frame waits for its `
|
|
14
|
-
* open
|
|
13
|
+
* How long a live request frame waits for its `decision.changed` event before
|
|
14
|
+
* the open decisions are read, once per entry; then it is yielded without one.
|
|
15
15
|
*/
|
|
16
|
-
|
|
16
|
+
decisionJoinDelaysMs: number[];
|
|
17
17
|
}
|
|
18
18
|
export declare const defaultStreamTiming: StreamTimingIface;
|
|
19
19
|
export interface FrameReplayArgsIface {
|
|
@@ -29,8 +29,8 @@ export interface SessionFrameStreamArgsIface {
|
|
|
29
29
|
replay: (args: FrameReplayArgsIface) => Promise<SessionFramesPageIface>;
|
|
30
30
|
transport: RealtimeTransportIface;
|
|
31
31
|
timing: StreamTimingIface;
|
|
32
|
-
/** The session's open
|
|
33
|
-
|
|
32
|
+
/** The session's open decisions, to join live request frames with. */
|
|
33
|
+
decisions?: (signal?: AbortSignal) => Promise<DecisionRecordIface[]>;
|
|
34
34
|
/** Frames from `fromSeq` over Streamable HTTP, followed live. */
|
|
35
35
|
httpStream?: (args: {
|
|
36
36
|
fromSeq: number;
|
|
@@ -46,6 +46,6 @@ export interface SessionFrameStreamArgsIface {
|
|
|
46
46
|
throughSeq: number;
|
|
47
47
|
} | null>;
|
|
48
48
|
}
|
|
49
|
-
/** Whether a frame is an agent request the session holds as a
|
|
50
|
-
export declare const
|
|
49
|
+
/** Whether a frame is an agent request the session holds as a decision. */
|
|
50
|
+
export declare const isDecisionRequestFrame: (event: AcpFrameEventIface) => boolean;
|
|
51
51
|
export declare const streamSessionFrames: (args: SessionFrameStreamArgsIface) => AsyncIterableIterator<AcpFrameEventIface>;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AcpFrameDirection,
|
|
3
3
|
acpFrameEventSchema,
|
|
4
|
-
acpPendingEventSchema,
|
|
5
4
|
agentRealtimeFrameSchema,
|
|
6
5
|
AgentRealtimeFrameType,
|
|
7
6
|
AgentRealtimeKind,
|
|
8
7
|
agentRealtimeTopics,
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
decisionChangedEventSchema,
|
|
9
|
+
DecisionEventState,
|
|
10
|
+
FIRST_ACP_FRAME_SEQ
|
|
11
11
|
} from "@finalai/agent-protocol/agent-platform";
|
|
12
12
|
import { createAsyncQueue, failOnAbort } from "./async-queue.mjs";
|
|
13
13
|
import {
|
|
@@ -23,10 +23,10 @@ const defaultStreamTiming = {
|
|
|
23
23
|
pollIntervalMs: 1e3,
|
|
24
24
|
conversationPollIntervalMs: 5e3,
|
|
25
25
|
replayPageSize: 500,
|
|
26
|
-
|
|
26
|
+
decisionJoinDelaysMs: [250, 1e3]
|
|
27
27
|
};
|
|
28
|
-
const
|
|
29
|
-
const
|
|
28
|
+
const DECISION_REQUEST_METHODS = /* @__PURE__ */ new Set(["session/request_permission", "elicitation/create"]);
|
|
29
|
+
const isDecisionRequestFrame = (event) => event.direction === AcpFrameDirection.AgentToClient && event.frame.id != null && event.frame.method != null && DECISION_REQUEST_METHODS.has(event.frame.method);
|
|
30
30
|
var FrameOrigin = /* @__PURE__ */ ((FrameOrigin2) => {
|
|
31
31
|
FrameOrigin2["Replay"] = "replay";
|
|
32
32
|
FrameOrigin2["Live"] = "live";
|
|
@@ -55,8 +55,8 @@ const streamSessionFrames = (args) => {
|
|
|
55
55
|
let detachClose = () => {
|
|
56
56
|
};
|
|
57
57
|
let output = Promise.resolve();
|
|
58
|
-
const
|
|
59
|
-
const
|
|
58
|
+
const decisionIds = /* @__PURE__ */ new Map();
|
|
59
|
+
const decisionWaiters = /* @__PURE__ */ new Map();
|
|
60
60
|
const gapWaiters = /* @__PURE__ */ new Set();
|
|
61
61
|
const stopFallback = () => {
|
|
62
62
|
if (pollTimer != null) clearInterval(pollTimer);
|
|
@@ -73,51 +73,51 @@ const streamSessionFrames = (args) => {
|
|
|
73
73
|
unsubscribe?.();
|
|
74
74
|
detachAbort();
|
|
75
75
|
detachClose();
|
|
76
|
-
for (const waiters of
|
|
77
|
-
|
|
76
|
+
for (const waiters of decisionWaiters.values()) for (const wake of waiters) wake();
|
|
77
|
+
decisionWaiters.clear();
|
|
78
78
|
});
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
for (const wake of
|
|
82
|
-
|
|
79
|
+
const noteDecision = (seq, decisionId) => {
|
|
80
|
+
decisionIds.set(seq, decisionId);
|
|
81
|
+
for (const wake of decisionWaiters.get(seq) ?? []) wake();
|
|
82
|
+
decisionWaiters.delete(seq);
|
|
83
83
|
};
|
|
84
|
-
const
|
|
85
|
-
const waiters =
|
|
84
|
+
const waitForDecision = (seq, ms) => new Promise((resolve) => {
|
|
85
|
+
const waiters = decisionWaiters.get(seq) ?? /* @__PURE__ */ new Set();
|
|
86
86
|
const wake = () => {
|
|
87
87
|
waiters.delete(wake);
|
|
88
88
|
resolve();
|
|
89
89
|
};
|
|
90
90
|
waiters.add(wake);
|
|
91
|
-
|
|
91
|
+
decisionWaiters.set(seq, waiters);
|
|
92
92
|
void timing.sleep(ms).then(wake);
|
|
93
93
|
});
|
|
94
|
-
const
|
|
95
|
-
if (args.
|
|
94
|
+
const readOpenDecisions = async () => {
|
|
95
|
+
if (args.decisions == null) return;
|
|
96
96
|
try {
|
|
97
|
-
for (const
|
|
98
|
-
if (
|
|
97
|
+
for (const decision of await args.decisions(readSignal)) {
|
|
98
|
+
if (decision.logSeq != null) noteDecision(decision.logSeq, decision.id);
|
|
99
99
|
}
|
|
100
100
|
} catch {
|
|
101
101
|
}
|
|
102
102
|
};
|
|
103
|
-
const
|
|
104
|
-
for (const delay of timing.
|
|
105
|
-
if (
|
|
106
|
-
await
|
|
107
|
-
if (
|
|
108
|
-
await
|
|
103
|
+
const joinDecisionId = async (seq) => {
|
|
104
|
+
for (const delay of timing.decisionJoinDelaysMs) {
|
|
105
|
+
if (decisionIds.has(seq) || queue.closed()) break;
|
|
106
|
+
await waitForDecision(seq, delay);
|
|
107
|
+
if (decisionIds.has(seq) || queue.closed()) break;
|
|
108
|
+
await readOpenDecisions();
|
|
109
109
|
}
|
|
110
|
-
return
|
|
110
|
+
return decisionIds.get(seq) ?? null;
|
|
111
111
|
};
|
|
112
112
|
const emit = (event, origin) => {
|
|
113
113
|
if (queue.closed()) return;
|
|
114
114
|
nextSeq = event.seq + 1;
|
|
115
|
-
if (event.
|
|
116
|
-
const join = event.
|
|
115
|
+
if (event.decisionId != null) noteDecision(event.seq, event.decisionId);
|
|
116
|
+
const join = event.decisionId == null && origin === "live" /* Live */ && isDecisionRequestFrame(event);
|
|
117
117
|
output = output.then(async () => {
|
|
118
118
|
if (queue.closed() || terminalThroughSeq != null && event.seq > terminalThroughSeq)
|
|
119
119
|
return;
|
|
120
|
-
const value = join ? { ...event,
|
|
120
|
+
const value = join ? { ...event, decisionId: await joinDecisionId(event.seq) } : event;
|
|
121
121
|
if (queue.closed() || terminalThroughSeq != null && event.seq > terminalThroughSeq)
|
|
122
122
|
return;
|
|
123
123
|
queue.push(value);
|
|
@@ -267,10 +267,10 @@ const streamSessionFrames = (args) => {
|
|
|
267
267
|
if (!frame.success) return;
|
|
268
268
|
switch (frame.data.type) {
|
|
269
269
|
case AgentRealtimeFrameType.Event: {
|
|
270
|
-
if (frame.data.kind === AgentRealtimeKind.
|
|
271
|
-
const
|
|
272
|
-
if (
|
|
273
|
-
|
|
270
|
+
if (frame.data.kind === AgentRealtimeKind.DecisionChanged) {
|
|
271
|
+
const changed = decisionChangedEventSchema.safeParse(frame.data.payload);
|
|
272
|
+
if (changed.success && changed.data.state === DecisionEventState.Created && changed.data.decision.logSeq != null) {
|
|
273
|
+
noteDecision(changed.data.decision.logSeq, changed.data.decision.id);
|
|
274
274
|
}
|
|
275
275
|
return;
|
|
276
276
|
}
|
|
@@ -327,7 +327,7 @@ const streamSessionFrames = (args) => {
|
|
|
327
327
|
};
|
|
328
328
|
export {
|
|
329
329
|
defaultStreamTiming,
|
|
330
|
-
|
|
330
|
+
isDecisionRequestFrame,
|
|
331
331
|
streamSessionFrames
|
|
332
332
|
};
|
|
333
333
|
//# sourceMappingURL=frame-stream.mjs.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/agent-client/frame-stream.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n AcpFrameDirection,\n acpFrameEventSchema,\n acpPendingEventSchema,\n agentRealtimeFrameSchema,\n AgentRealtimeFrameType,\n AgentRealtimeKind,\n agentRealtimeTopics,\n FIRST_ACP_FRAME_SEQ,\n PendingEventState,\n type AcpFrameEventIface,\n type PendingRequestIface,\n type SessionFramesPageIface,\n} from '@finalai/agent-protocol/agent-platform';\nimport { createAsyncQueue, failOnAbort } from \"./async-queue.mjs\";\nimport {\n ClientErrorCode,\n isClientError,\n isRetryableClientError,\n isTerminalRealtimeError,\n realtimeSubscriptionError,\n} from \"./errors.mjs\";\nimport type { RealtimeTransportFrameIface, RealtimeTransportIface } from \"./realtime.mjs\";\n\n// A session's ACP frames in dense seq order: HTTP replay from `fromSeq`, then\n// live frames from the session topic. Live frames that arrive ahead of the\n// next expected seq are held while replay fills the gap; a (re)subscription,\n// a resync or a transport error triggers replay too, so reconnects never drop\n// frames. A missing seq is retained across replay attempts, never skipped.\n//\n// While the realtime transport reports errors, frames come over Streamable\n// HTTP (the service's server-sent frame stream) until it subscribes again;\n// where the fetch cannot stream, replay is polled instead.\n//\n// An agent request frame (permission, elicitation) carries the `pendingId` to\n// answer it with. Replay pages set it; a live frame is published before its\n// pending request exists, so it is held until the session's `acp.pending`\n// event for its seq arrives, or the open requests are read.\n\nexport interface StreamTimingIface {\n sleep: (ms: number) => Promise<void>;\n /** Delays between replay attempts while a gap stays open. */\n gapRetryDelaysMs: number[];\n /** Replay polling, and Streamable HTTP reconnects, while the realtime transport reports errors. */\n pollIntervalMs: number;\n /** Conversation recovery polling (`events()`) while the realtime transport reports errors. */\n conversationPollIntervalMs: number;\n replayPageSize: number;\n /**\n * How long a live request frame waits for its `acp.pending` event before the\n * open requests are read, once per entry; then it is yielded without one.\n */\n pendingJoinDelaysMs: number[];\n}\n\nexport const defaultStreamTiming: StreamTimingIface = {\n sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),\n gapRetryDelaysMs: [100, 250, 500, 1000, 2000],\n pollIntervalMs: 1000,\n conversationPollIntervalMs: 5000,\n replayPageSize: 500,\n pendingJoinDelaysMs: [250, 1000],\n};\n\nexport interface FrameReplayArgsIface {\n fromSeq: number;\n limit: number;\n signal?: AbortSignal;\n}\n\nexport interface SessionFrameStreamArgsIface {\n sessionId: string;\n fromSeq: number;\n /** Keep streaming live frames after replay catches up. */\n follow: boolean;\n replay: (args: FrameReplayArgsIface) => Promise<SessionFramesPageIface>;\n transport: RealtimeTransportIface;\n timing: StreamTimingIface;\n /** The session's open pending requests, to join live request frames with. */\n pending?: (signal?: AbortSignal) => Promise<PendingRequestIface[]>;\n /** Frames from `fromSeq` over Streamable HTTP, followed live. */\n httpStream?: (args: {\n fromSeq: number;\n signal: AbortSignal;\n }) => AsyncIterable<AcpFrameEventIface>;\n signal?: AbortSignal;\n /** The client's close signal: ends the stream like `signal`. */\n closeSignal?: AbortSignal;\n /** Return true to end the stream after yielding this frame. */\n until?: (event: AcpFrameEventIface) => boolean;\n /** A durable terminal receipt, including turns that ended without an ACP echo. */\n terminal?: (signal: AbortSignal) => Promise<{ throughSeq: number } | null>;\n}\n\nconst PENDING_REQUEST_METHODS = new Set(['session/request_permission', 'elicitation/create']);\n\n/** Whether a frame is an agent request the session holds as a pending request. */\nexport const isPendingRequestFrame = (event: AcpFrameEventIface): boolean =>\n event.direction === AcpFrameDirection.AgentToClient &&\n event.frame.id != null &&\n event.frame.method != null &&\n PENDING_REQUEST_METHODS.has(event.frame.method);\n\n/** Where a frame came from: replay pages carry `pendingId`; live and streamed frames may not yet. */\nenum FrameOrigin {\n Replay = 'replay',\n Live = 'live',\n}\n\nexport const streamSessionFrames = (\n args: SessionFrameStreamArgsIface,\n): AsyncIterableIterator<AcpFrameEventIface> => {\n const { timing } = args;\n const ahead = new Map<number, { event: AcpFrameEventIface; origin: FrameOrigin }>();\n // The service numbers frames from 1 and clamps earlier requests; start where frames exist.\n let nextSeq = Math.max(FIRST_ACP_FRAME_SEQ, args.fromSeq);\n let filling = false;\n let terminalThroughSeq: number | null = null;\n let terminalInitialized = args.terminal == null;\n let realtimeSubscribed = false;\n let fillAgain = false;\n let pollTimer: ReturnType<typeof setInterval> | null = null;\n let terminalTimer: ReturnType<typeof setInterval> | null = null;\n const closing = new AbortController();\n const readSignal = AbortSignal.any([\n closing.signal,\n ...[args.signal, args.closeSignal].filter((signal) => signal != null),\n ]);\n let httpFallback: AbortController | null = null;\n let unsubscribe: (() => void) | null = null;\n let detachAbort: () => void = () => {};\n let detachClose: () => void = () => {};\n // Frames are yielded through one chain, so a request frame waiting for its\n // pending id holds back the frames after it.\n let output: Promise<void> = Promise.resolve();\n const pendingIds = new Map<number, string>();\n const pendingWaiters = new Map<number, Set<() => void>>();\n const gapWaiters = new Set<() => void>();\n\n const stopFallback = (): void => {\n if (pollTimer != null) clearInterval(pollTimer);\n pollTimer = null;\n httpFallback?.abort();\n httpFallback = null;\n };\n\n const queue = createAsyncQueue<AcpFrameEventIface>(() => {\n closing.abort();\n if (terminalTimer != null) clearInterval(terminalTimer);\n ahead.clear();\n for (const wake of gapWaiters) wake();\n stopFallback();\n unsubscribe?.();\n detachAbort();\n detachClose();\n for (const waiters of pendingWaiters.values()) for (const wake of waiters) wake();\n pendingWaiters.clear();\n });\n\n const notePending = (seq: number, pendingId: string): void => {\n pendingIds.set(seq, pendingId);\n for (const wake of pendingWaiters.get(seq) ?? []) wake();\n pendingWaiters.delete(seq);\n };\n\n const waitForPending = (seq: number, ms: number): Promise<void> =>\n new Promise((resolve) => {\n const waiters = pendingWaiters.get(seq) ?? new Set<() => void>();\n const wake = (): void => {\n waiters.delete(wake);\n resolve();\n };\n waiters.add(wake);\n pendingWaiters.set(seq, waiters);\n void timing.sleep(ms).then(wake);\n });\n\n const readOpenPending = async (): Promise<void> => {\n if (args.pending == null) return;\n try {\n for (const request of await args.pending(readSignal)) {\n if (request.logSeq != null) notePending(request.logSeq, request.id);\n }\n } catch {\n // The next attempt, or the frame without an id.\n }\n };\n\n const joinPendingId = async (seq: number): Promise<string | null> => {\n for (const delay of timing.pendingJoinDelaysMs) {\n if (pendingIds.has(seq) || queue.closed()) break;\n await waitForPending(seq, delay);\n if (pendingIds.has(seq) || queue.closed()) break;\n await readOpenPending();\n }\n return pendingIds.get(seq) ?? null;\n };\n\n const emit = (event: AcpFrameEventIface, origin: FrameOrigin): void => {\n if (queue.closed()) return;\n nextSeq = event.seq + 1;\n if (event.pendingId != null) notePending(event.seq, event.pendingId);\n const join =\n event.pendingId == null && origin === FrameOrigin.Live && isPendingRequestFrame(event);\n output = output\n .then(async () => {\n if (queue.closed() || (terminalThroughSeq != null && event.seq > terminalThroughSeq))\n return;\n const value = join ? { ...event, pendingId: await joinPendingId(event.seq) } : event;\n if (queue.closed() || (terminalThroughSeq != null && event.seq > terminalThroughSeq))\n return;\n queue.push(value);\n if (args.until?.(value) === true) queue.end();\n })\n .catch((cause: unknown) => queue.fail(cause));\n };\n\n const drainAhead = (): void => {\n for (const seq of [...ahead.keys()]) if (seq < nextSeq) ahead.delete(seq);\n for (let held = ahead.get(nextSeq); held != null; held = ahead.get(nextSeq)) {\n if (terminalThroughSeq != null && held.event.seq > terminalThroughSeq) {\n ahead.clear();\n return;\n }\n ahead.delete(held.event.seq);\n emit(held.event, held.origin);\n }\n };\n\n const deliver = (event: AcpFrameEventIface, origin: FrameOrigin): boolean => {\n if (terminalThroughSeq != null && event.seq > terminalThroughSeq) return false;\n if (queue.closed() || event.seq < nextSeq) return false;\n if (!terminalInitialized || event.seq > nextSeq) {\n if (!ahead.has(event.seq) && ahead.size >= timing.replayPageSize * 2) {\n queue.fail(\n new Error('Frame replay fell behind; reconnect from the last received sequence'),\n );\n return false;\n }\n ahead.set(event.seq, { event, origin });\n return true;\n }\n emit(event, origin);\n drainAhead();\n return false;\n };\n\n const refreshTerminal = async (): Promise<void> => {\n if (args.terminal == null || queue.closed()) return;\n const terminal = await args.terminal(readSignal);\n terminalInitialized = true;\n if (terminal == null) return;\n terminalThroughSeq = terminal.throughSeq;\n for (const seq of ahead.keys()) if (seq > terminalThroughSeq) ahead.delete(seq);\n if (terminalThroughSeq < nextSeq) await output.then(() => queue.end());\n };\n\n /** Pages forward from the next expected seq until the page reaches the log head. */\n const replayOnce = async (): Promise<void> => {\n let from = nextSeq;\n for (;;) {\n const page = await args.replay({\n fromSeq: from,\n limit: timing.replayPageSize,\n signal: readSignal,\n });\n const frames = [...page.frames].sort((left, right) => left.seq - right.seq);\n for (const event of frames) deliver(event, FrameOrigin.Replay);\n const last = frames.at(-1)?.seq;\n if (queue.closed() || last == null) return;\n // Page by what the server returned, not by what was emitted, so frames held behind a gap still advance it.\n const next = Math.max(nextSeq, last + 1);\n if (next <= from || (!page.hasMore && last >= page.headSeq)) return;\n from = next;\n }\n };\n\n const fill = async (): Promise<void> => {\n await replayOnce();\n let attempt = 0;\n while (ahead.size > 0 && !queue.closed()) {\n if (ahead.size === 0 || queue.closed()) return;\n const delay = timing.gapRetryDelaysMs[attempt] ?? timing.pollIntervalMs;\n attempt += 1;\n await new Promise<void>((resolve) => {\n const wake = () => {\n clearTimeout(timer);\n gapWaiters.delete(wake);\n resolve();\n };\n const timer = setTimeout(wake, Math.max(1, delay));\n gapWaiters.add(wake);\n });\n if (queue.closed()) return;\n await refreshTerminal();\n if (queue.closed()) return;\n await replayOnce();\n }\n };\n\n const requestFill = (): void => {\n if (filling) {\n fillAgain = true;\n return;\n }\n filling = true;\n void (async () => {\n try {\n do {\n fillAgain = false;\n await refreshTerminal();\n if (queue.closed()) return;\n await fill();\n await refreshTerminal();\n } while (fillAgain && !queue.closed());\n if (realtimeSubscribed) stopFallback();\n if (!args.follow) await output.then(() => queue.end());\n } catch (cause) {\n if (args.follow && isRetryableClientError(cause)) {\n startHttpFallback();\n } else queue.fail(cause);\n } finally {\n filling = false;\n }\n })();\n };\n\n const pollReplay = (): void => {\n pollTimer ??= setInterval(requestFill, timing.pollIntervalMs);\n };\n\n /** Streams frames over HTTP until the transport subscribes again or the stream ends. */\n const startHttpFallback = (): void => {\n if (httpFallback != null || pollTimer != null || queue.closed()) return;\n const open = args.httpStream;\n if (open == null) {\n pollReplay();\n return;\n }\n const controller = new AbortController();\n httpFallback = controller;\n void (async () => {\n while (!controller.signal.aborted && !queue.closed()) {\n try {\n for await (const event of open({ fromSeq: nextSeq, signal: controller.signal })) {\n if (deliver(event, FrameOrigin.Live)) requestFill();\n }\n } catch (cause) {\n if (controller.signal.aborted || queue.closed()) return;\n if (\n isClientError(cause) &&\n (cause.code === ClientErrorCode.StreamUnsupported ||\n cause.status === 404 ||\n cause.status === 405)\n ) {\n if (httpFallback === controller) httpFallback = null;\n pollReplay();\n return;\n }\n if (!isRetryableClientError(cause)) {\n queue.fail(cause);\n return;\n }\n }\n if (controller.signal.aborted) return;\n await timing.sleep(timing.pollIntervalMs);\n }\n })();\n };\n\n const onFrame = (raw: RealtimeTransportFrameIface): void => {\n for (const wake of gapWaiters) wake();\n const frame = agentRealtimeFrameSchema.safeParse(raw);\n if (!frame.success) return;\n switch (frame.data.type) {\n case AgentRealtimeFrameType.Event: {\n if (frame.data.kind === AgentRealtimeKind.AcpPending) {\n const pending = acpPendingEventSchema.safeParse(frame.data.payload);\n if (\n pending.success &&\n pending.data.state === PendingEventState.Created &&\n pending.data.pending.logSeq != null\n ) {\n notePending(pending.data.pending.logSeq, pending.data.pending.id);\n }\n return;\n }\n if (frame.data.kind === AgentRealtimeKind.TurnEnded && args.terminal != null) {\n terminalInitialized = false;\n requestFill();\n return;\n }\n if (frame.data.kind !== AgentRealtimeKind.AcpFrame) return;\n const event = acpFrameEventSchema.safeParse(frame.data.payload);\n if (event.success && deliver(event.data, FrameOrigin.Live)) requestFill();\n return;\n }\n case AgentRealtimeFrameType.Subscribed:\n realtimeSubscribed = true;\n stopFallback();\n requestFill();\n return;\n case AgentRealtimeFrameType.ResyncRequired:\n requestFill();\n return;\n case AgentRealtimeFrameType.Error:\n if (isTerminalRealtimeError(frame.data)) {\n queue.fail(\n realtimeSubscriptionError({\n topic: frame.data.topic ?? agentRealtimeTopics.session(args.sessionId),\n code: frame.data.code ?? 'unknown',\n message: frame.data.message ?? 'Realtime subscription was refused',\n }),\n );\n return;\n }\n realtimeSubscribed = false;\n // Retryable: the transport resubscribes; Streamable HTTP covers the outage.\n requestFill();\n startHttpFallback();\n return;\n default:\n return;\n }\n };\n\n detachAbort = failOnAbort(queue, args.signal);\n detachClose = failOnAbort(queue, args.closeSignal);\n if (!queue.closed()) {\n // Subscribe before the first replay so nothing published in between is lost.\n if (args.follow) {\n const stop = args.transport.subscribe(agentRealtimeTopics.session(args.sessionId), onFrame);\n if (queue.closed()) stop();\n else unsubscribe = stop;\n }\n requestFill();\n if (args.terminal != null && args.follow && !queue.closed())\n terminalTimer = setInterval(requestFill, Math.max(1, timing.conversationPollIntervalMs));\n }\n return queue.iterator;\n};\n"],
|
|
5
|
-
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,kBAAkB,mBAAmB;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAkCA,MAAM,sBAAyC;AAAA,EACpD,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,EAC/D,kBAAkB,CAAC,KAAK,KAAK,KAAK,KAAM,GAAI;AAAA,EAC5C,gBAAgB;AAAA,EAChB,4BAA4B;AAAA,EAC5B,gBAAgB;AAAA,EAChB,
|
|
4
|
+
"sourcesContent": ["import {\n AcpFrameDirection,\n acpFrameEventSchema,\n agentRealtimeFrameSchema,\n AgentRealtimeFrameType,\n AgentRealtimeKind,\n agentRealtimeTopics,\n decisionChangedEventSchema,\n DecisionEventState,\n FIRST_ACP_FRAME_SEQ,\n type AcpFrameEventIface,\n type DecisionRecordIface,\n type SessionFramesPageIface,\n} from '@finalai/agent-protocol/agent-platform';\nimport { createAsyncQueue, failOnAbort } from \"./async-queue.mjs\";\nimport {\n ClientErrorCode,\n isClientError,\n isRetryableClientError,\n isTerminalRealtimeError,\n realtimeSubscriptionError,\n} from \"./errors.mjs\";\nimport type { RealtimeTransportFrameIface, RealtimeTransportIface } from \"./realtime.mjs\";\n\n// A session's ACP frames in dense seq order: HTTP replay from `fromSeq`, then\n// live frames from the session topic. Live frames that arrive ahead of the\n// next expected seq are held while replay fills the gap; a (re)subscription,\n// a resync or a transport error triggers replay too, so reconnects never drop\n// frames. A missing seq is retained across replay attempts, never skipped.\n//\n// While the realtime transport reports errors, frames come over Streamable\n// HTTP (the service's server-sent frame stream) until it subscribes again;\n// where the fetch cannot stream, replay is polled instead.\n//\n// An agent request frame (permission, elicitation) carries the `decisionId` to\n// answer it with. Replay pages set it; a live frame is published before its\n// decision exists, so it is held until the session's `decision.changed` event\n// for its seq arrives, or the open decisions are read.\n\nexport interface StreamTimingIface {\n sleep: (ms: number) => Promise<void>;\n /** Delays between replay attempts while a gap stays open. */\n gapRetryDelaysMs: number[];\n /** Replay polling, and Streamable HTTP reconnects, while the realtime transport reports errors. */\n pollIntervalMs: number;\n /** Conversation recovery polling (`events()`) while the realtime transport reports errors. */\n conversationPollIntervalMs: number;\n replayPageSize: number;\n /**\n * How long a live request frame waits for its `decision.changed` event before\n * the open decisions are read, once per entry; then it is yielded without one.\n */\n decisionJoinDelaysMs: number[];\n}\n\nexport const defaultStreamTiming: StreamTimingIface = {\n sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),\n gapRetryDelaysMs: [100, 250, 500, 1000, 2000],\n pollIntervalMs: 1000,\n conversationPollIntervalMs: 5000,\n replayPageSize: 500,\n decisionJoinDelaysMs: [250, 1000],\n};\n\nexport interface FrameReplayArgsIface {\n fromSeq: number;\n limit: number;\n signal?: AbortSignal;\n}\n\nexport interface SessionFrameStreamArgsIface {\n sessionId: string;\n fromSeq: number;\n /** Keep streaming live frames after replay catches up. */\n follow: boolean;\n replay: (args: FrameReplayArgsIface) => Promise<SessionFramesPageIface>;\n transport: RealtimeTransportIface;\n timing: StreamTimingIface;\n /** The session's open decisions, to join live request frames with. */\n decisions?: (signal?: AbortSignal) => Promise<DecisionRecordIface[]>;\n /** Frames from `fromSeq` over Streamable HTTP, followed live. */\n httpStream?: (args: {\n fromSeq: number;\n signal: AbortSignal;\n }) => AsyncIterable<AcpFrameEventIface>;\n signal?: AbortSignal;\n /** The client's close signal: ends the stream like `signal`. */\n closeSignal?: AbortSignal;\n /** Return true to end the stream after yielding this frame. */\n until?: (event: AcpFrameEventIface) => boolean;\n /** A durable terminal receipt, including turns that ended without an ACP echo. */\n terminal?: (signal: AbortSignal) => Promise<{ throughSeq: number } | null>;\n}\n\nconst DECISION_REQUEST_METHODS = new Set(['session/request_permission', 'elicitation/create']);\n\n/** Whether a frame is an agent request the session holds as a decision. */\nexport const isDecisionRequestFrame = (event: AcpFrameEventIface): boolean =>\n event.direction === AcpFrameDirection.AgentToClient &&\n event.frame.id != null &&\n event.frame.method != null &&\n DECISION_REQUEST_METHODS.has(event.frame.method);\n\n/** Where a frame came from: replay pages carry `decisionId`; live and streamed frames may not yet. */\nenum FrameOrigin {\n Replay = 'replay',\n Live = 'live',\n}\n\nexport const streamSessionFrames = (\n args: SessionFrameStreamArgsIface,\n): AsyncIterableIterator<AcpFrameEventIface> => {\n const { timing } = args;\n const ahead = new Map<number, { event: AcpFrameEventIface; origin: FrameOrigin }>();\n // The service numbers frames from 1 and clamps earlier requests; start where frames exist.\n let nextSeq = Math.max(FIRST_ACP_FRAME_SEQ, args.fromSeq);\n let filling = false;\n let terminalThroughSeq: number | null = null;\n let terminalInitialized = args.terminal == null;\n let realtimeSubscribed = false;\n let fillAgain = false;\n let pollTimer: ReturnType<typeof setInterval> | null = null;\n let terminalTimer: ReturnType<typeof setInterval> | null = null;\n const closing = new AbortController();\n const readSignal = AbortSignal.any([\n closing.signal,\n ...[args.signal, args.closeSignal].filter((signal) => signal != null),\n ]);\n let httpFallback: AbortController | null = null;\n let unsubscribe: (() => void) | null = null;\n let detachAbort: () => void = () => {};\n let detachClose: () => void = () => {};\n // Frames are yielded through one chain, so a request frame waiting for its\n // decision id holds back the frames after it.\n let output: Promise<void> = Promise.resolve();\n const decisionIds = new Map<number, string>();\n const decisionWaiters = new Map<number, Set<() => void>>();\n const gapWaiters = new Set<() => void>();\n\n const stopFallback = (): void => {\n if (pollTimer != null) clearInterval(pollTimer);\n pollTimer = null;\n httpFallback?.abort();\n httpFallback = null;\n };\n\n const queue = createAsyncQueue<AcpFrameEventIface>(() => {\n closing.abort();\n if (terminalTimer != null) clearInterval(terminalTimer);\n ahead.clear();\n for (const wake of gapWaiters) wake();\n stopFallback();\n unsubscribe?.();\n detachAbort();\n detachClose();\n for (const waiters of decisionWaiters.values()) for (const wake of waiters) wake();\n decisionWaiters.clear();\n });\n\n const noteDecision = (seq: number, decisionId: string): void => {\n decisionIds.set(seq, decisionId);\n for (const wake of decisionWaiters.get(seq) ?? []) wake();\n decisionWaiters.delete(seq);\n };\n\n const waitForDecision = (seq: number, ms: number): Promise<void> =>\n new Promise((resolve) => {\n const waiters = decisionWaiters.get(seq) ?? new Set<() => void>();\n const wake = (): void => {\n waiters.delete(wake);\n resolve();\n };\n waiters.add(wake);\n decisionWaiters.set(seq, waiters);\n void timing.sleep(ms).then(wake);\n });\n\n const readOpenDecisions = async (): Promise<void> => {\n if (args.decisions == null) return;\n try {\n for (const decision of await args.decisions(readSignal)) {\n if (decision.logSeq != null) noteDecision(decision.logSeq, decision.id);\n }\n } catch {\n // The next attempt, or the frame without an id.\n }\n };\n\n const joinDecisionId = async (seq: number): Promise<string | null> => {\n for (const delay of timing.decisionJoinDelaysMs) {\n if (decisionIds.has(seq) || queue.closed()) break;\n await waitForDecision(seq, delay);\n if (decisionIds.has(seq) || queue.closed()) break;\n await readOpenDecisions();\n }\n return decisionIds.get(seq) ?? null;\n };\n\n const emit = (event: AcpFrameEventIface, origin: FrameOrigin): void => {\n if (queue.closed()) return;\n nextSeq = event.seq + 1;\n if (event.decisionId != null) noteDecision(event.seq, event.decisionId);\n const join =\n event.decisionId == null && origin === FrameOrigin.Live && isDecisionRequestFrame(event);\n output = output\n .then(async () => {\n if (queue.closed() || (terminalThroughSeq != null && event.seq > terminalThroughSeq))\n return;\n const value = join ? { ...event, decisionId: await joinDecisionId(event.seq) } : event;\n if (queue.closed() || (terminalThroughSeq != null && event.seq > terminalThroughSeq))\n return;\n queue.push(value);\n if (args.until?.(value) === true) queue.end();\n })\n .catch((cause: unknown) => queue.fail(cause));\n };\n\n const drainAhead = (): void => {\n for (const seq of [...ahead.keys()]) if (seq < nextSeq) ahead.delete(seq);\n for (let held = ahead.get(nextSeq); held != null; held = ahead.get(nextSeq)) {\n if (terminalThroughSeq != null && held.event.seq > terminalThroughSeq) {\n ahead.clear();\n return;\n }\n ahead.delete(held.event.seq);\n emit(held.event, held.origin);\n }\n };\n\n const deliver = (event: AcpFrameEventIface, origin: FrameOrigin): boolean => {\n if (terminalThroughSeq != null && event.seq > terminalThroughSeq) return false;\n if (queue.closed() || event.seq < nextSeq) return false;\n if (!terminalInitialized || event.seq > nextSeq) {\n if (!ahead.has(event.seq) && ahead.size >= timing.replayPageSize * 2) {\n queue.fail(\n new Error('Frame replay fell behind; reconnect from the last received sequence'),\n );\n return false;\n }\n ahead.set(event.seq, { event, origin });\n return true;\n }\n emit(event, origin);\n drainAhead();\n return false;\n };\n\n const refreshTerminal = async (): Promise<void> => {\n if (args.terminal == null || queue.closed()) return;\n const terminal = await args.terminal(readSignal);\n terminalInitialized = true;\n if (terminal == null) return;\n terminalThroughSeq = terminal.throughSeq;\n for (const seq of ahead.keys()) if (seq > terminalThroughSeq) ahead.delete(seq);\n if (terminalThroughSeq < nextSeq) await output.then(() => queue.end());\n };\n\n /** Pages forward from the next expected seq until the page reaches the log head. */\n const replayOnce = async (): Promise<void> => {\n let from = nextSeq;\n for (;;) {\n const page = await args.replay({\n fromSeq: from,\n limit: timing.replayPageSize,\n signal: readSignal,\n });\n const frames = [...page.frames].sort((left, right) => left.seq - right.seq);\n for (const event of frames) deliver(event, FrameOrigin.Replay);\n const last = frames.at(-1)?.seq;\n if (queue.closed() || last == null) return;\n // Page by what the server returned, not by what was emitted, so frames held behind a gap still advance it.\n const next = Math.max(nextSeq, last + 1);\n if (next <= from || (!page.hasMore && last >= page.headSeq)) return;\n from = next;\n }\n };\n\n const fill = async (): Promise<void> => {\n await replayOnce();\n let attempt = 0;\n while (ahead.size > 0 && !queue.closed()) {\n if (ahead.size === 0 || queue.closed()) return;\n const delay = timing.gapRetryDelaysMs[attempt] ?? timing.pollIntervalMs;\n attempt += 1;\n await new Promise<void>((resolve) => {\n const wake = () => {\n clearTimeout(timer);\n gapWaiters.delete(wake);\n resolve();\n };\n const timer = setTimeout(wake, Math.max(1, delay));\n gapWaiters.add(wake);\n });\n if (queue.closed()) return;\n await refreshTerminal();\n if (queue.closed()) return;\n await replayOnce();\n }\n };\n\n const requestFill = (): void => {\n if (filling) {\n fillAgain = true;\n return;\n }\n filling = true;\n void (async () => {\n try {\n do {\n fillAgain = false;\n await refreshTerminal();\n if (queue.closed()) return;\n await fill();\n await refreshTerminal();\n } while (fillAgain && !queue.closed());\n if (realtimeSubscribed) stopFallback();\n if (!args.follow) await output.then(() => queue.end());\n } catch (cause) {\n if (args.follow && isRetryableClientError(cause)) {\n startHttpFallback();\n } else queue.fail(cause);\n } finally {\n filling = false;\n }\n })();\n };\n\n const pollReplay = (): void => {\n pollTimer ??= setInterval(requestFill, timing.pollIntervalMs);\n };\n\n /** Streams frames over HTTP until the transport subscribes again or the stream ends. */\n const startHttpFallback = (): void => {\n if (httpFallback != null || pollTimer != null || queue.closed()) return;\n const open = args.httpStream;\n if (open == null) {\n pollReplay();\n return;\n }\n const controller = new AbortController();\n httpFallback = controller;\n void (async () => {\n while (!controller.signal.aborted && !queue.closed()) {\n try {\n for await (const event of open({ fromSeq: nextSeq, signal: controller.signal })) {\n if (deliver(event, FrameOrigin.Live)) requestFill();\n }\n } catch (cause) {\n if (controller.signal.aborted || queue.closed()) return;\n if (\n isClientError(cause) &&\n (cause.code === ClientErrorCode.StreamUnsupported ||\n cause.status === 404 ||\n cause.status === 405)\n ) {\n if (httpFallback === controller) httpFallback = null;\n pollReplay();\n return;\n }\n if (!isRetryableClientError(cause)) {\n queue.fail(cause);\n return;\n }\n }\n if (controller.signal.aborted) return;\n await timing.sleep(timing.pollIntervalMs);\n }\n })();\n };\n\n const onFrame = (raw: RealtimeTransportFrameIface): void => {\n for (const wake of gapWaiters) wake();\n const frame = agentRealtimeFrameSchema.safeParse(raw);\n if (!frame.success) return;\n switch (frame.data.type) {\n case AgentRealtimeFrameType.Event: {\n if (frame.data.kind === AgentRealtimeKind.DecisionChanged) {\n const changed = decisionChangedEventSchema.safeParse(frame.data.payload);\n if (\n changed.success &&\n changed.data.state === DecisionEventState.Created &&\n changed.data.decision.logSeq != null\n ) {\n noteDecision(changed.data.decision.logSeq, changed.data.decision.id);\n }\n return;\n }\n if (frame.data.kind === AgentRealtimeKind.TurnEnded && args.terminal != null) {\n terminalInitialized = false;\n requestFill();\n return;\n }\n if (frame.data.kind !== AgentRealtimeKind.AcpFrame) return;\n const event = acpFrameEventSchema.safeParse(frame.data.payload);\n if (event.success && deliver(event.data, FrameOrigin.Live)) requestFill();\n return;\n }\n case AgentRealtimeFrameType.Subscribed:\n realtimeSubscribed = true;\n stopFallback();\n requestFill();\n return;\n case AgentRealtimeFrameType.ResyncRequired:\n requestFill();\n return;\n case AgentRealtimeFrameType.Error:\n if (isTerminalRealtimeError(frame.data)) {\n queue.fail(\n realtimeSubscriptionError({\n topic: frame.data.topic ?? agentRealtimeTopics.session(args.sessionId),\n code: frame.data.code ?? 'unknown',\n message: frame.data.message ?? 'Realtime subscription was refused',\n }),\n );\n return;\n }\n realtimeSubscribed = false;\n // Retryable: the transport resubscribes; Streamable HTTP covers the outage.\n requestFill();\n startHttpFallback();\n return;\n default:\n return;\n }\n };\n\n detachAbort = failOnAbort(queue, args.signal);\n detachClose = failOnAbort(queue, args.closeSignal);\n if (!queue.closed()) {\n // Subscribe before the first replay so nothing published in between is lost.\n if (args.follow) {\n const stop = args.transport.subscribe(agentRealtimeTopics.session(args.sessionId), onFrame);\n if (queue.closed()) stop();\n else unsubscribe = stop;\n }\n requestFill();\n if (args.terminal != null && args.follow && !queue.closed())\n terminalTimer = setInterval(requestFill, Math.max(1, timing.conversationPollIntervalMs));\n }\n return queue.iterator;\n};\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,kBAAkB,mBAAmB;AAC9C;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAkCA,MAAM,sBAAyC;AAAA,EACpD,OAAO,CAAC,OAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,EAC/D,kBAAkB,CAAC,KAAK,KAAK,KAAK,KAAM,GAAI;AAAA,EAC5C,gBAAgB;AAAA,EAChB,4BAA4B;AAAA,EAC5B,gBAAgB;AAAA,EAChB,sBAAsB,CAAC,KAAK,GAAI;AAClC;AAgCA,MAAM,2BAA2B,oBAAI,IAAI,CAAC,8BAA8B,oBAAoB,CAAC;AAGtF,MAAM,yBAAyB,CAAC,UACrC,MAAM,cAAc,kBAAkB,iBACtC,MAAM,MAAM,MAAM,QAClB,MAAM,MAAM,UAAU,QACtB,yBAAyB,IAAI,MAAM,MAAM,MAAM;AAGjD,IAAK,cAAL,kBAAKA,iBAAL;AACE,EAAAA,aAAA,YAAS;AACT,EAAAA,aAAA,UAAO;AAFJ,SAAAA;AAAA,GAAA;AAKE,MAAM,sBAAsB,CACjC,SAC8C;AAC9C,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,QAAQ,oBAAI,IAAgE;AAElF,MAAI,UAAU,KAAK,IAAI,qBAAqB,KAAK,OAAO;AACxD,MAAI,UAAU;AACd,MAAI,qBAAoC;AACxC,MAAI,sBAAsB,KAAK,YAAY;AAC3C,MAAI,qBAAqB;AACzB,MAAI,YAAY;AAChB,MAAI,YAAmD;AACvD,MAAI,gBAAuD;AAC3D,QAAM,UAAU,IAAI,gBAAgB;AACpC,QAAM,aAAa,YAAY,IAAI;AAAA,IACjC,QAAQ;AAAA,IACR,GAAG,CAAC,KAAK,QAAQ,KAAK,WAAW,EAAE,OAAO,CAAC,WAAW,UAAU,IAAI;AAAA,EACtE,CAAC;AACD,MAAI,eAAuC;AAC3C,MAAI,cAAmC;AACvC,MAAI,cAA0B,MAAM;AAAA,EAAC;AACrC,MAAI,cAA0B,MAAM;AAAA,EAAC;AAGrC,MAAI,SAAwB,QAAQ,QAAQ;AAC5C,QAAM,cAAc,oBAAI,IAAoB;AAC5C,QAAM,kBAAkB,oBAAI,IAA6B;AACzD,QAAM,aAAa,oBAAI,IAAgB;AAEvC,QAAM,eAAe,MAAY;AAC/B,QAAI,aAAa,KAAM,eAAc,SAAS;AAC9C,gBAAY;AACZ,kBAAc,MAAM;AACpB,mBAAe;AAAA,EACjB;AAEA,QAAM,QAAQ,iBAAqC,MAAM;AACvD,YAAQ,MAAM;AACd,QAAI,iBAAiB,KAAM,eAAc,aAAa;AACtD,UAAM,MAAM;AACZ,eAAW,QAAQ,WAAY,MAAK;AACpC,iBAAa;AACb,kBAAc;AACd,gBAAY;AACZ,gBAAY;AACZ,eAAW,WAAW,gBAAgB,OAAO,EAAG,YAAW,QAAQ,QAAS,MAAK;AACjF,oBAAgB,MAAM;AAAA,EACxB,CAAC;AAED,QAAM,eAAe,CAAC,KAAa,eAA6B;AAC9D,gBAAY,IAAI,KAAK,UAAU;AAC/B,eAAW,QAAQ,gBAAgB,IAAI,GAAG,KAAK,CAAC,EAAG,MAAK;AACxD,oBAAgB,OAAO,GAAG;AAAA,EAC5B;AAEA,QAAM,kBAAkB,CAAC,KAAa,OACpC,IAAI,QAAQ,CAAC,YAAY;AACvB,UAAM,UAAU,gBAAgB,IAAI,GAAG,KAAK,oBAAI,IAAgB;AAChE,UAAM,OAAO,MAAY;AACvB,cAAQ,OAAO,IAAI;AACnB,cAAQ;AAAA,IACV;AACA,YAAQ,IAAI,IAAI;AAChB,oBAAgB,IAAI,KAAK,OAAO;AAChC,SAAK,OAAO,MAAM,EAAE,EAAE,KAAK,IAAI;AAAA,EACjC,CAAC;AAEH,QAAM,oBAAoB,YAA2B;AACnD,QAAI,KAAK,aAAa,KAAM;AAC5B,QAAI;AACF,iBAAW,YAAY,MAAM,KAAK,UAAU,UAAU,GAAG;AACvD,YAAI,SAAS,UAAU,KAAM,cAAa,SAAS,QAAQ,SAAS,EAAE;AAAA,MACxE;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,iBAAiB,OAAO,QAAwC;AACpE,eAAW,SAAS,OAAO,sBAAsB;AAC/C,UAAI,YAAY,IAAI,GAAG,KAAK,MAAM,OAAO,EAAG;AAC5C,YAAM,gBAAgB,KAAK,KAAK;AAChC,UAAI,YAAY,IAAI,GAAG,KAAK,MAAM,OAAO,EAAG;AAC5C,YAAM,kBAAkB;AAAA,IAC1B;AACA,WAAO,YAAY,IAAI,GAAG,KAAK;AAAA,EACjC;AAEA,QAAM,OAAO,CAAC,OAA2B,WAA8B;AACrE,QAAI,MAAM,OAAO,EAAG;AACpB,cAAU,MAAM,MAAM;AACtB,QAAI,MAAM,cAAc,KAAM,cAAa,MAAM,KAAK,MAAM,UAAU;AACtE,UAAM,OACJ,MAAM,cAAc,QAAQ,WAAW,qBAAoB,uBAAuB,KAAK;AACzF,aAAS,OACN,KAAK,YAAY;AAChB,UAAI,MAAM,OAAO,KAAM,sBAAsB,QAAQ,MAAM,MAAM;AAC/D;AACF,YAAM,QAAQ,OAAO,EAAE,GAAG,OAAO,YAAY,MAAM,eAAe,MAAM,GAAG,EAAE,IAAI;AACjF,UAAI,MAAM,OAAO,KAAM,sBAAsB,QAAQ,MAAM,MAAM;AAC/D;AACF,YAAM,KAAK,KAAK;AAChB,UAAI,KAAK,QAAQ,KAAK,MAAM,KAAM,OAAM,IAAI;AAAA,IAC9C,CAAC,EACA,MAAM,CAAC,UAAmB,MAAM,KAAK,KAAK,CAAC;AAAA,EAChD;AAEA,QAAM,aAAa,MAAY;AAC7B,eAAW,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC,EAAG,KAAI,MAAM,QAAS,OAAM,OAAO,GAAG;AACxE,aAAS,OAAO,MAAM,IAAI,OAAO,GAAG,QAAQ,MAAM,OAAO,MAAM,IAAI,OAAO,GAAG;AAC3E,UAAI,sBAAsB,QAAQ,KAAK,MAAM,MAAM,oBAAoB;AACrE,cAAM,MAAM;AACZ;AAAA,MACF;AACA,YAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,WAAK,KAAK,OAAO,KAAK,MAAM;AAAA,IAC9B;AAAA,EACF;AAEA,QAAM,UAAU,CAAC,OAA2B,WAAiC;AAC3E,QAAI,sBAAsB,QAAQ,MAAM,MAAM,mBAAoB,QAAO;AACzE,QAAI,MAAM,OAAO,KAAK,MAAM,MAAM,QAAS,QAAO;AAClD,QAAI,CAAC,uBAAuB,MAAM,MAAM,SAAS;AAC/C,UAAI,CAAC,MAAM,IAAI,MAAM,GAAG,KAAK,MAAM,QAAQ,OAAO,iBAAiB,GAAG;AACpE,cAAM;AAAA,UACJ,IAAI,MAAM,qEAAqE;AAAA,QACjF;AACA,eAAO;AAAA,MACT;AACA,YAAM,IAAI,MAAM,KAAK,EAAE,OAAO,OAAO,CAAC;AACtC,aAAO;AAAA,IACT;AACA,SAAK,OAAO,MAAM;AAClB,eAAW;AACX,WAAO;AAAA,EACT;AAEA,QAAM,kBAAkB,YAA2B;AACjD,QAAI,KAAK,YAAY,QAAQ,MAAM,OAAO,EAAG;AAC7C,UAAM,WAAW,MAAM,KAAK,SAAS,UAAU;AAC/C,0BAAsB;AACtB,QAAI,YAAY,KAAM;AACtB,yBAAqB,SAAS;AAC9B,eAAW,OAAO,MAAM,KAAK,EAAG,KAAI,MAAM,mBAAoB,OAAM,OAAO,GAAG;AAC9E,QAAI,qBAAqB,QAAS,OAAM,OAAO,KAAK,MAAM,MAAM,IAAI,CAAC;AAAA,EACvE;AAGA,QAAM,aAAa,YAA2B;AAC5C,QAAI,OAAO;AACX,eAAS;AACP,YAAM,OAAO,MAAM,KAAK,OAAO;AAAA,QAC7B,SAAS;AAAA,QACT,OAAO,OAAO;AAAA,QACd,QAAQ;AAAA,MACV,CAAC;AACD,YAAM,SAAS,CAAC,GAAG,KAAK,MAAM,EAAE,KAAK,CAAC,MAAM,UAAU,KAAK,MAAM,MAAM,GAAG;AAC1E,iBAAW,SAAS,OAAQ,SAAQ,OAAO,qBAAkB;AAC7D,YAAM,OAAO,OAAO,GAAG,EAAE,GAAG;AAC5B,UAAI,MAAM,OAAO,KAAK,QAAQ,KAAM;AAEpC,YAAM,OAAO,KAAK,IAAI,SAAS,OAAO,CAAC;AACvC,UAAI,QAAQ,QAAS,CAAC,KAAK,WAAW,QAAQ,KAAK,QAAU;AAC7D,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,OAAO,YAA2B;AACtC,UAAM,WAAW;AACjB,QAAI,UAAU;AACd,WAAO,MAAM,OAAO,KAAK,CAAC,MAAM,OAAO,GAAG;AACxC,UAAI,MAAM,SAAS,KAAK,MAAM,OAAO,EAAG;AACxC,YAAM,QAAQ,OAAO,iBAAiB,OAAO,KAAK,OAAO;AACzD,iBAAW;AACX,YAAM,IAAI,QAAc,CAAC,YAAY;AACnC,cAAM,OAAO,MAAM;AACjB,uBAAa,KAAK;AAClB,qBAAW,OAAO,IAAI;AACtB,kBAAQ;AAAA,QACV;AACA,cAAM,QAAQ,WAAW,MAAM,KAAK,IAAI,GAAG,KAAK,CAAC;AACjD,mBAAW,IAAI,IAAI;AAAA,MACrB,CAAC;AACD,UAAI,MAAM,OAAO,EAAG;AACpB,YAAM,gBAAgB;AACtB,UAAI,MAAM,OAAO,EAAG;AACpB,YAAM,WAAW;AAAA,IACnB;AAAA,EACF;AAEA,QAAM,cAAc,MAAY;AAC9B,QAAI,SAAS;AACX,kBAAY;AACZ;AAAA,IACF;AACA,cAAU;AACV,UAAM,YAAY;AAChB,UAAI;AACF,WAAG;AACD,sBAAY;AACZ,gBAAM,gBAAgB;AACtB,cAAI,MAAM,OAAO,EAAG;AACpB,gBAAM,KAAK;AACX,gBAAM,gBAAgB;AAAA,QACxB,SAAS,aAAa,CAAC,MAAM,OAAO;AACpC,YAAI,mBAAoB,cAAa;AACrC,YAAI,CAAC,KAAK,OAAQ,OAAM,OAAO,KAAK,MAAM,MAAM,IAAI,CAAC;AAAA,MACvD,SAAS,OAAO;AACd,YAAI,KAAK,UAAU,uBAAuB,KAAK,GAAG;AAChD,4BAAkB;AAAA,QACpB,MAAO,OAAM,KAAK,KAAK;AAAA,MACzB,UAAE;AACA,kBAAU;AAAA,MACZ;AAAA,IACF,GAAG;AAAA,EACL;AAEA,QAAM,aAAa,MAAY;AAC7B,kBAAc,YAAY,aAAa,OAAO,cAAc;AAAA,EAC9D;AAGA,QAAM,oBAAoB,MAAY;AACpC,QAAI,gBAAgB,QAAQ,aAAa,QAAQ,MAAM,OAAO,EAAG;AACjE,UAAM,OAAO,KAAK;AAClB,QAAI,QAAQ,MAAM;AAChB,iBAAW;AACX;AAAA,IACF;AACA,UAAM,aAAa,IAAI,gBAAgB;AACvC,mBAAe;AACf,UAAM,YAAY;AAChB,aAAO,CAAC,WAAW,OAAO,WAAW,CAAC,MAAM,OAAO,GAAG;AACpD,YAAI;AACF,2BAAiB,SAAS,KAAK,EAAE,SAAS,SAAS,QAAQ,WAAW,OAAO,CAAC,GAAG;AAC/E,gBAAI,QAAQ,OAAO,iBAAgB,EAAG,aAAY;AAAA,UACpD;AAAA,QACF,SAAS,OAAO;AACd,cAAI,WAAW,OAAO,WAAW,MAAM,OAAO,EAAG;AACjD,cACE,cAAc,KAAK,MAClB,MAAM,SAAS,gBAAgB,qBAC9B,MAAM,WAAW,OACjB,MAAM,WAAW,MACnB;AACA,gBAAI,iBAAiB,WAAY,gBAAe;AAChD,uBAAW;AACX;AAAA,UACF;AACA,cAAI,CAAC,uBAAuB,KAAK,GAAG;AAClC,kBAAM,KAAK,KAAK;AAChB;AAAA,UACF;AAAA,QACF;AACA,YAAI,WAAW,OAAO,QAAS;AAC/B,cAAM,OAAO,MAAM,OAAO,cAAc;AAAA,MAC1C;AAAA,IACF,GAAG;AAAA,EACL;AAEA,QAAM,UAAU,CAAC,QAA2C;AAC1D,eAAW,QAAQ,WAAY,MAAK;AACpC,UAAM,QAAQ,yBAAyB,UAAU,GAAG;AACpD,QAAI,CAAC,MAAM,QAAS;AACpB,YAAQ,MAAM,KAAK,MAAM;AAAA,MACvB,KAAK,uBAAuB,OAAO;AACjC,YAAI,MAAM,KAAK,SAAS,kBAAkB,iBAAiB;AACzD,gBAAM,UAAU,2BAA2B,UAAU,MAAM,KAAK,OAAO;AACvE,cACE,QAAQ,WACR,QAAQ,KAAK,UAAU,mBAAmB,WAC1C,QAAQ,KAAK,SAAS,UAAU,MAChC;AACA,yBAAa,QAAQ,KAAK,SAAS,QAAQ,QAAQ,KAAK,SAAS,EAAE;AAAA,UACrE;AACA;AAAA,QACF;AACA,YAAI,MAAM,KAAK,SAAS,kBAAkB,aAAa,KAAK,YAAY,MAAM;AAC5E,gCAAsB;AACtB,sBAAY;AACZ;AAAA,QACF;AACA,YAAI,MAAM,KAAK,SAAS,kBAAkB,SAAU;AACpD,cAAM,QAAQ,oBAAoB,UAAU,MAAM,KAAK,OAAO;AAC9D,YAAI,MAAM,WAAW,QAAQ,MAAM,MAAM,iBAAgB,EAAG,aAAY;AACxE;AAAA,MACF;AAAA,MACA,KAAK,uBAAuB;AAC1B,6BAAqB;AACrB,qBAAa;AACb,oBAAY;AACZ;AAAA,MACF,KAAK,uBAAuB;AAC1B,oBAAY;AACZ;AAAA,MACF,KAAK,uBAAuB;AAC1B,YAAI,wBAAwB,MAAM,IAAI,GAAG;AACvC,gBAAM;AAAA,YACJ,0BAA0B;AAAA,cACxB,OAAO,MAAM,KAAK,SAAS,oBAAoB,QAAQ,KAAK,SAAS;AAAA,cACrE,MAAM,MAAM,KAAK,QAAQ;AAAA,cACzB,SAAS,MAAM,KAAK,WAAW;AAAA,YACjC,CAAC;AAAA,UACH;AACA;AAAA,QACF;AACA,6BAAqB;AAErB,oBAAY;AACZ,0BAAkB;AAClB;AAAA,MACF;AACE;AAAA,IACJ;AAAA,EACF;AAEA,gBAAc,YAAY,OAAO,KAAK,MAAM;AAC5C,gBAAc,YAAY,OAAO,KAAK,WAAW;AACjD,MAAI,CAAC,MAAM,OAAO,GAAG;AAEnB,QAAI,KAAK,QAAQ;AACf,YAAM,OAAO,KAAK,UAAU,UAAU,oBAAoB,QAAQ,KAAK,SAAS,GAAG,OAAO;AAC1F,UAAI,MAAM,OAAO,EAAG,MAAK;AAAA,UACpB,eAAc;AAAA,IACrB;AACA,gBAAY;AACZ,QAAI,KAAK,YAAY,QAAQ,KAAK,UAAU,CAAC,MAAM,OAAO;AACxD,sBAAgB,YAAY,aAAa,KAAK,IAAI,GAAG,OAAO,0BAA0B,CAAC;AAAA,EAC3F;AACA,SAAO,MAAM;AACf;",
|
|
6
6
|
"names": ["FrameOrigin"]
|
|
7
7
|
}
|
|
@@ -34,9 +34,9 @@ export interface HttpRequestArgsIface<Output> {
|
|
|
34
34
|
response: z.ZodType<Output>;
|
|
35
35
|
signal?: AbortSignal;
|
|
36
36
|
keepalive?: boolean;
|
|
37
|
-
/** Ids the error mapping attaches to
|
|
37
|
+
/** Ids the error mapping attaches to DecisionError / TurnRejectedError. */
|
|
38
38
|
context?: {
|
|
39
|
-
|
|
39
|
+
decisionId?: string;
|
|
40
40
|
sessionId?: string;
|
|
41
41
|
};
|
|
42
42
|
}
|
|
@@ -3,8 +3,8 @@ import { AgentApiErrorCode, apiErrorResponseSchema } from "@finalai/agent-protoc
|
|
|
3
3
|
import {
|
|
4
4
|
clientError,
|
|
5
5
|
ClientErrorCode,
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
decisionError,
|
|
7
|
+
DecisionErrorReason,
|
|
8
8
|
turnRejectedError
|
|
9
9
|
} from "./errors.mjs";
|
|
10
10
|
var HttpMethod = /* @__PURE__ */ ((HttpMethod2) => {
|
|
@@ -15,11 +15,11 @@ var HttpMethod = /* @__PURE__ */ ((HttpMethod2) => {
|
|
|
15
15
|
HttpMethod2["Delete"] = "DELETE";
|
|
16
16
|
return HttpMethod2;
|
|
17
17
|
})(HttpMethod || {});
|
|
18
|
-
const
|
|
19
|
-
[AgentApiErrorCode.
|
|
20
|
-
[AgentApiErrorCode.
|
|
21
|
-
[AgentApiErrorCode.
|
|
22
|
-
[AgentApiErrorCode.
|
|
18
|
+
const decisionReasonByCode = /* @__PURE__ */ new Map([
|
|
19
|
+
[AgentApiErrorCode.DecisionNotFound, DecisionErrorReason.NotFound],
|
|
20
|
+
[AgentApiErrorCode.DecisionNotInAudience, DecisionErrorReason.NotInAudience],
|
|
21
|
+
[AgentApiErrorCode.DecisionAlreadyResolved, DecisionErrorReason.AlreadyResolved],
|
|
22
|
+
[AgentApiErrorCode.DecisionExpired, DecisionErrorReason.Expired]
|
|
23
23
|
]);
|
|
24
24
|
const parseJson = (text) => {
|
|
25
25
|
if (text.trim().length === 0) return { ok: true, value: {} };
|
|
@@ -54,14 +54,14 @@ const errorFromResponse = (args) => {
|
|
|
54
54
|
state: detail.state
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
|
-
const reason =
|
|
57
|
+
const reason = decisionReasonByCode.get(detail.code);
|
|
58
58
|
if (reason != null) {
|
|
59
|
-
return
|
|
59
|
+
return decisionError({
|
|
60
60
|
message,
|
|
61
61
|
status: args.status,
|
|
62
62
|
code: detail.code,
|
|
63
63
|
body,
|
|
64
|
-
|
|
64
|
+
decisionId: detail.decisionId ?? args.context?.decisionId ?? null,
|
|
65
65
|
reason
|
|
66
66
|
});
|
|
67
67
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/agent-client/http.ts"],
|
|
4
|
-
"sourcesContent": ["import { jsonValueSchema, type JsonValue } from '@finalai/agent-protocol';\nimport { AgentApiErrorCode, apiErrorResponseSchema } from '@finalai/agent-protocol/agent-platform';\nimport type * as z from 'zod';\nimport {\n clientError,\n ClientErrorCode,\n
|
|
5
|
-
"mappings": "AAAA,SAAS,uBAAuC;AAChD,SAAS,mBAAmB,8BAA8B;AAE1D;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAcA,IAAK,aAAL,kBAAKA,gBAAL;AACL,EAAAA,YAAA,SAAM;AACN,EAAAA,YAAA,UAAO;AACP,EAAAA,YAAA,WAAQ;AACR,EAAAA,YAAA,SAAM;AACN,EAAAA,YAAA,YAAS;AALC,SAAAA;AAAA,GAAA;AA4CZ,MAAM,
|
|
4
|
+
"sourcesContent": ["import { jsonValueSchema, type JsonValue } from '@finalai/agent-protocol';\nimport { AgentApiErrorCode, apiErrorResponseSchema } from '@finalai/agent-protocol/agent-platform';\nimport type * as z from 'zod';\nimport {\n clientError,\n ClientErrorCode,\n decisionError,\n DecisionErrorReason,\n turnRejectedError,\n type AgentClientError,\n} from \"./errors.mjs\";\n\nexport type FetchIface = (input: string, init: RequestInit) => Promise<Response>;\n\n/** API key (`fk_...`), a bearer source (console access token, service grant), or the browser's console cookie. */\nexport type AgentClientAuth =\n | { anonymous: true }\n | { apiKey: string }\n | { bearer: () => Promise<string> | string }\n | { cookies: true };\n\n/** Extra headers per request (client identity, request source). */\nexport type HeadersOption = () => Record<string, string> | Promise<Record<string, string>>;\n\nexport enum HttpMethod {\n Get = 'GET',\n Post = 'POST',\n Patch = 'PATCH',\n Put = 'PUT',\n Delete = 'DELETE',\n}\n\nexport type QueryValue = string | number | boolean | undefined;\n\nexport interface HttpBodyIface {\n /** The strict client-to-server schema the body must satisfy. */\n schema: z.ZodType;\n value: unknown;\n}\n\nexport interface HttpRequestArgsIface<Output> {\n method: HttpMethod;\n path: string;\n query?: Record<string, QueryValue>;\n body?: HttpBodyIface;\n response: z.ZodType<Output>;\n signal?: AbortSignal;\n keepalive?: boolean;\n /** Ids the error mapping attaches to DecisionError / TurnRejectedError. */\n context?: { decisionId?: string; sessionId?: string };\n}\n\nexport interface HttpIface {\n request: <Output>(args: HttpRequestArgsIface<Output>) => Promise<Output>;\n /** Auth and caller headers for non-fetch transports (ACP WebSocket). */\n headers: () => Promise<Record<string, string>>;\n url: (path: string) => URL;\n fetch: FetchIface;\n usesCookies: boolean;\n}\n\nexport interface CreateHttpOptionsIface {\n host: string;\n auth: AgentClientAuth;\n headers?: HeadersOption;\n fetch?: FetchIface;\n}\n\nconst decisionReasonByCode = new Map<string, DecisionErrorReason>([\n [AgentApiErrorCode.DecisionNotFound, DecisionErrorReason.NotFound],\n [AgentApiErrorCode.DecisionNotInAudience, DecisionErrorReason.NotInAudience],\n [AgentApiErrorCode.DecisionAlreadyResolved, DecisionErrorReason.AlreadyResolved],\n [AgentApiErrorCode.DecisionExpired, DecisionErrorReason.Expired],\n]);\n\nconst parseJson = (text: string): { ok: true; value: JsonValue } | { ok: false } => {\n if (text.trim().length === 0) return { ok: true, value: {} };\n try {\n const parsed = jsonValueSchema.safeParse(JSON.parse(text));\n return parsed.success ? { ok: true, value: parsed.data } : { ok: false };\n } catch {\n return { ok: false };\n }\n};\n\ninterface ErrorResponseArgsIface {\n status: number;\n text: string;\n context: HttpRequestArgsIface<unknown>['context'];\n}\n\n/** Maps a non-2xx response to the SDK error family. */\nexport const errorFromResponse = (args: ErrorResponseArgsIface): AgentClientError => {\n const json = parseJson(args.text);\n const body = json.ok ? json.value : args.text.length > 0 ? args.text : null;\n const parsed = apiErrorResponseSchema.safeParse(body);\n if (!parsed.success) {\n return clientError({\n message: `Request failed with status ${args.status}`,\n status: args.status,\n code: ClientErrorCode.Unknown,\n body,\n });\n }\n const detail = parsed.data.error;\n const message = detail.message.length > 0 ? detail.message : detail.code;\n if (detail.code === AgentApiErrorCode.TurnRejected) {\n return turnRejectedError({\n message,\n status: args.status,\n code: detail.code,\n body,\n sessionId: detail.sessionId ?? args.context?.sessionId ?? null,\n state: detail.state,\n });\n }\n const reason = decisionReasonByCode.get(detail.code);\n if (reason != null) {\n return decisionError({\n message,\n status: args.status,\n code: detail.code,\n body,\n decisionId: detail.decisionId ?? args.context?.decisionId ?? null,\n reason,\n });\n }\n return clientError({ message, status: args.status, code: detail.code, body });\n};\n\nconst resolveHeaders = async (option: HeadersOption | undefined): Promise<Record<string, string>> =>\n option == null ? {} : await option();\n\nconst authHeaders = async (auth: AgentClientAuth): Promise<Record<string, string>> => {\n if ('apiKey' in auth) return { authorization: `Bearer ${auth.apiKey}` };\n if ('bearer' in auth) return { authorization: `Bearer ${await auth.bearer()}` };\n return {};\n};\n\nconst isAbort = (signal: AbortSignal | undefined): boolean => signal?.aborted === true;\n\n/** Where the session service mounts its API routes when `host` is a bare origin. */\nexport const DEFAULT_API_PREFIX = '/api';\n\n// `host` is the session service's origin (`https://agent-session.final.ai`),\n// whose routes live under `/api`, or a base URL with its own path prefix\n// (console-server's `/api/agent-platform` proxy, or `<origin>/api`), which\n// `new URL(path, host)` would drop for absolute paths.\nexport const joinHostPath = (host: string, path: string): URL => {\n const base = new URL(host);\n const trimmed = base.pathname.replace(/\\/+$/, '');\n const prefix = trimmed.length === 0 ? DEFAULT_API_PREFIX : trimmed;\n const [pathname, search] = path.split('?', 2);\n const target = new URL(base.origin);\n target.pathname = `${prefix}${pathname?.startsWith('/') ? '' : '/'}${pathname ?? ''}`;\n if (search != null) target.search = search;\n return target;\n};\n\nexport const createHttp = (options: CreateHttpOptionsIface): HttpIface => {\n const fetchImpl: FetchIface = options.fetch ?? ((input, init) => globalThis.fetch(input, init));\n const usesCookies = 'cookies' in options.auth;\n\n const headers = async (): Promise<Record<string, string>> => ({\n ...(await resolveHeaders(options.headers)),\n ...(await authHeaders(options.auth)),\n });\n\n const url = (path: string): URL => joinHostPath(options.host, path);\n\n const request = async <Output>(args: HttpRequestArgsIface<Output>): Promise<Output> => {\n const target = url(args.path);\n for (const [key, value] of Object.entries(args.query ?? {})) {\n if (value !== undefined) target.searchParams.set(key, String(value));\n }\n let body: string | undefined;\n if (args.body != null) {\n const validated = args.body.schema.safeParse(args.body.value);\n if (!validated.success) {\n throw clientError({\n message: `Invalid request for ${args.method} ${args.path}: ${validated.error.message}`,\n status: 0,\n code: ClientErrorCode.InvalidRequest,\n });\n }\n body = JSON.stringify(validated.data);\n }\n const baseHeaders = { accept: 'application/json', ...(await headers()) };\n const requestHeaders =\n body === undefined ? baseHeaders : { ...baseHeaders, 'content-type': 'application/json' };\n\n let response: Response;\n let text: string;\n try {\n response = await fetchImpl(target.toString(), {\n method: args.method,\n headers: requestHeaders,\n body,\n signal: args.signal,\n credentials: 'anonymous' in options.auth ? 'omit' : usesCookies ? 'include' : undefined,\n keepalive: args.keepalive,\n });\n // Read failures are network failures too.\n text = await response.text();\n } catch (cause) {\n if (isAbort(args.signal)) throw cause;\n throw clientError({\n message: `Network request to ${target.pathname} failed`,\n status: 0,\n code: ClientErrorCode.Network,\n cause,\n });\n }\n // Read text first so proxy and CDN error bodies survive non-JSON responses.\n if (!response.ok) {\n throw errorFromResponse({ status: response.status, text, context: args.context });\n }\n const json = parseJson(text);\n if (!json.ok) {\n throw clientError({\n message: `Response from ${args.method} ${args.path} was not JSON`,\n status: response.status,\n code: ClientErrorCode.InvalidResponse,\n body: text,\n });\n }\n const parsed = args.response.safeParse(json.value);\n if (!parsed.success) {\n throw clientError({\n message: `Unexpected response from ${args.method} ${args.path}: ${parsed.error.message}`,\n status: response.status,\n code: ClientErrorCode.InvalidResponse,\n body: json.value,\n });\n }\n return parsed.data;\n };\n\n return { request, headers, url, fetch: fetchImpl, usesCookies };\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["HttpMethod"]
|
|
7
7
|
}
|
|
@@ -2,13 +2,13 @@ export * from '@finalai/agent-protocol/agent-platform';
|
|
|
2
2
|
export { AcpAuthMode, type AcpApiIface, type AcpConnectArgsIface } from "./acp.mjs";
|
|
3
3
|
export { createTextCollector, isUserMessageFor, sessionUpdateOf, textOf, turnEndOf, type AcpSessionUpdateIface, type TurnEndIface, } from "./acp-frames.mjs";
|
|
4
4
|
export type { ComputerSetupGuidesApiIface, DefinitionRefIface, DefinitionsApiIface, ProvidersApiIface, ScheduleRef, SchedulesApiIface, } from "./build.mjs";
|
|
5
|
-
export { createClient, type AgentClientIface, type AgentHandleIface, type AgentsApiIface, type CreateClientOptionsIface, type
|
|
5
|
+
export { createClient, type AgentClientIface, type AgentHandleIface, type AgentsApiIface, type CreateClientOptionsIface, type PeopleApiIface, type RealtimeApiIface, } from "./client.mjs";
|
|
6
6
|
export { CollectionEventKind, CollectionResyncReason, type CollectionEvent, type CollectionEventsOptionsIface, type CollectionResyncEventIface, } from "./collection-events.mjs";
|
|
7
7
|
export { ConfigOptionCategory, configSelectFor, configSelectsOf, type ConfigSelectChoiceIface, type ConfigSelectIface, type SessionConfigOptionIface, } from "./config-options.mjs";
|
|
8
8
|
export type { EnumInput, SignalOptionsIface } from "./context.mjs";
|
|
9
9
|
export { TURN_OPEN_SESSION_STATES, isNewerMessageVersion, messageVersionOf, type MessageVersionIface, } from "./conversations.mjs";
|
|
10
10
|
export type { ConversationAgentTurnIface, ConversationEvent, ConversationEventMetaIface, ConversationEventsOptionsIface, ConversationHandleIface, ConversationsApiIface, CreateConversationArgsIface, ListMessagesOptionsIface, OpenedConversationIface, ParticipantCreateInput, SandboxFileContentArgsIface, SandboxFileContentRequestIface, SendMessageOptionsIface, SentMessageIface, UploadAttachmentArgsIface, } from "./conversations.mjs";
|
|
11
|
-
export { AgentClientErrorName, ClientErrorCode,
|
|
11
|
+
export { AgentClientErrorName, ClientErrorCode, DecisionErrorReason, clientError, decisionError, isClientError, isDecisionError, isRealtimeSubscriptionError, isTerminalRealtimeError, isTurnRejectedError, realtimeSubscriptionError, turnRejectedError, type AgentClientError, type ClientErrorIface, type DecisionErrorIface, type RealtimeSubscriptionErrorIface, type TurnRejectedErrorIface, } from "./errors.mjs";
|
|
12
12
|
export { defaultStreamTiming, type StreamTimingIface } from "./frame-stream.mjs";
|
|
13
13
|
export type { AgentClientAuth, FetchIface, HeadersOption } from "./http.mjs";
|
|
14
14
|
export { SessionLiveEventKind, type SessionLiveEvent } from "./live-stream.mjs";
|