@astralform/js 4.8.0 → 4.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +88 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +88 -26
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -784,7 +784,8 @@ var AstralformClient = class {
|
|
|
784
784
|
name: a.name,
|
|
785
785
|
teamId: a.team_id,
|
|
786
786
|
createdAt: a.created_at,
|
|
787
|
-
updatedAt: a.updated_at
|
|
787
|
+
updatedAt: a.updated_at,
|
|
788
|
+
avatarUrl: a.avatar_url ?? null
|
|
788
789
|
}));
|
|
789
790
|
}
|
|
790
791
|
// --- Jobs API ---
|
|
@@ -1066,6 +1067,19 @@ function translateAgentIdentity(raw) {
|
|
|
1066
1067
|
description: raw.description ?? null
|
|
1067
1068
|
};
|
|
1068
1069
|
}
|
|
1070
|
+
function translateTodoItem(raw) {
|
|
1071
|
+
return {
|
|
1072
|
+
id: raw.id ?? 0,
|
|
1073
|
+
subject: raw.subject ?? "",
|
|
1074
|
+
status: raw.status ?? "pending",
|
|
1075
|
+
description: raw.description ?? null,
|
|
1076
|
+
activeForm: raw.active_form ?? null,
|
|
1077
|
+
owner: raw.owner ?? null,
|
|
1078
|
+
blockedBy: raw.blocked_by ?? null,
|
|
1079
|
+
blocks: raw.blocks ?? null,
|
|
1080
|
+
priority: raw.priority ?? null
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1069
1083
|
function translateCustomEvent(name, data) {
|
|
1070
1084
|
switch (name) {
|
|
1071
1085
|
case "user_message":
|
|
@@ -1082,7 +1096,9 @@ function translateCustomEvent(name, data) {
|
|
|
1082
1096
|
case "todo_update":
|
|
1083
1097
|
return {
|
|
1084
1098
|
type: "todo_update",
|
|
1085
|
-
todos: data.todos ?? []
|
|
1099
|
+
todos: (data.todos ?? []).map(
|
|
1100
|
+
(t) => translateTodoItem(t)
|
|
1101
|
+
)
|
|
1086
1102
|
};
|
|
1087
1103
|
case "plan_update":
|
|
1088
1104
|
return {
|
|
@@ -1275,7 +1291,8 @@ function translateWireEvent(wire) {
|
|
|
1275
1291
|
usage: {
|
|
1276
1292
|
inputTokens: wire.usage.input_tokens ?? 0,
|
|
1277
1293
|
outputTokens: wire.usage.output_tokens ?? 0,
|
|
1278
|
-
cachedTokens: wire.usage.cached_tokens ?? 0
|
|
1294
|
+
cachedTokens: wire.usage.cached_tokens ?? 0,
|
|
1295
|
+
cacheCreationTokens: wire.usage.cache_creation_tokens ?? 0
|
|
1279
1296
|
},
|
|
1280
1297
|
ttfbMs: wire.ttfb_ms,
|
|
1281
1298
|
totalMs: wire.total_ms,
|
|
@@ -1321,6 +1338,7 @@ function translateWireEvent(wire) {
|
|
|
1321
1338
|
|
|
1322
1339
|
// src/session.ts
|
|
1323
1340
|
var SSE_MAX_RECONNECTS = 6;
|
|
1341
|
+
var SSE_STALL_TIMEOUT_MS = 45e3;
|
|
1324
1342
|
var TOOL_RESULT_MAX_RETRIES = 3;
|
|
1325
1343
|
var CONVERSATION_PAGE_SIZE = 50;
|
|
1326
1344
|
function sseReconnectDelayMs(attempt) {
|
|
@@ -1483,6 +1501,7 @@ var ChatSession = class {
|
|
|
1483
1501
|
agent_name: options?.agentName,
|
|
1484
1502
|
plan_mode: options?.planMode,
|
|
1485
1503
|
image_mode: options?.imageMode,
|
|
1504
|
+
video_mode: options?.videoMode,
|
|
1486
1505
|
goal: options?.goal,
|
|
1487
1506
|
// Per-request model choice (client-side model selection).
|
|
1488
1507
|
provider: options?.provider,
|
|
@@ -1571,14 +1590,23 @@ var ChatSession = class {
|
|
|
1571
1590
|
async consumeEventStream(jobId, conversationId, messageId, executeClientTools) {
|
|
1572
1591
|
const signal = this.abortController?.signal;
|
|
1573
1592
|
for (let attempt = 0; ; attempt++) {
|
|
1574
|
-
|
|
1593
|
+
if (signal?.aborted) return;
|
|
1594
|
+
const attemptController = new AbortController();
|
|
1595
|
+
const linkAbort = () => attemptController.abort();
|
|
1596
|
+
signal?.addEventListener("abort", linkAbort);
|
|
1575
1597
|
let sawTerminal;
|
|
1576
1598
|
try {
|
|
1599
|
+
const stream = this.client.streamJobEvents(
|
|
1600
|
+
jobId,
|
|
1601
|
+
this.lastSeq,
|
|
1602
|
+
attemptController.signal
|
|
1603
|
+
);
|
|
1577
1604
|
sawTerminal = await this.pumpStream(
|
|
1578
1605
|
stream,
|
|
1579
1606
|
conversationId,
|
|
1580
1607
|
messageId,
|
|
1581
|
-
executeClientTools
|
|
1608
|
+
executeClientTools,
|
|
1609
|
+
() => attemptController.abort()
|
|
1582
1610
|
);
|
|
1583
1611
|
} catch (err) {
|
|
1584
1612
|
if (signal?.aborted) return;
|
|
@@ -1588,6 +1616,8 @@ var ChatSession = class {
|
|
|
1588
1616
|
if (attempt >= SSE_MAX_RECONNECTS) throw err;
|
|
1589
1617
|
await this.sleepUnlessAborted(sseReconnectDelayMs(attempt + 1), signal);
|
|
1590
1618
|
continue;
|
|
1619
|
+
} finally {
|
|
1620
|
+
signal?.removeEventListener("abort", linkAbort);
|
|
1591
1621
|
}
|
|
1592
1622
|
if (sawTerminal || signal?.aborted) return;
|
|
1593
1623
|
if (attempt >= SSE_MAX_RECONNECTS) {
|
|
@@ -1600,35 +1630,66 @@ var ChatSession = class {
|
|
|
1600
1630
|
* Consume a single SSE stream to exhaustion. Returns whether a terminal
|
|
1601
1631
|
* event (``message_stop`` / ``error``) was seen, so the caller can decide
|
|
1602
1632
|
* whether an ended stream means "turn done" vs "dropped, reconnect".
|
|
1633
|
+
*
|
|
1634
|
+
* ``onStall`` aborts the per-attempt connection: if no event arrives within
|
|
1635
|
+
* SSE_STALL_TIMEOUT_MS (backend keepalives land every 15s), the stream is a
|
|
1636
|
+
* zombie — ``reader.read()`` will never settle — so we kill the fetch and
|
|
1637
|
+
* throw a ConnectionError, feeding the caller's reconnect-from-lastSeq loop.
|
|
1603
1638
|
*/
|
|
1604
|
-
async pumpStream(stream, conversationId, messageId, executeClientTools) {
|
|
1639
|
+
async pumpStream(stream, conversationId, messageId, executeClientTools, onStall) {
|
|
1605
1640
|
let sawTerminal = false;
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
const
|
|
1610
|
-
|
|
1611
|
-
|
|
1641
|
+
const iterator = stream[Symbol.asyncIterator]();
|
|
1642
|
+
try {
|
|
1643
|
+
while (true) {
|
|
1644
|
+
const next = iterator.next();
|
|
1645
|
+
let stallTimer;
|
|
1646
|
+
const stall = new Promise((_, reject) => {
|
|
1647
|
+
stallTimer = setTimeout(() => {
|
|
1648
|
+
reject(
|
|
1649
|
+
new ConnectionError(
|
|
1650
|
+
`Stream stalled: no events for ${SSE_STALL_TIMEOUT_MS}ms`
|
|
1651
|
+
)
|
|
1652
|
+
);
|
|
1653
|
+
onStall?.();
|
|
1654
|
+
}, SSE_STALL_TIMEOUT_MS);
|
|
1655
|
+
});
|
|
1656
|
+
let result;
|
|
1657
|
+
try {
|
|
1658
|
+
result = await Promise.race([next, stall]);
|
|
1659
|
+
} finally {
|
|
1660
|
+
clearTimeout(stallTimer);
|
|
1661
|
+
}
|
|
1662
|
+
if (result.done) break;
|
|
1663
|
+
const raw = result.value;
|
|
1664
|
+
let parsed;
|
|
1665
|
+
try {
|
|
1666
|
+
const data = JSON.parse(raw.data);
|
|
1667
|
+
if (typeof data !== "object" || data === null || typeof data.type !== "string") {
|
|
1668
|
+
if (typeof data?.seq === "number") {
|
|
1669
|
+
this.lastSeq = data.seq;
|
|
1670
|
+
}
|
|
1671
|
+
continue;
|
|
1672
|
+
}
|
|
1673
|
+
parsed = data;
|
|
1674
|
+
if (typeof data.seq === "number") {
|
|
1612
1675
|
this.lastSeq = data.seq;
|
|
1613
1676
|
}
|
|
1677
|
+
} catch {
|
|
1614
1678
|
continue;
|
|
1615
1679
|
}
|
|
1616
|
-
parsed
|
|
1617
|
-
|
|
1618
|
-
this.lastSeq = data.seq;
|
|
1680
|
+
if (parsed.type === "message_stop" || parsed.type === "error") {
|
|
1681
|
+
sawTerminal = true;
|
|
1619
1682
|
}
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1683
|
+
await this.dispatchWireEvent(
|
|
1684
|
+
parsed,
|
|
1685
|
+
conversationId,
|
|
1686
|
+
messageId,
|
|
1687
|
+
executeClientTools
|
|
1688
|
+
);
|
|
1625
1689
|
}
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
messageId,
|
|
1630
|
-
executeClientTools
|
|
1631
|
-
);
|
|
1690
|
+
} finally {
|
|
1691
|
+
void iterator.return?.(void 0).catch(() => {
|
|
1692
|
+
});
|
|
1632
1693
|
}
|
|
1633
1694
|
return sawTerminal;
|
|
1634
1695
|
}
|
|
@@ -2190,6 +2251,7 @@ var StreamManager = class {
|
|
|
2190
2251
|
uploadIds: options?.uploadIds,
|
|
2191
2252
|
planMode: options?.planMode,
|
|
2192
2253
|
imageMode: options?.imageMode,
|
|
2254
|
+
videoMode: options?.videoMode,
|
|
2193
2255
|
goal: options?.goal,
|
|
2194
2256
|
provider: options?.provider,
|
|
2195
2257
|
model: options?.model,
|