@octavus/client-sdk 0.2.0 → 2.0.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/README.md +196 -0
- package/dist/index.d.ts +194 -26
- package/dist/index.js +460 -35
- package/dist/index.js.map +1 -1
- package/package.json +14 -3
package/dist/index.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import {
|
|
3
3
|
generateId,
|
|
4
4
|
threadForPart,
|
|
5
|
-
isFileReferenceArray
|
|
5
|
+
isFileReferenceArray,
|
|
6
|
+
OctavusError
|
|
6
7
|
} from "@octavus/core";
|
|
7
8
|
|
|
8
9
|
// src/files.ts
|
|
@@ -180,6 +181,19 @@ var OctavusChat = class {
|
|
|
180
181
|
options;
|
|
181
182
|
transport;
|
|
182
183
|
streamingState = null;
|
|
184
|
+
// Client tool state
|
|
185
|
+
// Keyed by toolName -> array of pending tools for that name
|
|
186
|
+
_pendingToolsByName = /* @__PURE__ */ new Map();
|
|
187
|
+
// Keyed by toolCallId -> pending tool state (for internal lookup when submitting)
|
|
188
|
+
_pendingToolsByCallId = /* @__PURE__ */ new Map();
|
|
189
|
+
// Cache for React useSyncExternalStore compatibility
|
|
190
|
+
_pendingClientToolsCache = {};
|
|
191
|
+
_completedToolResults = [];
|
|
192
|
+
_clientToolAbortController = null;
|
|
193
|
+
// Server tool results from mixed server+client tools (for continuation)
|
|
194
|
+
_serverToolResults = [];
|
|
195
|
+
// Execution ID for continuation (from client-tool-request event)
|
|
196
|
+
_pendingExecutionId = null;
|
|
183
197
|
// Listener sets for reactive frameworks
|
|
184
198
|
listeners = /* @__PURE__ */ new Set();
|
|
185
199
|
constructor(options) {
|
|
@@ -196,9 +210,34 @@ var OctavusChat = class {
|
|
|
196
210
|
get status() {
|
|
197
211
|
return this._status;
|
|
198
212
|
}
|
|
213
|
+
/**
|
|
214
|
+
* The current error, if any.
|
|
215
|
+
* Contains structured error information including type, source, and retryability.
|
|
216
|
+
*/
|
|
199
217
|
get error() {
|
|
200
218
|
return this._error;
|
|
201
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* Pending interactive tool calls keyed by tool name.
|
|
222
|
+
* Each tool has bound `submit()` and `cancel()` methods.
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* ```tsx
|
|
226
|
+
* const feedbackTools = pendingClientTools['request-feedback'] ?? [];
|
|
227
|
+
*
|
|
228
|
+
* {feedbackTools.map(tool => (
|
|
229
|
+
* <FeedbackModal
|
|
230
|
+
* key={tool.toolCallId}
|
|
231
|
+
* {...tool.args}
|
|
232
|
+
* onSubmit={(result) => tool.submit(result)}
|
|
233
|
+
* onCancel={() => tool.cancel()}
|
|
234
|
+
* />
|
|
235
|
+
* ))}
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
get pendingClientTools() {
|
|
239
|
+
return this._pendingClientToolsCache;
|
|
240
|
+
}
|
|
202
241
|
// =========================================================================
|
|
203
242
|
// Subscription Methods (for reactive frameworks)
|
|
204
243
|
// =========================================================================
|
|
@@ -228,6 +267,19 @@ var OctavusChat = class {
|
|
|
228
267
|
this._error = error;
|
|
229
268
|
this.notifyListeners();
|
|
230
269
|
}
|
|
270
|
+
updatePendingClientToolsCache() {
|
|
271
|
+
const cache = {};
|
|
272
|
+
for (const [toolName, tools] of this._pendingToolsByName.entries()) {
|
|
273
|
+
cache[toolName] = tools.map((tool) => ({
|
|
274
|
+
toolCallId: tool.toolCallId,
|
|
275
|
+
toolName: tool.toolName,
|
|
276
|
+
args: tool.args,
|
|
277
|
+
submit: (result) => this.submitToolResult(tool.toolCallId, result),
|
|
278
|
+
cancel: (reason) => this.submitToolResult(tool.toolCallId, void 0, reason ?? "User cancelled")
|
|
279
|
+
}));
|
|
280
|
+
}
|
|
281
|
+
this._pendingClientToolsCache = cache;
|
|
282
|
+
}
|
|
231
283
|
// =========================================================================
|
|
232
284
|
// Public Methods
|
|
233
285
|
// =========================================================================
|
|
@@ -289,13 +341,67 @@ var OctavusChat = class {
|
|
|
289
341
|
this.setStatus("streaming");
|
|
290
342
|
this.setError(null);
|
|
291
343
|
this.streamingState = createEmptyStreamingState();
|
|
344
|
+
this._pendingToolsByName.clear();
|
|
345
|
+
this._pendingToolsByCallId.clear();
|
|
346
|
+
this._completedToolResults = [];
|
|
347
|
+
this._serverToolResults = [];
|
|
348
|
+
this._pendingExecutionId = null;
|
|
349
|
+
this.updatePendingClientToolsCache();
|
|
292
350
|
try {
|
|
293
351
|
for await (const event of this.transport.trigger(triggerName, processedInput)) {
|
|
294
352
|
if (this.streamingState === null) break;
|
|
295
353
|
this.handleStreamEvent(event, this.streamingState);
|
|
296
354
|
}
|
|
297
355
|
} catch (err) {
|
|
298
|
-
const errorObj = err
|
|
356
|
+
const errorObj = OctavusError.isInstance(err) ? err : new OctavusError({
|
|
357
|
+
errorType: "internal_error",
|
|
358
|
+
message: err instanceof Error ? err.message : "Unknown error",
|
|
359
|
+
source: "client",
|
|
360
|
+
retryable: false,
|
|
361
|
+
cause: err
|
|
362
|
+
});
|
|
363
|
+
const state = this.streamingState;
|
|
364
|
+
if (state !== null) {
|
|
365
|
+
const messages = [...this._messages];
|
|
366
|
+
const lastMsg = messages[messages.length - 1];
|
|
367
|
+
if (state.parts.length > 0) {
|
|
368
|
+
const finalParts = state.parts.map((part) => {
|
|
369
|
+
if (part.type === "text" || part.type === "reasoning") {
|
|
370
|
+
if (part.status === "streaming") {
|
|
371
|
+
return { ...part, status: "done" };
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (part.type === "object" && part.status === "streaming") {
|
|
375
|
+
return { ...part, status: "done" };
|
|
376
|
+
}
|
|
377
|
+
if (part.type === "tool-call") {
|
|
378
|
+
if (part.status === "pending" || part.status === "running") {
|
|
379
|
+
return { ...part, status: "cancelled" };
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
if (part.type === "operation" && part.status === "running") {
|
|
383
|
+
return { ...part, status: "cancelled" };
|
|
384
|
+
}
|
|
385
|
+
return part;
|
|
386
|
+
});
|
|
387
|
+
const finalMessage = {
|
|
388
|
+
id: state.messageId,
|
|
389
|
+
role: "assistant",
|
|
390
|
+
parts: finalParts,
|
|
391
|
+
status: "done",
|
|
392
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
393
|
+
};
|
|
394
|
+
if (lastMsg?.id === state.messageId) {
|
|
395
|
+
messages[messages.length - 1] = finalMessage;
|
|
396
|
+
} else {
|
|
397
|
+
messages.push(finalMessage);
|
|
398
|
+
}
|
|
399
|
+
this.setMessages(messages);
|
|
400
|
+
} else if (lastMsg?.id === state.messageId) {
|
|
401
|
+
messages.pop();
|
|
402
|
+
this.setMessages(messages);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
299
405
|
this.setError(errorObj);
|
|
300
406
|
this.setStatus("error");
|
|
301
407
|
this.streamingState = null;
|
|
@@ -328,11 +434,58 @@ var OctavusChat = class {
|
|
|
328
434
|
onProgress
|
|
329
435
|
});
|
|
330
436
|
}
|
|
437
|
+
/**
|
|
438
|
+
* Internal: Submit a result for a pending tool.
|
|
439
|
+
* Called by bound submit/cancel methods on InteractiveTool.
|
|
440
|
+
*/
|
|
441
|
+
submitToolResult(toolCallId, result, error) {
|
|
442
|
+
const pendingTool = this._pendingToolsByCallId.get(toolCallId);
|
|
443
|
+
if (!pendingTool) {
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
this._pendingToolsByCallId.delete(toolCallId);
|
|
447
|
+
const toolsForName = this._pendingToolsByName.get(pendingTool.toolName);
|
|
448
|
+
if (toolsForName) {
|
|
449
|
+
const filtered = toolsForName.filter((t) => t.toolCallId !== toolCallId);
|
|
450
|
+
if (filtered.length === 0) {
|
|
451
|
+
this._pendingToolsByName.delete(pendingTool.toolName);
|
|
452
|
+
} else {
|
|
453
|
+
this._pendingToolsByName.set(pendingTool.toolName, filtered);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
this.updatePendingClientToolsCache();
|
|
457
|
+
const toolResult = {
|
|
458
|
+
toolCallId,
|
|
459
|
+
toolName: pendingTool.toolName,
|
|
460
|
+
result: error ? void 0 : result,
|
|
461
|
+
error,
|
|
462
|
+
outputVariable: pendingTool.outputVariable,
|
|
463
|
+
blockIndex: pendingTool.blockIndex
|
|
464
|
+
};
|
|
465
|
+
this._completedToolResults.push(toolResult);
|
|
466
|
+
if (error) {
|
|
467
|
+
this.emitToolOutputError(toolCallId, error);
|
|
468
|
+
} else {
|
|
469
|
+
this.emitToolOutputAvailable(toolCallId, result);
|
|
470
|
+
}
|
|
471
|
+
if (this._pendingToolsByCallId.size === 0) {
|
|
472
|
+
void this.continueWithClientToolResults();
|
|
473
|
+
}
|
|
474
|
+
this.notifyListeners();
|
|
475
|
+
}
|
|
331
476
|
/** Stop the current streaming and finalize any partial message */
|
|
332
477
|
stop() {
|
|
333
|
-
if (this._status !== "streaming") {
|
|
478
|
+
if (this._status !== "streaming" && this._status !== "awaiting-input") {
|
|
334
479
|
return;
|
|
335
480
|
}
|
|
481
|
+
this._clientToolAbortController?.abort();
|
|
482
|
+
this._clientToolAbortController = null;
|
|
483
|
+
this._pendingToolsByName.clear();
|
|
484
|
+
this._pendingToolsByCallId.clear();
|
|
485
|
+
this._completedToolResults = [];
|
|
486
|
+
this._serverToolResults = [];
|
|
487
|
+
this._pendingExecutionId = null;
|
|
488
|
+
this.updatePendingClientToolsCache();
|
|
336
489
|
this.transport.stop();
|
|
337
490
|
const state = this.streamingState;
|
|
338
491
|
if (state && state.parts.length > 0) {
|
|
@@ -372,7 +525,7 @@ var OctavusChat = class {
|
|
|
372
525
|
};
|
|
373
526
|
const messages = [...this._messages];
|
|
374
527
|
const lastMsg = messages[messages.length - 1];
|
|
375
|
-
if (lastMsg
|
|
528
|
+
if (lastMsg?.id === state.messageId) {
|
|
376
529
|
messages[messages.length - 1] = finalMessage;
|
|
377
530
|
} else {
|
|
378
531
|
messages.push(finalMessage);
|
|
@@ -615,7 +768,7 @@ var OctavusChat = class {
|
|
|
615
768
|
);
|
|
616
769
|
if (toolPartIndex >= 0) {
|
|
617
770
|
const part = state.parts[toolPartIndex];
|
|
618
|
-
part.error = event.
|
|
771
|
+
part.error = event.error;
|
|
619
772
|
part.status = "error";
|
|
620
773
|
state.parts[toolPartIndex] = { ...part };
|
|
621
774
|
this.updateStreamingMessage();
|
|
@@ -668,6 +821,12 @@ var OctavusChat = class {
|
|
|
668
821
|
this.options.onResourceUpdate?.(event.name, event.value);
|
|
669
822
|
break;
|
|
670
823
|
case "finish": {
|
|
824
|
+
if (event.finishReason === "client-tool-calls") {
|
|
825
|
+
if (this._pendingToolsByCallId.size > 0) {
|
|
826
|
+
this.setStatus("awaiting-input");
|
|
827
|
+
}
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
671
830
|
const finalMessage = buildMessageFromState(state, "done");
|
|
672
831
|
finalMessage.parts = finalMessage.parts.map((part) => {
|
|
673
832
|
if (part.type === "text" || part.type === "reasoning") {
|
|
@@ -681,7 +840,7 @@ var OctavusChat = class {
|
|
|
681
840
|
if (finalMessage.parts.length > 0) {
|
|
682
841
|
const messages = [...this._messages];
|
|
683
842
|
const lastMsg = messages[messages.length - 1];
|
|
684
|
-
if (lastMsg
|
|
843
|
+
if (lastMsg?.id === state.messageId) {
|
|
685
844
|
messages[messages.length - 1] = finalMessage;
|
|
686
845
|
} else {
|
|
687
846
|
messages.push(finalMessage);
|
|
@@ -693,10 +852,25 @@ var OctavusChat = class {
|
|
|
693
852
|
this.options.onFinish?.();
|
|
694
853
|
break;
|
|
695
854
|
}
|
|
696
|
-
case "error":
|
|
697
|
-
throw new
|
|
855
|
+
case "error": {
|
|
856
|
+
throw new OctavusError({
|
|
857
|
+
errorType: event.errorType,
|
|
858
|
+
message: event.message,
|
|
859
|
+
source: event.source,
|
|
860
|
+
retryable: event.retryable,
|
|
861
|
+
retryAfter: event.retryAfter,
|
|
862
|
+
code: event.code,
|
|
863
|
+
provider: event.provider,
|
|
864
|
+
tool: event.tool
|
|
865
|
+
});
|
|
866
|
+
}
|
|
698
867
|
case "tool-request":
|
|
699
868
|
break;
|
|
869
|
+
case "client-tool-request":
|
|
870
|
+
this._pendingExecutionId = event.executionId;
|
|
871
|
+
this._serverToolResults = event.serverToolResults ?? [];
|
|
872
|
+
void this.handleClientToolRequest(event.toolCalls, state);
|
|
873
|
+
break;
|
|
700
874
|
}
|
|
701
875
|
}
|
|
702
876
|
updateStreamingMessage() {
|
|
@@ -705,13 +879,168 @@ var OctavusChat = class {
|
|
|
705
879
|
const msg = buildMessageFromState(state, "streaming");
|
|
706
880
|
const messages = [...this._messages];
|
|
707
881
|
const lastMsg = messages[messages.length - 1];
|
|
708
|
-
if (lastMsg
|
|
882
|
+
if (lastMsg?.id === state.messageId) {
|
|
709
883
|
messages[messages.length - 1] = msg;
|
|
710
884
|
} else {
|
|
711
885
|
messages.push(msg);
|
|
712
886
|
}
|
|
713
887
|
this.setMessages(messages);
|
|
714
888
|
}
|
|
889
|
+
/**
|
|
890
|
+
* Emit a tool-output-available event for a client tool result.
|
|
891
|
+
*/
|
|
892
|
+
emitToolOutputAvailable(toolCallId, output) {
|
|
893
|
+
const state = this.streamingState;
|
|
894
|
+
if (!state) return;
|
|
895
|
+
const toolPartIndex = state.parts.findIndex(
|
|
896
|
+
(p) => p.type === "tool-call" && p.toolCallId === toolCallId
|
|
897
|
+
);
|
|
898
|
+
if (toolPartIndex >= 0) {
|
|
899
|
+
const part = state.parts[toolPartIndex];
|
|
900
|
+
part.result = output;
|
|
901
|
+
part.status = "done";
|
|
902
|
+
state.parts[toolPartIndex] = { ...part };
|
|
903
|
+
this.updateStreamingMessage();
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
/**
|
|
907
|
+
* Emit a tool-output-error event for a client tool result.
|
|
908
|
+
*/
|
|
909
|
+
emitToolOutputError(toolCallId, error) {
|
|
910
|
+
const state = this.streamingState;
|
|
911
|
+
if (!state) return;
|
|
912
|
+
const toolPartIndex = state.parts.findIndex(
|
|
913
|
+
(p) => p.type === "tool-call" && p.toolCallId === toolCallId
|
|
914
|
+
);
|
|
915
|
+
if (toolPartIndex >= 0) {
|
|
916
|
+
const part = state.parts[toolPartIndex];
|
|
917
|
+
part.error = error;
|
|
918
|
+
part.status = "error";
|
|
919
|
+
state.parts[toolPartIndex] = { ...part };
|
|
920
|
+
this.updateStreamingMessage();
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Continue execution with collected client tool results.
|
|
925
|
+
*/
|
|
926
|
+
async continueWithClientToolResults() {
|
|
927
|
+
if (this._completedToolResults.length === 0) return;
|
|
928
|
+
if (this._pendingExecutionId === null) {
|
|
929
|
+
const errorObj = new OctavusError({
|
|
930
|
+
errorType: "internal_error",
|
|
931
|
+
message: "Cannot continue execution: execution ID was lost.",
|
|
932
|
+
source: "client",
|
|
933
|
+
retryable: false
|
|
934
|
+
});
|
|
935
|
+
this.setError(errorObj);
|
|
936
|
+
this.setStatus("error");
|
|
937
|
+
this.options.onError?.(errorObj);
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
const allResults = [...this._serverToolResults, ...this._completedToolResults];
|
|
941
|
+
const executionId = this._pendingExecutionId;
|
|
942
|
+
this._serverToolResults = [];
|
|
943
|
+
this._completedToolResults = [];
|
|
944
|
+
this._pendingExecutionId = null;
|
|
945
|
+
this.setStatus("streaming");
|
|
946
|
+
try {
|
|
947
|
+
for await (const event of this.transport.continueWithToolResults(executionId, allResults)) {
|
|
948
|
+
if (this.streamingState === null) break;
|
|
949
|
+
this.handleStreamEvent(event, this.streamingState);
|
|
950
|
+
}
|
|
951
|
+
} catch (err) {
|
|
952
|
+
const errorObj = OctavusError.isInstance(err) ? err : new OctavusError({
|
|
953
|
+
errorType: "internal_error",
|
|
954
|
+
message: err instanceof Error ? err.message : "Unknown error",
|
|
955
|
+
source: "client",
|
|
956
|
+
retryable: false,
|
|
957
|
+
cause: err
|
|
958
|
+
});
|
|
959
|
+
this.setError(errorObj);
|
|
960
|
+
this.setStatus("error");
|
|
961
|
+
this.streamingState = null;
|
|
962
|
+
this.options.onError?.(errorObj);
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
/**
|
|
966
|
+
* Handle client tool request event.
|
|
967
|
+
*
|
|
968
|
+
* IMPORTANT: Interactive tools must be registered synchronously (before any await)
|
|
969
|
+
* to avoid a race condition where the finish event is processed before tools are added.
|
|
970
|
+
*/
|
|
971
|
+
async handleClientToolRequest(toolCalls, state) {
|
|
972
|
+
this._clientToolAbortController = new AbortController();
|
|
973
|
+
for (const tc of toolCalls) {
|
|
974
|
+
const handler = this.options.clientTools?.[tc.toolName];
|
|
975
|
+
if (handler === "interactive") {
|
|
976
|
+
const toolState = {
|
|
977
|
+
toolCallId: tc.toolCallId,
|
|
978
|
+
toolName: tc.toolName,
|
|
979
|
+
args: tc.args,
|
|
980
|
+
source: tc.source,
|
|
981
|
+
outputVariable: tc.outputVariable,
|
|
982
|
+
blockIndex: tc.blockIndex
|
|
983
|
+
};
|
|
984
|
+
this._pendingToolsByCallId.set(tc.toolCallId, toolState);
|
|
985
|
+
const existing = this._pendingToolsByName.get(tc.toolName) ?? [];
|
|
986
|
+
this._pendingToolsByName.set(tc.toolName, [...existing, toolState]);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
if (this._pendingToolsByCallId.size > 0) {
|
|
990
|
+
this.updatePendingClientToolsCache();
|
|
991
|
+
}
|
|
992
|
+
for (const tc of toolCalls) {
|
|
993
|
+
const handler = this.options.clientTools?.[tc.toolName];
|
|
994
|
+
if (handler === "interactive") {
|
|
995
|
+
const toolPartIndex = state.parts.findIndex(
|
|
996
|
+
(p) => p.type === "tool-call" && p.toolCallId === tc.toolCallId
|
|
997
|
+
);
|
|
998
|
+
if (toolPartIndex >= 0) {
|
|
999
|
+
const part = state.parts[toolPartIndex];
|
|
1000
|
+
state.parts[toolPartIndex] = { ...part };
|
|
1001
|
+
}
|
|
1002
|
+
} else if (handler) {
|
|
1003
|
+
try {
|
|
1004
|
+
const result = await handler(tc.args, {
|
|
1005
|
+
toolCallId: tc.toolCallId,
|
|
1006
|
+
toolName: tc.toolName,
|
|
1007
|
+
signal: this._clientToolAbortController.signal
|
|
1008
|
+
});
|
|
1009
|
+
this._completedToolResults.push({
|
|
1010
|
+
toolCallId: tc.toolCallId,
|
|
1011
|
+
toolName: tc.toolName,
|
|
1012
|
+
result,
|
|
1013
|
+
outputVariable: tc.outputVariable,
|
|
1014
|
+
blockIndex: tc.blockIndex
|
|
1015
|
+
});
|
|
1016
|
+
this.emitToolOutputAvailable(tc.toolCallId, result);
|
|
1017
|
+
} catch (err) {
|
|
1018
|
+
const errorMessage = err instanceof Error ? err.message : "Tool execution failed";
|
|
1019
|
+
this._completedToolResults.push({
|
|
1020
|
+
toolCallId: tc.toolCallId,
|
|
1021
|
+
toolName: tc.toolName,
|
|
1022
|
+
error: errorMessage,
|
|
1023
|
+
outputVariable: tc.outputVariable,
|
|
1024
|
+
blockIndex: tc.blockIndex
|
|
1025
|
+
});
|
|
1026
|
+
this.emitToolOutputError(tc.toolCallId, errorMessage);
|
|
1027
|
+
}
|
|
1028
|
+
} else {
|
|
1029
|
+
const errorMessage = `No client handler for tool: ${tc.toolName}`;
|
|
1030
|
+
this._completedToolResults.push({
|
|
1031
|
+
toolCallId: tc.toolCallId,
|
|
1032
|
+
toolName: tc.toolName,
|
|
1033
|
+
error: errorMessage,
|
|
1034
|
+
outputVariable: tc.outputVariable,
|
|
1035
|
+
blockIndex: tc.blockIndex
|
|
1036
|
+
});
|
|
1037
|
+
this.emitToolOutputError(tc.toolCallId, errorMessage);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
if (this._pendingToolsByCallId.size === 0 && this._completedToolResults.length > 0) {
|
|
1041
|
+
await this.continueWithClientToolResults();
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
715
1044
|
};
|
|
716
1045
|
|
|
717
1046
|
// src/stream/reader.ts
|
|
@@ -763,9 +1092,6 @@ async function* parseSSEStream(response, signal) {
|
|
|
763
1092
|
}
|
|
764
1093
|
}
|
|
765
1094
|
|
|
766
|
-
// src/index.ts
|
|
767
|
-
import { isOtherThread, isFileReference, isFileReferenceArray as isFileReferenceArray2 } from "@octavus/core";
|
|
768
|
-
|
|
769
1095
|
// src/transports/types.ts
|
|
770
1096
|
function isSocketTransport(transport) {
|
|
771
1097
|
return "connect" in transport && "disconnect" in transport && "connectionState" in transport && "onConnectionStateChange" in transport;
|
|
@@ -775,32 +1101,45 @@ function isSocketTransport(transport) {
|
|
|
775
1101
|
import { isAbortError as isAbortError2 } from "@octavus/core";
|
|
776
1102
|
function createHttpTransport(options) {
|
|
777
1103
|
let abortController = null;
|
|
1104
|
+
async function* streamResponse(responsePromise) {
|
|
1105
|
+
try {
|
|
1106
|
+
const response = await responsePromise;
|
|
1107
|
+
if (!response.ok) {
|
|
1108
|
+
const errorText = await response.text().catch(() => `Request failed: ${response.status}`);
|
|
1109
|
+
throw new Error(errorText);
|
|
1110
|
+
}
|
|
1111
|
+
if (!response.body) {
|
|
1112
|
+
throw new Error("Response body is empty");
|
|
1113
|
+
}
|
|
1114
|
+
for await (const event of parseSSEStream(response, abortController.signal)) {
|
|
1115
|
+
if (abortController?.signal.aborted) {
|
|
1116
|
+
break;
|
|
1117
|
+
}
|
|
1118
|
+
yield event;
|
|
1119
|
+
}
|
|
1120
|
+
} catch (err) {
|
|
1121
|
+
if (isAbortError2(err)) {
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
throw err;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
778
1127
|
return {
|
|
779
1128
|
async *trigger(triggerName, input) {
|
|
780
1129
|
abortController = new AbortController();
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
break;
|
|
795
|
-
}
|
|
796
|
-
yield event;
|
|
797
|
-
}
|
|
798
|
-
} catch (err) {
|
|
799
|
-
if (isAbortError2(err)) {
|
|
800
|
-
return;
|
|
801
|
-
}
|
|
802
|
-
throw err;
|
|
803
|
-
}
|
|
1130
|
+
const response = options.request(
|
|
1131
|
+
{ type: "trigger", triggerName, input },
|
|
1132
|
+
{ signal: abortController.signal }
|
|
1133
|
+
);
|
|
1134
|
+
yield* streamResponse(response);
|
|
1135
|
+
},
|
|
1136
|
+
async *continueWithToolResults(executionId, toolResults) {
|
|
1137
|
+
abortController = new AbortController();
|
|
1138
|
+
const response = options.request(
|
|
1139
|
+
{ type: "continue", executionId, toolResults },
|
|
1140
|
+
{ signal: abortController.signal }
|
|
1141
|
+
);
|
|
1142
|
+
yield* streamResponse(response);
|
|
804
1143
|
},
|
|
805
1144
|
stop() {
|
|
806
1145
|
abortController?.abort();
|
|
@@ -956,18 +1295,104 @@ function createSocketTransport(options) {
|
|
|
956
1295
|
eventResolver(null);
|
|
957
1296
|
eventResolver = null;
|
|
958
1297
|
}
|
|
1298
|
+
},
|
|
1299
|
+
/**
|
|
1300
|
+
* Continue execution with tool results after client-side tool handling.
|
|
1301
|
+
* @param executionId - The execution ID from the client-tool-request event
|
|
1302
|
+
* @param toolResults - All tool results (server + client) to send
|
|
1303
|
+
*/
|
|
1304
|
+
async *continueWithToolResults(executionId, toolResults) {
|
|
1305
|
+
await ensureConnected();
|
|
1306
|
+
eventQueue = [];
|
|
1307
|
+
isStreaming = true;
|
|
1308
|
+
socket.send(
|
|
1309
|
+
JSON.stringify({
|
|
1310
|
+
type: "continue",
|
|
1311
|
+
executionId,
|
|
1312
|
+
toolResults
|
|
1313
|
+
})
|
|
1314
|
+
);
|
|
1315
|
+
while (true) {
|
|
1316
|
+
const event = await nextEvent();
|
|
1317
|
+
if (event === null) break;
|
|
1318
|
+
yield event;
|
|
1319
|
+
if (event.type === "finish" || event.type === "error") break;
|
|
1320
|
+
}
|
|
959
1321
|
}
|
|
960
1322
|
};
|
|
961
1323
|
}
|
|
1324
|
+
|
|
1325
|
+
// src/index.ts
|
|
1326
|
+
import {
|
|
1327
|
+
AppError,
|
|
1328
|
+
NotFoundError,
|
|
1329
|
+
ValidationError,
|
|
1330
|
+
ConflictError,
|
|
1331
|
+
ForbiddenError,
|
|
1332
|
+
OctavusError as OctavusError2,
|
|
1333
|
+
isRateLimitError,
|
|
1334
|
+
isAuthenticationError,
|
|
1335
|
+
isProviderError,
|
|
1336
|
+
isToolError,
|
|
1337
|
+
isRetryableError,
|
|
1338
|
+
isValidationError,
|
|
1339
|
+
createErrorEvent,
|
|
1340
|
+
errorToStreamEvent,
|
|
1341
|
+
createInternalErrorEvent,
|
|
1342
|
+
createApiErrorEvent,
|
|
1343
|
+
generateId as generateId2,
|
|
1344
|
+
isAbortError as isAbortError3,
|
|
1345
|
+
MAIN_THREAD,
|
|
1346
|
+
resolveThread,
|
|
1347
|
+
isMainThread,
|
|
1348
|
+
threadForPart as threadForPart2,
|
|
1349
|
+
isOtherThread,
|
|
1350
|
+
isFileReference,
|
|
1351
|
+
isFileReferenceArray as isFileReferenceArray2,
|
|
1352
|
+
safeParseStreamEvent as safeParseStreamEvent3,
|
|
1353
|
+
safeParseUIMessage,
|
|
1354
|
+
safeParseUIMessages,
|
|
1355
|
+
OCTAVUS_SKILL_TOOLS,
|
|
1356
|
+
isOctavusSkillTool,
|
|
1357
|
+
getSkillSlugFromToolCall
|
|
1358
|
+
} from "@octavus/core";
|
|
962
1359
|
export {
|
|
1360
|
+
AppError,
|
|
1361
|
+
ConflictError,
|
|
1362
|
+
ForbiddenError,
|
|
1363
|
+
MAIN_THREAD,
|
|
1364
|
+
NotFoundError,
|
|
1365
|
+
OCTAVUS_SKILL_TOOLS,
|
|
963
1366
|
OctavusChat,
|
|
1367
|
+
OctavusError2 as OctavusError,
|
|
1368
|
+
ValidationError,
|
|
1369
|
+
createApiErrorEvent,
|
|
1370
|
+
createErrorEvent,
|
|
964
1371
|
createHttpTransport,
|
|
1372
|
+
createInternalErrorEvent,
|
|
965
1373
|
createSocketTransport,
|
|
1374
|
+
errorToStreamEvent,
|
|
1375
|
+
generateId2 as generateId,
|
|
1376
|
+
getSkillSlugFromToolCall,
|
|
1377
|
+
isAbortError3 as isAbortError,
|
|
1378
|
+
isAuthenticationError,
|
|
966
1379
|
isFileReference,
|
|
967
1380
|
isFileReferenceArray2 as isFileReferenceArray,
|
|
1381
|
+
isMainThread,
|
|
1382
|
+
isOctavusSkillTool,
|
|
968
1383
|
isOtherThread,
|
|
1384
|
+
isProviderError,
|
|
1385
|
+
isRateLimitError,
|
|
1386
|
+
isRetryableError,
|
|
969
1387
|
isSocketTransport,
|
|
1388
|
+
isToolError,
|
|
1389
|
+
isValidationError,
|
|
970
1390
|
parseSSEStream,
|
|
1391
|
+
resolveThread,
|
|
1392
|
+
safeParseStreamEvent3 as safeParseStreamEvent,
|
|
1393
|
+
safeParseUIMessage,
|
|
1394
|
+
safeParseUIMessages,
|
|
1395
|
+
threadForPart2 as threadForPart,
|
|
971
1396
|
uploadFiles
|
|
972
1397
|
};
|
|
973
1398
|
//# sourceMappingURL=index.js.map
|