@bunny-agent/runner-cli 0.9.51-release.1 → 0.9.52-beta.1
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 +196 -57
- package/package.json +11 -10
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
|
}
|
|
@@ -5501,7 +5628,7 @@ function createPiRunner(options = {}) {
|
|
|
5501
5628
|
const apiKeyEnvKey = `${provider.toUpperCase().replace(/-/g, "_")}_API_KEY`;
|
|
5502
5629
|
const inlineApiKey = typeof options.env?.[apiKeyEnvKey] === "string" && options.env[apiKeyEnvKey].length > 0 ? options.env[apiKeyEnvKey] : void 0;
|
|
5503
5630
|
const modelRegistry = ModelRegistry.inMemory(AuthStorage.create());
|
|
5504
|
-
const defaultModel =
|
|
5631
|
+
const defaultModel = getBuiltinModel(provider, modelName);
|
|
5505
5632
|
let model = defaultModel ?? modelRegistry.find(provider, modelName);
|
|
5506
5633
|
if (model == null) {
|
|
5507
5634
|
const baseUrlEnvKey = `${provider.toUpperCase().replace(/-/g, "_")}_BASE_URL`;
|
|
@@ -5572,7 +5699,7 @@ function createPiRunner(options = {}) {
|
|
|
5572
5699
|
return SessionManager2.create(cwd);
|
|
5573
5700
|
})();
|
|
5574
5701
|
stripLLMThoughtSignaturesFromSessionManager(sessionManager, model);
|
|
5575
|
-
const resourceLoader = options.skillPaths ? new BunnyAgentResourceLoader({
|
|
5702
|
+
const resourceLoader = options.skillPaths || options.systemPrompt ? new BunnyAgentResourceLoader({
|
|
5576
5703
|
cwd,
|
|
5577
5704
|
skillPaths: options.skillPaths,
|
|
5578
5705
|
appendSystemPrompt: options.systemPrompt
|
|
@@ -5790,10 +5917,21 @@ function dispatchRunner(runner, base, cwd, options) {
|
|
|
5790
5917
|
const _env = base.env;
|
|
5791
5918
|
switch (runner) {
|
|
5792
5919
|
case "claude":
|
|
5793
|
-
return createClaudeRunner(
|
|
5920
|
+
return createClaudeRunner({
|
|
5921
|
+
...base,
|
|
5922
|
+
cwd,
|
|
5923
|
+
forkFrom: options.forkFrom
|
|
5924
|
+
}).run(options.userInput);
|
|
5794
5925
|
case "codex": {
|
|
5795
5926
|
const { outputFormat: _of, ...codexBase } = base;
|
|
5796
|
-
|
|
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);
|
|
5797
5935
|
}
|
|
5798
5936
|
case "gemini":
|
|
5799
5937
|
return createGeminiRunner({
|
|
@@ -5839,7 +5977,8 @@ async function* captureSessionId(stream, cwd) {
|
|
|
5839
5977
|
writeSessionId(cwd, sessionId);
|
|
5840
5978
|
}
|
|
5841
5979
|
}
|
|
5842
|
-
} catch {
|
|
5980
|
+
} catch (error) {
|
|
5981
|
+
console.debug("[captureSessionId] failed to parse chunk", error);
|
|
5843
5982
|
}
|
|
5844
5983
|
}
|
|
5845
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.52-beta.1",
|
|
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,12 +54,12 @@
|
|
|
53
54
|
"esbuild": "^0.27.2",
|
|
54
55
|
"typescript": "^5.3.0",
|
|
55
56
|
"vitest": "^1.6.1",
|
|
56
|
-
"@bunny-agent/runner-harness": "0.1.1-beta.0",
|
|
57
57
|
"@bunny-agent/runner-claude": "0.6.2",
|
|
58
|
-
"@bunny-agent/runner-
|
|
58
|
+
"@bunny-agent/runner-codex": "0.6.2",
|
|
59
59
|
"@bunny-agent/runner-gemini": "0.6.2",
|
|
60
|
-
"@bunny-agent/runner-
|
|
61
|
-
"@bunny-agent/runner-
|
|
60
|
+
"@bunny-agent/runner-opencode": "0.6.2",
|
|
61
|
+
"@bunny-agent/runner-harness": "0.1.1-beta.0",
|
|
62
|
+
"@bunny-agent/runner-pi": "0.6.4-beta.0"
|
|
62
63
|
},
|
|
63
64
|
"scripts": {
|
|
64
65
|
"build": "tsc && pnpm bundle",
|