@astralform/js 0.1.2 → 0.2.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/dist/index.cjs +475 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +225 -24
- package/dist/index.d.ts +225 -24
- package/dist/index.js +473 -30
- 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);
|
|
@@ -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,47 @@ 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
|
-
|
|
1090
|
+
parent_id: event.parent_id,
|
|
1091
|
+
structured_output: event.structured_output
|
|
1092
|
+
});
|
|
1093
|
+
break;
|
|
1094
|
+
case "editor_content_start":
|
|
1095
|
+
this.emit({
|
|
1096
|
+
type: "editor_content_start",
|
|
1097
|
+
callId: event.call_id,
|
|
1098
|
+
path: event.path,
|
|
1099
|
+
language: event.language
|
|
1100
|
+
});
|
|
1101
|
+
break;
|
|
1102
|
+
case "editor_content_delta":
|
|
1103
|
+
this.emit({
|
|
1104
|
+
type: "editor_content_delta",
|
|
1105
|
+
callId: event.call_id,
|
|
1106
|
+
path: event.path,
|
|
1107
|
+
delta: event.delta
|
|
1108
|
+
});
|
|
1109
|
+
break;
|
|
1110
|
+
case "editor_content_end":
|
|
1111
|
+
this.emit({
|
|
1112
|
+
type: "editor_content_end",
|
|
1113
|
+
callId: event.call_id
|
|
930
1114
|
});
|
|
931
1115
|
break;
|
|
932
1116
|
}
|
|
@@ -954,7 +1138,7 @@ var ChatSession = class {
|
|
|
954
1138
|
this.executingTool = null;
|
|
955
1139
|
return results;
|
|
956
1140
|
}
|
|
957
|
-
async completeStream(conversationId, messageId, title) {
|
|
1141
|
+
async completeStream(conversationId, messageId, title, metrics, jobId) {
|
|
958
1142
|
const assistantMessage = {
|
|
959
1143
|
id: messageId || generateId(),
|
|
960
1144
|
conversationId,
|
|
@@ -977,9 +1161,57 @@ var ChatSession = class {
|
|
|
977
1161
|
content: this.streamingContent,
|
|
978
1162
|
conversationId,
|
|
979
1163
|
messageId: assistantMessage.id,
|
|
980
|
-
title
|
|
1164
|
+
title,
|
|
1165
|
+
metrics,
|
|
1166
|
+
job_id: jobId
|
|
981
1167
|
});
|
|
982
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
|
+
}
|
|
983
1215
|
disconnect() {
|
|
984
1216
|
if (this.currentJobId) {
|
|
985
1217
|
this.client.cancelJob(this.currentJobId).catch(() => {
|
|
@@ -1008,6 +1240,7 @@ var ChatSession = class {
|
|
|
1008
1240
|
async switchConversation(id) {
|
|
1009
1241
|
this.conversationId = id;
|
|
1010
1242
|
this.resetStreamingState();
|
|
1243
|
+
this.blockBuilder.reset();
|
|
1011
1244
|
const [messagesResult, eventsResult] = await Promise.allSettled([
|
|
1012
1245
|
this.client.getMessages(id).catch(() => this.storage.fetchMessages(id)),
|
|
1013
1246
|
this.client.getConversationEvents(id)
|
|
@@ -1015,20 +1248,10 @@ var ChatSession = class {
|
|
|
1015
1248
|
this.messages = messagesResult.status === "fulfilled" ? messagesResult.value : [];
|
|
1016
1249
|
if (eventsResult.status === "fulfilled") {
|
|
1017
1250
|
for (const ev of eventsResult.value) {
|
|
1018
|
-
this.
|
|
1251
|
+
this.applyEvent({ type: ev.event, ...ev.data });
|
|
1019
1252
|
}
|
|
1020
1253
|
}
|
|
1021
1254
|
}
|
|
1022
|
-
/**
|
|
1023
|
-
* Replay a single persisted event to reconstruct session state.
|
|
1024
|
-
* Skips text deltas (final content is already in messages[]).
|
|
1025
|
-
*/
|
|
1026
|
-
replayEvent(eventType, data) {
|
|
1027
|
-
if (eventType === "content_block_delta" || eventType === "thinking_delta" || eventType === "subagent_content_delta" || eventType === "thinking_complete") {
|
|
1028
|
-
return;
|
|
1029
|
-
}
|
|
1030
|
-
this.applyEvent({ type: eventType, ...data });
|
|
1031
|
-
}
|
|
1032
1255
|
async deleteConversation(id) {
|
|
1033
1256
|
try {
|
|
1034
1257
|
await this.client.deleteConversation(id);
|
|
@@ -1050,11 +1273,232 @@ var ChatSession = class {
|
|
|
1050
1273
|
return true;
|
|
1051
1274
|
}
|
|
1052
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
|
+
};
|
|
1053
1496
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1054
1497
|
0 && (module.exports = {
|
|
1055
1498
|
AstralformClient,
|
|
1056
1499
|
AstralformError,
|
|
1057
1500
|
AuthenticationError,
|
|
1501
|
+
BlockBuilder,
|
|
1058
1502
|
ChatSession,
|
|
1059
1503
|
ConnectionError,
|
|
1060
1504
|
InMemoryStorage,
|
|
@@ -1064,6 +1508,7 @@ var ChatSession = class {
|
|
|
1064
1508
|
StreamAbortedError,
|
|
1065
1509
|
ToolRegistry,
|
|
1066
1510
|
generateId,
|
|
1511
|
+
standardHandlers,
|
|
1067
1512
|
streamJobSSE
|
|
1068
1513
|
});
|
|
1069
1514
|
//# sourceMappingURL=index.cjs.map
|