@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.js
CHANGED
|
@@ -321,6 +321,87 @@ var AstralformClient = class {
|
|
|
321
321
|
}
|
|
322
322
|
};
|
|
323
323
|
|
|
324
|
+
// src/block-builder.ts
|
|
325
|
+
var _idCounter = 0;
|
|
326
|
+
var BlockBuilder = class {
|
|
327
|
+
constructor() {
|
|
328
|
+
this._blocks = [];
|
|
329
|
+
this._handlers = /* @__PURE__ */ new Map();
|
|
330
|
+
this._onChange = null;
|
|
331
|
+
// Active block refs — public so handlers can read/write them
|
|
332
|
+
this.activeTextId = null;
|
|
333
|
+
this.activeThinkingId = null;
|
|
334
|
+
this.thinkingStartMs = null;
|
|
335
|
+
}
|
|
336
|
+
// ── Registration ──────────────────────────────────────────────
|
|
337
|
+
on(eventType, handler) {
|
|
338
|
+
this._handlers.set(eventType, handler);
|
|
339
|
+
}
|
|
340
|
+
registerHandlers(handlers) {
|
|
341
|
+
for (const [type, handler] of Object.entries(handlers)) {
|
|
342
|
+
this._handlers.set(type, handler);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
// ── Event processing ──────────────────────────────────────────
|
|
346
|
+
processEvent(event) {
|
|
347
|
+
const handler = this._handlers.get(event.type);
|
|
348
|
+
if (handler === null) return;
|
|
349
|
+
if (!handler) return;
|
|
350
|
+
handler(event, this);
|
|
351
|
+
}
|
|
352
|
+
// ── State ─────────────────────────────────────────────────────
|
|
353
|
+
getBlocks() {
|
|
354
|
+
return [...this._blocks];
|
|
355
|
+
}
|
|
356
|
+
reset() {
|
|
357
|
+
this._blocks = [];
|
|
358
|
+
this.activeTextId = null;
|
|
359
|
+
this.activeThinkingId = null;
|
|
360
|
+
this.thinkingStartMs = null;
|
|
361
|
+
}
|
|
362
|
+
setOnChange(fn) {
|
|
363
|
+
this._onChange = fn;
|
|
364
|
+
}
|
|
365
|
+
// ── Block manipulation (used by handlers) ─────────────────────
|
|
366
|
+
addBlock(block) {
|
|
367
|
+
this._blocks = [...this._blocks, block];
|
|
368
|
+
this._notify();
|
|
369
|
+
}
|
|
370
|
+
updateBlock(id, updater) {
|
|
371
|
+
let changed = false;
|
|
372
|
+
this._blocks = this._blocks.map((b) => {
|
|
373
|
+
if (b.id !== id) return b;
|
|
374
|
+
changed = true;
|
|
375
|
+
return updater(b);
|
|
376
|
+
});
|
|
377
|
+
if (changed) this._notify();
|
|
378
|
+
}
|
|
379
|
+
/** Update any block by id with a partial update (type-loose for handlers). */
|
|
380
|
+
patchBlock(id, patch) {
|
|
381
|
+
let changed = false;
|
|
382
|
+
this._blocks = this._blocks.map((b) => {
|
|
383
|
+
if (b.id !== id) return b;
|
|
384
|
+
changed = true;
|
|
385
|
+
return { ...b, ...patch };
|
|
386
|
+
});
|
|
387
|
+
if (changed) this._notify();
|
|
388
|
+
}
|
|
389
|
+
findBlock(predicate) {
|
|
390
|
+
for (let i = this._blocks.length - 1; i >= 0; i--) {
|
|
391
|
+
const block = this._blocks[i];
|
|
392
|
+
if (block && predicate(block)) return block;
|
|
393
|
+
}
|
|
394
|
+
return void 0;
|
|
395
|
+
}
|
|
396
|
+
nextId() {
|
|
397
|
+
return `blk_${++_idCounter}`;
|
|
398
|
+
}
|
|
399
|
+
// ── Internal ──────────────────────────────────────────────────
|
|
400
|
+
_notify() {
|
|
401
|
+
this._onChange?.();
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
|
|
324
405
|
// src/storage.ts
|
|
325
406
|
var InMemoryStorage = class {
|
|
326
407
|
constructor() {
|
|
@@ -485,7 +566,7 @@ function generateId() {
|
|
|
485
566
|
|
|
486
567
|
// src/session.ts
|
|
487
568
|
var ChatSession = class {
|
|
488
|
-
constructor(config, storage) {
|
|
569
|
+
constructor(config, storage, blockBuilder) {
|
|
489
570
|
// State
|
|
490
571
|
this.conversationId = null;
|
|
491
572
|
this.conversations = [];
|
|
@@ -515,6 +596,13 @@ var ChatSession = class {
|
|
|
515
596
|
this.client = new AstralformClient(config);
|
|
516
597
|
this.toolRegistry = new ToolRegistry();
|
|
517
598
|
this.storage = storage ?? new InMemoryStorage();
|
|
599
|
+
this.blockBuilder = blockBuilder ?? new BlockBuilder();
|
|
600
|
+
this.blockBuilder.setOnChange(() => {
|
|
601
|
+
this.emit({
|
|
602
|
+
type: "blocks_changed",
|
|
603
|
+
blocks: this.blockBuilder.getBlocks()
|
|
604
|
+
});
|
|
605
|
+
});
|
|
518
606
|
}
|
|
519
607
|
on(handler) {
|
|
520
608
|
this.handlers.add(handler);
|
|
@@ -523,6 +611,9 @@ var ChatSession = class {
|
|
|
523
611
|
};
|
|
524
612
|
}
|
|
525
613
|
emit(event) {
|
|
614
|
+
if (event.type !== "blocks_changed" && event.type !== "connected") {
|
|
615
|
+
this.blockBuilder.processEvent(event);
|
|
616
|
+
}
|
|
526
617
|
for (const handler of this.handlers) {
|
|
527
618
|
try {
|
|
528
619
|
handler(event);
|
|
@@ -579,14 +670,15 @@ var ChatSession = class {
|
|
|
579
670
|
};
|
|
580
671
|
await this.processStream(request);
|
|
581
672
|
}
|
|
582
|
-
async resendFromCheckpoint(messageId, newContent) {
|
|
673
|
+
async resendFromCheckpoint(messageId, newContent, options) {
|
|
583
674
|
if (this.isStreaming) return;
|
|
584
675
|
const request = {
|
|
585
676
|
message: newContent,
|
|
586
677
|
conversation_id: this.conversationId ?? void 0,
|
|
587
678
|
resend_from: messageId,
|
|
588
679
|
mcp_manifest: this.toolRegistry.getManifest(),
|
|
589
|
-
enabled_mcp: Array.from(this.enabledClientTools)
|
|
680
|
+
enabled_mcp: Array.from(this.enabledClientTools),
|
|
681
|
+
enable_search: options?.enableSearch
|
|
590
682
|
};
|
|
591
683
|
await this.processStream(request);
|
|
592
684
|
}
|
|
@@ -626,12 +718,23 @@ var ChatSession = class {
|
|
|
626
718
|
}
|
|
627
719
|
const messageId = job.message_id;
|
|
628
720
|
this.lastSeq = -1;
|
|
629
|
-
let stopTitle;
|
|
630
721
|
const stream = this.client.streamJobEvents(
|
|
631
722
|
job.job_id,
|
|
632
723
|
this.lastSeq,
|
|
633
724
|
this.abortController?.signal
|
|
634
725
|
);
|
|
726
|
+
await this.consumeEventStream(
|
|
727
|
+
stream,
|
|
728
|
+
conversationId,
|
|
729
|
+
messageId,
|
|
730
|
+
true
|
|
731
|
+
// executeClientTools
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Shared event consumption loop used by both consumeJobStream and reconnectToJob.
|
|
736
|
+
*/
|
|
737
|
+
async consumeEventStream(stream, conversationId, messageId, executeClientTools) {
|
|
635
738
|
for await (const raw of stream) {
|
|
636
739
|
let parsed;
|
|
637
740
|
try {
|
|
@@ -655,6 +758,9 @@ var ChatSession = class {
|
|
|
655
758
|
if (!this.conversationId) {
|
|
656
759
|
this.conversationId = conversationId;
|
|
657
760
|
}
|
|
761
|
+
if (parsed.message_id) {
|
|
762
|
+
messageId = parsed.message_id;
|
|
763
|
+
}
|
|
658
764
|
if (parsed.model_display_name) {
|
|
659
765
|
this.modelDisplayName = parsed.model_display_name;
|
|
660
766
|
this.emit({
|
|
@@ -669,7 +775,7 @@ var ChatSession = class {
|
|
|
669
775
|
break;
|
|
670
776
|
case "tool_use_start": {
|
|
671
777
|
this.applyEvent(parsed);
|
|
672
|
-
if (parsed.is_client_tool) {
|
|
778
|
+
if (executeClientTools && parsed.is_client_tool) {
|
|
673
779
|
const results = await this.executeClientTools([
|
|
674
780
|
{
|
|
675
781
|
callId: parsed.call_id,
|
|
@@ -721,7 +827,15 @@ var ChatSession = class {
|
|
|
721
827
|
});
|
|
722
828
|
break;
|
|
723
829
|
case "message_stop":
|
|
724
|
-
|
|
830
|
+
await this.completeStream(
|
|
831
|
+
conversationId,
|
|
832
|
+
messageId,
|
|
833
|
+
parsed.title,
|
|
834
|
+
parsed.metrics,
|
|
835
|
+
parsed.job_id
|
|
836
|
+
);
|
|
837
|
+
this.isStreaming = false;
|
|
838
|
+
this.currentJobId = null;
|
|
725
839
|
break;
|
|
726
840
|
case "error":
|
|
727
841
|
this.emit({
|
|
@@ -733,8 +847,6 @@ var ChatSession = class {
|
|
|
733
847
|
this.applyEvent(parsed);
|
|
734
848
|
}
|
|
735
849
|
}
|
|
736
|
-
this.currentJobId = null;
|
|
737
|
-
await this.completeStream(conversationId, messageId, stopTitle);
|
|
738
850
|
}
|
|
739
851
|
/**
|
|
740
852
|
* Apply a single SSE event to session state and notify consumers.
|
|
@@ -742,6 +854,45 @@ var ChatSession = class {
|
|
|
742
854
|
*/
|
|
743
855
|
applyEvent(event) {
|
|
744
856
|
switch (event.type) {
|
|
857
|
+
case "user_message":
|
|
858
|
+
this.emit({ type: "user_message", content: event.content });
|
|
859
|
+
break;
|
|
860
|
+
case "title_generated":
|
|
861
|
+
this.emit({ type: "title_generated", title: event.title });
|
|
862
|
+
break;
|
|
863
|
+
case "message_start":
|
|
864
|
+
if (event.conversation_id && !this.conversationId) {
|
|
865
|
+
this.conversationId = event.conversation_id;
|
|
866
|
+
}
|
|
867
|
+
if (event.model_display_name) {
|
|
868
|
+
this.modelDisplayName = event.model_display_name;
|
|
869
|
+
this.emit({ type: "model_info", name: event.model_display_name });
|
|
870
|
+
}
|
|
871
|
+
break;
|
|
872
|
+
case "content_block_delta":
|
|
873
|
+
this.streamingContent += event.delta.text;
|
|
874
|
+
this.emit({ type: "chunk", text: event.delta.text });
|
|
875
|
+
break;
|
|
876
|
+
case "thinking_delta":
|
|
877
|
+
this.thinkingContent += event.delta.text;
|
|
878
|
+
this.isThinking = true;
|
|
879
|
+
this.emit({ type: "thinking_delta", text: event.delta.text });
|
|
880
|
+
break;
|
|
881
|
+
case "thinking_complete":
|
|
882
|
+
this.isThinking = false;
|
|
883
|
+
this.emit({ type: "thinking_complete" });
|
|
884
|
+
break;
|
|
885
|
+
case "message_stop":
|
|
886
|
+
this.emit({
|
|
887
|
+
type: "complete",
|
|
888
|
+
content: this.streamingContent,
|
|
889
|
+
conversationId: this.conversationId ?? "",
|
|
890
|
+
messageId: event.job_id ?? "",
|
|
891
|
+
title: event.title,
|
|
892
|
+
metrics: event.metrics,
|
|
893
|
+
job_id: event.job_id
|
|
894
|
+
});
|
|
895
|
+
break;
|
|
745
896
|
case "tool_use_start": {
|
|
746
897
|
const request = {
|
|
747
898
|
callId: event.call_id,
|
|
@@ -769,7 +920,9 @@ var ChatSession = class {
|
|
|
769
920
|
type: "tool_end",
|
|
770
921
|
callId: event.call_id,
|
|
771
922
|
toolName: event.tool,
|
|
772
|
-
result: event.result
|
|
923
|
+
result: event.result,
|
|
924
|
+
sources: event.sources,
|
|
925
|
+
durationMs: event.duration_ms
|
|
773
926
|
});
|
|
774
927
|
break;
|
|
775
928
|
}
|
|
@@ -877,18 +1030,47 @@ var ChatSession = class {
|
|
|
877
1030
|
sizeBytes: event.size_bytes
|
|
878
1031
|
});
|
|
879
1032
|
break;
|
|
880
|
-
case "
|
|
1033
|
+
case "timeline_entry":
|
|
881
1034
|
this.emit({
|
|
882
|
-
type: "
|
|
883
|
-
|
|
1035
|
+
type: "timeline_entry",
|
|
1036
|
+
id: event.id,
|
|
884
1037
|
status: event.status,
|
|
885
|
-
|
|
886
|
-
|
|
1038
|
+
kind: event.kind,
|
|
1039
|
+
agent_name: event.agent_name,
|
|
1040
|
+
tool_name: event.tool_name,
|
|
1041
|
+
display_name: event.display_name,
|
|
1042
|
+
tool_category: event.tool_category,
|
|
1043
|
+
viewer: event.viewer,
|
|
1044
|
+
call_id: event.call_id,
|
|
887
1045
|
detail: event.detail,
|
|
1046
|
+
started_at: event.started_at,
|
|
1047
|
+
duration_ms: event.duration_ms,
|
|
1048
|
+
output_summary: event.output_summary,
|
|
888
1049
|
sources: event.sources,
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1050
|
+
parent_id: event.parent_id,
|
|
1051
|
+
structured_output: event.structured_output
|
|
1052
|
+
});
|
|
1053
|
+
break;
|
|
1054
|
+
case "editor_content_start":
|
|
1055
|
+
this.emit({
|
|
1056
|
+
type: "editor_content_start",
|
|
1057
|
+
callId: event.call_id,
|
|
1058
|
+
path: event.path,
|
|
1059
|
+
language: event.language
|
|
1060
|
+
});
|
|
1061
|
+
break;
|
|
1062
|
+
case "editor_content_delta":
|
|
1063
|
+
this.emit({
|
|
1064
|
+
type: "editor_content_delta",
|
|
1065
|
+
callId: event.call_id,
|
|
1066
|
+
path: event.path,
|
|
1067
|
+
delta: event.delta
|
|
1068
|
+
});
|
|
1069
|
+
break;
|
|
1070
|
+
case "editor_content_end":
|
|
1071
|
+
this.emit({
|
|
1072
|
+
type: "editor_content_end",
|
|
1073
|
+
callId: event.call_id
|
|
892
1074
|
});
|
|
893
1075
|
break;
|
|
894
1076
|
}
|
|
@@ -916,7 +1098,7 @@ var ChatSession = class {
|
|
|
916
1098
|
this.executingTool = null;
|
|
917
1099
|
return results;
|
|
918
1100
|
}
|
|
919
|
-
async completeStream(conversationId, messageId, title) {
|
|
1101
|
+
async completeStream(conversationId, messageId, title, metrics, jobId) {
|
|
920
1102
|
const assistantMessage = {
|
|
921
1103
|
id: messageId || generateId(),
|
|
922
1104
|
conversationId,
|
|
@@ -939,9 +1121,57 @@ var ChatSession = class {
|
|
|
939
1121
|
content: this.streamingContent,
|
|
940
1122
|
conversationId,
|
|
941
1123
|
messageId: assistantMessage.id,
|
|
942
|
-
title
|
|
1124
|
+
title,
|
|
1125
|
+
metrics,
|
|
1126
|
+
job_id: jobId
|
|
943
1127
|
});
|
|
944
1128
|
}
|
|
1129
|
+
/**
|
|
1130
|
+
* Load conversation context (messages) without replaying events.
|
|
1131
|
+
* Used before reconnectToJob — SSE replay handles event replay.
|
|
1132
|
+
*/
|
|
1133
|
+
async loadConversation(id) {
|
|
1134
|
+
this.conversationId = id;
|
|
1135
|
+
this.resetStreamingState();
|
|
1136
|
+
this.blockBuilder.reset();
|
|
1137
|
+
this.messages = await this.client.getMessages(id).catch(() => this.storage.fetchMessages(id));
|
|
1138
|
+
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Reconnect to a running job's SSE stream (e.g. after page reload).
|
|
1141
|
+
* Replays all events from the beginning and continues live.
|
|
1142
|
+
* Does NOT reset BlockBuilder — caller controls reset.
|
|
1143
|
+
*/
|
|
1144
|
+
async reconnectToJob(jobId) {
|
|
1145
|
+
if (this.isStreaming) return;
|
|
1146
|
+
this.isStreaming = true;
|
|
1147
|
+
this.currentJobId = jobId;
|
|
1148
|
+
this.lastSeq = -1;
|
|
1149
|
+
this.resetStreamingState();
|
|
1150
|
+
this.abortController = new AbortController();
|
|
1151
|
+
try {
|
|
1152
|
+
const stream = this.client.streamJobEvents(
|
|
1153
|
+
jobId,
|
|
1154
|
+
this.lastSeq,
|
|
1155
|
+
this.abortController?.signal
|
|
1156
|
+
);
|
|
1157
|
+
await this.consumeEventStream(
|
|
1158
|
+
stream,
|
|
1159
|
+
this.conversationId ?? "",
|
|
1160
|
+
"",
|
|
1161
|
+
false
|
|
1162
|
+
// don't execute client tools on reconnect
|
|
1163
|
+
);
|
|
1164
|
+
} catch (err) {
|
|
1165
|
+
this.emit({
|
|
1166
|
+
type: "error",
|
|
1167
|
+
error: err instanceof Error ? err : new ConnectionError(String(err))
|
|
1168
|
+
});
|
|
1169
|
+
} finally {
|
|
1170
|
+
this.isStreaming = false;
|
|
1171
|
+
this.executingTool = null;
|
|
1172
|
+
this.abortController = null;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
945
1175
|
disconnect() {
|
|
946
1176
|
if (this.currentJobId) {
|
|
947
1177
|
this.client.cancelJob(this.currentJobId).catch(() => {
|
|
@@ -970,6 +1200,7 @@ var ChatSession = class {
|
|
|
970
1200
|
async switchConversation(id) {
|
|
971
1201
|
this.conversationId = id;
|
|
972
1202
|
this.resetStreamingState();
|
|
1203
|
+
this.blockBuilder.reset();
|
|
973
1204
|
const [messagesResult, eventsResult] = await Promise.allSettled([
|
|
974
1205
|
this.client.getMessages(id).catch(() => this.storage.fetchMessages(id)),
|
|
975
1206
|
this.client.getConversationEvents(id)
|
|
@@ -977,20 +1208,10 @@ var ChatSession = class {
|
|
|
977
1208
|
this.messages = messagesResult.status === "fulfilled" ? messagesResult.value : [];
|
|
978
1209
|
if (eventsResult.status === "fulfilled") {
|
|
979
1210
|
for (const ev of eventsResult.value) {
|
|
980
|
-
this.
|
|
1211
|
+
this.applyEvent({ type: ev.event, ...ev.data });
|
|
981
1212
|
}
|
|
982
1213
|
}
|
|
983
1214
|
}
|
|
984
|
-
/**
|
|
985
|
-
* Replay a single persisted event to reconstruct session state.
|
|
986
|
-
* Skips text deltas (final content is already in messages[]).
|
|
987
|
-
*/
|
|
988
|
-
replayEvent(eventType, data) {
|
|
989
|
-
if (eventType === "content_block_delta" || eventType === "thinking_delta" || eventType === "subagent_content_delta" || eventType === "thinking_complete") {
|
|
990
|
-
return;
|
|
991
|
-
}
|
|
992
|
-
this.applyEvent({ type: eventType, ...data });
|
|
993
|
-
}
|
|
994
1215
|
async deleteConversation(id) {
|
|
995
1216
|
try {
|
|
996
1217
|
await this.client.deleteConversation(id);
|
|
@@ -1012,10 +1233,231 @@ var ChatSession = class {
|
|
|
1012
1233
|
return true;
|
|
1013
1234
|
}
|
|
1014
1235
|
};
|
|
1236
|
+
|
|
1237
|
+
// src/standard-handlers.ts
|
|
1238
|
+
function finalizeText(builder) {
|
|
1239
|
+
if (builder.activeTextId) {
|
|
1240
|
+
builder.patchBlock(builder.activeTextId, {
|
|
1241
|
+
isStreaming: false
|
|
1242
|
+
});
|
|
1243
|
+
builder.activeTextId = null;
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
function finalizeThinking(builder) {
|
|
1247
|
+
if (builder.activeThinkingId) {
|
|
1248
|
+
builder.patchBlock(builder.activeThinkingId, {
|
|
1249
|
+
isActive: false
|
|
1250
|
+
});
|
|
1251
|
+
builder.activeThinkingId = null;
|
|
1252
|
+
builder.thinkingStartMs = null;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
var handleUserMessage = (event, builder) => {
|
|
1256
|
+
if (builder.findBlock((b) => b.type === "user")) return;
|
|
1257
|
+
const e = event;
|
|
1258
|
+
builder.addBlock({ type: "user", id: builder.nextId(), content: e.content });
|
|
1259
|
+
};
|
|
1260
|
+
var handleChunk = (event, builder) => {
|
|
1261
|
+
const e = event;
|
|
1262
|
+
if (!builder.activeTextId) {
|
|
1263
|
+
const id = builder.nextId();
|
|
1264
|
+
builder.activeTextId = id;
|
|
1265
|
+
builder.addBlock({
|
|
1266
|
+
type: "text",
|
|
1267
|
+
id,
|
|
1268
|
+
content: e.text,
|
|
1269
|
+
isStreaming: true
|
|
1270
|
+
});
|
|
1271
|
+
} else {
|
|
1272
|
+
const id = builder.activeTextId;
|
|
1273
|
+
const existing = builder.findBlock((b) => b.id === id);
|
|
1274
|
+
if (existing && existing.type === "text") {
|
|
1275
|
+
builder.patchBlock(id, {
|
|
1276
|
+
content: existing.content + e.text
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
};
|
|
1281
|
+
var handleToolCall = (event, builder) => {
|
|
1282
|
+
const e = event;
|
|
1283
|
+
finalizeText(builder);
|
|
1284
|
+
builder.addBlock({
|
|
1285
|
+
type: "tool",
|
|
1286
|
+
id: builder.nextId(),
|
|
1287
|
+
callId: e.request.callId,
|
|
1288
|
+
toolName: e.request.toolName,
|
|
1289
|
+
displayName: e.request.displayName,
|
|
1290
|
+
description: e.request.description,
|
|
1291
|
+
arguments: e.request.arguments,
|
|
1292
|
+
toolCategory: e.request.toolCategory,
|
|
1293
|
+
iconUrl: e.request.iconUrl,
|
|
1294
|
+
status: "calling"
|
|
1295
|
+
});
|
|
1296
|
+
};
|
|
1297
|
+
var handleToolExecuting = (event, builder) => {
|
|
1298
|
+
const e = event;
|
|
1299
|
+
const block = builder.findBlock(
|
|
1300
|
+
(b) => b.type === "tool" && b.toolName === e.name && b.status === "calling"
|
|
1301
|
+
);
|
|
1302
|
+
if (block) {
|
|
1303
|
+
builder.patchBlock(block.id, { status: "executing" });
|
|
1304
|
+
}
|
|
1305
|
+
};
|
|
1306
|
+
var handleToolEnd = (event, builder) => {
|
|
1307
|
+
const e = event;
|
|
1308
|
+
const callId = e.type === "tool_end" ? e.callId : void 0;
|
|
1309
|
+
const name = e.type === "tool_end" ? e.toolName : e.name;
|
|
1310
|
+
const block = builder.findBlock(
|
|
1311
|
+
(b) => b.type === "tool" && (callId ? b.callId === callId : b.toolName === name) && b.status !== "completed"
|
|
1312
|
+
);
|
|
1313
|
+
if (block) {
|
|
1314
|
+
const toolEnd = e.type === "tool_end" ? e : null;
|
|
1315
|
+
builder.patchBlock(block.id, {
|
|
1316
|
+
status: "completed",
|
|
1317
|
+
...toolEnd?.sources ? { sources: toolEnd.sources } : {},
|
|
1318
|
+
...toolEnd?.durationMs != null ? { durationMs: toolEnd.durationMs } : {},
|
|
1319
|
+
...toolEnd?.result ? { result: toolEnd.result } : {}
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
};
|
|
1323
|
+
var handleAgentStart = (event, builder) => {
|
|
1324
|
+
const e = event;
|
|
1325
|
+
finalizeText(builder);
|
|
1326
|
+
builder.addBlock({
|
|
1327
|
+
type: "agent",
|
|
1328
|
+
id: builder.nextId(),
|
|
1329
|
+
agentName: e.agentName,
|
|
1330
|
+
displayName: e.agentDisplayName,
|
|
1331
|
+
avatarUrl: e.avatarUrl
|
|
1332
|
+
});
|
|
1333
|
+
};
|
|
1334
|
+
var handleThinkingDelta = (event, builder) => {
|
|
1335
|
+
const e = event;
|
|
1336
|
+
if (!builder.activeThinkingId) {
|
|
1337
|
+
const id = builder.nextId();
|
|
1338
|
+
builder.activeThinkingId = id;
|
|
1339
|
+
builder.thinkingStartMs = Date.now();
|
|
1340
|
+
builder.addBlock({
|
|
1341
|
+
type: "thinking",
|
|
1342
|
+
id,
|
|
1343
|
+
content: e.text,
|
|
1344
|
+
isActive: true
|
|
1345
|
+
});
|
|
1346
|
+
} else {
|
|
1347
|
+
const id = builder.activeThinkingId;
|
|
1348
|
+
const existing = builder.findBlock((b) => b.id === id);
|
|
1349
|
+
if (existing && existing.type === "thinking") {
|
|
1350
|
+
builder.patchBlock(id, {
|
|
1351
|
+
content: existing.content + e.text
|
|
1352
|
+
});
|
|
1353
|
+
}
|
|
1354
|
+
}
|
|
1355
|
+
};
|
|
1356
|
+
var handleThinkingComplete = (_event, builder) => {
|
|
1357
|
+
if (builder.activeThinkingId) {
|
|
1358
|
+
const durationMs = builder.thinkingStartMs ? Math.max(0, Date.now() - builder.thinkingStartMs) : void 0;
|
|
1359
|
+
builder.patchBlock(builder.activeThinkingId, {
|
|
1360
|
+
isActive: false,
|
|
1361
|
+
durationMs
|
|
1362
|
+
});
|
|
1363
|
+
builder.activeThinkingId = null;
|
|
1364
|
+
builder.thinkingStartMs = null;
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
var handleSubagentStart = (event, builder) => {
|
|
1368
|
+
const e = event;
|
|
1369
|
+
finalizeText(builder);
|
|
1370
|
+
builder.addBlock({
|
|
1371
|
+
type: "subagent",
|
|
1372
|
+
id: builder.nextId(),
|
|
1373
|
+
agentName: e.agentName,
|
|
1374
|
+
displayName: e.displayName,
|
|
1375
|
+
toolCallId: e.toolCallId,
|
|
1376
|
+
avatarUrl: e.avatarUrl,
|
|
1377
|
+
description: e.description,
|
|
1378
|
+
content: "",
|
|
1379
|
+
isActive: true
|
|
1380
|
+
});
|
|
1381
|
+
};
|
|
1382
|
+
var handleSubagentChunk = (event, builder) => {
|
|
1383
|
+
const e = event;
|
|
1384
|
+
const block = builder.findBlock(
|
|
1385
|
+
(b) => b.type === "subagent" && b.toolCallId === e.toolCallId
|
|
1386
|
+
);
|
|
1387
|
+
if (block && block.type === "subagent") {
|
|
1388
|
+
builder.patchBlock(block.id, {
|
|
1389
|
+
content: block.content + e.text
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1392
|
+
};
|
|
1393
|
+
var handleSubagentUpdate = (event, builder) => {
|
|
1394
|
+
const e = event;
|
|
1395
|
+
const block = builder.findBlock(
|
|
1396
|
+
(b) => b.type === "subagent" && b.toolCallId === e.toolCallId
|
|
1397
|
+
);
|
|
1398
|
+
if (block) {
|
|
1399
|
+
builder.patchBlock(block.id, {
|
|
1400
|
+
displayName: e.displayName
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1403
|
+
};
|
|
1404
|
+
var handleSubagentEnd = (event, builder) => {
|
|
1405
|
+
const e = event;
|
|
1406
|
+
const block = builder.findBlock(
|
|
1407
|
+
(b) => b.type === "subagent" && b.toolCallId === e.toolCallId
|
|
1408
|
+
);
|
|
1409
|
+
if (block) {
|
|
1410
|
+
builder.patchBlock(block.id, {
|
|
1411
|
+
isActive: false
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
};
|
|
1415
|
+
var handleComplete = (_event, builder) => {
|
|
1416
|
+
finalizeText(builder);
|
|
1417
|
+
finalizeThinking(builder);
|
|
1418
|
+
for (const b of builder.getBlocks()) {
|
|
1419
|
+
if (b.type === "tool" && b.status !== "completed") {
|
|
1420
|
+
builder.patchBlock(b.id, { status: "completed" });
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
};
|
|
1424
|
+
var handleError = (event, builder) => {
|
|
1425
|
+
const e = event;
|
|
1426
|
+
finalizeText(builder);
|
|
1427
|
+
finalizeThinking(builder);
|
|
1428
|
+
builder.addBlock({
|
|
1429
|
+
type: "error",
|
|
1430
|
+
id: builder.nextId(),
|
|
1431
|
+
message: e.error.message
|
|
1432
|
+
});
|
|
1433
|
+
};
|
|
1434
|
+
var handleDisconnected = (_event, builder) => {
|
|
1435
|
+
finalizeText(builder);
|
|
1436
|
+
finalizeThinking(builder);
|
|
1437
|
+
};
|
|
1438
|
+
var standardHandlers = {
|
|
1439
|
+
user_message: handleUserMessage,
|
|
1440
|
+
chunk: handleChunk,
|
|
1441
|
+
tool_call: handleToolCall,
|
|
1442
|
+
tool_executing: handleToolExecuting,
|
|
1443
|
+
tool_completed: handleToolEnd,
|
|
1444
|
+
tool_end: handleToolEnd,
|
|
1445
|
+
agent_start: handleAgentStart,
|
|
1446
|
+
thinking_delta: handleThinkingDelta,
|
|
1447
|
+
thinking_complete: handleThinkingComplete,
|
|
1448
|
+
subagent_start: handleSubagentStart,
|
|
1449
|
+
subagent_chunk: handleSubagentChunk,
|
|
1450
|
+
subagent_update: handleSubagentUpdate,
|
|
1451
|
+
subagent_end: handleSubagentEnd,
|
|
1452
|
+
complete: handleComplete,
|
|
1453
|
+
error: handleError,
|
|
1454
|
+
disconnected: handleDisconnected
|
|
1455
|
+
};
|
|
1015
1456
|
export {
|
|
1016
1457
|
AstralformClient,
|
|
1017
1458
|
AstralformError,
|
|
1018
1459
|
AuthenticationError,
|
|
1460
|
+
BlockBuilder,
|
|
1019
1461
|
ChatSession,
|
|
1020
1462
|
ConnectionError,
|
|
1021
1463
|
InMemoryStorage,
|
|
@@ -1025,6 +1467,7 @@ export {
|
|
|
1025
1467
|
StreamAbortedError,
|
|
1026
1468
|
ToolRegistry,
|
|
1027
1469
|
generateId,
|
|
1470
|
+
standardHandlers,
|
|
1028
1471
|
streamJobSSE
|
|
1029
1472
|
};
|
|
1030
1473
|
//# sourceMappingURL=index.js.map
|