@astralform/js 0.2.1 → 0.2.3
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 +558 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +260 -70
- package/dist/index.d.ts +260 -70
- package/dist/index.js +556 -42
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ __export(index_exports, {
|
|
|
24
24
|
AstralformError: () => AstralformError,
|
|
25
25
|
AuthenticationError: () => AuthenticationError,
|
|
26
26
|
BlockBuilder: () => BlockBuilder,
|
|
27
|
+
ChatEventType: () => ChatEventType,
|
|
27
28
|
ChatSession: () => ChatSession,
|
|
28
29
|
ConnectionError: () => ConnectionError,
|
|
29
30
|
InMemoryStorage: () => InMemoryStorage,
|
|
@@ -31,6 +32,7 @@ __export(index_exports, {
|
|
|
31
32
|
RateLimitError: () => RateLimitError,
|
|
32
33
|
ServerError: () => ServerError,
|
|
33
34
|
StreamAbortedError: () => StreamAbortedError,
|
|
35
|
+
StreamManager: () => StreamManager,
|
|
34
36
|
ToolRegistry: () => ToolRegistry,
|
|
35
37
|
generateId: () => generateId,
|
|
36
38
|
standardHandlers: () => standardHandlers,
|
|
@@ -372,6 +374,8 @@ var BlockBuilder = class {
|
|
|
372
374
|
this.activeTextId = null;
|
|
373
375
|
this.activeThinkingId = null;
|
|
374
376
|
this.thinkingStartMs = null;
|
|
377
|
+
this.activeEditorId = null;
|
|
378
|
+
this.activeTodoId = null;
|
|
375
379
|
}
|
|
376
380
|
// ── Registration ──────────────────────────────────────────────
|
|
377
381
|
on(eventType, handler) {
|
|
@@ -398,6 +402,8 @@ var BlockBuilder = class {
|
|
|
398
402
|
this.activeTextId = null;
|
|
399
403
|
this.activeThinkingId = null;
|
|
400
404
|
this.thinkingStartMs = null;
|
|
405
|
+
this.activeEditorId = null;
|
|
406
|
+
this.activeTodoId = null;
|
|
401
407
|
}
|
|
402
408
|
setOnChange(fn) {
|
|
403
409
|
this._onChange = fn;
|
|
@@ -623,7 +629,6 @@ var ChatSession = class {
|
|
|
623
629
|
this.thinkingContent = "";
|
|
624
630
|
this.isThinking = false;
|
|
625
631
|
this.activeSubagents = /* @__PURE__ */ new Map();
|
|
626
|
-
this.sources = [];
|
|
627
632
|
this.capsuleOutputs = [];
|
|
628
633
|
this.todos = [];
|
|
629
634
|
this.activeTools = /* @__PURE__ */ new Map();
|
|
@@ -727,7 +732,6 @@ var ChatSession = class {
|
|
|
727
732
|
this.thinkingContent = "";
|
|
728
733
|
this.isThinking = false;
|
|
729
734
|
this.activeSubagents.clear();
|
|
730
|
-
this.sources = [];
|
|
731
735
|
this.capsuleOutputs = [];
|
|
732
736
|
this.todos = [];
|
|
733
737
|
this.activeTools.clear();
|
|
@@ -739,10 +743,12 @@ var ChatSession = class {
|
|
|
739
743
|
try {
|
|
740
744
|
await this.consumeJobStream(request);
|
|
741
745
|
} catch (err) {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
+
if (!(err instanceof DOMException && err.name === "AbortError")) {
|
|
747
|
+
this.emit({
|
|
748
|
+
type: "error",
|
|
749
|
+
error: err instanceof Error ? err : new ConnectionError(String(err))
|
|
750
|
+
});
|
|
751
|
+
}
|
|
746
752
|
} finally {
|
|
747
753
|
this.isStreaming = false;
|
|
748
754
|
this.executingTool = null;
|
|
@@ -895,11 +901,24 @@ var ChatSession = class {
|
|
|
895
901
|
applyEvent(event) {
|
|
896
902
|
switch (event.type) {
|
|
897
903
|
case "user_message":
|
|
898
|
-
this.emit({
|
|
904
|
+
this.emit({
|
|
905
|
+
type: "user_message",
|
|
906
|
+
content: event.content,
|
|
907
|
+
createdAt: event.created_at
|
|
908
|
+
});
|
|
899
909
|
break;
|
|
900
|
-
case "title_generated":
|
|
910
|
+
case "title_generated": {
|
|
911
|
+
if (this.conversationId && event.title) {
|
|
912
|
+
const conv = this.conversations.find(
|
|
913
|
+
(c) => c.id === this.conversationId
|
|
914
|
+
);
|
|
915
|
+
if (conv) {
|
|
916
|
+
conv.title = event.title;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
901
919
|
this.emit({ type: "title_generated", title: event.title });
|
|
902
920
|
break;
|
|
921
|
+
}
|
|
903
922
|
case "message_start":
|
|
904
923
|
if (event.conversation_id && !this.conversationId) {
|
|
905
924
|
this.conversationId = event.conversation_id;
|
|
@@ -922,6 +941,23 @@ var ChatSession = class {
|
|
|
922
941
|
this.isThinking = false;
|
|
923
942
|
this.emit({ type: "thinking_complete" });
|
|
924
943
|
break;
|
|
944
|
+
case "tool_executing":
|
|
945
|
+
this.emit({
|
|
946
|
+
type: "tool_executing",
|
|
947
|
+
name: event.tool,
|
|
948
|
+
call_id: event.call_id
|
|
949
|
+
});
|
|
950
|
+
break;
|
|
951
|
+
case "tool_progress":
|
|
952
|
+
this.emit({
|
|
953
|
+
type: "tool_progress",
|
|
954
|
+
callId: event.call_id,
|
|
955
|
+
tool: event.tool,
|
|
956
|
+
index: event.index,
|
|
957
|
+
total: event.total,
|
|
958
|
+
item: event.item
|
|
959
|
+
});
|
|
960
|
+
break;
|
|
925
961
|
case "message_stop":
|
|
926
962
|
this.emit({
|
|
927
963
|
type: "complete",
|
|
@@ -1031,10 +1067,6 @@ var ChatSession = class {
|
|
|
1031
1067
|
result: event.result
|
|
1032
1068
|
});
|
|
1033
1069
|
break;
|
|
1034
|
-
case "sources":
|
|
1035
|
-
this.sources.push(...event.sources);
|
|
1036
|
-
this.emit({ type: "sources", sources: event.sources });
|
|
1037
|
-
break;
|
|
1038
1070
|
case "capsule_output": {
|
|
1039
1071
|
const capsule = {
|
|
1040
1072
|
toolName: event.tool_name,
|
|
@@ -1060,6 +1092,40 @@ var ChatSession = class {
|
|
|
1060
1092
|
this.todos = event.todos;
|
|
1061
1093
|
this.emit({ type: "todo_update", todos: event.todos });
|
|
1062
1094
|
break;
|
|
1095
|
+
case "context_update":
|
|
1096
|
+
this.emit({
|
|
1097
|
+
type: "context_update",
|
|
1098
|
+
context: event.context,
|
|
1099
|
+
phase: event.phase,
|
|
1100
|
+
updatedAt: event.updated_at
|
|
1101
|
+
});
|
|
1102
|
+
break;
|
|
1103
|
+
case "desktop_stream":
|
|
1104
|
+
this.emit({
|
|
1105
|
+
type: "desktop_stream",
|
|
1106
|
+
url: event.url,
|
|
1107
|
+
authKey: event.auth_key,
|
|
1108
|
+
sandboxId: event.sandbox_id
|
|
1109
|
+
});
|
|
1110
|
+
break;
|
|
1111
|
+
case "attachment_staged":
|
|
1112
|
+
this.emit({
|
|
1113
|
+
type: "attachment_staged",
|
|
1114
|
+
files: (event.files || []).map((f) => ({
|
|
1115
|
+
name: f.name,
|
|
1116
|
+
path: f.path,
|
|
1117
|
+
mediaType: f.media_type,
|
|
1118
|
+
sizeBytes: f.size_bytes
|
|
1119
|
+
}))
|
|
1120
|
+
});
|
|
1121
|
+
break;
|
|
1122
|
+
case "workspace_ready":
|
|
1123
|
+
this.emit({
|
|
1124
|
+
type: "workspace_ready",
|
|
1125
|
+
conversationId: event.conversation_id,
|
|
1126
|
+
sandboxId: event.sandbox_id
|
|
1127
|
+
});
|
|
1128
|
+
break;
|
|
1063
1129
|
case "asset_created":
|
|
1064
1130
|
this.emit({
|
|
1065
1131
|
type: "asset_created",
|
|
@@ -1070,27 +1136,6 @@ var ChatSession = class {
|
|
|
1070
1136
|
sizeBytes: event.size_bytes
|
|
1071
1137
|
});
|
|
1072
1138
|
break;
|
|
1073
|
-
case "timeline_entry":
|
|
1074
|
-
this.emit({
|
|
1075
|
-
type: "timeline_entry",
|
|
1076
|
-
id: event.id,
|
|
1077
|
-
status: event.status,
|
|
1078
|
-
kind: event.kind,
|
|
1079
|
-
agent_name: event.agent_name,
|
|
1080
|
-
tool_name: event.tool_name,
|
|
1081
|
-
display_name: event.display_name,
|
|
1082
|
-
tool_category: event.tool_category,
|
|
1083
|
-
viewer: event.viewer,
|
|
1084
|
-
call_id: event.call_id,
|
|
1085
|
-
detail: event.detail,
|
|
1086
|
-
started_at: event.started_at,
|
|
1087
|
-
duration_ms: event.duration_ms,
|
|
1088
|
-
output_summary: event.output_summary,
|
|
1089
|
-
sources: event.sources,
|
|
1090
|
-
parent_id: event.parent_id,
|
|
1091
|
-
structured_output: event.structured_output
|
|
1092
|
-
});
|
|
1093
|
-
break;
|
|
1094
1139
|
case "editor_content_start":
|
|
1095
1140
|
this.emit({
|
|
1096
1141
|
type: "editor_content_start",
|
|
@@ -1212,19 +1257,26 @@ var ChatSession = class {
|
|
|
1212
1257
|
this.abortController = null;
|
|
1213
1258
|
}
|
|
1214
1259
|
}
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
});
|
|
1219
|
-
this.currentJobId = null;
|
|
1220
|
-
}
|
|
1260
|
+
/** Detach from the SSE stream without cancelling the job.
|
|
1261
|
+
* The backend job keeps running — caller can reconnect later. */
|
|
1262
|
+
detach() {
|
|
1221
1263
|
this.abortController?.abort();
|
|
1222
1264
|
this.abortController = null;
|
|
1223
1265
|
this.isStreaming = false;
|
|
1224
1266
|
this.streamingContent = "";
|
|
1225
1267
|
this.executingTool = null;
|
|
1268
|
+
this.blockBuilder.reset();
|
|
1226
1269
|
this.emit({ type: "disconnected" });
|
|
1227
1270
|
}
|
|
1271
|
+
/** Stop the job and disconnect (explicit user action). */
|
|
1272
|
+
disconnect() {
|
|
1273
|
+
if (this.currentJobId) {
|
|
1274
|
+
this.client.cancelJob(this.currentJobId).catch(() => {
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
1277
|
+
this.detach();
|
|
1278
|
+
this.currentJobId = null;
|
|
1279
|
+
}
|
|
1228
1280
|
async createNewConversation() {
|
|
1229
1281
|
const id = generateId();
|
|
1230
1282
|
const conversation = await this.storage.createConversation(
|
|
@@ -1292,10 +1344,31 @@ function finalizeThinking(builder) {
|
|
|
1292
1344
|
builder.thinkingStartMs = null;
|
|
1293
1345
|
}
|
|
1294
1346
|
}
|
|
1347
|
+
function finalizeEditor(builder) {
|
|
1348
|
+
if (builder.activeEditorId) {
|
|
1349
|
+
builder.patchBlock(builder.activeEditorId, {
|
|
1350
|
+
isStreaming: false
|
|
1351
|
+
});
|
|
1352
|
+
builder.activeEditorId = null;
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1295
1355
|
var handleUserMessage = (event, builder) => {
|
|
1296
|
-
if (builder.findBlock((b) => b.type === "user")) return;
|
|
1297
1356
|
const e = event;
|
|
1298
|
-
|
|
1357
|
+
const existing = builder.findBlock((b) => b.type === "user");
|
|
1358
|
+
if (existing) {
|
|
1359
|
+
if (e.createdAt) {
|
|
1360
|
+
builder.patchBlock(existing.id, {
|
|
1361
|
+
createdAt: e.createdAt
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
builder.addBlock({
|
|
1367
|
+
type: "user",
|
|
1368
|
+
id: builder.nextId(),
|
|
1369
|
+
content: e.content,
|
|
1370
|
+
createdAt: e.createdAt
|
|
1371
|
+
});
|
|
1299
1372
|
};
|
|
1300
1373
|
var handleChunk = (event, builder) => {
|
|
1301
1374
|
const e = event;
|
|
@@ -1337,12 +1410,26 @@ var handleToolCall = (event, builder) => {
|
|
|
1337
1410
|
var handleToolExecuting = (event, builder) => {
|
|
1338
1411
|
const e = event;
|
|
1339
1412
|
const block = builder.findBlock(
|
|
1340
|
-
(b) => b.type === "tool" && b.toolName === e.name && b.status === "calling"
|
|
1413
|
+
(b) => b.type === "tool" && (e.call_id ? b.callId === e.call_id : b.toolName === e.name) && b.status === "calling"
|
|
1341
1414
|
);
|
|
1342
1415
|
if (block) {
|
|
1343
1416
|
builder.patchBlock(block.id, { status: "executing" });
|
|
1344
1417
|
}
|
|
1345
1418
|
};
|
|
1419
|
+
var handleToolProgress = (event, builder) => {
|
|
1420
|
+
const e = event;
|
|
1421
|
+
const block = builder.findBlock(
|
|
1422
|
+
(b) => b.type === "tool" && b.callId === e.callId
|
|
1423
|
+
);
|
|
1424
|
+
if (block && block.type === "tool") {
|
|
1425
|
+
const sources = block.sources ? [...block.sources] : [];
|
|
1426
|
+
sources.push(e.item);
|
|
1427
|
+
builder.patchBlock(block.id, {
|
|
1428
|
+
sources,
|
|
1429
|
+
status: "executing"
|
|
1430
|
+
});
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1346
1433
|
var handleToolEnd = (event, builder) => {
|
|
1347
1434
|
const e = event;
|
|
1348
1435
|
const callId = e.type === "tool_end" ? e.callId : void 0;
|
|
@@ -1455,6 +1542,7 @@ var handleSubagentEnd = (event, builder) => {
|
|
|
1455
1542
|
var handleComplete = (_event, builder) => {
|
|
1456
1543
|
finalizeText(builder);
|
|
1457
1544
|
finalizeThinking(builder);
|
|
1545
|
+
finalizeEditor(builder);
|
|
1458
1546
|
for (const b of builder.getBlocks()) {
|
|
1459
1547
|
if (b.type === "tool" && b.status !== "completed") {
|
|
1460
1548
|
builder.patchBlock(b.id, { status: "completed" });
|
|
@@ -1474,31 +1562,458 @@ var handleError = (event, builder) => {
|
|
|
1474
1562
|
var handleDisconnected = (_event, builder) => {
|
|
1475
1563
|
finalizeText(builder);
|
|
1476
1564
|
finalizeThinking(builder);
|
|
1565
|
+
finalizeEditor(builder);
|
|
1566
|
+
};
|
|
1567
|
+
var handleCapsuleOutputChunk = (event, builder) => {
|
|
1568
|
+
const e = event;
|
|
1569
|
+
const block = builder.findBlock(
|
|
1570
|
+
(b) => b.type === "capsule" && b.callId === e.callId
|
|
1571
|
+
);
|
|
1572
|
+
if (block && block.type === "capsule") {
|
|
1573
|
+
builder.patchBlock(block.id, {
|
|
1574
|
+
output: block.output + e.chunk
|
|
1575
|
+
});
|
|
1576
|
+
} else {
|
|
1577
|
+
builder.addBlock({
|
|
1578
|
+
type: "capsule",
|
|
1579
|
+
id: builder.nextId(),
|
|
1580
|
+
callId: e.callId,
|
|
1581
|
+
toolName: "",
|
|
1582
|
+
output: e.chunk,
|
|
1583
|
+
isActive: true
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
};
|
|
1587
|
+
var handleCapsuleOutput = (event, builder) => {
|
|
1588
|
+
const e = event;
|
|
1589
|
+
const block = builder.findBlock(
|
|
1590
|
+
(b) => b.type === "capsule" && b.callId === (e.callId ?? "")
|
|
1591
|
+
);
|
|
1592
|
+
if (block) {
|
|
1593
|
+
builder.patchBlock(block.id, {
|
|
1594
|
+
output: e.output,
|
|
1595
|
+
command: e.command,
|
|
1596
|
+
toolName: e.toolName,
|
|
1597
|
+
durationMs: e.durationMs,
|
|
1598
|
+
isActive: false
|
|
1599
|
+
});
|
|
1600
|
+
} else {
|
|
1601
|
+
builder.addBlock({
|
|
1602
|
+
type: "capsule",
|
|
1603
|
+
id: builder.nextId(),
|
|
1604
|
+
callId: e.callId ?? "",
|
|
1605
|
+
toolName: e.toolName,
|
|
1606
|
+
command: e.command,
|
|
1607
|
+
output: e.output,
|
|
1608
|
+
durationMs: e.durationMs,
|
|
1609
|
+
isActive: false
|
|
1610
|
+
});
|
|
1611
|
+
}
|
|
1612
|
+
};
|
|
1613
|
+
var handleAssetCreated = (event, builder) => {
|
|
1614
|
+
const e = event;
|
|
1615
|
+
builder.addBlock({
|
|
1616
|
+
type: "asset",
|
|
1617
|
+
id: builder.nextId(),
|
|
1618
|
+
assetId: e.assetId,
|
|
1619
|
+
name: e.name,
|
|
1620
|
+
url: e.url,
|
|
1621
|
+
mediaType: e.mediaType,
|
|
1622
|
+
sizeBytes: e.sizeBytes
|
|
1623
|
+
});
|
|
1624
|
+
};
|
|
1625
|
+
var handleTodoUpdate = (event, builder) => {
|
|
1626
|
+
const e = event;
|
|
1627
|
+
if (builder.activeTodoId) {
|
|
1628
|
+
builder.patchBlock(builder.activeTodoId, {
|
|
1629
|
+
todos: e.todos
|
|
1630
|
+
});
|
|
1631
|
+
} else {
|
|
1632
|
+
const id = builder.nextId();
|
|
1633
|
+
builder.activeTodoId = id;
|
|
1634
|
+
builder.addBlock({
|
|
1635
|
+
type: "todo",
|
|
1636
|
+
id,
|
|
1637
|
+
todos: e.todos
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
};
|
|
1641
|
+
var handleEditorContentStart = (event, builder) => {
|
|
1642
|
+
const e = event;
|
|
1643
|
+
const id = builder.nextId();
|
|
1644
|
+
builder.activeEditorId = id;
|
|
1645
|
+
builder.addBlock({
|
|
1646
|
+
type: "editor",
|
|
1647
|
+
id,
|
|
1648
|
+
callId: e.callId,
|
|
1649
|
+
path: e.path,
|
|
1650
|
+
language: e.language,
|
|
1651
|
+
content: "",
|
|
1652
|
+
isStreaming: true
|
|
1653
|
+
});
|
|
1654
|
+
};
|
|
1655
|
+
var handleEditorContentDelta = (event, builder) => {
|
|
1656
|
+
const e = event;
|
|
1657
|
+
const block = builder.findBlock(
|
|
1658
|
+
(b) => b.type === "editor" && b.callId === e.callId
|
|
1659
|
+
);
|
|
1660
|
+
if (block && block.type === "editor") {
|
|
1661
|
+
builder.patchBlock(block.id, {
|
|
1662
|
+
content: block.content + e.delta
|
|
1663
|
+
});
|
|
1664
|
+
}
|
|
1665
|
+
};
|
|
1666
|
+
var handleEditorContentEnd = (event, builder) => {
|
|
1667
|
+
const e = event;
|
|
1668
|
+
const block = builder.findBlock(
|
|
1669
|
+
(b) => b.type === "editor" && b.callId === e.callId
|
|
1670
|
+
);
|
|
1671
|
+
if (block) {
|
|
1672
|
+
builder.patchBlock(block.id, {
|
|
1673
|
+
isStreaming: false
|
|
1674
|
+
});
|
|
1675
|
+
}
|
|
1676
|
+
builder.activeEditorId = null;
|
|
1677
|
+
};
|
|
1678
|
+
var handleDesktopStream = (event, builder) => {
|
|
1679
|
+
const e = event;
|
|
1680
|
+
if (!e.url) return;
|
|
1681
|
+
const existing = builder.findBlock((b) => b.type === "desktop_stream");
|
|
1682
|
+
if (existing) {
|
|
1683
|
+
builder.patchBlock(existing.id, {
|
|
1684
|
+
url: e.url,
|
|
1685
|
+
authKey: e.authKey,
|
|
1686
|
+
sandboxId: e.sandboxId
|
|
1687
|
+
});
|
|
1688
|
+
} else {
|
|
1689
|
+
builder.addBlock({
|
|
1690
|
+
type: "desktop_stream",
|
|
1691
|
+
id: builder.nextId(),
|
|
1692
|
+
url: e.url,
|
|
1693
|
+
authKey: e.authKey,
|
|
1694
|
+
sandboxId: e.sandboxId
|
|
1695
|
+
});
|
|
1696
|
+
}
|
|
1697
|
+
};
|
|
1698
|
+
var handleAttachmentStaged = (event, builder) => {
|
|
1699
|
+
const e = event;
|
|
1700
|
+
if (!e.files || e.files.length === 0) return;
|
|
1701
|
+
builder.addBlock({
|
|
1702
|
+
type: "attachment",
|
|
1703
|
+
id: builder.nextId(),
|
|
1704
|
+
files: e.files
|
|
1705
|
+
});
|
|
1706
|
+
};
|
|
1707
|
+
var noop = () => {
|
|
1477
1708
|
};
|
|
1478
1709
|
var standardHandlers = {
|
|
1479
1710
|
user_message: handleUserMessage,
|
|
1480
1711
|
chunk: handleChunk,
|
|
1481
1712
|
tool_call: handleToolCall,
|
|
1482
1713
|
tool_executing: handleToolExecuting,
|
|
1714
|
+
tool_progress: handleToolProgress,
|
|
1483
1715
|
tool_completed: handleToolEnd,
|
|
1484
1716
|
tool_end: handleToolEnd,
|
|
1485
1717
|
agent_start: handleAgentStart,
|
|
1718
|
+
agent_end: noop,
|
|
1486
1719
|
thinking_delta: handleThinkingDelta,
|
|
1487
1720
|
thinking_complete: handleThinkingComplete,
|
|
1488
1721
|
subagent_start: handleSubagentStart,
|
|
1489
1722
|
subagent_chunk: handleSubagentChunk,
|
|
1490
1723
|
subagent_update: handleSubagentUpdate,
|
|
1491
1724
|
subagent_end: handleSubagentEnd,
|
|
1725
|
+
subagent_tool_use: noop,
|
|
1726
|
+
capsule_output: handleCapsuleOutput,
|
|
1727
|
+
capsule_output_chunk: handleCapsuleOutputChunk,
|
|
1728
|
+
asset_created: handleAssetCreated,
|
|
1729
|
+
todo_update: handleTodoUpdate,
|
|
1730
|
+
editor_content_start: handleEditorContentStart,
|
|
1731
|
+
editor_content_delta: handleEditorContentDelta,
|
|
1732
|
+
editor_content_end: handleEditorContentEnd,
|
|
1733
|
+
desktop_stream: handleDesktopStream,
|
|
1734
|
+
attachment_staged: handleAttachmentStaged,
|
|
1735
|
+
workspace_ready: noop,
|
|
1736
|
+
retry: noop,
|
|
1492
1737
|
complete: handleComplete,
|
|
1493
1738
|
error: handleError,
|
|
1494
1739
|
disconnected: handleDisconnected
|
|
1495
1740
|
};
|
|
1741
|
+
|
|
1742
|
+
// src/types.ts
|
|
1743
|
+
var ChatEventType = {
|
|
1744
|
+
Connected: "connected",
|
|
1745
|
+
BlocksChanged: "blocks_changed",
|
|
1746
|
+
UserMessage: "user_message",
|
|
1747
|
+
TitleGenerated: "title_generated",
|
|
1748
|
+
ModelInfo: "model_info",
|
|
1749
|
+
Chunk: "chunk",
|
|
1750
|
+
ToolCall: "tool_call",
|
|
1751
|
+
ToolExecuting: "tool_executing",
|
|
1752
|
+
ToolProgress: "tool_progress",
|
|
1753
|
+
ToolCompleted: "tool_completed",
|
|
1754
|
+
ToolEnd: "tool_end",
|
|
1755
|
+
AgentStart: "agent_start",
|
|
1756
|
+
AgentEnd: "agent_end",
|
|
1757
|
+
ThinkingDelta: "thinking_delta",
|
|
1758
|
+
ThinkingComplete: "thinking_complete",
|
|
1759
|
+
SubagentStart: "subagent_start",
|
|
1760
|
+
SubagentChunk: "subagent_chunk",
|
|
1761
|
+
SubagentUpdate: "subagent_update",
|
|
1762
|
+
SubagentEnd: "subagent_end",
|
|
1763
|
+
SubagentToolUse: "subagent_tool_use",
|
|
1764
|
+
CapsuleOutput: "capsule_output",
|
|
1765
|
+
CapsuleOutputChunk: "capsule_output_chunk",
|
|
1766
|
+
AssetCreated: "asset_created",
|
|
1767
|
+
TodoUpdate: "todo_update",
|
|
1768
|
+
EditorContentStart: "editor_content_start",
|
|
1769
|
+
EditorContentDelta: "editor_content_delta",
|
|
1770
|
+
EditorContentEnd: "editor_content_end",
|
|
1771
|
+
Complete: "complete",
|
|
1772
|
+
Error: "error",
|
|
1773
|
+
Disconnected: "disconnected",
|
|
1774
|
+
Retry: "retry",
|
|
1775
|
+
ContextUpdate: "context_update",
|
|
1776
|
+
DesktopStream: "desktop_stream",
|
|
1777
|
+
AttachmentStaged: "attachment_staged",
|
|
1778
|
+
WorkspaceReady: "workspace_ready"
|
|
1779
|
+
};
|
|
1780
|
+
|
|
1781
|
+
// src/stream-manager.ts
|
|
1782
|
+
var StreamManager = class {
|
|
1783
|
+
constructor(session) {
|
|
1784
|
+
this._state = "idle";
|
|
1785
|
+
this._activeConversationId = null;
|
|
1786
|
+
this._backgroundJobs = /* @__PURE__ */ new Map();
|
|
1787
|
+
this.handlers = [];
|
|
1788
|
+
this.unsub = null;
|
|
1789
|
+
this.session = session;
|
|
1790
|
+
this.attach();
|
|
1791
|
+
}
|
|
1792
|
+
// ── Public state ──────────────────────────────────────────────
|
|
1793
|
+
get state() {
|
|
1794
|
+
return this._state;
|
|
1795
|
+
}
|
|
1796
|
+
get activeConversationId() {
|
|
1797
|
+
return this._activeConversationId;
|
|
1798
|
+
}
|
|
1799
|
+
get backgroundJobs() {
|
|
1800
|
+
return this._backgroundJobs;
|
|
1801
|
+
}
|
|
1802
|
+
// ── Event subscription ────────────────────────────────────────
|
|
1803
|
+
on(handler) {
|
|
1804
|
+
this.handlers.push(handler);
|
|
1805
|
+
return () => {
|
|
1806
|
+
this.handlers = this.handlers.filter((h) => h !== handler);
|
|
1807
|
+
};
|
|
1808
|
+
}
|
|
1809
|
+
emit(event) {
|
|
1810
|
+
for (const handler of this.handlers) {
|
|
1811
|
+
try {
|
|
1812
|
+
handler(event);
|
|
1813
|
+
} catch {
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
setState(state) {
|
|
1818
|
+
this._state = state;
|
|
1819
|
+
this.emit({
|
|
1820
|
+
type: "stateChange",
|
|
1821
|
+
state,
|
|
1822
|
+
conversationId: this._activeConversationId
|
|
1823
|
+
});
|
|
1824
|
+
}
|
|
1825
|
+
// ── Session event wiring ──────────────────────────────────────
|
|
1826
|
+
attach() {
|
|
1827
|
+
this.unsub = this.session.on((event) => {
|
|
1828
|
+
this.onSessionEvent(event);
|
|
1829
|
+
});
|
|
1830
|
+
}
|
|
1831
|
+
onSessionEvent(event) {
|
|
1832
|
+
const convId = this.session.conversationId;
|
|
1833
|
+
if (event.type === ChatEventType.BlocksChanged) {
|
|
1834
|
+
if (this._state === "streaming" && convId) {
|
|
1835
|
+
this.emit({
|
|
1836
|
+
type: "blocksChanged",
|
|
1837
|
+
conversationId: convId,
|
|
1838
|
+
blocks: event.blocks
|
|
1839
|
+
});
|
|
1840
|
+
}
|
|
1841
|
+
return;
|
|
1842
|
+
}
|
|
1843
|
+
this.emit({
|
|
1844
|
+
type: "event",
|
|
1845
|
+
conversationId: convId,
|
|
1846
|
+
event
|
|
1847
|
+
});
|
|
1848
|
+
if (event.type === ChatEventType.Complete) {
|
|
1849
|
+
if (this._state === "streaming") {
|
|
1850
|
+
this.setState("idle");
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
// ── Send ──────────────────────────────────────────────────────
|
|
1855
|
+
async send(content, options) {
|
|
1856
|
+
if (this._state === "streaming") return;
|
|
1857
|
+
if (!this._activeConversationId) {
|
|
1858
|
+
const id = await this.session.createNewConversation();
|
|
1859
|
+
this.setActiveConversation(id);
|
|
1860
|
+
}
|
|
1861
|
+
this.prepareUserBlock(content);
|
|
1862
|
+
this.setState("streaming");
|
|
1863
|
+
try {
|
|
1864
|
+
await this.session.send(content, {
|
|
1865
|
+
enableSearch: options?.enableSearch,
|
|
1866
|
+
agentName: options?.agentName,
|
|
1867
|
+
uploadIds: options?.uploadIds
|
|
1868
|
+
});
|
|
1869
|
+
} catch {
|
|
1870
|
+
}
|
|
1871
|
+
this.finalizeStream();
|
|
1872
|
+
}
|
|
1873
|
+
// ── Regenerate ────────────────────────────────────────────────
|
|
1874
|
+
async regenerate() {
|
|
1875
|
+
if (this._state === "streaming") return;
|
|
1876
|
+
const userMsgs = this.session.messages.filter(
|
|
1877
|
+
(m) => m.role === "user"
|
|
1878
|
+
);
|
|
1879
|
+
const lastUserMsg = userMsgs[userMsgs.length - 1];
|
|
1880
|
+
if (!lastUserMsg) return;
|
|
1881
|
+
this.prepareUserBlock(lastUserMsg.content);
|
|
1882
|
+
this.setState("streaming");
|
|
1883
|
+
try {
|
|
1884
|
+
await this.session.resendFromCheckpoint(
|
|
1885
|
+
lastUserMsg.id,
|
|
1886
|
+
lastUserMsg.content
|
|
1887
|
+
);
|
|
1888
|
+
} catch {
|
|
1889
|
+
}
|
|
1890
|
+
this.finalizeStream();
|
|
1891
|
+
}
|
|
1892
|
+
// ── Switch conversation ───────────────────────────────────────
|
|
1893
|
+
async switchTo(conversationId) {
|
|
1894
|
+
if (conversationId === this._activeConversationId) return;
|
|
1895
|
+
if (this._state === "streaming") {
|
|
1896
|
+
const oldConvId = this._activeConversationId;
|
|
1897
|
+
const jobId = this.session.currentJobId;
|
|
1898
|
+
if (oldConvId && jobId) {
|
|
1899
|
+
this._backgroundJobs.set(oldConvId, jobId);
|
|
1900
|
+
this.emit({
|
|
1901
|
+
type: "backgroundJobsChanged",
|
|
1902
|
+
jobs: this._backgroundJobs
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
this.session.detach();
|
|
1906
|
+
}
|
|
1907
|
+
if (this._backgroundJobs.has(conversationId)) {
|
|
1908
|
+
this._backgroundJobs.delete(conversationId);
|
|
1909
|
+
this.emit({
|
|
1910
|
+
type: "backgroundJobsChanged",
|
|
1911
|
+
jobs: this._backgroundJobs
|
|
1912
|
+
});
|
|
1913
|
+
}
|
|
1914
|
+
this.setActiveConversation(conversationId);
|
|
1915
|
+
await this.restore(conversationId);
|
|
1916
|
+
}
|
|
1917
|
+
// ── Create / delete conversation ──────────────────────────────
|
|
1918
|
+
async createConversation() {
|
|
1919
|
+
const id = await this.session.createNewConversation();
|
|
1920
|
+
this.setActiveConversation(id);
|
|
1921
|
+
return id;
|
|
1922
|
+
}
|
|
1923
|
+
async deleteConversation(id) {
|
|
1924
|
+
await this.session.deleteConversation(id);
|
|
1925
|
+
this._backgroundJobs.delete(id);
|
|
1926
|
+
if (this._activeConversationId === id) {
|
|
1927
|
+
this._activeConversationId = null;
|
|
1928
|
+
this.emit({ type: "conversationChanged", conversationId: null });
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
// ── Stop (explicit cancel) ────────────────────────────────────
|
|
1932
|
+
stop() {
|
|
1933
|
+
this.session.disconnect();
|
|
1934
|
+
this.setState("idle");
|
|
1935
|
+
}
|
|
1936
|
+
// ── Cleanup ───────────────────────────────────────────────────
|
|
1937
|
+
destroy() {
|
|
1938
|
+
if (this.unsub) {
|
|
1939
|
+
this.unsub();
|
|
1940
|
+
this.unsub = null;
|
|
1941
|
+
}
|
|
1942
|
+
this.handlers = [];
|
|
1943
|
+
}
|
|
1944
|
+
// ── Internal: helpers ──────────────────────────────────────────
|
|
1945
|
+
prepareUserBlock(content) {
|
|
1946
|
+
this.session.blockBuilder.reset();
|
|
1947
|
+
this.session.blockBuilder.addBlock({
|
|
1948
|
+
type: "user",
|
|
1949
|
+
id: this.session.blockBuilder.nextId(),
|
|
1950
|
+
content
|
|
1951
|
+
});
|
|
1952
|
+
}
|
|
1953
|
+
finalizeStream() {
|
|
1954
|
+
if (this._state === "streaming") {
|
|
1955
|
+
this.setState("idle");
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
// ── Internal: restore ─────────────────────────────────────────
|
|
1959
|
+
async restore(conversationId) {
|
|
1960
|
+
this.setState("restoring");
|
|
1961
|
+
let activeJobId = null;
|
|
1962
|
+
try {
|
|
1963
|
+
const res = await this.session.client.get(`/v1/conversations/${encodeURIComponent(conversationId)}/active-job`);
|
|
1964
|
+
activeJobId = res.job_id ?? null;
|
|
1965
|
+
} catch {
|
|
1966
|
+
}
|
|
1967
|
+
if (activeJobId) {
|
|
1968
|
+
await this.session.loadConversation(conversationId);
|
|
1969
|
+
this.setState("streaming");
|
|
1970
|
+
try {
|
|
1971
|
+
await this.session.reconnectToJob(activeJobId);
|
|
1972
|
+
} catch {
|
|
1973
|
+
}
|
|
1974
|
+
if (this._state === "streaming") {
|
|
1975
|
+
this.setState("idle");
|
|
1976
|
+
}
|
|
1977
|
+
} else {
|
|
1978
|
+
await this.session.loadConversation(conversationId);
|
|
1979
|
+
try {
|
|
1980
|
+
const jobs = await this.session.client.get(`/v1/conversations/${encodeURIComponent(conversationId)}/jobs`);
|
|
1981
|
+
const completedJobs = jobs.filter(
|
|
1982
|
+
(j) => j.status === "completed"
|
|
1983
|
+
);
|
|
1984
|
+
for (const job of completedJobs) {
|
|
1985
|
+
await this.session.switchConversation(conversationId, job.job_id);
|
|
1986
|
+
}
|
|
1987
|
+
if (completedJobs.length > 0) {
|
|
1988
|
+
this.emit({
|
|
1989
|
+
type: "blocksChanged",
|
|
1990
|
+
conversationId,
|
|
1991
|
+
blocks: this.session.blockBuilder.getBlocks()
|
|
1992
|
+
});
|
|
1993
|
+
this.emit({
|
|
1994
|
+
type: "versionsReady",
|
|
1995
|
+
conversationId,
|
|
1996
|
+
count: completedJobs.length
|
|
1997
|
+
});
|
|
1998
|
+
}
|
|
1999
|
+
} catch {
|
|
2000
|
+
}
|
|
2001
|
+
this.setState("idle");
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
// ── Internal: set active conversation ─────────────────────────
|
|
2005
|
+
setActiveConversation(id) {
|
|
2006
|
+
this._activeConversationId = id;
|
|
2007
|
+
this.emit({ type: "conversationChanged", conversationId: id });
|
|
2008
|
+
}
|
|
2009
|
+
};
|
|
1496
2010
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1497
2011
|
0 && (module.exports = {
|
|
1498
2012
|
AstralformClient,
|
|
1499
2013
|
AstralformError,
|
|
1500
2014
|
AuthenticationError,
|
|
1501
2015
|
BlockBuilder,
|
|
2016
|
+
ChatEventType,
|
|
1502
2017
|
ChatSession,
|
|
1503
2018
|
ConnectionError,
|
|
1504
2019
|
InMemoryStorage,
|
|
@@ -1506,6 +2021,7 @@ var standardHandlers = {
|
|
|
1506
2021
|
RateLimitError,
|
|
1507
2022
|
ServerError,
|
|
1508
2023
|
StreamAbortedError,
|
|
2024
|
+
StreamManager,
|
|
1509
2025
|
ToolRegistry,
|
|
1510
2026
|
generateId,
|
|
1511
2027
|
standardHandlers,
|