@cubos/agent-sdk 0.0.1142885 → 0.0.1143127
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/README.md +22 -7
- package/dist/client.d.ts +18 -3
- package/dist/errors.d.ts +7 -0
- package/dist/generated/schema.d.ts +10 -0
- package/dist/index.js +156 -56
- package/dist/index.js.map +6 -6
- package/dist/sse.d.ts +21 -3
- package/dist/sse.js +23 -6
- package/dist/sse.js.map +4 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -439,13 +439,28 @@ Transient stream failures do not end a subscription: the SDK reconnects with
|
|
|
439
439
|
exponential backoff and reports them through `onError`, for logging or a
|
|
440
440
|
"reconnecting" hint.
|
|
441
441
|
|
|
442
|
-
|
|
443
|
-
buys one immediate reconnect with a forced token refresh — a short-lived
|
|
444
|
-
expiring under a stream that outlives it is the expected case, not a
|
|
445
|
-
misconfiguration — and only a second rejection is final. A
|
|
446
|
-
|
|
447
|
-
`
|
|
448
|
-
|
|
442
|
+
Three failures that look like silence get handled rather than reported. A
|
|
443
|
+
**401** buys one immediate reconnect with a forced token refresh — a short-lived
|
|
444
|
+
token expiring under a stream that outlives it is the expected case, not a
|
|
445
|
+
misconfiguration — and only a second rejection is final. A **429** — the per-user
|
|
446
|
+
cap on open streams, which one tab too many reaches — waits out the server's
|
|
447
|
+
`Retry-After` and reconnects, since the cap clears the moment any tab closes. A
|
|
448
|
+
connection that stops sending **anything**, keep-alive comments included, is
|
|
449
|
+
dropped and reopened after `idleTimeoutMs` (30s, twice the server's keep-alive
|
|
450
|
+
interval): a half-open socket otherwise leaves the reader waiting forever with
|
|
451
|
+
no error to react to.
|
|
452
|
+
|
|
453
|
+
And a stream has to **prove itself before it is trusted**. The server sends a
|
|
454
|
+
frame on every connect, so until a connection has delivered one — and again
|
|
455
|
+
whenever one ends — `subscribe` polls the same log every 3s through the `after`
|
|
456
|
+
cursor, and the conversation row with it. On a healthy network the frame lands
|
|
457
|
+
inside the first poll's 2s grace and no poll is ever made. On a network whose
|
|
458
|
+
proxy holds a `text/event-stream` response until it ends (corporate TLS
|
|
459
|
+
inspection, some antivirus — Chrome negotiating HTTP/1.1 with a host that speaks
|
|
460
|
+
h2 is the tell), every connection sits silent until something cuts it, and the
|
|
461
|
+
reply used to show up only after a page reload; now it shows up within 3s. The
|
|
462
|
+
same rule covers the gap between a drop and the reconnect that follows. One
|
|
463
|
+
cursor serves both paths, so nothing is delivered twice.
|
|
449
464
|
|
|
450
465
|
What remains final — a 4xx that survived the refresh, a deleted conversation —
|
|
451
466
|
closes the subscription for good and fires **`onFatal`** (`onError` sees it too).
|
package/dist/client.d.ts
CHANGED
|
@@ -249,9 +249,10 @@ export declare class AgentClient {
|
|
|
249
249
|
* the page before this one, and `latestChangeSeq` to start a subscription
|
|
250
250
|
* from here instead of replaying everything.
|
|
251
251
|
*
|
|
252
|
-
* `hasOlder`
|
|
253
|
-
*
|
|
254
|
-
*
|
|
252
|
+
* `hasOlder` says whether any event precedes this page, which is not the
|
|
253
|
+
* same as whether the page was full: a page can hold events that are not
|
|
254
|
+
* messages, and a page shorter than asked for is what the server's own cap
|
|
255
|
+
* on `limit` returns for a large request.
|
|
255
256
|
*/
|
|
256
257
|
/**
|
|
257
258
|
* One page of the conversation's **event log**, oldest-first — the same rows
|
|
@@ -423,9 +424,23 @@ export declare class AgentClient {
|
|
|
423
424
|
* to skip that backfill and receive only what is new; that is what makes
|
|
424
425
|
* paging backwards meaningful, since otherwise the stream re-delivers the
|
|
425
426
|
* history you just paged through.
|
|
427
|
+
*
|
|
428
|
+
* **A stream has to prove itself before it is trusted.** Until a connection
|
|
429
|
+
* delivers its first frame — and again whenever one ends — the same log is
|
|
430
|
+
* polled every `STREAM_POLL_INTERVAL_MS` with the `after` cursor, and the
|
|
431
|
+
* conversation row with it. On a healthy network the server's first frame
|
|
432
|
+
* arrives well inside the first poll's grace and no poll is ever made. On a
|
|
433
|
+
* network whose proxy holds a `text/event-stream` response until it ends —
|
|
434
|
+
* which it never does — every connection sits silent until something cuts
|
|
435
|
+
* it, and without this the reply only ever showed up after a page reload.
|
|
436
|
+
* The same rule covers the gap between a drop and the reconnect that follows.
|
|
426
437
|
*/
|
|
427
438
|
subscribe(id: string, handlers: ConversationHandlers, opts?: {
|
|
428
439
|
since?: number;
|
|
440
|
+
/** Overrides `STREAM_POLL_GRACE_MS` for this subscription. */
|
|
441
|
+
pollGraceMs?: number;
|
|
442
|
+
/** Overrides `STREAM_POLL_INTERVAL_MS` for this subscription. */
|
|
443
|
+
pollIntervalMs?: number;
|
|
429
444
|
}): ConversationSubscription;
|
|
430
445
|
/** Live chat list. Fires per conversation whose activity advances; upsert by
|
|
431
446
|
* id and re-sort by `lastActivityAt` locally. */
|
package/dist/errors.d.ts
CHANGED
|
@@ -50,3 +50,10 @@ export declare class AgentNetworkError extends AgentError {
|
|
|
50
50
|
constructor(message: string, cause: unknown, timedOut?: boolean);
|
|
51
51
|
}
|
|
52
52
|
export declare function raiseForStatus(res: Response, fallback: string): Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Milliseconds from a `Retry-After`, which is either a delta in seconds or an
|
|
55
|
+
* HTTP date. Returns null when absent or unusable, so the caller can decide not
|
|
56
|
+
* to retry rather than guess an interval. Shared by the request retry and the
|
|
57
|
+
* stream reconnect, which honour the same header from the same limiter.
|
|
58
|
+
*/
|
|
59
|
+
export declare function parseRetryAfter(header: string | null): number | null;
|
|
@@ -4995,10 +4995,14 @@ export interface paths {
|
|
|
4995
4995
|
/**
|
|
4996
4996
|
* List conversation events
|
|
4997
4997
|
* @description Returns one page of the conversation's append-only event log in `seq` ascending order. Discarded (rolled-back) events are filtered out; use `events/stream` for the live delta view that surfaces them.
|
|
4998
|
+
*
|
|
4999
|
+
* With `after`, the page is instead the delta the stream would have sent: every row whose `change_seq` is past the cursor, in `change_seq` order, discarded and tentative rows included so a client can apply them exactly as it applies stream frames. This is how a client behind a proxy that buffers `text/event-stream` keeps up — poll it with the newest `change_seq` held and merge, the same loop the stream runs on its own reconnect. `before` and `after` cannot be combined (400).
|
|
4998
5000
|
*/
|
|
4999
5001
|
get: {
|
|
5000
5002
|
parameters: {
|
|
5001
5003
|
query?: {
|
|
5004
|
+
/** @description Return events with `change_seq > after`, oldest change first — the stream's delta, as a page. Excludes `before`. */
|
|
5005
|
+
after?: number;
|
|
5002
5006
|
/** @description Return events with `seq < before`; omit for the most recent page. */
|
|
5003
5007
|
before?: number;
|
|
5004
5008
|
/** @description Page size; clamped to 1..=200, default 50. */
|
|
@@ -5023,6 +5027,12 @@ export interface paths {
|
|
|
5023
5027
|
"application/json": components["schemas"]["ConversationEvent"][];
|
|
5024
5028
|
};
|
|
5025
5029
|
};
|
|
5030
|
+
400: {
|
|
5031
|
+
headers: {
|
|
5032
|
+
[name: string]: unknown;
|
|
5033
|
+
};
|
|
5034
|
+
content?: never;
|
|
5035
|
+
};
|
|
5026
5036
|
401: {
|
|
5027
5037
|
headers: {
|
|
5028
5038
|
[name: string]: unknown;
|
package/dist/index.js
CHANGED
|
@@ -76,6 +76,17 @@ async function raiseForStatus(res, fallback) {
|
|
|
76
76
|
const base = DEFAULT_MESSAGES[res.status] ?? fallback;
|
|
77
77
|
throw new AgentApiError(detail ? `${base} (${detail.slice(0, 500)})` : base, res.status, res.headers.get("x-request-id"), detail);
|
|
78
78
|
}
|
|
79
|
+
function parseRetryAfter(header) {
|
|
80
|
+
if (!header)
|
|
81
|
+
return null;
|
|
82
|
+
const seconds = Number(header.trim());
|
|
83
|
+
if (Number.isFinite(seconds))
|
|
84
|
+
return Math.max(0, seconds * 1000);
|
|
85
|
+
const date = Date.parse(header);
|
|
86
|
+
if (Number.isNaN(date))
|
|
87
|
+
return null;
|
|
88
|
+
return Math.max(0, date - Date.now());
|
|
89
|
+
}
|
|
79
90
|
|
|
80
91
|
// src/sse.ts
|
|
81
92
|
var MAX_BACKOFF_MS = 30000;
|
|
@@ -98,11 +109,12 @@ class SseIdleTimeout extends Error {
|
|
|
98
109
|
async function readSse(opts) {
|
|
99
110
|
const doFetch = opts.fetchImpl ?? globalThis.fetch;
|
|
100
111
|
const idleMs = opts.idleTimeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
|
|
101
|
-
|
|
112
|
+
const cursor = opts.cursor ?? { lastEventId: opts.lastEventId };
|
|
102
113
|
let attempt = 0;
|
|
103
114
|
let refreshing = false;
|
|
104
115
|
while (!opts.signal.aborted) {
|
|
105
116
|
let madeProgress = false;
|
|
117
|
+
let retryAfterMs = null;
|
|
106
118
|
const connection = new AbortController;
|
|
107
119
|
const unlink = forward(opts.signal, connection);
|
|
108
120
|
let idleTimer;
|
|
@@ -121,8 +133,8 @@ async function readSse(opts) {
|
|
|
121
133
|
...await opts.headers?.({ forceRefresh: refreshing }),
|
|
122
134
|
Accept: "text/event-stream"
|
|
123
135
|
};
|
|
124
|
-
if (lastEventId !== undefined)
|
|
125
|
-
headers["Last-Event-ID"] = lastEventId;
|
|
136
|
+
if (cursor.lastEventId !== undefined)
|
|
137
|
+
headers["Last-Event-ID"] = cursor.lastEventId;
|
|
126
138
|
armIdle();
|
|
127
139
|
const res = await doFetch(opts.url, { headers, signal: connection.signal });
|
|
128
140
|
if (opts.signal.aborted)
|
|
@@ -136,6 +148,10 @@ async function readSse(opts) {
|
|
|
136
148
|
refreshing = true;
|
|
137
149
|
continue;
|
|
138
150
|
}
|
|
151
|
+
if (res.status === 429) {
|
|
152
|
+
retryAfterMs = Math.min(MAX_BACKOFF_MS, parseRetryAfter(res.headers.get("retry-after")) ?? MAX_BACKOFF_MS);
|
|
153
|
+
await raiseForStatus(res, `Could not open ${opts.url}.`);
|
|
154
|
+
}
|
|
139
155
|
if (res.status >= 400 && res.status < 500) {
|
|
140
156
|
await raiseForStatus(res, `Could not open ${opts.url}.`).catch((err) => {
|
|
141
157
|
throw new Fatal(err);
|
|
@@ -149,7 +165,7 @@ async function readSse(opts) {
|
|
|
149
165
|
if (parsed === null)
|
|
150
166
|
continue;
|
|
151
167
|
if (parsed.id !== null)
|
|
152
|
-
lastEventId = parsed.id;
|
|
168
|
+
cursor.lastEventId = parsed.id;
|
|
153
169
|
opts.onEvent(parsed.data, parsed.event);
|
|
154
170
|
madeProgress = true;
|
|
155
171
|
}
|
|
@@ -165,12 +181,13 @@ async function readSse(opts) {
|
|
|
165
181
|
clearTimeout(idleTimer);
|
|
166
182
|
unlink();
|
|
167
183
|
connection.abort();
|
|
184
|
+
opts.onClose?.();
|
|
168
185
|
}
|
|
169
186
|
if (opts.signal.aborted)
|
|
170
187
|
return;
|
|
171
188
|
if (madeProgress)
|
|
172
189
|
attempt = 0;
|
|
173
|
-
const delayMs = Math.min(MAX_BACKOFF_MS, 1000 * 2 ** attempt);
|
|
190
|
+
const delayMs = retryAfterMs ?? Math.min(MAX_BACKOFF_MS, 1000 * 2 ** attempt);
|
|
174
191
|
attempt += 1;
|
|
175
192
|
await sleep(delayMs, opts.signal);
|
|
176
193
|
}
|
|
@@ -250,17 +267,6 @@ function forward(outer, child) {
|
|
|
250
267
|
var DEFAULT_TIMEOUT_MS = 30000;
|
|
251
268
|
var DEFAULT_MAX_RETRIES = 2;
|
|
252
269
|
var MAX_RETRY_WAIT_MS = 20000;
|
|
253
|
-
function parseRetryAfter(header) {
|
|
254
|
-
if (!header)
|
|
255
|
-
return null;
|
|
256
|
-
const seconds = Number(header.trim());
|
|
257
|
-
if (Number.isFinite(seconds))
|
|
258
|
-
return Math.max(0, seconds * 1000);
|
|
259
|
-
const date = Date.parse(header);
|
|
260
|
-
if (Number.isNaN(date))
|
|
261
|
-
return null;
|
|
262
|
-
return Math.max(0, date - Date.now());
|
|
263
|
-
}
|
|
264
270
|
function sleep2(ms, signal) {
|
|
265
271
|
return new Promise((resolve, reject) => {
|
|
266
272
|
if (signal?.aborted) {
|
|
@@ -1406,6 +1412,12 @@ function fold(a, b) {
|
|
|
1406
1412
|
|
|
1407
1413
|
// src/client.ts
|
|
1408
1414
|
var MAX_IMAGES_PER_MESSAGE = 10;
|
|
1415
|
+
function hasEventsBefore(oldestSeq) {
|
|
1416
|
+
return oldestSeq !== null && oldestSeq > 1;
|
|
1417
|
+
}
|
|
1418
|
+
var EVENTS_MAX_LIMIT = 200;
|
|
1419
|
+
var STREAM_POLL_GRACE_MS = 2000;
|
|
1420
|
+
var STREAM_POLL_INTERVAL_MS = 3000;
|
|
1409
1421
|
|
|
1410
1422
|
class AgentClient {
|
|
1411
1423
|
#transport;
|
|
@@ -1483,7 +1495,7 @@ class AgentClient {
|
|
|
1483
1495
|
const page = await this.#messagePage(id, { limit, before, signal: opts.signal });
|
|
1484
1496
|
for (let i = page.messages.length - 1;i >= 0; i--)
|
|
1485
1497
|
yield page.messages[i];
|
|
1486
|
-
if (page.
|
|
1498
|
+
if (page.oldestSeq === null || !hasEventsBefore(page.oldestSeq))
|
|
1487
1499
|
return;
|
|
1488
1500
|
before = page.oldestSeq;
|
|
1489
1501
|
}
|
|
@@ -1641,7 +1653,7 @@ class AgentClient {
|
|
|
1641
1653
|
events: page.events,
|
|
1642
1654
|
oldestSeq: page.oldestSeq,
|
|
1643
1655
|
latestChangeSeq: page.latestChangeSeq,
|
|
1644
|
-
hasOlder: page.
|
|
1656
|
+
hasOlder: hasEventsBefore(page.oldestSeq)
|
|
1645
1657
|
};
|
|
1646
1658
|
}
|
|
1647
1659
|
async listMessagesPage(id, opts = {}) {
|
|
@@ -1654,7 +1666,7 @@ class AgentClient {
|
|
|
1654
1666
|
lastTurnDoneSeq: page.lastTurnDoneSeq,
|
|
1655
1667
|
oldestSeq: page.oldestSeq,
|
|
1656
1668
|
latestChangeSeq: page.latestChangeSeq,
|
|
1657
|
-
hasOlder: page.
|
|
1669
|
+
hasOlder: hasEventsBefore(page.oldestSeq)
|
|
1658
1670
|
};
|
|
1659
1671
|
}
|
|
1660
1672
|
async sendMessage(id, content, signal) {
|
|
@@ -1772,66 +1784,154 @@ class AgentClient {
|
|
|
1772
1784
|
}
|
|
1773
1785
|
subscribe(id, handlers, opts = {}) {
|
|
1774
1786
|
const controller = new AbortController;
|
|
1787
|
+
const signal = controller.signal;
|
|
1788
|
+
const graceMs = opts.pollGraceMs ?? STREAM_POLL_GRACE_MS;
|
|
1789
|
+
const intervalMs = opts.pollIntervalMs ?? STREAM_POLL_INTERVAL_MS;
|
|
1775
1790
|
const streamedArgs = new Map;
|
|
1791
|
+
const cursor = { lastEventId: opts.since === undefined ? undefined : String(opts.since) };
|
|
1792
|
+
let delivered = opts.since ?? 0;
|
|
1793
|
+
const deliverEvent = (raw) => {
|
|
1794
|
+
if (raw.change_seq <= delivered)
|
|
1795
|
+
return;
|
|
1796
|
+
delivered = raw.change_seq;
|
|
1797
|
+
handlers.onEvent?.(raw);
|
|
1798
|
+
const message = toMessage(raw);
|
|
1799
|
+
if (message)
|
|
1800
|
+
handlers.onMessage?.(message);
|
|
1801
|
+
const todos = toTodos(raw);
|
|
1802
|
+
if (todos)
|
|
1803
|
+
handlers.onTodos?.(todos, raw.seq);
|
|
1804
|
+
const turnDone = toTurnDone(raw);
|
|
1805
|
+
if (turnDone !== null)
|
|
1806
|
+
handlers.onTurnDone?.(turnDone);
|
|
1807
|
+
const call = toClientToolCall(raw);
|
|
1808
|
+
if (call)
|
|
1809
|
+
handlers.onClientToolCall?.(call);
|
|
1810
|
+
for (const call2 of toToolCallArguments(raw)) {
|
|
1811
|
+
streamedArgs.set(call2.toolCallId, call2.arguments);
|
|
1812
|
+
}
|
|
1813
|
+
const activity = toToolActivity(raw);
|
|
1814
|
+
if (activity)
|
|
1815
|
+
handlers.onToolActivity?.(withToolArguments(activity, streamedArgs));
|
|
1816
|
+
handlers.onCursor?.(raw.change_seq);
|
|
1817
|
+
};
|
|
1818
|
+
const wantsEvents = Boolean(handlers.onMessage || handlers.onEvent || handlers.onTodos || handlers.onClientToolCall || handlers.onToolActivity || handlers.onTurnDone || handlers.onActivity || handlers.onOpen);
|
|
1819
|
+
const wantsMeta = Boolean(handlers.onConversation);
|
|
1776
1820
|
this.#base().then((base) => {
|
|
1777
|
-
if (
|
|
1821
|
+
if (signal.aborted)
|
|
1778
1822
|
return;
|
|
1779
|
-
|
|
1823
|
+
let eventsProven = !wantsEvents;
|
|
1824
|
+
let metaProven = !wantsMeta;
|
|
1825
|
+
let ended = false;
|
|
1826
|
+
let pollTimer;
|
|
1827
|
+
let polling = false;
|
|
1828
|
+
let polledStatus;
|
|
1829
|
+
let polledRow;
|
|
1830
|
+
const poll = async () => {
|
|
1831
|
+
pollTimer = undefined;
|
|
1832
|
+
if (signal.aborted || ended || polling)
|
|
1833
|
+
return;
|
|
1834
|
+
if (eventsProven && metaProven)
|
|
1835
|
+
return;
|
|
1836
|
+
polling = true;
|
|
1837
|
+
try {
|
|
1838
|
+
const row = await this.#transport.request("GET", `${base}/${id}`, {
|
|
1839
|
+
signal
|
|
1840
|
+
});
|
|
1841
|
+
if (!eventsProven) {
|
|
1842
|
+
for (;; ) {
|
|
1843
|
+
const rows = await this.#transport.request("GET", `${base}/${id}/events`, { query: { after: delivered, limit: EVENTS_MAX_LIMIT }, signal });
|
|
1844
|
+
if (signal.aborted)
|
|
1845
|
+
return;
|
|
1846
|
+
for (const raw of rows) {
|
|
1847
|
+
deliverEvent(raw);
|
|
1848
|
+
cursor.lastEventId = String(delivered);
|
|
1849
|
+
}
|
|
1850
|
+
if (rows.length < EVENTS_MAX_LIMIT)
|
|
1851
|
+
break;
|
|
1852
|
+
}
|
|
1853
|
+
const status = `${row.is_processing}:${row.has_pending_turn}`;
|
|
1854
|
+
if (status !== polledStatus) {
|
|
1855
|
+
polledStatus = status;
|
|
1856
|
+
handlers.onActivity?.(toTurnStatus(row));
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
if (!metaProven) {
|
|
1860
|
+
const serialized = JSON.stringify(row);
|
|
1861
|
+
if (serialized !== polledRow) {
|
|
1862
|
+
polledRow = serialized;
|
|
1863
|
+
handlers.onConversation?.(toConversation(row));
|
|
1864
|
+
}
|
|
1865
|
+
}
|
|
1866
|
+
} catch (err) {
|
|
1867
|
+
if (!signal.aborted)
|
|
1868
|
+
handlers.onError?.(err);
|
|
1869
|
+
} finally {
|
|
1870
|
+
polling = false;
|
|
1871
|
+
schedulePoll(intervalMs);
|
|
1872
|
+
}
|
|
1873
|
+
};
|
|
1874
|
+
const schedulePoll = (delayMs) => {
|
|
1875
|
+
if (signal.aborted || ended || pollTimer !== undefined)
|
|
1876
|
+
return;
|
|
1877
|
+
if (eventsProven && metaProven)
|
|
1878
|
+
return;
|
|
1879
|
+
pollTimer = setTimeout(() => void poll(), delayMs);
|
|
1880
|
+
};
|
|
1881
|
+
const stopPolling = () => {
|
|
1882
|
+
clearTimeout(pollTimer);
|
|
1883
|
+
pollTimer = undefined;
|
|
1884
|
+
};
|
|
1885
|
+
signal.addEventListener("abort", stopPolling, { once: true });
|
|
1886
|
+
const fatal = (err) => {
|
|
1887
|
+
ended = true;
|
|
1888
|
+
stopPolling();
|
|
1889
|
+
handlers.onError?.(err);
|
|
1890
|
+
handlers.onFatal?.(err);
|
|
1891
|
+
};
|
|
1892
|
+
if (wantsEvents) {
|
|
1780
1893
|
readSse({
|
|
1781
1894
|
url: this.#transport.url(`${base}/${id}/events/stream`),
|
|
1782
1895
|
event: ["conversation_event", "conversation_status"],
|
|
1783
|
-
|
|
1896
|
+
cursor,
|
|
1784
1897
|
headers: ({ forceRefresh }) => this.#transport.streamHeaders(forceRefresh),
|
|
1785
1898
|
fetchImpl: this.#transport.fetchImpl,
|
|
1786
|
-
signal
|
|
1899
|
+
signal,
|
|
1787
1900
|
onError: handlers.onError,
|
|
1788
1901
|
onOpen: handlers.onOpen,
|
|
1902
|
+
onClose: () => {
|
|
1903
|
+
eventsProven = false;
|
|
1904
|
+
schedulePoll(graceMs);
|
|
1905
|
+
},
|
|
1789
1906
|
onEvent: (frame, name) => {
|
|
1907
|
+
eventsProven = true;
|
|
1790
1908
|
if (name === "conversation_status") {
|
|
1791
1909
|
handlers.onActivity?.(toTurnStatus(frame));
|
|
1792
1910
|
return;
|
|
1793
1911
|
}
|
|
1794
|
-
|
|
1795
|
-
handlers.onEvent?.(raw);
|
|
1796
|
-
const message = toMessage(raw);
|
|
1797
|
-
if (message)
|
|
1798
|
-
handlers.onMessage?.(message);
|
|
1799
|
-
const todos = toTodos(raw);
|
|
1800
|
-
if (todos)
|
|
1801
|
-
handlers.onTodos?.(todos, raw.seq);
|
|
1802
|
-
const turnDone = toTurnDone(raw);
|
|
1803
|
-
if (turnDone !== null)
|
|
1804
|
-
handlers.onTurnDone?.(turnDone);
|
|
1805
|
-
const call = toClientToolCall(raw);
|
|
1806
|
-
if (call)
|
|
1807
|
-
handlers.onClientToolCall?.(call);
|
|
1808
|
-
for (const call2 of toToolCallArguments(raw)) {
|
|
1809
|
-
streamedArgs.set(call2.toolCallId, call2.arguments);
|
|
1810
|
-
}
|
|
1811
|
-
const activity = toToolActivity(raw);
|
|
1812
|
-
if (activity)
|
|
1813
|
-
handlers.onToolActivity?.(withToolArguments(activity, streamedArgs));
|
|
1814
|
-
handlers.onCursor?.(raw.change_seq);
|
|
1912
|
+
deliverEvent(frame);
|
|
1815
1913
|
}
|
|
1816
|
-
}).catch(
|
|
1817
|
-
handlers.onError?.(err);
|
|
1818
|
-
handlers.onFatal?.(err);
|
|
1819
|
-
});
|
|
1914
|
+
}).catch(fatal);
|
|
1820
1915
|
}
|
|
1821
|
-
if (
|
|
1916
|
+
if (wantsMeta) {
|
|
1822
1917
|
readSse({
|
|
1823
1918
|
url: this.#transport.url(`${base}/${id}/meta/stream`),
|
|
1824
1919
|
event: "conversation_meta",
|
|
1825
1920
|
headers: ({ forceRefresh }) => this.#transport.streamHeaders(forceRefresh),
|
|
1826
1921
|
fetchImpl: this.#transport.fetchImpl,
|
|
1827
|
-
signal
|
|
1922
|
+
signal,
|
|
1828
1923
|
onError: handlers.onError,
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1924
|
+
onClose: () => {
|
|
1925
|
+
metaProven = false;
|
|
1926
|
+
schedulePoll(graceMs);
|
|
1927
|
+
},
|
|
1928
|
+
onEvent: (raw) => {
|
|
1929
|
+
metaProven = true;
|
|
1930
|
+
handlers.onConversation?.(toConversation(raw));
|
|
1931
|
+
}
|
|
1932
|
+
}).catch(fatal);
|
|
1834
1933
|
}
|
|
1934
|
+
schedulePoll(graceMs);
|
|
1835
1935
|
});
|
|
1836
1936
|
return { close: () => controller.abort() };
|
|
1837
1937
|
}
|
|
@@ -1878,5 +1978,5 @@ export {
|
|
|
1878
1978
|
AgentApiError
|
|
1879
1979
|
};
|
|
1880
1980
|
|
|
1881
|
-
//# debugId=
|
|
1981
|
+
//# debugId=F147527891A76CE064756E2164756E21
|
|
1882
1982
|
//# sourceMappingURL=index.js.map
|