@octavus/client-sdk 1.0.0 → 2.1.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 +6 -6
- package/dist/index.d.ts +168 -22
- package/dist/index.js +442 -25
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -181,6 +181,22 @@ var OctavusChat = class {
|
|
|
181
181
|
options;
|
|
182
182
|
transport;
|
|
183
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;
|
|
197
|
+
// Flag indicating automatic client tools have completed and are ready to continue
|
|
198
|
+
// We wait for the finish event before actually continuing to avoid race conditions
|
|
199
|
+
_readyToContinue = false;
|
|
184
200
|
// Listener sets for reactive frameworks
|
|
185
201
|
listeners = /* @__PURE__ */ new Set();
|
|
186
202
|
constructor(options) {
|
|
@@ -204,6 +220,27 @@ var OctavusChat = class {
|
|
|
204
220
|
get error() {
|
|
205
221
|
return this._error;
|
|
206
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Pending interactive tool calls keyed by tool name.
|
|
225
|
+
* Each tool has bound `submit()` and `cancel()` methods.
|
|
226
|
+
*
|
|
227
|
+
* @example
|
|
228
|
+
* ```tsx
|
|
229
|
+
* const feedbackTools = pendingClientTools['request-feedback'] ?? [];
|
|
230
|
+
*
|
|
231
|
+
* {feedbackTools.map(tool => (
|
|
232
|
+
* <FeedbackModal
|
|
233
|
+
* key={tool.toolCallId}
|
|
234
|
+
* {...tool.args}
|
|
235
|
+
* onSubmit={(result) => tool.submit(result)}
|
|
236
|
+
* onCancel={() => tool.cancel()}
|
|
237
|
+
* />
|
|
238
|
+
* ))}
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
241
|
+
get pendingClientTools() {
|
|
242
|
+
return this._pendingClientToolsCache;
|
|
243
|
+
}
|
|
207
244
|
// =========================================================================
|
|
208
245
|
// Subscription Methods (for reactive frameworks)
|
|
209
246
|
// =========================================================================
|
|
@@ -233,6 +270,19 @@ var OctavusChat = class {
|
|
|
233
270
|
this._error = error;
|
|
234
271
|
this.notifyListeners();
|
|
235
272
|
}
|
|
273
|
+
updatePendingClientToolsCache() {
|
|
274
|
+
const cache = {};
|
|
275
|
+
for (const [toolName, tools] of this._pendingToolsByName.entries()) {
|
|
276
|
+
cache[toolName] = tools.map((tool) => ({
|
|
277
|
+
toolCallId: tool.toolCallId,
|
|
278
|
+
toolName: tool.toolName,
|
|
279
|
+
args: tool.args,
|
|
280
|
+
submit: (result) => this.submitToolResult(tool.toolCallId, result),
|
|
281
|
+
cancel: (reason) => this.submitToolResult(tool.toolCallId, void 0, reason ?? "User cancelled")
|
|
282
|
+
}));
|
|
283
|
+
}
|
|
284
|
+
this._pendingClientToolsCache = cache;
|
|
285
|
+
}
|
|
236
286
|
// =========================================================================
|
|
237
287
|
// Public Methods
|
|
238
288
|
// =========================================================================
|
|
@@ -294,6 +344,13 @@ var OctavusChat = class {
|
|
|
294
344
|
this.setStatus("streaming");
|
|
295
345
|
this.setError(null);
|
|
296
346
|
this.streamingState = createEmptyStreamingState();
|
|
347
|
+
this._pendingToolsByName.clear();
|
|
348
|
+
this._pendingToolsByCallId.clear();
|
|
349
|
+
this._completedToolResults = [];
|
|
350
|
+
this._serverToolResults = [];
|
|
351
|
+
this._pendingExecutionId = null;
|
|
352
|
+
this._readyToContinue = false;
|
|
353
|
+
this.updatePendingClientToolsCache();
|
|
297
354
|
try {
|
|
298
355
|
for await (const event of this.transport.trigger(triggerName, processedInput)) {
|
|
299
356
|
if (this.streamingState === null) break;
|
|
@@ -307,6 +364,48 @@ var OctavusChat = class {
|
|
|
307
364
|
retryable: false,
|
|
308
365
|
cause: err
|
|
309
366
|
});
|
|
367
|
+
const state = this.streamingState;
|
|
368
|
+
if (state !== null) {
|
|
369
|
+
const messages = [...this._messages];
|
|
370
|
+
const lastMsg = messages[messages.length - 1];
|
|
371
|
+
if (state.parts.length > 0) {
|
|
372
|
+
const finalParts = state.parts.map((part) => {
|
|
373
|
+
if (part.type === "text" || part.type === "reasoning") {
|
|
374
|
+
if (part.status === "streaming") {
|
|
375
|
+
return { ...part, status: "done" };
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
if (part.type === "object" && part.status === "streaming") {
|
|
379
|
+
return { ...part, status: "done" };
|
|
380
|
+
}
|
|
381
|
+
if (part.type === "tool-call") {
|
|
382
|
+
if (part.status === "pending" || part.status === "running") {
|
|
383
|
+
return { ...part, status: "cancelled" };
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
if (part.type === "operation" && part.status === "running") {
|
|
387
|
+
return { ...part, status: "cancelled" };
|
|
388
|
+
}
|
|
389
|
+
return part;
|
|
390
|
+
});
|
|
391
|
+
const finalMessage = {
|
|
392
|
+
id: state.messageId,
|
|
393
|
+
role: "assistant",
|
|
394
|
+
parts: finalParts,
|
|
395
|
+
status: "done",
|
|
396
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
397
|
+
};
|
|
398
|
+
if (lastMsg?.id === state.messageId) {
|
|
399
|
+
messages[messages.length - 1] = finalMessage;
|
|
400
|
+
} else {
|
|
401
|
+
messages.push(finalMessage);
|
|
402
|
+
}
|
|
403
|
+
this.setMessages(messages);
|
|
404
|
+
} else if (lastMsg?.id === state.messageId) {
|
|
405
|
+
messages.pop();
|
|
406
|
+
this.setMessages(messages);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
310
409
|
this.setError(errorObj);
|
|
311
410
|
this.setStatus("error");
|
|
312
411
|
this.streamingState = null;
|
|
@@ -339,11 +438,59 @@ var OctavusChat = class {
|
|
|
339
438
|
onProgress
|
|
340
439
|
});
|
|
341
440
|
}
|
|
441
|
+
/**
|
|
442
|
+
* Internal: Submit a result for a pending tool.
|
|
443
|
+
* Called by bound submit/cancel methods on InteractiveTool.
|
|
444
|
+
*/
|
|
445
|
+
submitToolResult(toolCallId, result, error) {
|
|
446
|
+
const pendingTool = this._pendingToolsByCallId.get(toolCallId);
|
|
447
|
+
if (!pendingTool) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
this._pendingToolsByCallId.delete(toolCallId);
|
|
451
|
+
const toolsForName = this._pendingToolsByName.get(pendingTool.toolName);
|
|
452
|
+
if (toolsForName) {
|
|
453
|
+
const filtered = toolsForName.filter((t) => t.toolCallId !== toolCallId);
|
|
454
|
+
if (filtered.length === 0) {
|
|
455
|
+
this._pendingToolsByName.delete(pendingTool.toolName);
|
|
456
|
+
} else {
|
|
457
|
+
this._pendingToolsByName.set(pendingTool.toolName, filtered);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
this.updatePendingClientToolsCache();
|
|
461
|
+
const toolResult = {
|
|
462
|
+
toolCallId,
|
|
463
|
+
toolName: pendingTool.toolName,
|
|
464
|
+
result: error ? void 0 : result,
|
|
465
|
+
error,
|
|
466
|
+
outputVariable: pendingTool.outputVariable,
|
|
467
|
+
blockIndex: pendingTool.blockIndex
|
|
468
|
+
};
|
|
469
|
+
this._completedToolResults.push(toolResult);
|
|
470
|
+
if (error) {
|
|
471
|
+
this.emitToolOutputError(toolCallId, error);
|
|
472
|
+
} else {
|
|
473
|
+
this.emitToolOutputAvailable(toolCallId, result);
|
|
474
|
+
}
|
|
475
|
+
if (this._pendingToolsByCallId.size === 0) {
|
|
476
|
+
void this.continueWithClientToolResults();
|
|
477
|
+
}
|
|
478
|
+
this.notifyListeners();
|
|
479
|
+
}
|
|
342
480
|
/** Stop the current streaming and finalize any partial message */
|
|
343
481
|
stop() {
|
|
344
|
-
if (this._status !== "streaming") {
|
|
482
|
+
if (this._status !== "streaming" && this._status !== "awaiting-input") {
|
|
345
483
|
return;
|
|
346
484
|
}
|
|
485
|
+
this._clientToolAbortController?.abort();
|
|
486
|
+
this._clientToolAbortController = null;
|
|
487
|
+
this._pendingToolsByName.clear();
|
|
488
|
+
this._pendingToolsByCallId.clear();
|
|
489
|
+
this._completedToolResults = [];
|
|
490
|
+
this._serverToolResults = [];
|
|
491
|
+
this._pendingExecutionId = null;
|
|
492
|
+
this._readyToContinue = false;
|
|
493
|
+
this.updatePendingClientToolsCache();
|
|
347
494
|
this.transport.stop();
|
|
348
495
|
const state = this.streamingState;
|
|
349
496
|
if (state && state.parts.length > 0) {
|
|
@@ -679,6 +826,15 @@ var OctavusChat = class {
|
|
|
679
826
|
this.options.onResourceUpdate?.(event.name, event.value);
|
|
680
827
|
break;
|
|
681
828
|
case "finish": {
|
|
829
|
+
if (event.finishReason === "client-tool-calls") {
|
|
830
|
+
if (this._pendingToolsByCallId.size > 0) {
|
|
831
|
+
this.setStatus("awaiting-input");
|
|
832
|
+
} else if (this._readyToContinue) {
|
|
833
|
+
this._readyToContinue = false;
|
|
834
|
+
void this.continueWithClientToolResults();
|
|
835
|
+
}
|
|
836
|
+
return;
|
|
837
|
+
}
|
|
682
838
|
const finalMessage = buildMessageFromState(state, "done");
|
|
683
839
|
finalMessage.parts = finalMessage.parts.map((part) => {
|
|
684
840
|
if (part.type === "text" || part.type === "reasoning") {
|
|
@@ -718,6 +874,11 @@ var OctavusChat = class {
|
|
|
718
874
|
}
|
|
719
875
|
case "tool-request":
|
|
720
876
|
break;
|
|
877
|
+
case "client-tool-request":
|
|
878
|
+
this._pendingExecutionId = event.executionId;
|
|
879
|
+
this._serverToolResults = event.serverToolResults ?? [];
|
|
880
|
+
void this.handleClientToolRequest(event.toolCalls, state);
|
|
881
|
+
break;
|
|
721
882
|
}
|
|
722
883
|
}
|
|
723
884
|
updateStreamingMessage() {
|
|
@@ -733,6 +894,161 @@ var OctavusChat = class {
|
|
|
733
894
|
}
|
|
734
895
|
this.setMessages(messages);
|
|
735
896
|
}
|
|
897
|
+
/**
|
|
898
|
+
* Emit a tool-output-available event for a client tool result.
|
|
899
|
+
*/
|
|
900
|
+
emitToolOutputAvailable(toolCallId, output) {
|
|
901
|
+
const state = this.streamingState;
|
|
902
|
+
if (!state) return;
|
|
903
|
+
const toolPartIndex = state.parts.findIndex(
|
|
904
|
+
(p) => p.type === "tool-call" && p.toolCallId === toolCallId
|
|
905
|
+
);
|
|
906
|
+
if (toolPartIndex >= 0) {
|
|
907
|
+
const part = state.parts[toolPartIndex];
|
|
908
|
+
part.result = output;
|
|
909
|
+
part.status = "done";
|
|
910
|
+
state.parts[toolPartIndex] = { ...part };
|
|
911
|
+
this.updateStreamingMessage();
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
/**
|
|
915
|
+
* Emit a tool-output-error event for a client tool result.
|
|
916
|
+
*/
|
|
917
|
+
emitToolOutputError(toolCallId, error) {
|
|
918
|
+
const state = this.streamingState;
|
|
919
|
+
if (!state) return;
|
|
920
|
+
const toolPartIndex = state.parts.findIndex(
|
|
921
|
+
(p) => p.type === "tool-call" && p.toolCallId === toolCallId
|
|
922
|
+
);
|
|
923
|
+
if (toolPartIndex >= 0) {
|
|
924
|
+
const part = state.parts[toolPartIndex];
|
|
925
|
+
part.error = error;
|
|
926
|
+
part.status = "error";
|
|
927
|
+
state.parts[toolPartIndex] = { ...part };
|
|
928
|
+
this.updateStreamingMessage();
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Continue execution with collected client tool results.
|
|
933
|
+
*/
|
|
934
|
+
async continueWithClientToolResults() {
|
|
935
|
+
if (this._completedToolResults.length === 0) return;
|
|
936
|
+
if (this._pendingExecutionId === null) {
|
|
937
|
+
const errorObj = new OctavusError({
|
|
938
|
+
errorType: "internal_error",
|
|
939
|
+
message: "Cannot continue execution: execution ID was lost.",
|
|
940
|
+
source: "client",
|
|
941
|
+
retryable: false
|
|
942
|
+
});
|
|
943
|
+
this.setError(errorObj);
|
|
944
|
+
this.setStatus("error");
|
|
945
|
+
this.options.onError?.(errorObj);
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
const allResults = [...this._serverToolResults, ...this._completedToolResults];
|
|
949
|
+
const executionId = this._pendingExecutionId;
|
|
950
|
+
this._serverToolResults = [];
|
|
951
|
+
this._completedToolResults = [];
|
|
952
|
+
this._pendingExecutionId = null;
|
|
953
|
+
this.setStatus("streaming");
|
|
954
|
+
try {
|
|
955
|
+
for await (const event of this.transport.continueWithToolResults(executionId, allResults)) {
|
|
956
|
+
if (this.streamingState === null) break;
|
|
957
|
+
this.handleStreamEvent(event, this.streamingState);
|
|
958
|
+
}
|
|
959
|
+
} catch (err) {
|
|
960
|
+
const errorObj = OctavusError.isInstance(err) ? err : new OctavusError({
|
|
961
|
+
errorType: "internal_error",
|
|
962
|
+
message: err instanceof Error ? err.message : "Unknown error",
|
|
963
|
+
source: "client",
|
|
964
|
+
retryable: false,
|
|
965
|
+
cause: err
|
|
966
|
+
});
|
|
967
|
+
this.setError(errorObj);
|
|
968
|
+
this.setStatus("error");
|
|
969
|
+
this.streamingState = null;
|
|
970
|
+
this.options.onError?.(errorObj);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Handle client tool request event.
|
|
975
|
+
*
|
|
976
|
+
* IMPORTANT: Interactive tools must be registered synchronously (before any await)
|
|
977
|
+
* to avoid a race condition where the finish event is processed before tools are added.
|
|
978
|
+
*/
|
|
979
|
+
async handleClientToolRequest(toolCalls, state) {
|
|
980
|
+
this._clientToolAbortController = new AbortController();
|
|
981
|
+
for (const tc of toolCalls) {
|
|
982
|
+
const handler = this.options.clientTools?.[tc.toolName];
|
|
983
|
+
if (handler === "interactive") {
|
|
984
|
+
const toolState = {
|
|
985
|
+
toolCallId: tc.toolCallId,
|
|
986
|
+
toolName: tc.toolName,
|
|
987
|
+
args: tc.args,
|
|
988
|
+
source: tc.source,
|
|
989
|
+
outputVariable: tc.outputVariable,
|
|
990
|
+
blockIndex: tc.blockIndex
|
|
991
|
+
};
|
|
992
|
+
this._pendingToolsByCallId.set(tc.toolCallId, toolState);
|
|
993
|
+
const existing = this._pendingToolsByName.get(tc.toolName) ?? [];
|
|
994
|
+
this._pendingToolsByName.set(tc.toolName, [...existing, toolState]);
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
if (this._pendingToolsByCallId.size > 0) {
|
|
998
|
+
this.updatePendingClientToolsCache();
|
|
999
|
+
}
|
|
1000
|
+
for (const tc of toolCalls) {
|
|
1001
|
+
const handler = this.options.clientTools?.[tc.toolName];
|
|
1002
|
+
if (handler === "interactive") {
|
|
1003
|
+
const toolPartIndex = state.parts.findIndex(
|
|
1004
|
+
(p) => p.type === "tool-call" && p.toolCallId === tc.toolCallId
|
|
1005
|
+
);
|
|
1006
|
+
if (toolPartIndex >= 0) {
|
|
1007
|
+
const part = state.parts[toolPartIndex];
|
|
1008
|
+
state.parts[toolPartIndex] = { ...part };
|
|
1009
|
+
}
|
|
1010
|
+
} else if (handler) {
|
|
1011
|
+
try {
|
|
1012
|
+
const result = await handler(tc.args, {
|
|
1013
|
+
toolCallId: tc.toolCallId,
|
|
1014
|
+
toolName: tc.toolName,
|
|
1015
|
+
signal: this._clientToolAbortController.signal
|
|
1016
|
+
});
|
|
1017
|
+
this._completedToolResults.push({
|
|
1018
|
+
toolCallId: tc.toolCallId,
|
|
1019
|
+
toolName: tc.toolName,
|
|
1020
|
+
result,
|
|
1021
|
+
outputVariable: tc.outputVariable,
|
|
1022
|
+
blockIndex: tc.blockIndex
|
|
1023
|
+
});
|
|
1024
|
+
this.emitToolOutputAvailable(tc.toolCallId, result);
|
|
1025
|
+
} catch (err) {
|
|
1026
|
+
const errorMessage = err instanceof Error ? err.message : "Tool execution failed";
|
|
1027
|
+
this._completedToolResults.push({
|
|
1028
|
+
toolCallId: tc.toolCallId,
|
|
1029
|
+
toolName: tc.toolName,
|
|
1030
|
+
error: errorMessage,
|
|
1031
|
+
outputVariable: tc.outputVariable,
|
|
1032
|
+
blockIndex: tc.blockIndex
|
|
1033
|
+
});
|
|
1034
|
+
this.emitToolOutputError(tc.toolCallId, errorMessage);
|
|
1035
|
+
}
|
|
1036
|
+
} else {
|
|
1037
|
+
const errorMessage = `No client handler for tool: ${tc.toolName}`;
|
|
1038
|
+
this._completedToolResults.push({
|
|
1039
|
+
toolCallId: tc.toolCallId,
|
|
1040
|
+
toolName: tc.toolName,
|
|
1041
|
+
error: errorMessage,
|
|
1042
|
+
outputVariable: tc.outputVariable,
|
|
1043
|
+
blockIndex: tc.blockIndex
|
|
1044
|
+
});
|
|
1045
|
+
this.emitToolOutputError(tc.toolCallId, errorMessage);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
if (this._pendingToolsByCallId.size === 0 && this._completedToolResults.length > 0) {
|
|
1049
|
+
this._readyToContinue = true;
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
736
1052
|
};
|
|
737
1053
|
|
|
738
1054
|
// src/stream/reader.ts
|
|
@@ -793,32 +1109,45 @@ function isSocketTransport(transport) {
|
|
|
793
1109
|
import { isAbortError as isAbortError2 } from "@octavus/core";
|
|
794
1110
|
function createHttpTransport(options) {
|
|
795
1111
|
let abortController = null;
|
|
1112
|
+
async function* streamResponse(responsePromise) {
|
|
1113
|
+
try {
|
|
1114
|
+
const response = await responsePromise;
|
|
1115
|
+
if (!response.ok) {
|
|
1116
|
+
const errorText = await response.text().catch(() => `Request failed: ${response.status}`);
|
|
1117
|
+
throw new Error(errorText);
|
|
1118
|
+
}
|
|
1119
|
+
if (!response.body) {
|
|
1120
|
+
throw new Error("Response body is empty");
|
|
1121
|
+
}
|
|
1122
|
+
for await (const event of parseSSEStream(response, abortController.signal)) {
|
|
1123
|
+
if (abortController?.signal.aborted) {
|
|
1124
|
+
break;
|
|
1125
|
+
}
|
|
1126
|
+
yield event;
|
|
1127
|
+
}
|
|
1128
|
+
} catch (err) {
|
|
1129
|
+
if (isAbortError2(err)) {
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
throw err;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
796
1135
|
return {
|
|
797
1136
|
async *trigger(triggerName, input) {
|
|
798
1137
|
abortController = new AbortController();
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
break;
|
|
813
|
-
}
|
|
814
|
-
yield event;
|
|
815
|
-
}
|
|
816
|
-
} catch (err) {
|
|
817
|
-
if (isAbortError2(err)) {
|
|
818
|
-
return;
|
|
819
|
-
}
|
|
820
|
-
throw err;
|
|
821
|
-
}
|
|
1138
|
+
const response = options.request(
|
|
1139
|
+
{ type: "trigger", triggerName, input },
|
|
1140
|
+
{ signal: abortController.signal }
|
|
1141
|
+
);
|
|
1142
|
+
yield* streamResponse(response);
|
|
1143
|
+
},
|
|
1144
|
+
async *continueWithToolResults(executionId, toolResults) {
|
|
1145
|
+
abortController = new AbortController();
|
|
1146
|
+
const response = options.request(
|
|
1147
|
+
{ type: "continue", executionId, toolResults },
|
|
1148
|
+
{ signal: abortController.signal }
|
|
1149
|
+
);
|
|
1150
|
+
yield* streamResponse(response);
|
|
822
1151
|
},
|
|
823
1152
|
stop() {
|
|
824
1153
|
abortController?.abort();
|
|
@@ -950,6 +1279,7 @@ function createSocketTransport(options) {
|
|
|
950
1279
|
async *trigger(triggerName, input) {
|
|
951
1280
|
await ensureConnected();
|
|
952
1281
|
eventQueue = [];
|
|
1282
|
+
eventResolver = null;
|
|
953
1283
|
isStreaming = true;
|
|
954
1284
|
socket.send(
|
|
955
1285
|
JSON.stringify({
|
|
@@ -974,18 +1304,105 @@ function createSocketTransport(options) {
|
|
|
974
1304
|
eventResolver(null);
|
|
975
1305
|
eventResolver = null;
|
|
976
1306
|
}
|
|
1307
|
+
},
|
|
1308
|
+
/**
|
|
1309
|
+
* Continue execution with tool results after client-side tool handling.
|
|
1310
|
+
* @param executionId - The execution ID from the client-tool-request event
|
|
1311
|
+
* @param toolResults - All tool results (server + client) to send
|
|
1312
|
+
*/
|
|
1313
|
+
async *continueWithToolResults(executionId, toolResults) {
|
|
1314
|
+
await ensureConnected();
|
|
1315
|
+
eventQueue = [];
|
|
1316
|
+
eventResolver = null;
|
|
1317
|
+
isStreaming = true;
|
|
1318
|
+
socket.send(
|
|
1319
|
+
JSON.stringify({
|
|
1320
|
+
type: "continue",
|
|
1321
|
+
executionId,
|
|
1322
|
+
toolResults
|
|
1323
|
+
})
|
|
1324
|
+
);
|
|
1325
|
+
while (true) {
|
|
1326
|
+
const event = await nextEvent();
|
|
1327
|
+
if (event === null) break;
|
|
1328
|
+
yield event;
|
|
1329
|
+
if (event.type === "finish" || event.type === "error") break;
|
|
1330
|
+
}
|
|
977
1331
|
}
|
|
978
1332
|
};
|
|
979
1333
|
}
|
|
980
1334
|
|
|
981
1335
|
// src/index.ts
|
|
982
|
-
|
|
1336
|
+
import {
|
|
1337
|
+
AppError,
|
|
1338
|
+
NotFoundError,
|
|
1339
|
+
ValidationError,
|
|
1340
|
+
ConflictError,
|
|
1341
|
+
ForbiddenError,
|
|
1342
|
+
OctavusError as OctavusError2,
|
|
1343
|
+
isRateLimitError,
|
|
1344
|
+
isAuthenticationError,
|
|
1345
|
+
isProviderError,
|
|
1346
|
+
isToolError,
|
|
1347
|
+
isRetryableError,
|
|
1348
|
+
isValidationError,
|
|
1349
|
+
createErrorEvent,
|
|
1350
|
+
errorToStreamEvent,
|
|
1351
|
+
createInternalErrorEvent,
|
|
1352
|
+
createApiErrorEvent,
|
|
1353
|
+
generateId as generateId2,
|
|
1354
|
+
isAbortError as isAbortError3,
|
|
1355
|
+
MAIN_THREAD,
|
|
1356
|
+
resolveThread,
|
|
1357
|
+
isMainThread,
|
|
1358
|
+
threadForPart as threadForPart2,
|
|
1359
|
+
isOtherThread,
|
|
1360
|
+
isFileReference,
|
|
1361
|
+
isFileReferenceArray as isFileReferenceArray2,
|
|
1362
|
+
safeParseStreamEvent as safeParseStreamEvent3,
|
|
1363
|
+
safeParseUIMessage,
|
|
1364
|
+
safeParseUIMessages,
|
|
1365
|
+
OCTAVUS_SKILL_TOOLS,
|
|
1366
|
+
isOctavusSkillTool,
|
|
1367
|
+
getSkillSlugFromToolCall
|
|
1368
|
+
} from "@octavus/core";
|
|
983
1369
|
export {
|
|
1370
|
+
AppError,
|
|
1371
|
+
ConflictError,
|
|
1372
|
+
ForbiddenError,
|
|
1373
|
+
MAIN_THREAD,
|
|
1374
|
+
NotFoundError,
|
|
1375
|
+
OCTAVUS_SKILL_TOOLS,
|
|
984
1376
|
OctavusChat,
|
|
1377
|
+
OctavusError2 as OctavusError,
|
|
1378
|
+
ValidationError,
|
|
1379
|
+
createApiErrorEvent,
|
|
1380
|
+
createErrorEvent,
|
|
985
1381
|
createHttpTransport,
|
|
1382
|
+
createInternalErrorEvent,
|
|
986
1383
|
createSocketTransport,
|
|
1384
|
+
errorToStreamEvent,
|
|
1385
|
+
generateId2 as generateId,
|
|
1386
|
+
getSkillSlugFromToolCall,
|
|
1387
|
+
isAbortError3 as isAbortError,
|
|
1388
|
+
isAuthenticationError,
|
|
1389
|
+
isFileReference,
|
|
1390
|
+
isFileReferenceArray2 as isFileReferenceArray,
|
|
1391
|
+
isMainThread,
|
|
1392
|
+
isOctavusSkillTool,
|
|
1393
|
+
isOtherThread,
|
|
1394
|
+
isProviderError,
|
|
1395
|
+
isRateLimitError,
|
|
1396
|
+
isRetryableError,
|
|
987
1397
|
isSocketTransport,
|
|
1398
|
+
isToolError,
|
|
1399
|
+
isValidationError,
|
|
988
1400
|
parseSSEStream,
|
|
1401
|
+
resolveThread,
|
|
1402
|
+
safeParseStreamEvent3 as safeParseStreamEvent,
|
|
1403
|
+
safeParseUIMessage,
|
|
1404
|
+
safeParseUIMessages,
|
|
1405
|
+
threadForPart2 as threadForPart,
|
|
989
1406
|
uploadFiles
|
|
990
1407
|
};
|
|
991
1408
|
//# sourceMappingURL=index.js.map
|