@usabledev/usable-chat 1.153.0 → 1.154.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/cli.js +394 -201
- package/package.json +1 -1
package/cli.js
CHANGED
|
@@ -77609,11 +77609,11 @@ var require_randomUUID = __commonJS({
|
|
|
77609
77609
|
var require_dist_cjs31 = __commonJS({
|
|
77610
77610
|
"node_modules/.pnpm/@smithy+uuid@1.1.2/node_modules/@smithy/uuid/dist-cjs/index.js"(exports) {
|
|
77611
77611
|
"use strict";
|
|
77612
|
-
var
|
|
77612
|
+
var randomUUID8 = require_randomUUID();
|
|
77613
77613
|
var decimalToHex = Array.from({ length: 256 }, (_16, i18) => i18.toString(16).padStart(2, "0"));
|
|
77614
77614
|
var v42 = () => {
|
|
77615
|
-
if (
|
|
77616
|
-
return
|
|
77615
|
+
if (randomUUID8.randomUUID) {
|
|
77616
|
+
return randomUUID8.randomUUID();
|
|
77617
77617
|
}
|
|
77618
77618
|
const rnds = new Uint8Array(16);
|
|
77619
77619
|
crypto.getRandomValues(rnds);
|
|
@@ -131517,7 +131517,7 @@ var require_gaxios = __commonJS({
|
|
|
131517
131517
|
var retry_js_1 = require_retry();
|
|
131518
131518
|
var stream_1 = __require("stream");
|
|
131519
131519
|
var interceptor_js_1 = require_interceptor();
|
|
131520
|
-
var
|
|
131520
|
+
var randomUUID8 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
|
|
131521
131521
|
var HTTP_STATUS_NO_CONTENT = 204;
|
|
131522
131522
|
var Gaxios = class {
|
|
131523
131523
|
agentCache = /* @__PURE__ */ new Map();
|
|
@@ -131790,7 +131790,7 @@ var require_gaxios = __commonJS({
|
|
|
131790
131790
|
*/
|
|
131791
131791
|
["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
|
|
131792
131792
|
if (opts.multipart?.length) {
|
|
131793
|
-
const boundary = await
|
|
131793
|
+
const boundary = await randomUUID8();
|
|
131794
131794
|
preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
|
|
131795
131795
|
opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
|
|
131796
131796
|
} else if (shouldDirectlyPassData) {
|
|
@@ -162589,6 +162589,7 @@ async function adaptOpenRouterStream(stream, options2) {
|
|
|
162589
162589
|
let finishReason = null;
|
|
162590
162590
|
const toolCalls = [];
|
|
162591
162591
|
const completedToolCalls = [];
|
|
162592
|
+
const toolExecutionPromises = [];
|
|
162592
162593
|
const toolResults = [];
|
|
162593
162594
|
let capturedUsage;
|
|
162594
162595
|
let capturedModel;
|
|
@@ -162598,6 +162599,188 @@ async function adaptOpenRouterStream(stream, options2) {
|
|
|
162598
162599
|
let lastEmittedReasoning = "";
|
|
162599
162600
|
const accumulatedReasoningDetails = [];
|
|
162600
162601
|
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
162602
|
+
const executeParsedToolCall = async (id, name18, args) => {
|
|
162603
|
+
if (context.abortSignal?.aborted) {
|
|
162604
|
+
streamLogger.info("Abort signal detected before tool execution, returning cancelled result", {
|
|
162605
|
+
toolName: name18
|
|
162606
|
+
});
|
|
162607
|
+
const errorResult = { error: "Request cancelled by user", success: false };
|
|
162608
|
+
toolCalls.push({ toolName: name18, success: false });
|
|
162609
|
+
toolResults.push({ id, name: name18, result: errorResult, isError: true });
|
|
162610
|
+
const errorEvent = emitter.emit("tool-result", {
|
|
162611
|
+
id,
|
|
162612
|
+
toolName: name18,
|
|
162613
|
+
input: args,
|
|
162614
|
+
result: errorResult,
|
|
162615
|
+
success: false,
|
|
162616
|
+
error: errorResult.error
|
|
162617
|
+
});
|
|
162618
|
+
multiplexer.send(errorEvent);
|
|
162619
|
+
return;
|
|
162620
|
+
}
|
|
162621
|
+
streamLogger.debug("Executing tool", { toolName: name18, args });
|
|
162622
|
+
try {
|
|
162623
|
+
const toolResult = await executeTool3(name18, args, {
|
|
162624
|
+
...context,
|
|
162625
|
+
toolCallId: id
|
|
162626
|
+
});
|
|
162627
|
+
const success2 = !toolResult?.error;
|
|
162628
|
+
toolCalls.push({ toolName: name18, success: success2 });
|
|
162629
|
+
toolResults.push({ id, name: name18, result: toolResult, isError: !success2 });
|
|
162630
|
+
if (context.session) {
|
|
162631
|
+
if (!context.session.toolHistory) {
|
|
162632
|
+
context.session.toolHistory = [];
|
|
162633
|
+
}
|
|
162634
|
+
const toolHistory = context.session.toolHistory;
|
|
162635
|
+
toolHistory.push({
|
|
162636
|
+
toolName: name18,
|
|
162637
|
+
args,
|
|
162638
|
+
result: toolResult,
|
|
162639
|
+
success: success2,
|
|
162640
|
+
timestamp: Date.now()
|
|
162641
|
+
});
|
|
162642
|
+
if (toolHistory.length > 50) {
|
|
162643
|
+
toolHistory.shift();
|
|
162644
|
+
}
|
|
162645
|
+
}
|
|
162646
|
+
const toolResultEvent = emitter.emit("tool-result", {
|
|
162647
|
+
id,
|
|
162648
|
+
toolName: name18,
|
|
162649
|
+
input: args,
|
|
162650
|
+
result: toolResult,
|
|
162651
|
+
success: success2,
|
|
162652
|
+
error: toolResult?.error ? String(toolResult.error) : void 0
|
|
162653
|
+
});
|
|
162654
|
+
multiplexer.send(toolResultEvent);
|
|
162655
|
+
if (name18 === "check-context-window" && success2 && toolResult?.data) {
|
|
162656
|
+
const data2 = toolResult.data;
|
|
162657
|
+
const breakdown = data2.breakdown.systemPrompt !== void 0 ? {
|
|
162658
|
+
systemPrompts: data2.breakdown.systemPrompt + (data2.breakdown.systemTools || 0),
|
|
162659
|
+
contextTokens: data2.breakdown.memoryFiles || 0,
|
|
162660
|
+
toolCallsAndResponses: data2.breakdown.toolUseAndResults || 0,
|
|
162661
|
+
userQuestions: 0,
|
|
162662
|
+
assistantMessages: data2.breakdown.messages || 0
|
|
162663
|
+
} : data2.breakdown;
|
|
162664
|
+
const cardEvent = emitter.emit("card", {
|
|
162665
|
+
component: "context-window",
|
|
162666
|
+
data: {
|
|
162667
|
+
totalTokens: data2.totalTokens,
|
|
162668
|
+
maxTokens: data2.maxTokens,
|
|
162669
|
+
percentage: data2.percentage,
|
|
162670
|
+
breakdown,
|
|
162671
|
+
freeSpace: data2.freeSpace,
|
|
162672
|
+
contextItems: data2.contextItems || {
|
|
162673
|
+
workspaces: 0,
|
|
162674
|
+
fragments: 0,
|
|
162675
|
+
toolResults: 0
|
|
162676
|
+
}
|
|
162677
|
+
}
|
|
162678
|
+
});
|
|
162679
|
+
multiplexer.send(cardEvent);
|
|
162680
|
+
}
|
|
162681
|
+
if (isAskQuestionPause(toolResult)) {
|
|
162682
|
+
pauseDetected = true;
|
|
162683
|
+
if (onPauseDetected) {
|
|
162684
|
+
await onPauseDetected({
|
|
162685
|
+
resumeToken: toolResult.__pause.resumeToken,
|
|
162686
|
+
questions: toolResult.__pause.questions,
|
|
162687
|
+
context: toolResult.__pause.context
|
|
162688
|
+
});
|
|
162689
|
+
}
|
|
162690
|
+
return;
|
|
162691
|
+
}
|
|
162692
|
+
if (toolResult?.__parentToolCall === true) {
|
|
162693
|
+
const parentToolName = toolResult.toolName;
|
|
162694
|
+
const parentToolArgs = toolResult.args;
|
|
162695
|
+
const requestId = `parent_${id}_${Date.now()}`;
|
|
162696
|
+
streamLogger.info("Parent tool call detected - waiting for parent response", {
|
|
162697
|
+
toolName: name18,
|
|
162698
|
+
parentToolName,
|
|
162699
|
+
requestId
|
|
162700
|
+
});
|
|
162701
|
+
const parentToolEvent = emitter.emit("parent-tool-call", {
|
|
162702
|
+
requestId,
|
|
162703
|
+
toolName: parentToolName,
|
|
162704
|
+
args: parentToolArgs
|
|
162705
|
+
});
|
|
162706
|
+
multiplexer.send(parentToolEvent);
|
|
162707
|
+
try {
|
|
162708
|
+
const parentResponse = await waitForParentToolResponse(
|
|
162709
|
+
requestId,
|
|
162710
|
+
parentToolName,
|
|
162711
|
+
parentToolArgs,
|
|
162712
|
+
3e4
|
|
162713
|
+
);
|
|
162714
|
+
streamLogger.info("Parent tool response received", {
|
|
162715
|
+
requestId,
|
|
162716
|
+
parentToolName,
|
|
162717
|
+
hasResult: parentResponse !== void 0
|
|
162718
|
+
});
|
|
162719
|
+
const resultIndex = toolResults.findIndex((r17) => r17.id === id);
|
|
162720
|
+
if (resultIndex !== -1) {
|
|
162721
|
+
toolResults[resultIndex].result = parentResponse;
|
|
162722
|
+
}
|
|
162723
|
+
const updatedResultEvent = emitter.emit("tool-result", {
|
|
162724
|
+
id,
|
|
162725
|
+
toolName: name18,
|
|
162726
|
+
input: args,
|
|
162727
|
+
result: parentResponse,
|
|
162728
|
+
success: true
|
|
162729
|
+
});
|
|
162730
|
+
multiplexer.send(updatedResultEvent);
|
|
162731
|
+
} catch (parentError) {
|
|
162732
|
+
streamLogger.error("Parent tool call failed", {
|
|
162733
|
+
requestId,
|
|
162734
|
+
parentToolName,
|
|
162735
|
+
error: parentError instanceof Error ? parentError.message : String(parentError)
|
|
162736
|
+
});
|
|
162737
|
+
const errorResult = {
|
|
162738
|
+
error: parentError instanceof Error ? parentError.message : String(parentError),
|
|
162739
|
+
success: false
|
|
162740
|
+
};
|
|
162741
|
+
const resultIndex = toolResults.findIndex((r17) => r17.id === id);
|
|
162742
|
+
if (resultIndex !== -1) {
|
|
162743
|
+
toolResults[resultIndex].result = errorResult;
|
|
162744
|
+
toolResults[resultIndex].isError = true;
|
|
162745
|
+
}
|
|
162746
|
+
const errorEvent = emitter.emit("tool-result", {
|
|
162747
|
+
id,
|
|
162748
|
+
toolName: name18,
|
|
162749
|
+
input: args,
|
|
162750
|
+
result: errorResult,
|
|
162751
|
+
success: false,
|
|
162752
|
+
error: parentError instanceof Error ? parentError.message : String(parentError)
|
|
162753
|
+
});
|
|
162754
|
+
multiplexer.send(errorEvent);
|
|
162755
|
+
}
|
|
162756
|
+
}
|
|
162757
|
+
if (emitObservations && success2) {
|
|
162758
|
+
const observation = generateObservation2(name18, toolResult);
|
|
162759
|
+
const observationEvent = emitter.emit("observation", {
|
|
162760
|
+
observation,
|
|
162761
|
+
toolCallIds: [id]
|
|
162762
|
+
});
|
|
162763
|
+
multiplexer.send(observationEvent);
|
|
162764
|
+
}
|
|
162765
|
+
} catch (toolError) {
|
|
162766
|
+
console.error(`\u274C Tool execution error for ${name18}:`, toolError);
|
|
162767
|
+
toolCalls.push({ toolName: name18, success: false });
|
|
162768
|
+
const errorResult = {
|
|
162769
|
+
error: toolError instanceof Error ? toolError.message : String(toolError),
|
|
162770
|
+
success: false
|
|
162771
|
+
};
|
|
162772
|
+
toolResults.push({ id, name: name18, result: errorResult, isError: true });
|
|
162773
|
+
const errorEvent = emitter.emit("tool-result", {
|
|
162774
|
+
id,
|
|
162775
|
+
toolName: name18,
|
|
162776
|
+
input: args,
|
|
162777
|
+
result: null,
|
|
162778
|
+
success: false,
|
|
162779
|
+
error: toolError instanceof Error ? toolError.message : String(toolError)
|
|
162780
|
+
});
|
|
162781
|
+
multiplexer.send(errorEvent);
|
|
162782
|
+
}
|
|
162783
|
+
};
|
|
162601
162784
|
try {
|
|
162602
162785
|
while (true) {
|
|
162603
162786
|
if (context.abortSignal?.aborted) {
|
|
@@ -162855,187 +163038,9 @@ async function adaptOpenRouterStream(stream, options2) {
|
|
|
162855
163038
|
});
|
|
162856
163039
|
multiplexer.send(retrievalEvent);
|
|
162857
163040
|
}
|
|
162858
|
-
|
|
162859
|
-
|
|
162860
|
-
|
|
162861
|
-
});
|
|
162862
|
-
break;
|
|
162863
|
-
}
|
|
162864
|
-
streamLogger.debug("Executing tool", {
|
|
162865
|
-
toolName: pending.name,
|
|
162866
|
-
args
|
|
162867
|
-
});
|
|
162868
|
-
try {
|
|
162869
|
-
const toolResult = await executeTool3(pending.name, args, { ...context, toolCallId: pending.id });
|
|
162870
|
-
const success2 = !toolResult?.error;
|
|
162871
|
-
toolCalls.push({ toolName: pending.name, success: success2 });
|
|
162872
|
-
toolResults.push({
|
|
162873
|
-
id: pending.id,
|
|
162874
|
-
name: pending.name,
|
|
162875
|
-
result: toolResult,
|
|
162876
|
-
isError: !success2
|
|
162877
|
-
});
|
|
162878
|
-
if (context.session) {
|
|
162879
|
-
if (!context.session.toolHistory) {
|
|
162880
|
-
context.session.toolHistory = [];
|
|
162881
|
-
}
|
|
162882
|
-
const toolHistory = context.session.toolHistory;
|
|
162883
|
-
toolHistory.push({
|
|
162884
|
-
toolName: pending.name,
|
|
162885
|
-
args,
|
|
162886
|
-
result: toolResult,
|
|
162887
|
-
success: success2,
|
|
162888
|
-
timestamp: Date.now()
|
|
162889
|
-
});
|
|
162890
|
-
if (toolHistory.length > 50) {
|
|
162891
|
-
toolHistory.shift();
|
|
162892
|
-
}
|
|
162893
|
-
}
|
|
162894
|
-
const toolResultEvent = emitter.emit("tool-result", {
|
|
162895
|
-
id: pending.id,
|
|
162896
|
-
toolName: pending.name,
|
|
162897
|
-
input: args,
|
|
162898
|
-
// Include input arguments
|
|
162899
|
-
result: toolResult,
|
|
162900
|
-
success: success2,
|
|
162901
|
-
error: toolResult?.error ? String(toolResult.error) : void 0
|
|
162902
|
-
});
|
|
162903
|
-
multiplexer.send(toolResultEvent);
|
|
162904
|
-
if (pending.name === "check-context-window" && success2 && toolResult?.data) {
|
|
162905
|
-
const data2 = toolResult.data;
|
|
162906
|
-
const breakdown = data2.breakdown.systemPrompt !== void 0 ? {
|
|
162907
|
-
// New format - map to old format
|
|
162908
|
-
systemPrompts: data2.breakdown.systemPrompt + (data2.breakdown.systemTools || 0),
|
|
162909
|
-
contextTokens: data2.breakdown.memoryFiles || 0,
|
|
162910
|
-
toolCallsAndResponses: data2.breakdown.toolUseAndResults || 0,
|
|
162911
|
-
userQuestions: 0,
|
|
162912
|
-
// Will be calculated from messages
|
|
162913
|
-
assistantMessages: data2.breakdown.messages || 0
|
|
162914
|
-
} : data2.breakdown;
|
|
162915
|
-
const cardEvent = emitter.emit("card", {
|
|
162916
|
-
component: "context-window",
|
|
162917
|
-
data: {
|
|
162918
|
-
totalTokens: data2.totalTokens,
|
|
162919
|
-
maxTokens: data2.maxTokens,
|
|
162920
|
-
percentage: data2.percentage,
|
|
162921
|
-
breakdown,
|
|
162922
|
-
freeSpace: data2.freeSpace,
|
|
162923
|
-
contextItems: data2.contextItems || {
|
|
162924
|
-
workspaces: 0,
|
|
162925
|
-
fragments: 0,
|
|
162926
|
-
toolResults: 0
|
|
162927
|
-
}
|
|
162928
|
-
}
|
|
162929
|
-
});
|
|
162930
|
-
multiplexer.send(cardEvent);
|
|
162931
|
-
}
|
|
162932
|
-
if (isAskQuestionPause(toolResult)) {
|
|
162933
|
-
pauseDetected = true;
|
|
162934
|
-
if (onPauseDetected) {
|
|
162935
|
-
await onPauseDetected({
|
|
162936
|
-
resumeToken: toolResult.__pause.resumeToken,
|
|
162937
|
-
questions: toolResult.__pause.questions,
|
|
162938
|
-
context: toolResult.__pause.context
|
|
162939
|
-
});
|
|
162940
|
-
}
|
|
162941
|
-
break;
|
|
162942
|
-
}
|
|
162943
|
-
if (toolResult?.__parentToolCall === true) {
|
|
162944
|
-
const parentToolName = toolResult.toolName;
|
|
162945
|
-
const parentToolArgs = toolResult.args;
|
|
162946
|
-
const requestId = `parent_${pending.id}_${Date.now()}`;
|
|
162947
|
-
streamLogger.info("Parent tool call detected - waiting for parent response", {
|
|
162948
|
-
toolName: pending.name,
|
|
162949
|
-
parentToolName,
|
|
162950
|
-
requestId
|
|
162951
|
-
});
|
|
162952
|
-
const parentToolEvent = emitter.emit("parent-tool-call", {
|
|
162953
|
-
requestId,
|
|
162954
|
-
toolName: parentToolName,
|
|
162955
|
-
args: parentToolArgs
|
|
162956
|
-
});
|
|
162957
|
-
multiplexer.send(parentToolEvent);
|
|
162958
|
-
try {
|
|
162959
|
-
const parentResponse = await waitForParentToolResponse(
|
|
162960
|
-
requestId,
|
|
162961
|
-
parentToolName,
|
|
162962
|
-
parentToolArgs,
|
|
162963
|
-
3e4
|
|
162964
|
-
// 30 second timeout
|
|
162965
|
-
);
|
|
162966
|
-
streamLogger.info("Parent tool response received", {
|
|
162967
|
-
requestId,
|
|
162968
|
-
parentToolName,
|
|
162969
|
-
hasResult: parentResponse !== void 0
|
|
162970
|
-
});
|
|
162971
|
-
const resultIndex = toolResults.findIndex((r17) => r17.id === pending.id);
|
|
162972
|
-
if (resultIndex !== -1) {
|
|
162973
|
-
toolResults[resultIndex].result = parentResponse;
|
|
162974
|
-
}
|
|
162975
|
-
const updatedResultEvent = emitter.emit("tool-result", {
|
|
162976
|
-
id: pending.id,
|
|
162977
|
-
toolName: pending.name,
|
|
162978
|
-
input: args,
|
|
162979
|
-
result: parentResponse,
|
|
162980
|
-
success: true
|
|
162981
|
-
});
|
|
162982
|
-
multiplexer.send(updatedResultEvent);
|
|
162983
|
-
} catch (parentError) {
|
|
162984
|
-
streamLogger.error("Parent tool call failed", {
|
|
162985
|
-
requestId,
|
|
162986
|
-
parentToolName,
|
|
162987
|
-
error: parentError instanceof Error ? parentError.message : String(parentError)
|
|
162988
|
-
});
|
|
162989
|
-
const errorResult = {
|
|
162990
|
-
error: parentError instanceof Error ? parentError.message : String(parentError),
|
|
162991
|
-
success: false
|
|
162992
|
-
};
|
|
162993
|
-
const resultIndex = toolResults.findIndex((r17) => r17.id === pending.id);
|
|
162994
|
-
if (resultIndex !== -1) {
|
|
162995
|
-
toolResults[resultIndex].result = errorResult;
|
|
162996
|
-
toolResults[resultIndex].isError = true;
|
|
162997
|
-
}
|
|
162998
|
-
const errorEvent = emitter.emit("tool-result", {
|
|
162999
|
-
id: pending.id,
|
|
163000
|
-
toolName: pending.name,
|
|
163001
|
-
input: args,
|
|
163002
|
-
result: errorResult,
|
|
163003
|
-
success: false,
|
|
163004
|
-
error: parentError instanceof Error ? parentError.message : String(parentError)
|
|
163005
|
-
});
|
|
163006
|
-
multiplexer.send(errorEvent);
|
|
163007
|
-
}
|
|
163008
|
-
}
|
|
163009
|
-
if (emitObservations && success2) {
|
|
163010
|
-
const observation = generateObservation2(pending.name, toolResult);
|
|
163011
|
-
const observationEvent = emitter.emit("observation", {
|
|
163012
|
-
observation,
|
|
163013
|
-
toolCallIds: [pending.id]
|
|
163014
|
-
});
|
|
163015
|
-
multiplexer.send(observationEvent);
|
|
163016
|
-
}
|
|
163017
|
-
} catch (toolError) {
|
|
163018
|
-
console.error(`\u274C Tool execution error for ${pending.name}:`, toolError);
|
|
163019
|
-
toolCalls.push({ toolName: pending.name, success: false });
|
|
163020
|
-
const errorResult = {
|
|
163021
|
-
error: toolError instanceof Error ? toolError.message : String(toolError),
|
|
163022
|
-
success: false
|
|
163023
|
-
};
|
|
163024
|
-
toolResults.push({
|
|
163025
|
-
id: pending.id,
|
|
163026
|
-
name: pending.name,
|
|
163027
|
-
result: errorResult,
|
|
163028
|
-
isError: true
|
|
163029
|
-
});
|
|
163030
|
-
const errorEvent = emitter.emit("tool-result", {
|
|
163031
|
-
id: pending.id,
|
|
163032
|
-
toolName: pending.name,
|
|
163033
|
-
result: null,
|
|
163034
|
-
success: false,
|
|
163035
|
-
error: toolError instanceof Error ? toolError.message : String(toolError)
|
|
163036
|
-
});
|
|
163037
|
-
multiplexer.send(errorEvent);
|
|
163038
|
-
}
|
|
163041
|
+
toolExecutionPromises.push(
|
|
163042
|
+
executeParsedToolCall(pending.id, pending.name, args)
|
|
163043
|
+
);
|
|
163039
163044
|
pendingToolCalls.delete(index2);
|
|
163040
163045
|
} catch {
|
|
163041
163046
|
}
|
|
@@ -163048,6 +163053,13 @@ async function adaptOpenRouterStream(stream, options2) {
|
|
|
163048
163053
|
finishReason: finish_reason,
|
|
163049
163054
|
hasUsage: !!capturedUsage
|
|
163050
163055
|
});
|
|
163056
|
+
if (finish_reason === "tool_calls" && toolExecutionPromises.length > 0) {
|
|
163057
|
+
streamLogger.debug("Waiting for OpenRouter tool executions", {
|
|
163058
|
+
toolCount: toolExecutionPromises.length
|
|
163059
|
+
});
|
|
163060
|
+
await Promise.allSettled(toolExecutionPromises);
|
|
163061
|
+
toolExecutionPromises.length = 0;
|
|
163062
|
+
}
|
|
163051
163063
|
if (finish_reason !== "tool_calls" && !summaryEmitted) {
|
|
163052
163064
|
if (capturedUsage && (capturedUsage.completion_tokens ?? 0) > 0) {
|
|
163053
163065
|
const usageData = {
|
|
@@ -163082,6 +163094,13 @@ async function adaptOpenRouterStream(stream, options2) {
|
|
|
163082
163094
|
}
|
|
163083
163095
|
}
|
|
163084
163096
|
}
|
|
163097
|
+
if (toolExecutionPromises.length > 0) {
|
|
163098
|
+
streamLogger.debug("Waiting for pending OpenRouter tool executions after stream end", {
|
|
163099
|
+
toolCount: toolExecutionPromises.length
|
|
163100
|
+
});
|
|
163101
|
+
await Promise.allSettled(toolExecutionPromises);
|
|
163102
|
+
toolExecutionPromises.length = 0;
|
|
163103
|
+
}
|
|
163085
163104
|
if (finishReason && !summaryEmitted && finishReason !== "tool_calls") {
|
|
163086
163105
|
streamLogger.warn("Stream ended without usage chunk - emitting summary without usage", {
|
|
163087
163106
|
finishReason
|
|
@@ -254228,6 +254247,7 @@ var init_skills3 = __esm({
|
|
|
254228
254247
|
// src/adapters/cli/subagent.ts
|
|
254229
254248
|
import { spawn as spawn5 } from "node:child_process";
|
|
254230
254249
|
import { basename as basename8 } from "node:path";
|
|
254250
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
254231
254251
|
function currentSubagentDepth() {
|
|
254232
254252
|
const d21 = Number(process.env.USABLE_SUBAGENT_DEPTH ?? 0);
|
|
254233
254253
|
return Number.isFinite(d21) && d21 > 0 ? Math.floor(d21) : 0;
|
|
@@ -254312,11 +254332,73 @@ async function runCliSubagent(input) {
|
|
|
254312
254332
|
}
|
|
254313
254333
|
return { ok: true, text: res.out.trim() };
|
|
254314
254334
|
}
|
|
254335
|
+
function publicTask(task) {
|
|
254336
|
+
return {
|
|
254337
|
+
taskId: task.taskId,
|
|
254338
|
+
status: task.status,
|
|
254339
|
+
prompt: task.prompt,
|
|
254340
|
+
model: task.model,
|
|
254341
|
+
cwd: task.cwd,
|
|
254342
|
+
startedAt: task.startedAt,
|
|
254343
|
+
completedAt: task.completedAt,
|
|
254344
|
+
...task.text ? { text: task.text } : {},
|
|
254345
|
+
...task.error ? { error: task.error } : {}
|
|
254346
|
+
};
|
|
254347
|
+
}
|
|
254348
|
+
function startCliSubagentTask(input) {
|
|
254349
|
+
const taskId = input.taskId ?? randomUUID6();
|
|
254350
|
+
const abortController = new AbortController();
|
|
254351
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
254352
|
+
const run2 = input._run ?? runCliSubagent;
|
|
254353
|
+
const onParentAbort = () => abortController.abort();
|
|
254354
|
+
input.parentAbortSignal?.addEventListener("abort", onParentAbort, { once: true });
|
|
254355
|
+
const task = {
|
|
254356
|
+
taskId,
|
|
254357
|
+
prompt: input.prompt,
|
|
254358
|
+
model: input.model,
|
|
254359
|
+
cwd: input.cwd,
|
|
254360
|
+
status: "running",
|
|
254361
|
+
startedAt,
|
|
254362
|
+
abortController,
|
|
254363
|
+
promise: Promise.resolve(void 0)
|
|
254364
|
+
};
|
|
254365
|
+
task.promise = (async () => {
|
|
254366
|
+
try {
|
|
254367
|
+
const res = await run2({
|
|
254368
|
+
prompt: input.prompt,
|
|
254369
|
+
model: input.model,
|
|
254370
|
+
cwd: input.cwd,
|
|
254371
|
+
abortSignal: abortController.signal,
|
|
254372
|
+
timeoutMs: input.timeoutMs
|
|
254373
|
+
});
|
|
254374
|
+
task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
254375
|
+
if (abortController.signal.aborted) {
|
|
254376
|
+
task.status = "cancelled";
|
|
254377
|
+
task.error = "subagent cancelled";
|
|
254378
|
+
} else if (res.ok) {
|
|
254379
|
+
task.status = "completed";
|
|
254380
|
+
task.text = res.text;
|
|
254381
|
+
} else {
|
|
254382
|
+
task.status = "failed";
|
|
254383
|
+
task.text = res.text;
|
|
254384
|
+
task.error = res.error ?? "subagent failed";
|
|
254385
|
+
}
|
|
254386
|
+
} catch (err) {
|
|
254387
|
+
task.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
254388
|
+
task.status = abortController.signal.aborted ? "cancelled" : "failed";
|
|
254389
|
+
task.error = err instanceof Error ? err.message : String(err);
|
|
254390
|
+
} finally {
|
|
254391
|
+
input.parentAbortSignal?.removeEventListener("abort", onParentAbort);
|
|
254392
|
+
}
|
|
254393
|
+
return task;
|
|
254394
|
+
})();
|
|
254395
|
+
cliSubagentTasks.set(taskId, task);
|
|
254396
|
+
return task;
|
|
254397
|
+
}
|
|
254315
254398
|
function buildCliSubagentTool(opts) {
|
|
254316
|
-
const run2 = opts._run ?? runCliSubagent;
|
|
254317
254399
|
return {
|
|
254318
254400
|
spawn_subagent: {
|
|
254319
|
-
description:
|
|
254401
|
+
description: ASYNC_SPAWN_DESCRIPTION,
|
|
254320
254402
|
parameters: {
|
|
254321
254403
|
type: "object",
|
|
254322
254404
|
properties: {
|
|
@@ -254335,31 +254417,89 @@ function buildCliSubagentTool(opts) {
|
|
|
254335
254417
|
const prompt = String(args.prompt ?? "").trim();
|
|
254336
254418
|
if (!prompt) return { error: "prompt is required" };
|
|
254337
254419
|
const model = typeof args.model === "string" && args.model.trim() ? args.model.trim() : opts.model;
|
|
254338
|
-
const
|
|
254420
|
+
const task = startCliSubagentTask({
|
|
254421
|
+
taskId: typeof args.taskId === "string" && args.taskId.trim() ? args.taskId.trim() : void 0,
|
|
254339
254422
|
prompt,
|
|
254340
254423
|
model,
|
|
254341
254424
|
cwd: process.cwd(),
|
|
254342
|
-
|
|
254425
|
+
parentAbortSignal: opts.abortSignal,
|
|
254426
|
+
_run: opts._run
|
|
254343
254427
|
});
|
|
254344
|
-
|
|
254345
|
-
|
|
254428
|
+
return publicTask(task);
|
|
254429
|
+
}
|
|
254430
|
+
},
|
|
254431
|
+
list_subagents: {
|
|
254432
|
+
description: "List background CLI subagents in this process. Use this before awaiting when you need task ids or status.",
|
|
254433
|
+
parameters: {
|
|
254434
|
+
type: "object",
|
|
254435
|
+
properties: {
|
|
254436
|
+
includeFinished: {
|
|
254437
|
+
type: "boolean",
|
|
254438
|
+
description: "Include completed, failed, and cancelled tasks. Defaults to true."
|
|
254439
|
+
}
|
|
254440
|
+
}
|
|
254441
|
+
},
|
|
254442
|
+
execute: async (args) => {
|
|
254443
|
+
const includeFinished = args.includeFinished !== false;
|
|
254444
|
+
const tasks = [...cliSubagentTasks.values()].filter(
|
|
254445
|
+
(task) => includeFinished || task.status === "running"
|
|
254446
|
+
);
|
|
254447
|
+
return { tasks: tasks.map(publicTask) };
|
|
254448
|
+
}
|
|
254449
|
+
},
|
|
254450
|
+
await_subagents: {
|
|
254451
|
+
description: "Wait for one or more background CLI subagents and collect their results. Omit taskIds to wait for all running tasks.",
|
|
254452
|
+
parameters: {
|
|
254453
|
+
type: "object",
|
|
254454
|
+
properties: {
|
|
254455
|
+
taskIds: {
|
|
254456
|
+
type: "array",
|
|
254457
|
+
items: { type: "string" },
|
|
254458
|
+
description: "Specific task ids to wait for. Defaults to all running tasks."
|
|
254459
|
+
},
|
|
254460
|
+
timeout: {
|
|
254461
|
+
type: "number",
|
|
254462
|
+
description: "Maximum seconds to wait. Defaults to 300."
|
|
254463
|
+
}
|
|
254346
254464
|
}
|
|
254347
|
-
|
|
254465
|
+
},
|
|
254466
|
+
execute: async (args) => {
|
|
254467
|
+
const ids = Array.isArray(args.taskIds) ? args.taskIds.filter((id) => typeof id === "string" && id.length > 0) : [...cliSubagentTasks.values()].filter((task) => task.status === "running").map((task) => task.taskId);
|
|
254468
|
+
const tasks = ids.map((id) => cliSubagentTasks.get(id));
|
|
254469
|
+
const missing = ids.filter((id, index2) => !tasks[index2]);
|
|
254470
|
+
const existing = tasks.filter((task) => !!task);
|
|
254471
|
+
if (missing.length > 0) return { error: `Unknown subagent task id(s): ${missing.join(", ")}` };
|
|
254472
|
+
if (existing.length === 0) return { results: [] };
|
|
254473
|
+
const timeoutS = typeof args.timeout === "number" && Number.isFinite(args.timeout) ? Math.max(1, args.timeout) : 300;
|
|
254474
|
+
const timeout = new Promise(
|
|
254475
|
+
(resolve8) => setTimeout(() => resolve8("timeout"), timeoutS * 1e3)
|
|
254476
|
+
);
|
|
254477
|
+
const settled = await Promise.race([
|
|
254478
|
+
Promise.all(existing.map((task) => task.promise)),
|
|
254479
|
+
timeout
|
|
254480
|
+
]);
|
|
254481
|
+
if (settled === "timeout") {
|
|
254482
|
+
return {
|
|
254483
|
+
error: `Timed out waiting for subagents after ${timeoutS}s`,
|
|
254484
|
+
pending: existing.filter((task) => task.status === "running").map(publicTask),
|
|
254485
|
+
results: existing.filter((task) => task.status !== "running").map(publicTask)
|
|
254486
|
+
};
|
|
254487
|
+
}
|
|
254488
|
+
return { results: settled.map(publicTask) };
|
|
254348
254489
|
}
|
|
254349
254490
|
}
|
|
254350
254491
|
};
|
|
254351
254492
|
}
|
|
254352
|
-
var SUBAGENT_TIMEOUT_MS, SUBAGENT_MAX_DEPTH,
|
|
254493
|
+
var SUBAGENT_TIMEOUT_MS, SUBAGENT_MAX_DEPTH, cliSubagentTasks, ASYNC_SPAWN_DESCRIPTION;
|
|
254353
254494
|
var init_subagent = __esm({
|
|
254354
254495
|
"src/adapters/cli/subagent.ts"() {
|
|
254355
254496
|
"use strict";
|
|
254356
254497
|
SUBAGENT_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
254357
254498
|
SUBAGENT_MAX_DEPTH = 2;
|
|
254358
|
-
|
|
254499
|
+
cliSubagentTasks = /* @__PURE__ */ new Map();
|
|
254500
|
+
ASYNC_SPAWN_DESCRIPTION = `Start a background subagent for a self-contained task and return immediately.
|
|
254359
254501
|
|
|
254360
|
-
The
|
|
254361
|
-
|
|
254362
|
-
Give it a complete, standalone \`prompt\` (it does not see your conversation). Keep tasks focused; it can read/run things on the user's machine.`;
|
|
254502
|
+
The task runs in this CLI process. Use list_subagents to inspect status and await_subagents to collect results. The subagent is a fresh \`usable-chat\` agent running in the current working directory, with the same provider/config and local tools.`;
|
|
254363
254503
|
}
|
|
254364
254504
|
});
|
|
254365
254505
|
|
|
@@ -269627,7 +269767,7 @@ var init_tui_markdown = __esm({
|
|
|
269627
269767
|
// src/cli/warp-agent.ts
|
|
269628
269768
|
import { openSync, writeSync } from "node:fs";
|
|
269629
269769
|
import { basename as basename9 } from "node:path";
|
|
269630
|
-
import { randomUUID as
|
|
269770
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
269631
269771
|
function isWarpAgentHost() {
|
|
269632
269772
|
return !!process.env.WARP_CLI_AGENT_PROTOCOL_VERSION && process.platform !== "win32";
|
|
269633
269773
|
}
|
|
@@ -269680,7 +269820,7 @@ var init_warp_agent = __esm({
|
|
|
269680
269820
|
"use strict";
|
|
269681
269821
|
WARP_AGENT_SLUG = "usable-chat";
|
|
269682
269822
|
APP_NAME = "usable-chat";
|
|
269683
|
-
sessionId =
|
|
269823
|
+
sessionId = randomUUID7();
|
|
269684
269824
|
}
|
|
269685
269825
|
});
|
|
269686
269826
|
|
|
@@ -269793,6 +269933,7 @@ async function launchTui(options2) {
|
|
|
269793
269933
|
const ui2 = new TUI(terminal);
|
|
269794
269934
|
const editor = new Editor(ui2, editorTheme, { paddingX: 1 });
|
|
269795
269935
|
editor.focused = true;
|
|
269936
|
+
const bangTools = createLocalTools();
|
|
269796
269937
|
let items = [...initialHistory];
|
|
269797
269938
|
let compactedPrefix = [];
|
|
269798
269939
|
let busy = false;
|
|
@@ -269803,6 +269944,7 @@ async function launchTui(options2) {
|
|
|
269803
269944
|
let exitArmed = false;
|
|
269804
269945
|
let toolsExpanded = false;
|
|
269805
269946
|
let abort = null;
|
|
269947
|
+
let lastBangCommand = null;
|
|
269806
269948
|
const extStatus = /* @__PURE__ */ new Map();
|
|
269807
269949
|
let picker = null;
|
|
269808
269950
|
const rebuildPicker = () => {
|
|
@@ -270056,6 +270198,56 @@ Edit it, then /verify-extension ${arg.trim()} to check it loads, /trust (project
|
|
|
270056
270198
|
async function submit(raw) {
|
|
270057
270199
|
const value = raw.trim();
|
|
270058
270200
|
if (!value || busy) return;
|
|
270201
|
+
if (value === "!!" || value.startsWith("!") && !value.startsWith("/")) {
|
|
270202
|
+
const command = value === "!!" ? lastBangCommand : value.slice(1).trim();
|
|
270203
|
+
if (!command) {
|
|
270204
|
+
sys(value === "!!" ? "No previous shell command." : "Usage: ! <command>", "error");
|
|
270205
|
+
return;
|
|
270206
|
+
}
|
|
270207
|
+
lastBangCommand = command;
|
|
270208
|
+
busy = true;
|
|
270209
|
+
push({ kind: "user", text: `! ${command}` });
|
|
270210
|
+
const toolId = `bang-${Date.now()}`;
|
|
270211
|
+
push({
|
|
270212
|
+
kind: "tool",
|
|
270213
|
+
id: toolId,
|
|
270214
|
+
name: "bash",
|
|
270215
|
+
args: short(JSON.stringify({ command })),
|
|
270216
|
+
argsFull: prettyJson({ command }),
|
|
270217
|
+
status: "running"
|
|
270218
|
+
});
|
|
270219
|
+
ui2.requestRender();
|
|
270220
|
+
try {
|
|
270221
|
+
const result = await bangTools.bash.execute({ command });
|
|
270222
|
+
const error41 = result && typeof result === "object" && "error" in result ? String(result.error) : void 0;
|
|
270223
|
+
items = items.map(
|
|
270224
|
+
(it7) => it7.kind === "tool" && it7.id === toolId ? {
|
|
270225
|
+
...it7,
|
|
270226
|
+
status: error41 ? "error" : "done",
|
|
270227
|
+
result: error41 ? void 0 : previewValue(result),
|
|
270228
|
+
error: error41
|
|
270229
|
+
} : it7
|
|
270230
|
+
);
|
|
270231
|
+
} catch (err) {
|
|
270232
|
+
items = items.map(
|
|
270233
|
+
(it7) => it7.kind === "tool" && it7.id === toolId ? {
|
|
270234
|
+
...it7,
|
|
270235
|
+
status: "error",
|
|
270236
|
+
error: err instanceof Error ? err.message : String(err)
|
|
270237
|
+
} : it7
|
|
270238
|
+
);
|
|
270239
|
+
} finally {
|
|
270240
|
+
busy = false;
|
|
270241
|
+
ui2.requestRender();
|
|
270242
|
+
if (autoSubmit) {
|
|
270243
|
+
setTimeout(() => {
|
|
270244
|
+
teardown();
|
|
270245
|
+
exit(0);
|
|
270246
|
+
}, 25);
|
|
270247
|
+
}
|
|
270248
|
+
}
|
|
270249
|
+
return;
|
|
270250
|
+
}
|
|
270059
270251
|
if (value.startsWith("/")) {
|
|
270060
270252
|
const [cmd, ...rest] = value.slice(1).split(/\s+/);
|
|
270061
270253
|
await runSlash(cmd.toLowerCase(), rest.join(" "));
|
|
@@ -270333,6 +270525,7 @@ var init_tui2 = __esm({
|
|
|
270333
270525
|
"use strict";
|
|
270334
270526
|
init_dist8();
|
|
270335
270527
|
init_tui_select();
|
|
270528
|
+
init_tools();
|
|
270336
270529
|
init_tui_markdown();
|
|
270337
270530
|
init_warp_agent();
|
|
270338
270531
|
BANNER_LINES = [
|
|
@@ -270983,7 +271176,7 @@ init_tui_select();
|
|
|
270983
271176
|
init_model_registry();
|
|
270984
271177
|
|
|
270985
271178
|
// package.json
|
|
270986
|
-
var version2 = "1.
|
|
271179
|
+
var version2 = "1.154.0";
|
|
270987
271180
|
|
|
270988
271181
|
// src/adapters/cli/model-catalog.ts
|
|
270989
271182
|
init_codex_auth();
|