@bunny-agent/runner-cli 0.9.50 → 0.9.51-beta.2
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/bundle.mjs +296 -74
- package/package.json +9 -8
package/dist/bundle.mjs
CHANGED
|
@@ -700,7 +700,11 @@ function createSDKOptions(options) {
|
|
|
700
700
|
],
|
|
701
701
|
cwd: options.cwd,
|
|
702
702
|
env: options.env,
|
|
703
|
-
|
|
703
|
+
// forkFrom snapshot-clones the source session into a new session id;
|
|
704
|
+
// plain resume continues the same session.
|
|
705
|
+
resume: options.forkFrom ?? options.resume,
|
|
706
|
+
forkSession: options.forkFrom != null ? true : void 0,
|
|
707
|
+
...options.skills ? { skills: options.skills } : {},
|
|
704
708
|
settingSources: ["project", "user"],
|
|
705
709
|
canUseTool: createCanUseToolCallback(options),
|
|
706
710
|
permissionMode: isRoot || options.yolo ? "bypassPermissions" : "default",
|
|
@@ -894,18 +898,33 @@ function toToolEndPayload(event) {
|
|
|
894
898
|
}
|
|
895
899
|
return null;
|
|
896
900
|
}
|
|
897
|
-
function
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
901
|
+
function sseData(obj) {
|
|
902
|
+
return `data: ${JSON.stringify(obj)}
|
|
903
|
+
|
|
904
|
+
`;
|
|
905
|
+
}
|
|
906
|
+
var ItemTextTracker = class {
|
|
907
|
+
emittedLength = /* @__PURE__ */ new Map();
|
|
908
|
+
started = /* @__PURE__ */ new Set();
|
|
909
|
+
/** Returns the new delta for this item, or empty string if nothing new. */
|
|
910
|
+
delta(itemId, fullText) {
|
|
911
|
+
const emitted = this.emittedLength.get(itemId) ?? 0;
|
|
912
|
+
if (fullText.length <= emitted)
|
|
913
|
+
return "";
|
|
914
|
+
this.emittedLength.set(itemId, fullText.length);
|
|
915
|
+
return fullText.slice(emitted);
|
|
916
|
+
}
|
|
917
|
+
/** Returns true the first time an item id is seen (caller emits text-start). */
|
|
918
|
+
markStarted(itemId) {
|
|
919
|
+
if (this.started.has(itemId))
|
|
920
|
+
return false;
|
|
921
|
+
this.started.add(itemId);
|
|
922
|
+
return true;
|
|
903
923
|
}
|
|
904
|
-
|
|
905
|
-
return
|
|
924
|
+
isStarted(itemId) {
|
|
925
|
+
return this.started.has(itemId);
|
|
906
926
|
}
|
|
907
|
-
|
|
908
|
-
}
|
|
927
|
+
};
|
|
909
928
|
function createCodexRunner(options) {
|
|
910
929
|
const codex = new Codex({
|
|
911
930
|
apiKey: process.env.CODEX_API_KEY || process.env.OPENAI_API_KEY,
|
|
@@ -954,62 +973,170 @@ function createCodexRunner(options) {
|
|
|
954
973
|
}
|
|
955
974
|
} catch (_e) {
|
|
956
975
|
}
|
|
976
|
+
if (options.systemPrompt && !options.resume) {
|
|
977
|
+
if (typeof inputToCodex === "string") {
|
|
978
|
+
inputToCodex = `${options.systemPrompt}
|
|
979
|
+
|
|
980
|
+
${inputToCodex}`;
|
|
981
|
+
} else {
|
|
982
|
+
inputToCodex = [
|
|
983
|
+
{ type: "text", text: options.systemPrompt },
|
|
984
|
+
...inputToCodex
|
|
985
|
+
];
|
|
986
|
+
}
|
|
987
|
+
}
|
|
957
988
|
const streamedTurn = await thread.runStreamed(inputToCodex, {
|
|
958
989
|
signal: options.abortController?.signal
|
|
959
990
|
});
|
|
991
|
+
let sessionId = options.resume ?? void 0;
|
|
992
|
+
let startEmitted = false;
|
|
993
|
+
let finished = false;
|
|
994
|
+
const textTracker = new ItemTextTracker();
|
|
995
|
+
const reasoningTracker = new ItemTextTracker();
|
|
996
|
+
const ensureStart = () => {
|
|
997
|
+
if (startEmitted)
|
|
998
|
+
return [];
|
|
999
|
+
startEmitted = true;
|
|
1000
|
+
return [
|
|
1001
|
+
sseData({ type: "start" }),
|
|
1002
|
+
sseData({
|
|
1003
|
+
type: "message-metadata",
|
|
1004
|
+
messageMetadata: { sessionId: sessionId ?? thread.id ?? void 0 }
|
|
1005
|
+
})
|
|
1006
|
+
];
|
|
1007
|
+
};
|
|
960
1008
|
for await (const event of streamedTurn.events) {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
yield
|
|
964
|
-
|
|
965
|
-
|
|
1009
|
+
if (event.type === "thread.started") {
|
|
1010
|
+
sessionId = event.thread_id;
|
|
1011
|
+
yield* ensureStart();
|
|
1012
|
+
continue;
|
|
1013
|
+
}
|
|
1014
|
+
yield* ensureStart();
|
|
1015
|
+
if ((event.type === "item.started" || event.type === "item.updated" || event.type === "item.completed") && event.item.type === "agent_message") {
|
|
1016
|
+
const item = event.item;
|
|
1017
|
+
if (textTracker.markStarted(item.id)) {
|
|
1018
|
+
yield sseData({ type: "text-start", id: item.id });
|
|
1019
|
+
}
|
|
1020
|
+
const delta = textTracker.delta(item.id, item.text);
|
|
1021
|
+
if (delta) {
|
|
1022
|
+
yield sseData({ type: "text-delta", id: item.id, delta });
|
|
1023
|
+
}
|
|
1024
|
+
if (event.type === "item.completed") {
|
|
1025
|
+
yield sseData({ type: "text-end", id: item.id });
|
|
1026
|
+
}
|
|
1027
|
+
continue;
|
|
1028
|
+
}
|
|
1029
|
+
if ((event.type === "item.updated" || event.type === "item.completed") && event.item.type === "reasoning") {
|
|
1030
|
+
const delta = reasoningTracker.delta(event.item.id, event.item.text);
|
|
1031
|
+
if (delta) {
|
|
1032
|
+
yield sseData({ type: "reasoning", text: delta });
|
|
1033
|
+
}
|
|
1034
|
+
continue;
|
|
1035
|
+
}
|
|
1036
|
+
if (event.type === "item.completed" && event.item.type === "error") {
|
|
1037
|
+
const id = `error-item-${event.item.id}`;
|
|
1038
|
+
yield sseData({ type: "text-start", id });
|
|
1039
|
+
yield sseData({
|
|
1040
|
+
type: "text-delta",
|
|
1041
|
+
id,
|
|
1042
|
+
delta: `[Error] ${event.item.message}`
|
|
1043
|
+
});
|
|
1044
|
+
yield sseData({ type: "text-end", id });
|
|
1045
|
+
continue;
|
|
1046
|
+
}
|
|
1047
|
+
if (event.type === "item.completed" && event.item.type === "file_change") {
|
|
1048
|
+
const item = event.item;
|
|
1049
|
+
yield sseData({
|
|
1050
|
+
type: "tool-input-start",
|
|
1051
|
+
toolCallId: item.id,
|
|
1052
|
+
toolName: "apply_patch"
|
|
1053
|
+
});
|
|
1054
|
+
yield sseData({
|
|
1055
|
+
type: "tool-input-available",
|
|
1056
|
+
toolCallId: item.id,
|
|
1057
|
+
toolName: "apply_patch",
|
|
1058
|
+
input: { changes: item.changes }
|
|
1059
|
+
});
|
|
1060
|
+
yield sseData({
|
|
1061
|
+
type: "tool-output-available",
|
|
1062
|
+
toolCallId: item.id,
|
|
1063
|
+
output: { status: item.status, changes: item.changes },
|
|
1064
|
+
isError: item.status === "failed"
|
|
1065
|
+
});
|
|
1066
|
+
continue;
|
|
966
1067
|
}
|
|
967
1068
|
const toolStart = toToolStartPayload(event);
|
|
968
1069
|
if (toolStart) {
|
|
969
|
-
yield
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1070
|
+
yield sseData({
|
|
1071
|
+
type: "tool-input-start",
|
|
1072
|
+
toolCallId: toolStart.toolCallId,
|
|
1073
|
+
toolName: toolStart.toolName
|
|
1074
|
+
});
|
|
1075
|
+
yield sseData({
|
|
1076
|
+
type: "tool-input-available",
|
|
1077
|
+
toolCallId: toolStart.toolCallId,
|
|
1078
|
+
toolName: toolStart.toolName,
|
|
1079
|
+
input: toolStart.args
|
|
1080
|
+
});
|
|
975
1081
|
}
|
|
976
1082
|
const toolEnd = toToolEndPayload(event);
|
|
977
1083
|
if (toolEnd) {
|
|
978
|
-
yield
|
|
979
|
-
|
|
980
|
-
|
|
1084
|
+
yield sseData({
|
|
1085
|
+
type: "tool-output-available",
|
|
1086
|
+
toolCallId: toolEnd.toolCallId,
|
|
1087
|
+
output: toolEnd.result,
|
|
1088
|
+
isError: toolEnd.isError
|
|
1089
|
+
});
|
|
981
1090
|
}
|
|
982
1091
|
if (event.type === "turn.completed") {
|
|
983
|
-
yield
|
|
984
|
-
|
|
985
|
-
|
|
1092
|
+
yield sseData({
|
|
1093
|
+
type: "finish",
|
|
1094
|
+
finishReason: "stop",
|
|
1095
|
+
messageMetadata: {
|
|
1096
|
+
sessionId: sessionId ?? thread.id ?? void 0,
|
|
1097
|
+
usage: {
|
|
1098
|
+
input_tokens: event.usage.input_tokens,
|
|
1099
|
+
output_tokens: event.usage.output_tokens,
|
|
1100
|
+
cache_read_input_tokens: event.usage.cached_input_tokens
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
});
|
|
986
1104
|
yield `data: [DONE]
|
|
987
1105
|
|
|
988
1106
|
`;
|
|
1107
|
+
finished = true;
|
|
989
1108
|
}
|
|
990
1109
|
if (event.type === "turn.failed") {
|
|
991
|
-
yield
|
|
992
|
-
|
|
993
|
-
`;
|
|
994
|
-
yield `data: ${JSON.stringify({ type: "finish", finishReason: "error" })}
|
|
995
|
-
|
|
996
|
-
`;
|
|
1110
|
+
yield sseData({ type: "error", errorText: event.error.message });
|
|
1111
|
+
yield sseData({ type: "finish", finishReason: "error" });
|
|
997
1112
|
yield `data: [DONE]
|
|
998
1113
|
|
|
999
1114
|
`;
|
|
1115
|
+
finished = true;
|
|
1000
1116
|
}
|
|
1001
1117
|
if (event.type === "error") {
|
|
1002
|
-
yield
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
`;
|
|
1118
|
+
yield sseData({
|
|
1119
|
+
type: "error",
|
|
1120
|
+
errorText: stringifyUnknown(event.message)
|
|
1121
|
+
});
|
|
1122
|
+
yield sseData({ type: "finish", finishReason: "error" });
|
|
1008
1123
|
yield `data: [DONE]
|
|
1009
1124
|
|
|
1010
1125
|
`;
|
|
1126
|
+
finished = true;
|
|
1011
1127
|
}
|
|
1012
1128
|
}
|
|
1129
|
+
if (!finished) {
|
|
1130
|
+
yield* ensureStart();
|
|
1131
|
+
yield sseData({
|
|
1132
|
+
type: "error",
|
|
1133
|
+
errorText: "Codex stream ended unexpectedly before completing."
|
|
1134
|
+
});
|
|
1135
|
+
yield sseData({ type: "finish", finishReason: "error" });
|
|
1136
|
+
yield `data: [DONE]
|
|
1137
|
+
|
|
1138
|
+
`;
|
|
1139
|
+
}
|
|
1013
1140
|
for (const tmpFile of tempFiles) {
|
|
1014
1141
|
try {
|
|
1015
1142
|
fs.unlinkSync(tmpFile);
|
|
@@ -1303,7 +1430,7 @@ function createOpenCodeRunner(options = {}) {
|
|
|
1303
1430
|
// ../../packages/runner-pi/dist/pi-runner.js
|
|
1304
1431
|
import { appendFileSync as appendFileSync2, existsSync as existsSync5, unlinkSync as unlinkSync3 } from "node:fs";
|
|
1305
1432
|
import { join as join8 } from "node:path";
|
|
1306
|
-
import {
|
|
1433
|
+
import { getBuiltinModel } from "@earendil-works/pi-ai/providers/all";
|
|
1307
1434
|
import { AuthStorage, createAgentSession, ModelRegistry, SessionManager as SessionManager2 } from "@earendil-works/pi-coding-agent";
|
|
1308
1435
|
|
|
1309
1436
|
// ../../packages/runner-pi/dist/bunny-agent-resource-loader.js
|
|
@@ -2077,7 +2204,7 @@ function extractToolResultText(result) {
|
|
|
2077
2204
|
return String(result);
|
|
2078
2205
|
}
|
|
2079
2206
|
}
|
|
2080
|
-
function
|
|
2207
|
+
function sseData2(obj) {
|
|
2081
2208
|
return "data: " + JSON.stringify(obj) + "\n\n";
|
|
2082
2209
|
}
|
|
2083
2210
|
var PiAISDKStreamConverter = class {
|
|
@@ -2121,13 +2248,13 @@ var PiAISDKStreamConverter = class {
|
|
|
2121
2248
|
}
|
|
2122
2249
|
if (event.type === "tool_execution_start") {
|
|
2123
2250
|
chunks.push(...this.endTextStreamIfOpen());
|
|
2124
|
-
chunks.push(
|
|
2251
|
+
chunks.push(sseData2({
|
|
2125
2252
|
type: "tool-input-start",
|
|
2126
2253
|
toolCallId: event.toolCallId,
|
|
2127
2254
|
toolName: event.toolName,
|
|
2128
2255
|
dynamic: true,
|
|
2129
2256
|
providerExecuted: true
|
|
2130
|
-
}),
|
|
2257
|
+
}), sseData2({
|
|
2131
2258
|
type: "tool-input-available",
|
|
2132
2259
|
toolCallId: event.toolCallId,
|
|
2133
2260
|
toolName: event.toolName,
|
|
@@ -2143,7 +2270,7 @@ var PiAISDKStreamConverter = class {
|
|
|
2143
2270
|
if (raw != null)
|
|
2144
2271
|
accumulateToolUsage(this.toolUsageTally, raw);
|
|
2145
2272
|
if (event.isError) {
|
|
2146
|
-
chunks.push(
|
|
2273
|
+
chunks.push(sseData2({
|
|
2147
2274
|
type: "tool-output-error",
|
|
2148
2275
|
toolCallId: event.toolCallId,
|
|
2149
2276
|
errorText: output,
|
|
@@ -2151,7 +2278,7 @@ var PiAISDKStreamConverter = class {
|
|
|
2151
2278
|
providerExecuted: true
|
|
2152
2279
|
}));
|
|
2153
2280
|
} else {
|
|
2154
|
-
chunks.push(
|
|
2281
|
+
chunks.push(sseData2({
|
|
2155
2282
|
type: "tool-output-available",
|
|
2156
2283
|
toolCallId: event.toolCallId,
|
|
2157
2284
|
output,
|
|
@@ -2180,8 +2307,8 @@ var PiAISDKStreamConverter = class {
|
|
|
2180
2307
|
return [];
|
|
2181
2308
|
this.hasStarted = true;
|
|
2182
2309
|
return [
|
|
2183
|
-
|
|
2184
|
-
|
|
2310
|
+
sseData2({ type: "start", messageId: this.messageId }),
|
|
2311
|
+
sseData2({
|
|
2185
2312
|
type: "message-metadata",
|
|
2186
2313
|
messageMetadata: { sessionId: this.options.sessionId }
|
|
2187
2314
|
})
|
|
@@ -2192,7 +2319,7 @@ var PiAISDKStreamConverter = class {
|
|
|
2192
2319
|
}
|
|
2193
2320
|
openTextStream() {
|
|
2194
2321
|
this.activeTextPartId = this.newTextPartId();
|
|
2195
|
-
return [
|
|
2322
|
+
return [sseData2({ type: "text-start", id: this.activeTextPartId })];
|
|
2196
2323
|
}
|
|
2197
2324
|
emitTextDelta(rawDelta) {
|
|
2198
2325
|
if (!rawDelta)
|
|
@@ -2200,7 +2327,7 @@ var PiAISDKStreamConverter = class {
|
|
|
2200
2327
|
const startChunk = this.activeTextPartId == null ? this.openTextStream() : [];
|
|
2201
2328
|
return [
|
|
2202
2329
|
...startChunk,
|
|
2203
|
-
|
|
2330
|
+
sseData2({
|
|
2204
2331
|
type: "text-delta",
|
|
2205
2332
|
id: this.activeTextPartId,
|
|
2206
2333
|
delta: rawDelta
|
|
@@ -2212,7 +2339,7 @@ var PiAISDKStreamConverter = class {
|
|
|
2212
2339
|
return [];
|
|
2213
2340
|
const id = this.activeTextPartId;
|
|
2214
2341
|
this.activeTextPartId = null;
|
|
2215
|
-
return [
|
|
2342
|
+
return [sseData2({ type: "text-end", id })];
|
|
2216
2343
|
}
|
|
2217
2344
|
finishSuccess(usage) {
|
|
2218
2345
|
const chunks = [...this.endTextStreamIfOpen()];
|
|
@@ -2236,7 +2363,7 @@ var PiAISDKStreamConverter = class {
|
|
|
2236
2363
|
if (usage) {
|
|
2237
2364
|
finishPayload.messageMetadata = { usage: { ...chatUsage, raw } };
|
|
2238
2365
|
}
|
|
2239
|
-
chunks.push(
|
|
2366
|
+
chunks.push(sseData2(finishPayload), "data: [DONE]\n\n");
|
|
2240
2367
|
this.hasFinished = true;
|
|
2241
2368
|
return chunks;
|
|
2242
2369
|
}
|
|
@@ -5349,12 +5476,79 @@ function serializeResult(result) {
|
|
|
5349
5476
|
|
|
5350
5477
|
// ../../packages/runner-pi/dist/pi-runner.js
|
|
5351
5478
|
var LOG_PREFIX2 = "[bunny-agent:pi]";
|
|
5479
|
+
var LLM_THOUGHT_SIGNATURE_SEPARATOR = "__thought__";
|
|
5352
5480
|
function applyAllowedTools(tools, allowedTools) {
|
|
5353
5481
|
if (!allowedTools)
|
|
5354
5482
|
return tools;
|
|
5355
5483
|
const allowed = new Set(allowedTools);
|
|
5356
5484
|
return tools.filter((tool) => allowed.has(tool.name));
|
|
5357
5485
|
}
|
|
5486
|
+
function shouldStripLLMThoughtSignaturesForModel(model) {
|
|
5487
|
+
const id = (model.id ?? "").toLowerCase();
|
|
5488
|
+
return !id.includes("gemini");
|
|
5489
|
+
}
|
|
5490
|
+
function stripLLMThoughtSignatureFromId(id) {
|
|
5491
|
+
const separatorIndex = id.indexOf(LLM_THOUGHT_SIGNATURE_SEPARATOR);
|
|
5492
|
+
if (separatorIndex === -1)
|
|
5493
|
+
return id;
|
|
5494
|
+
return id.slice(0, separatorIndex);
|
|
5495
|
+
}
|
|
5496
|
+
function stripLLMThoughtSignaturesFromSessionManager(sessionManager, model) {
|
|
5497
|
+
if (!shouldStripLLMThoughtSignaturesForModel(model))
|
|
5498
|
+
return;
|
|
5499
|
+
const manager = sessionManager;
|
|
5500
|
+
const entries = manager.getEntries?.();
|
|
5501
|
+
if (Array.isArray(entries)) {
|
|
5502
|
+
for (const entry of entries) {
|
|
5503
|
+
if (entry == null || typeof entry !== "object")
|
|
5504
|
+
continue;
|
|
5505
|
+
const message = entry.message;
|
|
5506
|
+
if (entry.type === "message") {
|
|
5507
|
+
stripLLMThoughtSignaturesFromMessage(message);
|
|
5508
|
+
}
|
|
5509
|
+
}
|
|
5510
|
+
return;
|
|
5511
|
+
}
|
|
5512
|
+
const context = sessionManager.buildSessionContext?.();
|
|
5513
|
+
const messages = context?.messages;
|
|
5514
|
+
if (!Array.isArray(messages))
|
|
5515
|
+
return;
|
|
5516
|
+
for (const message of messages) {
|
|
5517
|
+
stripLLMThoughtSignaturesFromMessage(message);
|
|
5518
|
+
}
|
|
5519
|
+
}
|
|
5520
|
+
function stripLLMThoughtSignaturesFromMessage(message) {
|
|
5521
|
+
if (message == null || typeof message !== "object")
|
|
5522
|
+
return;
|
|
5523
|
+
const msg = message;
|
|
5524
|
+
if (typeof msg.toolCallId === "string") {
|
|
5525
|
+
msg.toolCallId = stripLLMThoughtSignatureFromId(msg.toolCallId);
|
|
5526
|
+
}
|
|
5527
|
+
if (typeof msg.tool_call_id === "string") {
|
|
5528
|
+
msg.tool_call_id = stripLLMThoughtSignatureFromId(msg.tool_call_id);
|
|
5529
|
+
}
|
|
5530
|
+
if (!Array.isArray(msg.content))
|
|
5531
|
+
return;
|
|
5532
|
+
for (const block of msg.content) {
|
|
5533
|
+
if (block == null || typeof block !== "object")
|
|
5534
|
+
continue;
|
|
5535
|
+
const contentBlock = block;
|
|
5536
|
+
if (contentBlock.type !== "toolCall")
|
|
5537
|
+
continue;
|
|
5538
|
+
if (typeof contentBlock.id === "string") {
|
|
5539
|
+
contentBlock.id = stripLLMThoughtSignatureFromId(contentBlock.id);
|
|
5540
|
+
}
|
|
5541
|
+
if (typeof contentBlock.toolCallId === "string") {
|
|
5542
|
+
contentBlock.toolCallId = stripLLMThoughtSignatureFromId(contentBlock.toolCallId);
|
|
5543
|
+
}
|
|
5544
|
+
if (typeof contentBlock.tool_call_id === "string") {
|
|
5545
|
+
contentBlock.tool_call_id = stripLLMThoughtSignatureFromId(contentBlock.tool_call_id);
|
|
5546
|
+
}
|
|
5547
|
+
if (typeof contentBlock.call_id === "string") {
|
|
5548
|
+
contentBlock.call_id = stripLLMThoughtSignatureFromId(contentBlock.call_id);
|
|
5549
|
+
}
|
|
5550
|
+
}
|
|
5551
|
+
}
|
|
5358
5552
|
function parseModelSpec(model) {
|
|
5359
5553
|
const trimmed = model.trim();
|
|
5360
5554
|
const separator = trimmed.indexOf(":");
|
|
@@ -5434,7 +5628,7 @@ function createPiRunner(options = {}) {
|
|
|
5434
5628
|
const apiKeyEnvKey = `${provider.toUpperCase().replace(/-/g, "_")}_API_KEY`;
|
|
5435
5629
|
const inlineApiKey = typeof options.env?.[apiKeyEnvKey] === "string" && options.env[apiKeyEnvKey].length > 0 ? options.env[apiKeyEnvKey] : void 0;
|
|
5436
5630
|
const modelRegistry = ModelRegistry.inMemory(AuthStorage.create());
|
|
5437
|
-
const defaultModel =
|
|
5631
|
+
const defaultModel = getBuiltinModel(provider, modelName);
|
|
5438
5632
|
let model = defaultModel ?? modelRegistry.find(provider, modelName);
|
|
5439
5633
|
if (model == null) {
|
|
5440
5634
|
const baseUrlEnvKey = `${provider.toUpperCase().replace(/-/g, "_")}_BASE_URL`;
|
|
@@ -5504,7 +5698,8 @@ function createPiRunner(options = {}) {
|
|
|
5504
5698
|
}
|
|
5505
5699
|
return SessionManager2.create(cwd);
|
|
5506
5700
|
})();
|
|
5507
|
-
|
|
5701
|
+
stripLLMThoughtSignaturesFromSessionManager(sessionManager, model);
|
|
5702
|
+
const resourceLoader = options.skillPaths || options.systemPrompt ? new BunnyAgentResourceLoader({
|
|
5508
5703
|
cwd,
|
|
5509
5704
|
skillPaths: options.skillPaths,
|
|
5510
5705
|
appendSystemPrompt: options.systemPrompt
|
|
@@ -5537,7 +5732,9 @@ function createPiRunner(options = {}) {
|
|
|
5537
5732
|
]
|
|
5538
5733
|
});
|
|
5539
5734
|
const eventQueue = [];
|
|
5540
|
-
let
|
|
5735
|
+
let promptSettled = false;
|
|
5736
|
+
let promptError;
|
|
5737
|
+
let finalAgentEnd;
|
|
5541
5738
|
let aborted = false;
|
|
5542
5739
|
let wakeConsumer = null;
|
|
5543
5740
|
const notify = () => {
|
|
@@ -5546,15 +5743,11 @@ function createPiRunner(options = {}) {
|
|
|
5546
5743
|
};
|
|
5547
5744
|
const unsubscribe = session.subscribe((e) => {
|
|
5548
5745
|
eventQueue.push(e);
|
|
5549
|
-
if (e.type === "agent_end") {
|
|
5550
|
-
isComplete = true;
|
|
5551
|
-
}
|
|
5552
5746
|
notify();
|
|
5553
5747
|
});
|
|
5554
5748
|
const abortSignal = options.abortController?.signal;
|
|
5555
5749
|
const abortHandler = () => {
|
|
5556
5750
|
aborted = true;
|
|
5557
|
-
isComplete = true;
|
|
5558
5751
|
void session.abort();
|
|
5559
5752
|
notify();
|
|
5560
5753
|
};
|
|
@@ -5568,6 +5761,14 @@ function createPiRunner(options = {}) {
|
|
|
5568
5761
|
traceRawMessage(cwd, null, true, options.env);
|
|
5569
5762
|
const promptText = userInput;
|
|
5570
5763
|
const promptPromise = session.prompt(promptText);
|
|
5764
|
+
void promptPromise.then(() => {
|
|
5765
|
+
promptSettled = true;
|
|
5766
|
+
notify();
|
|
5767
|
+
}, (error) => {
|
|
5768
|
+
promptError = error;
|
|
5769
|
+
promptSettled = true;
|
|
5770
|
+
notify();
|
|
5771
|
+
});
|
|
5571
5772
|
const streamConverter = new PiAISDKStreamConverter({
|
|
5572
5773
|
sessionId: session.sessionId,
|
|
5573
5774
|
model,
|
|
@@ -5575,10 +5776,14 @@ function createPiRunner(options = {}) {
|
|
|
5575
5776
|
getUsageFromAgentEndMessages,
|
|
5576
5777
|
getErrorFromAgentEndMessages
|
|
5577
5778
|
});
|
|
5578
|
-
while (!
|
|
5779
|
+
while (!promptSettled && !aborted || eventQueue.length > 0) {
|
|
5579
5780
|
while (eventQueue.length > 0) {
|
|
5580
5781
|
const event = eventQueue.shift();
|
|
5581
5782
|
traceRawMessage(cwd, event, false, options.env);
|
|
5783
|
+
if (event.type === "agent_end") {
|
|
5784
|
+
finalAgentEnd = event;
|
|
5785
|
+
continue;
|
|
5786
|
+
}
|
|
5582
5787
|
const chunks = streamConverter.handleEvent(event, aborted);
|
|
5583
5788
|
for (const chunk of chunks) {
|
|
5584
5789
|
yield chunk;
|
|
@@ -5590,30 +5795,35 @@ function createPiRunner(options = {}) {
|
|
|
5590
5795
|
}
|
|
5591
5796
|
break;
|
|
5592
5797
|
}
|
|
5593
|
-
if (!
|
|
5798
|
+
if (!promptSettled && !aborted && eventQueue.length === 0) {
|
|
5594
5799
|
await new Promise((resolve4) => {
|
|
5595
5800
|
wakeConsumer = resolve4;
|
|
5596
5801
|
});
|
|
5597
5802
|
}
|
|
5598
5803
|
}
|
|
5599
|
-
if (
|
|
5804
|
+
if (aborted) {
|
|
5600
5805
|
return;
|
|
5601
5806
|
}
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
const message = error instanceof Error ? error.message : "Pi agent run failed.";
|
|
5607
|
-
for (const chunk of streamConverter.forceError(message)) {
|
|
5608
|
-
yield chunk;
|
|
5609
|
-
}
|
|
5807
|
+
if (promptError !== void 0) {
|
|
5808
|
+
const message = promptError instanceof Error ? promptError.message : "Pi agent run failed.";
|
|
5809
|
+
for (const chunk of streamConverter.forceError(message)) {
|
|
5810
|
+
yield chunk;
|
|
5610
5811
|
}
|
|
5611
5812
|
return;
|
|
5612
5813
|
}
|
|
5613
|
-
if (
|
|
5814
|
+
if (finalAgentEnd) {
|
|
5815
|
+
const chunks = streamConverter.handleEvent(finalAgentEnd, false);
|
|
5816
|
+
for (const chunk of chunks) {
|
|
5817
|
+
yield chunk;
|
|
5818
|
+
}
|
|
5819
|
+
} else if (session.agent.state.errorMessage) {
|
|
5614
5820
|
for (const chunk of streamConverter.forceError(session.agent.state.errorMessage)) {
|
|
5615
5821
|
yield chunk;
|
|
5616
5822
|
}
|
|
5823
|
+
} else {
|
|
5824
|
+
for (const chunk of streamConverter.forceError("Pi agent run completed without an agent_end event.")) {
|
|
5825
|
+
yield chunk;
|
|
5826
|
+
}
|
|
5617
5827
|
}
|
|
5618
5828
|
} finally {
|
|
5619
5829
|
if (abortSignal) {
|
|
@@ -5707,10 +5917,21 @@ function dispatchRunner(runner, base, cwd, options) {
|
|
|
5707
5917
|
const _env = base.env;
|
|
5708
5918
|
switch (runner) {
|
|
5709
5919
|
case "claude":
|
|
5710
|
-
return createClaudeRunner(
|
|
5920
|
+
return createClaudeRunner({
|
|
5921
|
+
...base,
|
|
5922
|
+
cwd,
|
|
5923
|
+
forkFrom: options.forkFrom
|
|
5924
|
+
}).run(options.userInput);
|
|
5711
5925
|
case "codex": {
|
|
5712
5926
|
const { outputFormat: _of, ...codexBase } = base;
|
|
5713
|
-
|
|
5927
|
+
const codexEfforts = ["minimal", "low", "medium", "high", "xhigh"];
|
|
5928
|
+
return createCodexRunner({
|
|
5929
|
+
...codexBase,
|
|
5930
|
+
cwd,
|
|
5931
|
+
...options.effort && codexEfforts.includes(options.effort) ? {
|
|
5932
|
+
modelReasoningEffort: options.effort
|
|
5933
|
+
} : {}
|
|
5934
|
+
}).run(options.userInput);
|
|
5714
5935
|
}
|
|
5715
5936
|
case "gemini":
|
|
5716
5937
|
return createGeminiRunner({
|
|
@@ -5756,7 +5977,8 @@ async function* captureSessionId(stream, cwd) {
|
|
|
5756
5977
|
writeSessionId(cwd, sessionId);
|
|
5757
5978
|
}
|
|
5758
5979
|
}
|
|
5759
|
-
} catch {
|
|
5980
|
+
} catch (error) {
|
|
5981
|
+
console.debug("[captureSessionId] failed to parse chunk", error);
|
|
5760
5982
|
}
|
|
5761
5983
|
}
|
|
5762
5984
|
yield chunk;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bunny-agent/runner-cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.51-beta.2",
|
|
4
4
|
"description": "BunnyAgent Runner CLI - Like gemini-cli or claude-code, runs in your local terminal with AI SDK UI streaming",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -40,11 +40,12 @@
|
|
|
40
40
|
"anthropic"
|
|
41
41
|
],
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@anthropic-ai/claude-agent-sdk": "0.
|
|
44
|
-
"@
|
|
45
|
-
"@earendil-works/pi-
|
|
46
|
-
"@earendil-works/pi-
|
|
47
|
-
"@
|
|
43
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.211",
|
|
44
|
+
"@anthropic-ai/sdk": "0.111.0",
|
|
45
|
+
"@earendil-works/pi-agent-core": "0.80.7",
|
|
46
|
+
"@earendil-works/pi-ai": "0.80.7",
|
|
47
|
+
"@earendil-works/pi-coding-agent": "0.80.7",
|
|
48
|
+
"@openai/codex-sdk": "^0.144.5",
|
|
48
49
|
"dotenv": "^17.3.1",
|
|
49
50
|
"zod": "^4.0.0"
|
|
50
51
|
},
|
|
@@ -53,11 +54,11 @@
|
|
|
53
54
|
"esbuild": "^0.27.2",
|
|
54
55
|
"typescript": "^5.3.0",
|
|
55
56
|
"vitest": "^1.6.1",
|
|
57
|
+
"@bunny-agent/runner-claude": "0.6.2",
|
|
58
|
+
"@bunny-agent/runner-codex": "0.6.2",
|
|
56
59
|
"@bunny-agent/runner-harness": "0.1.1-beta.0",
|
|
57
60
|
"@bunny-agent/runner-gemini": "0.6.2",
|
|
58
|
-
"@bunny-agent/runner-claude": "0.6.2",
|
|
59
61
|
"@bunny-agent/runner-opencode": "0.6.2",
|
|
60
|
-
"@bunny-agent/runner-codex": "0.6.2",
|
|
61
62
|
"@bunny-agent/runner-pi": "0.6.4-beta.0"
|
|
62
63
|
},
|
|
63
64
|
"scripts": {
|