@astralform/js 0.1.3 → 0.2.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 +459 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +198 -26
- package/dist/index.d.ts +198 -26
- package/dist/index.js +457 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -23,6 +23,7 @@ __export(index_exports, {
|
|
|
23
23
|
AstralformClient: () => AstralformClient,
|
|
24
24
|
AstralformError: () => AstralformError,
|
|
25
25
|
AuthenticationError: () => AuthenticationError,
|
|
26
|
+
BlockBuilder: () => BlockBuilder,
|
|
26
27
|
ChatSession: () => ChatSession,
|
|
27
28
|
ConnectionError: () => ConnectionError,
|
|
28
29
|
InMemoryStorage: () => InMemoryStorage,
|
|
@@ -32,6 +33,7 @@ __export(index_exports, {
|
|
|
32
33
|
StreamAbortedError: () => StreamAbortedError,
|
|
33
34
|
ToolRegistry: () => ToolRegistry,
|
|
34
35
|
generateId: () => generateId,
|
|
36
|
+
standardHandlers: () => standardHandlers,
|
|
35
37
|
streamJobSSE: () => streamJobSSE
|
|
36
38
|
});
|
|
37
39
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -285,10 +287,10 @@ var AstralformClient = class {
|
|
|
285
287
|
isEnabled: s.is_enabled
|
|
286
288
|
}));
|
|
287
289
|
}
|
|
288
|
-
async getConversationEvents(conversationId) {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
);
|
|
290
|
+
async getConversationEvents(conversationId, jobId) {
|
|
291
|
+
let url = `/v1/conversations/${encodeURIComponent(conversationId)}/events`;
|
|
292
|
+
if (jobId) url += `?job_id=${encodeURIComponent(jobId)}`;
|
|
293
|
+
return this.get(url);
|
|
292
294
|
}
|
|
293
295
|
async submitToolResult(request) {
|
|
294
296
|
await this.post("/v1/tool-result", request);
|
|
@@ -359,6 +361,87 @@ var AstralformClient = class {
|
|
|
359
361
|
}
|
|
360
362
|
};
|
|
361
363
|
|
|
364
|
+
// src/block-builder.ts
|
|
365
|
+
var _idCounter = 0;
|
|
366
|
+
var BlockBuilder = class {
|
|
367
|
+
constructor() {
|
|
368
|
+
this._blocks = [];
|
|
369
|
+
this._handlers = /* @__PURE__ */ new Map();
|
|
370
|
+
this._onChange = null;
|
|
371
|
+
// Active block refs — public so handlers can read/write them
|
|
372
|
+
this.activeTextId = null;
|
|
373
|
+
this.activeThinkingId = null;
|
|
374
|
+
this.thinkingStartMs = null;
|
|
375
|
+
}
|
|
376
|
+
// ── Registration ──────────────────────────────────────────────
|
|
377
|
+
on(eventType, handler) {
|
|
378
|
+
this._handlers.set(eventType, handler);
|
|
379
|
+
}
|
|
380
|
+
registerHandlers(handlers) {
|
|
381
|
+
for (const [type, handler] of Object.entries(handlers)) {
|
|
382
|
+
this._handlers.set(type, handler);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
// ── Event processing ──────────────────────────────────────────
|
|
386
|
+
processEvent(event) {
|
|
387
|
+
const handler = this._handlers.get(event.type);
|
|
388
|
+
if (handler === null) return;
|
|
389
|
+
if (!handler) return;
|
|
390
|
+
handler(event, this);
|
|
391
|
+
}
|
|
392
|
+
// ── State ─────────────────────────────────────────────────────
|
|
393
|
+
getBlocks() {
|
|
394
|
+
return [...this._blocks];
|
|
395
|
+
}
|
|
396
|
+
reset() {
|
|
397
|
+
this._blocks = [];
|
|
398
|
+
this.activeTextId = null;
|
|
399
|
+
this.activeThinkingId = null;
|
|
400
|
+
this.thinkingStartMs = null;
|
|
401
|
+
}
|
|
402
|
+
setOnChange(fn) {
|
|
403
|
+
this._onChange = fn;
|
|
404
|
+
}
|
|
405
|
+
// ── Block manipulation (used by handlers) ─────────────────────
|
|
406
|
+
addBlock(block) {
|
|
407
|
+
this._blocks = [...this._blocks, block];
|
|
408
|
+
this._notify();
|
|
409
|
+
}
|
|
410
|
+
updateBlock(id, updater) {
|
|
411
|
+
let changed = false;
|
|
412
|
+
this._blocks = this._blocks.map((b) => {
|
|
413
|
+
if (b.id !== id) return b;
|
|
414
|
+
changed = true;
|
|
415
|
+
return updater(b);
|
|
416
|
+
});
|
|
417
|
+
if (changed) this._notify();
|
|
418
|
+
}
|
|
419
|
+
/** Update any block by id with a partial update (type-loose for handlers). */
|
|
420
|
+
patchBlock(id, patch) {
|
|
421
|
+
let changed = false;
|
|
422
|
+
this._blocks = this._blocks.map((b) => {
|
|
423
|
+
if (b.id !== id) return b;
|
|
424
|
+
changed = true;
|
|
425
|
+
return { ...b, ...patch };
|
|
426
|
+
});
|
|
427
|
+
if (changed) this._notify();
|
|
428
|
+
}
|
|
429
|
+
findBlock(predicate) {
|
|
430
|
+
for (let i = this._blocks.length - 1; i >= 0; i--) {
|
|
431
|
+
const block = this._blocks[i];
|
|
432
|
+
if (block && predicate(block)) return block;
|
|
433
|
+
}
|
|
434
|
+
return void 0;
|
|
435
|
+
}
|
|
436
|
+
nextId() {
|
|
437
|
+
return `blk_${++_idCounter}`;
|
|
438
|
+
}
|
|
439
|
+
// ── Internal ──────────────────────────────────────────────────
|
|
440
|
+
_notify() {
|
|
441
|
+
this._onChange?.();
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
|
|
362
445
|
// src/storage.ts
|
|
363
446
|
var InMemoryStorage = class {
|
|
364
447
|
constructor() {
|
|
@@ -523,7 +606,7 @@ function generateId() {
|
|
|
523
606
|
|
|
524
607
|
// src/session.ts
|
|
525
608
|
var ChatSession = class {
|
|
526
|
-
constructor(config, storage) {
|
|
609
|
+
constructor(config, storage, blockBuilder) {
|
|
527
610
|
// State
|
|
528
611
|
this.conversationId = null;
|
|
529
612
|
this.conversations = [];
|
|
@@ -553,6 +636,13 @@ var ChatSession = class {
|
|
|
553
636
|
this.client = new AstralformClient(config);
|
|
554
637
|
this.toolRegistry = new ToolRegistry();
|
|
555
638
|
this.storage = storage ?? new InMemoryStorage();
|
|
639
|
+
this.blockBuilder = blockBuilder ?? new BlockBuilder();
|
|
640
|
+
this.blockBuilder.setOnChange(() => {
|
|
641
|
+
this.emit({
|
|
642
|
+
type: "blocks_changed",
|
|
643
|
+
blocks: this.blockBuilder.getBlocks()
|
|
644
|
+
});
|
|
645
|
+
});
|
|
556
646
|
}
|
|
557
647
|
on(handler) {
|
|
558
648
|
this.handlers.add(handler);
|
|
@@ -561,6 +651,9 @@ var ChatSession = class {
|
|
|
561
651
|
};
|
|
562
652
|
}
|
|
563
653
|
emit(event) {
|
|
654
|
+
if (event.type !== "blocks_changed" && event.type !== "connected") {
|
|
655
|
+
this.blockBuilder.processEvent(event);
|
|
656
|
+
}
|
|
564
657
|
for (const handler of this.handlers) {
|
|
565
658
|
try {
|
|
566
659
|
handler(event);
|
|
@@ -617,14 +710,15 @@ var ChatSession = class {
|
|
|
617
710
|
};
|
|
618
711
|
await this.processStream(request);
|
|
619
712
|
}
|
|
620
|
-
async resendFromCheckpoint(messageId, newContent) {
|
|
713
|
+
async resendFromCheckpoint(messageId, newContent, options) {
|
|
621
714
|
if (this.isStreaming) return;
|
|
622
715
|
const request = {
|
|
623
716
|
message: newContent,
|
|
624
717
|
conversation_id: this.conversationId ?? void 0,
|
|
625
718
|
resend_from: messageId,
|
|
626
719
|
mcp_manifest: this.toolRegistry.getManifest(),
|
|
627
|
-
enabled_mcp: Array.from(this.enabledClientTools)
|
|
720
|
+
enabled_mcp: Array.from(this.enabledClientTools),
|
|
721
|
+
enable_search: options?.enableSearch
|
|
628
722
|
};
|
|
629
723
|
await this.processStream(request);
|
|
630
724
|
}
|
|
@@ -664,12 +758,23 @@ var ChatSession = class {
|
|
|
664
758
|
}
|
|
665
759
|
const messageId = job.message_id;
|
|
666
760
|
this.lastSeq = -1;
|
|
667
|
-
let stopTitle;
|
|
668
761
|
const stream = this.client.streamJobEvents(
|
|
669
762
|
job.job_id,
|
|
670
763
|
this.lastSeq,
|
|
671
764
|
this.abortController?.signal
|
|
672
765
|
);
|
|
766
|
+
await this.consumeEventStream(
|
|
767
|
+
stream,
|
|
768
|
+
conversationId,
|
|
769
|
+
messageId,
|
|
770
|
+
true
|
|
771
|
+
// executeClientTools
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Shared event consumption loop used by both consumeJobStream and reconnectToJob.
|
|
776
|
+
*/
|
|
777
|
+
async consumeEventStream(stream, conversationId, messageId, executeClientTools) {
|
|
673
778
|
for await (const raw of stream) {
|
|
674
779
|
let parsed;
|
|
675
780
|
try {
|
|
@@ -693,6 +798,9 @@ var ChatSession = class {
|
|
|
693
798
|
if (!this.conversationId) {
|
|
694
799
|
this.conversationId = conversationId;
|
|
695
800
|
}
|
|
801
|
+
if (parsed.message_id) {
|
|
802
|
+
messageId = parsed.message_id;
|
|
803
|
+
}
|
|
696
804
|
if (parsed.model_display_name) {
|
|
697
805
|
this.modelDisplayName = parsed.model_display_name;
|
|
698
806
|
this.emit({
|
|
@@ -707,7 +815,7 @@ var ChatSession = class {
|
|
|
707
815
|
break;
|
|
708
816
|
case "tool_use_start": {
|
|
709
817
|
this.applyEvent(parsed);
|
|
710
|
-
if (parsed.is_client_tool) {
|
|
818
|
+
if (executeClientTools && parsed.is_client_tool) {
|
|
711
819
|
const results = await this.executeClientTools([
|
|
712
820
|
{
|
|
713
821
|
callId: parsed.call_id,
|
|
@@ -759,7 +867,15 @@ var ChatSession = class {
|
|
|
759
867
|
});
|
|
760
868
|
break;
|
|
761
869
|
case "message_stop":
|
|
762
|
-
|
|
870
|
+
await this.completeStream(
|
|
871
|
+
conversationId,
|
|
872
|
+
messageId,
|
|
873
|
+
parsed.title,
|
|
874
|
+
parsed.metrics,
|
|
875
|
+
parsed.job_id
|
|
876
|
+
);
|
|
877
|
+
this.isStreaming = false;
|
|
878
|
+
this.currentJobId = null;
|
|
763
879
|
break;
|
|
764
880
|
case "error":
|
|
765
881
|
this.emit({
|
|
@@ -771,8 +887,6 @@ var ChatSession = class {
|
|
|
771
887
|
this.applyEvent(parsed);
|
|
772
888
|
}
|
|
773
889
|
}
|
|
774
|
-
this.currentJobId = null;
|
|
775
|
-
await this.completeStream(conversationId, messageId, stopTitle);
|
|
776
890
|
}
|
|
777
891
|
/**
|
|
778
892
|
* Apply a single SSE event to session state and notify consumers.
|
|
@@ -780,6 +894,45 @@ var ChatSession = class {
|
|
|
780
894
|
*/
|
|
781
895
|
applyEvent(event) {
|
|
782
896
|
switch (event.type) {
|
|
897
|
+
case "user_message":
|
|
898
|
+
this.emit({ type: "user_message", content: event.content });
|
|
899
|
+
break;
|
|
900
|
+
case "title_generated":
|
|
901
|
+
this.emit({ type: "title_generated", title: event.title });
|
|
902
|
+
break;
|
|
903
|
+
case "message_start":
|
|
904
|
+
if (event.conversation_id && !this.conversationId) {
|
|
905
|
+
this.conversationId = event.conversation_id;
|
|
906
|
+
}
|
|
907
|
+
if (event.model_display_name) {
|
|
908
|
+
this.modelDisplayName = event.model_display_name;
|
|
909
|
+
this.emit({ type: "model_info", name: event.model_display_name });
|
|
910
|
+
}
|
|
911
|
+
break;
|
|
912
|
+
case "content_block_delta":
|
|
913
|
+
this.streamingContent += event.delta.text;
|
|
914
|
+
this.emit({ type: "chunk", text: event.delta.text });
|
|
915
|
+
break;
|
|
916
|
+
case "thinking_delta":
|
|
917
|
+
this.thinkingContent += event.delta.text;
|
|
918
|
+
this.isThinking = true;
|
|
919
|
+
this.emit({ type: "thinking_delta", text: event.delta.text });
|
|
920
|
+
break;
|
|
921
|
+
case "thinking_complete":
|
|
922
|
+
this.isThinking = false;
|
|
923
|
+
this.emit({ type: "thinking_complete" });
|
|
924
|
+
break;
|
|
925
|
+
case "message_stop":
|
|
926
|
+
this.emit({
|
|
927
|
+
type: "complete",
|
|
928
|
+
content: this.streamingContent,
|
|
929
|
+
conversationId: this.conversationId ?? "",
|
|
930
|
+
messageId: event.job_id ?? "",
|
|
931
|
+
title: event.title,
|
|
932
|
+
metrics: event.metrics,
|
|
933
|
+
job_id: event.job_id
|
|
934
|
+
});
|
|
935
|
+
break;
|
|
783
936
|
case "tool_use_start": {
|
|
784
937
|
const request = {
|
|
785
938
|
callId: event.call_id,
|
|
@@ -807,7 +960,9 @@ var ChatSession = class {
|
|
|
807
960
|
type: "tool_end",
|
|
808
961
|
callId: event.call_id,
|
|
809
962
|
toolName: event.tool,
|
|
810
|
-
result: event.result
|
|
963
|
+
result: event.result,
|
|
964
|
+
sources: event.sources,
|
|
965
|
+
durationMs: event.duration_ms
|
|
811
966
|
});
|
|
812
967
|
break;
|
|
813
968
|
}
|
|
@@ -915,18 +1070,25 @@ var ChatSession = class {
|
|
|
915
1070
|
sizeBytes: event.size_bytes
|
|
916
1071
|
});
|
|
917
1072
|
break;
|
|
918
|
-
case "
|
|
1073
|
+
case "timeline_entry":
|
|
919
1074
|
this.emit({
|
|
920
|
-
type: "
|
|
921
|
-
|
|
1075
|
+
type: "timeline_entry",
|
|
1076
|
+
id: event.id,
|
|
922
1077
|
status: event.status,
|
|
923
|
-
|
|
924
|
-
|
|
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,
|
|
925
1085
|
detail: event.detail,
|
|
1086
|
+
started_at: event.started_at,
|
|
1087
|
+
duration_ms: event.duration_ms,
|
|
1088
|
+
output_summary: event.output_summary,
|
|
926
1089
|
sources: event.sources,
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
durationMs: event.duration_ms
|
|
1090
|
+
parent_id: event.parent_id,
|
|
1091
|
+
structured_output: event.structured_output
|
|
930
1092
|
});
|
|
931
1093
|
break;
|
|
932
1094
|
case "editor_content_start":
|
|
@@ -976,7 +1138,7 @@ var ChatSession = class {
|
|
|
976
1138
|
this.executingTool = null;
|
|
977
1139
|
return results;
|
|
978
1140
|
}
|
|
979
|
-
async completeStream(conversationId, messageId, title) {
|
|
1141
|
+
async completeStream(conversationId, messageId, title, metrics, jobId) {
|
|
980
1142
|
const assistantMessage = {
|
|
981
1143
|
id: messageId || generateId(),
|
|
982
1144
|
conversationId,
|
|
@@ -999,9 +1161,57 @@ var ChatSession = class {
|
|
|
999
1161
|
content: this.streamingContent,
|
|
1000
1162
|
conversationId,
|
|
1001
1163
|
messageId: assistantMessage.id,
|
|
1002
|
-
title
|
|
1164
|
+
title,
|
|
1165
|
+
metrics,
|
|
1166
|
+
job_id: jobId
|
|
1003
1167
|
});
|
|
1004
1168
|
}
|
|
1169
|
+
/**
|
|
1170
|
+
* Load conversation context (messages) without replaying events.
|
|
1171
|
+
* Used before reconnectToJob — SSE replay handles event replay.
|
|
1172
|
+
*/
|
|
1173
|
+
async loadConversation(id) {
|
|
1174
|
+
this.conversationId = id;
|
|
1175
|
+
this.resetStreamingState();
|
|
1176
|
+
this.blockBuilder.reset();
|
|
1177
|
+
this.messages = await this.client.getMessages(id).catch(() => this.storage.fetchMessages(id));
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Reconnect to a running job's SSE stream (e.g. after page reload).
|
|
1181
|
+
* Replays all events from the beginning and continues live.
|
|
1182
|
+
* Does NOT reset BlockBuilder — caller controls reset.
|
|
1183
|
+
*/
|
|
1184
|
+
async reconnectToJob(jobId) {
|
|
1185
|
+
if (this.isStreaming) return;
|
|
1186
|
+
this.isStreaming = true;
|
|
1187
|
+
this.currentJobId = jobId;
|
|
1188
|
+
this.lastSeq = -1;
|
|
1189
|
+
this.resetStreamingState();
|
|
1190
|
+
this.abortController = new AbortController();
|
|
1191
|
+
try {
|
|
1192
|
+
const stream = this.client.streamJobEvents(
|
|
1193
|
+
jobId,
|
|
1194
|
+
this.lastSeq,
|
|
1195
|
+
this.abortController?.signal
|
|
1196
|
+
);
|
|
1197
|
+
await this.consumeEventStream(
|
|
1198
|
+
stream,
|
|
1199
|
+
this.conversationId ?? "",
|
|
1200
|
+
"",
|
|
1201
|
+
false
|
|
1202
|
+
// don't execute client tools on reconnect
|
|
1203
|
+
);
|
|
1204
|
+
} catch (err) {
|
|
1205
|
+
this.emit({
|
|
1206
|
+
type: "error",
|
|
1207
|
+
error: err instanceof Error ? err : new ConnectionError(String(err))
|
|
1208
|
+
});
|
|
1209
|
+
} finally {
|
|
1210
|
+
this.isStreaming = false;
|
|
1211
|
+
this.executingTool = null;
|
|
1212
|
+
this.abortController = null;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1005
1215
|
disconnect() {
|
|
1006
1216
|
if (this.currentJobId) {
|
|
1007
1217
|
this.client.cancelJob(this.currentJobId).catch(() => {
|
|
@@ -1027,30 +1237,21 @@ var ChatSession = class {
|
|
|
1027
1237
|
this.streamingContent = "";
|
|
1028
1238
|
return id;
|
|
1029
1239
|
}
|
|
1030
|
-
async switchConversation(id) {
|
|
1240
|
+
async switchConversation(id, jobId) {
|
|
1031
1241
|
this.conversationId = id;
|
|
1032
1242
|
this.resetStreamingState();
|
|
1243
|
+
this.blockBuilder.reset();
|
|
1033
1244
|
const [messagesResult, eventsResult] = await Promise.allSettled([
|
|
1034
1245
|
this.client.getMessages(id).catch(() => this.storage.fetchMessages(id)),
|
|
1035
|
-
this.client.getConversationEvents(id)
|
|
1246
|
+
this.client.getConversationEvents(id, jobId)
|
|
1036
1247
|
]);
|
|
1037
1248
|
this.messages = messagesResult.status === "fulfilled" ? messagesResult.value : [];
|
|
1038
1249
|
if (eventsResult.status === "fulfilled") {
|
|
1039
1250
|
for (const ev of eventsResult.value) {
|
|
1040
|
-
this.
|
|
1251
|
+
this.applyEvent({ type: ev.event, ...ev.data });
|
|
1041
1252
|
}
|
|
1042
1253
|
}
|
|
1043
1254
|
}
|
|
1044
|
-
/**
|
|
1045
|
-
* Replay a single persisted event to reconstruct session state.
|
|
1046
|
-
* Skips text deltas (final content is already in messages[]).
|
|
1047
|
-
*/
|
|
1048
|
-
replayEvent(eventType, data) {
|
|
1049
|
-
if (eventType === "content_block_delta" || eventType === "thinking_delta" || eventType === "subagent_content_delta" || eventType === "thinking_complete" || eventType === "editor_content_start" || eventType === "editor_content_delta" || eventType === "editor_content_end") {
|
|
1050
|
-
return;
|
|
1051
|
-
}
|
|
1052
|
-
this.applyEvent({ type: eventType, ...data });
|
|
1053
|
-
}
|
|
1054
1255
|
async deleteConversation(id) {
|
|
1055
1256
|
try {
|
|
1056
1257
|
await this.client.deleteConversation(id);
|
|
@@ -1072,11 +1273,232 @@ var ChatSession = class {
|
|
|
1072
1273
|
return true;
|
|
1073
1274
|
}
|
|
1074
1275
|
};
|
|
1276
|
+
|
|
1277
|
+
// src/standard-handlers.ts
|
|
1278
|
+
function finalizeText(builder) {
|
|
1279
|
+
if (builder.activeTextId) {
|
|
1280
|
+
builder.patchBlock(builder.activeTextId, {
|
|
1281
|
+
isStreaming: false
|
|
1282
|
+
});
|
|
1283
|
+
builder.activeTextId = null;
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
function finalizeThinking(builder) {
|
|
1287
|
+
if (builder.activeThinkingId) {
|
|
1288
|
+
builder.patchBlock(builder.activeThinkingId, {
|
|
1289
|
+
isActive: false
|
|
1290
|
+
});
|
|
1291
|
+
builder.activeThinkingId = null;
|
|
1292
|
+
builder.thinkingStartMs = null;
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
var handleUserMessage = (event, builder) => {
|
|
1296
|
+
if (builder.findBlock((b) => b.type === "user")) return;
|
|
1297
|
+
const e = event;
|
|
1298
|
+
builder.addBlock({ type: "user", id: builder.nextId(), content: e.content });
|
|
1299
|
+
};
|
|
1300
|
+
var handleChunk = (event, builder) => {
|
|
1301
|
+
const e = event;
|
|
1302
|
+
if (!builder.activeTextId) {
|
|
1303
|
+
const id = builder.nextId();
|
|
1304
|
+
builder.activeTextId = id;
|
|
1305
|
+
builder.addBlock({
|
|
1306
|
+
type: "text",
|
|
1307
|
+
id,
|
|
1308
|
+
content: e.text,
|
|
1309
|
+
isStreaming: true
|
|
1310
|
+
});
|
|
1311
|
+
} else {
|
|
1312
|
+
const id = builder.activeTextId;
|
|
1313
|
+
const existing = builder.findBlock((b) => b.id === id);
|
|
1314
|
+
if (existing && existing.type === "text") {
|
|
1315
|
+
builder.patchBlock(id, {
|
|
1316
|
+
content: existing.content + e.text
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
};
|
|
1321
|
+
var handleToolCall = (event, builder) => {
|
|
1322
|
+
const e = event;
|
|
1323
|
+
finalizeText(builder);
|
|
1324
|
+
builder.addBlock({
|
|
1325
|
+
type: "tool",
|
|
1326
|
+
id: builder.nextId(),
|
|
1327
|
+
callId: e.request.callId,
|
|
1328
|
+
toolName: e.request.toolName,
|
|
1329
|
+
displayName: e.request.displayName,
|
|
1330
|
+
description: e.request.description,
|
|
1331
|
+
arguments: e.request.arguments,
|
|
1332
|
+
toolCategory: e.request.toolCategory,
|
|
1333
|
+
iconUrl: e.request.iconUrl,
|
|
1334
|
+
status: "calling"
|
|
1335
|
+
});
|
|
1336
|
+
};
|
|
1337
|
+
var handleToolExecuting = (event, builder) => {
|
|
1338
|
+
const e = event;
|
|
1339
|
+
const block = builder.findBlock(
|
|
1340
|
+
(b) => b.type === "tool" && b.toolName === e.name && b.status === "calling"
|
|
1341
|
+
);
|
|
1342
|
+
if (block) {
|
|
1343
|
+
builder.patchBlock(block.id, { status: "executing" });
|
|
1344
|
+
}
|
|
1345
|
+
};
|
|
1346
|
+
var handleToolEnd = (event, builder) => {
|
|
1347
|
+
const e = event;
|
|
1348
|
+
const callId = e.type === "tool_end" ? e.callId : void 0;
|
|
1349
|
+
const name = e.type === "tool_end" ? e.toolName : e.name;
|
|
1350
|
+
const block = builder.findBlock(
|
|
1351
|
+
(b) => b.type === "tool" && (callId ? b.callId === callId : b.toolName === name) && b.status !== "completed"
|
|
1352
|
+
);
|
|
1353
|
+
if (block) {
|
|
1354
|
+
const toolEnd = e.type === "tool_end" ? e : null;
|
|
1355
|
+
builder.patchBlock(block.id, {
|
|
1356
|
+
status: "completed",
|
|
1357
|
+
...toolEnd?.sources ? { sources: toolEnd.sources } : {},
|
|
1358
|
+
...toolEnd?.durationMs != null ? { durationMs: toolEnd.durationMs } : {},
|
|
1359
|
+
...toolEnd?.result ? { result: toolEnd.result } : {}
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
};
|
|
1363
|
+
var handleAgentStart = (event, builder) => {
|
|
1364
|
+
const e = event;
|
|
1365
|
+
finalizeText(builder);
|
|
1366
|
+
builder.addBlock({
|
|
1367
|
+
type: "agent",
|
|
1368
|
+
id: builder.nextId(),
|
|
1369
|
+
agentName: e.agentName,
|
|
1370
|
+
displayName: e.agentDisplayName,
|
|
1371
|
+
avatarUrl: e.avatarUrl
|
|
1372
|
+
});
|
|
1373
|
+
};
|
|
1374
|
+
var handleThinkingDelta = (event, builder) => {
|
|
1375
|
+
const e = event;
|
|
1376
|
+
if (!builder.activeThinkingId) {
|
|
1377
|
+
const id = builder.nextId();
|
|
1378
|
+
builder.activeThinkingId = id;
|
|
1379
|
+
builder.thinkingStartMs = Date.now();
|
|
1380
|
+
builder.addBlock({
|
|
1381
|
+
type: "thinking",
|
|
1382
|
+
id,
|
|
1383
|
+
content: e.text,
|
|
1384
|
+
isActive: true
|
|
1385
|
+
});
|
|
1386
|
+
} else {
|
|
1387
|
+
const id = builder.activeThinkingId;
|
|
1388
|
+
const existing = builder.findBlock((b) => b.id === id);
|
|
1389
|
+
if (existing && existing.type === "thinking") {
|
|
1390
|
+
builder.patchBlock(id, {
|
|
1391
|
+
content: existing.content + e.text
|
|
1392
|
+
});
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
};
|
|
1396
|
+
var handleThinkingComplete = (_event, builder) => {
|
|
1397
|
+
if (builder.activeThinkingId) {
|
|
1398
|
+
const durationMs = builder.thinkingStartMs ? Math.max(0, Date.now() - builder.thinkingStartMs) : void 0;
|
|
1399
|
+
builder.patchBlock(builder.activeThinkingId, {
|
|
1400
|
+
isActive: false,
|
|
1401
|
+
durationMs
|
|
1402
|
+
});
|
|
1403
|
+
builder.activeThinkingId = null;
|
|
1404
|
+
builder.thinkingStartMs = null;
|
|
1405
|
+
}
|
|
1406
|
+
};
|
|
1407
|
+
var handleSubagentStart = (event, builder) => {
|
|
1408
|
+
const e = event;
|
|
1409
|
+
finalizeText(builder);
|
|
1410
|
+
builder.addBlock({
|
|
1411
|
+
type: "subagent",
|
|
1412
|
+
id: builder.nextId(),
|
|
1413
|
+
agentName: e.agentName,
|
|
1414
|
+
displayName: e.displayName,
|
|
1415
|
+
toolCallId: e.toolCallId,
|
|
1416
|
+
avatarUrl: e.avatarUrl,
|
|
1417
|
+
description: e.description,
|
|
1418
|
+
content: "",
|
|
1419
|
+
isActive: true
|
|
1420
|
+
});
|
|
1421
|
+
};
|
|
1422
|
+
var handleSubagentChunk = (event, builder) => {
|
|
1423
|
+
const e = event;
|
|
1424
|
+
const block = builder.findBlock(
|
|
1425
|
+
(b) => b.type === "subagent" && b.toolCallId === e.toolCallId
|
|
1426
|
+
);
|
|
1427
|
+
if (block && block.type === "subagent") {
|
|
1428
|
+
builder.patchBlock(block.id, {
|
|
1429
|
+
content: block.content + e.text
|
|
1430
|
+
});
|
|
1431
|
+
}
|
|
1432
|
+
};
|
|
1433
|
+
var handleSubagentUpdate = (event, builder) => {
|
|
1434
|
+
const e = event;
|
|
1435
|
+
const block = builder.findBlock(
|
|
1436
|
+
(b) => b.type === "subagent" && b.toolCallId === e.toolCallId
|
|
1437
|
+
);
|
|
1438
|
+
if (block) {
|
|
1439
|
+
builder.patchBlock(block.id, {
|
|
1440
|
+
displayName: e.displayName
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
};
|
|
1444
|
+
var handleSubagentEnd = (event, builder) => {
|
|
1445
|
+
const e = event;
|
|
1446
|
+
const block = builder.findBlock(
|
|
1447
|
+
(b) => b.type === "subagent" && b.toolCallId === e.toolCallId
|
|
1448
|
+
);
|
|
1449
|
+
if (block) {
|
|
1450
|
+
builder.patchBlock(block.id, {
|
|
1451
|
+
isActive: false
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
};
|
|
1455
|
+
var handleComplete = (_event, builder) => {
|
|
1456
|
+
finalizeText(builder);
|
|
1457
|
+
finalizeThinking(builder);
|
|
1458
|
+
for (const b of builder.getBlocks()) {
|
|
1459
|
+
if (b.type === "tool" && b.status !== "completed") {
|
|
1460
|
+
builder.patchBlock(b.id, { status: "completed" });
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
var handleError = (event, builder) => {
|
|
1465
|
+
const e = event;
|
|
1466
|
+
finalizeText(builder);
|
|
1467
|
+
finalizeThinking(builder);
|
|
1468
|
+
builder.addBlock({
|
|
1469
|
+
type: "error",
|
|
1470
|
+
id: builder.nextId(),
|
|
1471
|
+
message: e.error.message
|
|
1472
|
+
});
|
|
1473
|
+
};
|
|
1474
|
+
var handleDisconnected = (_event, builder) => {
|
|
1475
|
+
finalizeText(builder);
|
|
1476
|
+
finalizeThinking(builder);
|
|
1477
|
+
};
|
|
1478
|
+
var standardHandlers = {
|
|
1479
|
+
user_message: handleUserMessage,
|
|
1480
|
+
chunk: handleChunk,
|
|
1481
|
+
tool_call: handleToolCall,
|
|
1482
|
+
tool_executing: handleToolExecuting,
|
|
1483
|
+
tool_completed: handleToolEnd,
|
|
1484
|
+
tool_end: handleToolEnd,
|
|
1485
|
+
agent_start: handleAgentStart,
|
|
1486
|
+
thinking_delta: handleThinkingDelta,
|
|
1487
|
+
thinking_complete: handleThinkingComplete,
|
|
1488
|
+
subagent_start: handleSubagentStart,
|
|
1489
|
+
subagent_chunk: handleSubagentChunk,
|
|
1490
|
+
subagent_update: handleSubagentUpdate,
|
|
1491
|
+
subagent_end: handleSubagentEnd,
|
|
1492
|
+
complete: handleComplete,
|
|
1493
|
+
error: handleError,
|
|
1494
|
+
disconnected: handleDisconnected
|
|
1495
|
+
};
|
|
1075
1496
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1076
1497
|
0 && (module.exports = {
|
|
1077
1498
|
AstralformClient,
|
|
1078
1499
|
AstralformError,
|
|
1079
1500
|
AuthenticationError,
|
|
1501
|
+
BlockBuilder,
|
|
1080
1502
|
ChatSession,
|
|
1081
1503
|
ConnectionError,
|
|
1082
1504
|
InMemoryStorage,
|
|
@@ -1086,6 +1508,7 @@ var ChatSession = class {
|
|
|
1086
1508
|
StreamAbortedError,
|
|
1087
1509
|
ToolRegistry,
|
|
1088
1510
|
generateId,
|
|
1511
|
+
standardHandlers,
|
|
1089
1512
|
streamJobSSE
|
|
1090
1513
|
});
|
|
1091
1514
|
//# sourceMappingURL=index.cjs.map
|