@bunny-agent/runner-cli 0.10.0-release.6 → 0.10.1-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 +1060 -175
- package/package.json +5 -5
package/dist/bundle.mjs
CHANGED
|
@@ -6,12 +6,12 @@ var __export = (target, all) => {
|
|
|
6
6
|
};
|
|
7
7
|
|
|
8
8
|
// src/cli.ts
|
|
9
|
-
import { resolve as
|
|
9
|
+
import { resolve as resolve5 } from "node:path";
|
|
10
10
|
import { config as config3 } from "dotenv";
|
|
11
11
|
import { parseArgs } from "node:util";
|
|
12
12
|
|
|
13
13
|
// ../../packages/server-acp/dist/acp-agent.js
|
|
14
|
-
import { randomUUID } from "node:crypto";
|
|
14
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
15
15
|
|
|
16
16
|
// ../../node_modules/.pnpm/@agentclientprotocol+sdk@1.2.1_zod@4.6.7/node_modules/@agentclientprotocol/sdk/dist/schema/index.js
|
|
17
17
|
var AGENT_METHODS = {
|
|
@@ -5132,7 +5132,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
5132
5132
|
var NONE = 0;
|
|
5133
5133
|
var ASSUMED = 1;
|
|
5134
5134
|
var PROVEN = 2;
|
|
5135
|
-
function isRecursive(inst, stack,
|
|
5135
|
+
function isRecursive(inst, stack, resolve6) {
|
|
5136
5136
|
const cached3 = recursive.get(inst);
|
|
5137
5137
|
if (cached3 !== void 0)
|
|
5138
5138
|
return cached3 ? PROVEN : NONE;
|
|
@@ -5142,7 +5142,7 @@ function isRecursive(inst, stack, resolve5) {
|
|
|
5142
5142
|
let result = NONE;
|
|
5143
5143
|
const check3 = (child) => {
|
|
5144
5144
|
if (result !== PROVEN && child?._zod) {
|
|
5145
|
-
const answer = isRecursive(child, stack,
|
|
5145
|
+
const answer = isRecursive(child, stack, resolve6);
|
|
5146
5146
|
if (answer > result)
|
|
5147
5147
|
result = answer;
|
|
5148
5148
|
}
|
|
@@ -5153,7 +5153,7 @@ function isRecursive(inst, stack, resolve5) {
|
|
|
5153
5153
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
5154
5154
|
if (spread && !desc.enumerable)
|
|
5155
5155
|
continue;
|
|
5156
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
5156
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve6) : NONE;
|
|
5157
5157
|
if (child > answer)
|
|
5158
5158
|
answer = child;
|
|
5159
5159
|
}
|
|
@@ -5217,7 +5217,7 @@ function isRecursive(inst, stack, resolve5) {
|
|
|
5217
5217
|
break;
|
|
5218
5218
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
5219
5219
|
case "lazy": {
|
|
5220
|
-
const inner = def._cachedInner ?? (
|
|
5220
|
+
const inner = def._cachedInner ?? (resolve6 ? inst._zod.innerType : void 0);
|
|
5221
5221
|
merge3(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
5222
5222
|
break;
|
|
5223
5223
|
}
|
|
@@ -21764,12 +21764,12 @@ var Connection = class {
|
|
|
21764
21764
|
const id = this.nextRequestId++;
|
|
21765
21765
|
let cancel = () => {
|
|
21766
21766
|
};
|
|
21767
|
-
const responsePromise = new Promise((
|
|
21767
|
+
const responsePromise = new Promise((resolve6, reject) => {
|
|
21768
21768
|
const pendingResponse = {
|
|
21769
21769
|
resolve: (response) => {
|
|
21770
21770
|
try {
|
|
21771
21771
|
const value = mapResponse ? mapResponse(response) : response;
|
|
21772
|
-
|
|
21772
|
+
resolve6(value);
|
|
21773
21773
|
} catch (error109) {
|
|
21774
21774
|
reject(error109);
|
|
21775
21775
|
}
|
|
@@ -21847,8 +21847,8 @@ var Connection = class {
|
|
|
21847
21847
|
initialize(stream, handlers) {
|
|
21848
21848
|
this.stream = stream;
|
|
21849
21849
|
this.staticHandlers = handlers;
|
|
21850
|
-
this.closedPromise = new Promise((
|
|
21851
|
-
this.abortController.signal.addEventListener("abort", () =>
|
|
21850
|
+
this.closedPromise = new Promise((resolve6) => {
|
|
21851
|
+
this.abortController.signal.addEventListener("abort", () => resolve6());
|
|
21852
21852
|
});
|
|
21853
21853
|
void this.receive();
|
|
21854
21854
|
}
|
|
@@ -22636,8 +22636,8 @@ var AsyncQueue = class {
|
|
|
22636
22636
|
if (this.failed) {
|
|
22637
22637
|
return Promise.reject(this.failure);
|
|
22638
22638
|
}
|
|
22639
|
-
return new Promise((
|
|
22640
|
-
this.waiters.push({ resolve:
|
|
22639
|
+
return new Promise((resolve6, reject) => {
|
|
22640
|
+
this.waiters.push({ resolve: resolve6, reject });
|
|
22641
22641
|
});
|
|
22642
22642
|
}
|
|
22643
22643
|
};
|
|
@@ -23929,6 +23929,12 @@ var AISDKStreamConverter = class {
|
|
|
23929
23929
|
if (message.type === "stream_event") {
|
|
23930
23930
|
const streamEvent = message;
|
|
23931
23931
|
const event = streamEvent.event;
|
|
23932
|
+
const parentToolCallId = message.parent_tool_use_id;
|
|
23933
|
+
if (!parentToolCallId && event.type === "message_start") {
|
|
23934
|
+
yield this.emit({ type: "start-step", id: event.message.id });
|
|
23935
|
+
} else if (!parentToolCallId && event.type === "message_stop") {
|
|
23936
|
+
yield this.emit({ type: "finish-step" });
|
|
23937
|
+
}
|
|
23932
23938
|
if (event.type === "message_start" && !this.hasEmittedStart) {
|
|
23933
23939
|
this.hasEmittedStart = true;
|
|
23934
23940
|
yield this.emit({ type: "start", messageId: event.message.id });
|
|
@@ -23959,7 +23965,8 @@ var AISDKStreamConverter = class {
|
|
|
23959
23965
|
toolName: tool.name,
|
|
23960
23966
|
input: tool.input,
|
|
23961
23967
|
dynamic: true,
|
|
23962
|
-
providerExecuted: true
|
|
23968
|
+
providerExecuted: true,
|
|
23969
|
+
parentToolCallId: message.parent_tool_use_id
|
|
23963
23970
|
});
|
|
23964
23971
|
}
|
|
23965
23972
|
}
|
|
@@ -23973,7 +23980,8 @@ var AISDKStreamConverter = class {
|
|
|
23973
23980
|
toolCallId: part.tool_use_id,
|
|
23974
23981
|
output: message.tool_use_result || part.content,
|
|
23975
23982
|
dynamic: true,
|
|
23976
|
-
providerExecuted: true
|
|
23983
|
+
providerExecuted: true,
|
|
23984
|
+
parentToolCallId: message.parent_tool_use_id
|
|
23977
23985
|
});
|
|
23978
23986
|
}
|
|
23979
23987
|
}
|
|
@@ -38037,6 +38045,21 @@ function createCanUseToolCallback(claudeOptions) {
|
|
|
38037
38045
|
updatedInput: input2
|
|
38038
38046
|
};
|
|
38039
38047
|
}
|
|
38048
|
+
if (claudeOptions.toolInteraction) {
|
|
38049
|
+
const decision = await claudeOptions.toolInteraction({
|
|
38050
|
+
toolCallId: toolUseID,
|
|
38051
|
+
toolName,
|
|
38052
|
+
input: input2,
|
|
38053
|
+
signal: options.signal,
|
|
38054
|
+
...toolName === "AskUserQuestion" ? {
|
|
38055
|
+
timeoutMs: claudeOptions.askUserQuestionTimeoutMs ?? DEFAULT_ASK_USER_QUESTION_TIMEOUT_MS
|
|
38056
|
+
} : {}
|
|
38057
|
+
});
|
|
38058
|
+
return decision.behavior === "allow" ? {
|
|
38059
|
+
behavior: "allow",
|
|
38060
|
+
updatedInput: decision.updatedInput ?? input2
|
|
38061
|
+
} : decision;
|
|
38062
|
+
}
|
|
38040
38063
|
const cwd = claudeOptions.cwd || process.cwd();
|
|
38041
38064
|
try {
|
|
38042
38065
|
const fs3 = await import("node:fs");
|
|
@@ -38086,7 +38109,7 @@ function createCanUseToolCallback(claudeOptions) {
|
|
|
38086
38109
|
}
|
|
38087
38110
|
} catch {
|
|
38088
38111
|
}
|
|
38089
|
-
await new Promise((
|
|
38112
|
+
await new Promise((resolve6) => setTimeout(resolve6, 500));
|
|
38090
38113
|
}
|
|
38091
38114
|
try {
|
|
38092
38115
|
fs3.unlinkSync(approvalFile);
|
|
@@ -38279,7 +38302,7 @@ Documentation: https://platform.claude.com/docs/en/agent-sdk/typescript-v2-previ
|
|
|
38279
38302
|
id: textId,
|
|
38280
38303
|
delta: word + " "
|
|
38281
38304
|
});
|
|
38282
|
-
await new Promise((
|
|
38305
|
+
await new Promise((resolve6) => setTimeout(resolve6, 20));
|
|
38283
38306
|
}
|
|
38284
38307
|
yield formatDataStream({ type: "text-end", id: textId });
|
|
38285
38308
|
yield formatDataStream({
|
|
@@ -38709,6 +38732,9 @@ ${inputToCodex}`;
|
|
|
38709
38732
|
continue;
|
|
38710
38733
|
}
|
|
38711
38734
|
yield* ensureStart();
|
|
38735
|
+
if (event.type === "turn.started") {
|
|
38736
|
+
yield sseData({ type: "start-step" });
|
|
38737
|
+
}
|
|
38712
38738
|
if ((event.type === "item.started" || event.type === "item.updated" || event.type === "item.completed") && event.item.type === "agent_message") {
|
|
38713
38739
|
const item = event.item;
|
|
38714
38740
|
if (textTracker.markStarted(item.id)) {
|
|
@@ -38786,6 +38812,7 @@ ${inputToCodex}`;
|
|
|
38786
38812
|
});
|
|
38787
38813
|
}
|
|
38788
38814
|
if (event.type === "turn.completed") {
|
|
38815
|
+
yield sseData({ type: "finish-step" });
|
|
38789
38816
|
yield sseData({
|
|
38790
38817
|
type: "finish",
|
|
38791
38818
|
finishReason: "stop",
|
|
@@ -38804,6 +38831,7 @@ ${inputToCodex}`;
|
|
|
38804
38831
|
finished = true;
|
|
38805
38832
|
}
|
|
38806
38833
|
if (event.type === "turn.failed") {
|
|
38834
|
+
yield sseData({ type: "finish-step" });
|
|
38807
38835
|
yield sseData({ type: "error", errorText: event.error.message });
|
|
38808
38836
|
yield sseData({ type: "finish", finishReason: "error" });
|
|
38809
38837
|
yield `data: [DONE]
|
|
@@ -38845,6 +38873,7 @@ ${inputToCodex}`;
|
|
|
38845
38873
|
}
|
|
38846
38874
|
|
|
38847
38875
|
// ../../packages/runner-copilot/dist/copilot-runner.js
|
|
38876
|
+
import { randomUUID } from "node:crypto";
|
|
38848
38877
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, unlinkSync as unlinkSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
38849
38878
|
import { join as join6 } from "node:path";
|
|
38850
38879
|
import { approveAll, CopilotClient } from "@github/copilot-sdk";
|
|
@@ -38889,8 +38918,8 @@ var AsyncEventQueue = class {
|
|
|
38889
38918
|
throw this.error;
|
|
38890
38919
|
if (this.ended)
|
|
38891
38920
|
return { value: void 0, done: true };
|
|
38892
|
-
return new Promise((
|
|
38893
|
-
this.waiters.push({ resolve:
|
|
38921
|
+
return new Promise((resolve6, reject) => {
|
|
38922
|
+
this.waiters.push({ resolve: resolve6, reject });
|
|
38894
38923
|
});
|
|
38895
38924
|
}
|
|
38896
38925
|
};
|
|
@@ -38961,7 +38990,7 @@ function createFilePermissionHandler(cwd) {
|
|
|
38961
38990
|
}
|
|
38962
38991
|
} catch {
|
|
38963
38992
|
}
|
|
38964
|
-
await new Promise((
|
|
38993
|
+
await new Promise((resolve6) => setTimeout(resolve6, 500));
|
|
38965
38994
|
}
|
|
38966
38995
|
return { kind: "reject", feedback: "Approval timed out." };
|
|
38967
38996
|
} finally {
|
|
@@ -39009,7 +39038,46 @@ function createCopilotRunner(options) {
|
|
|
39009
39038
|
enableConfigDiscovery: true,
|
|
39010
39039
|
availableTools: options.allowedTools,
|
|
39011
39040
|
systemMessage: options.systemPrompt ? { mode: "append", content: options.systemPrompt } : void 0,
|
|
39012
|
-
onPermissionRequest: options.yolo ? approveAll :
|
|
39041
|
+
onPermissionRequest: options.yolo ? approveAll : options.toolInteraction ? async (request) => {
|
|
39042
|
+
const decision = await options.toolInteraction({
|
|
39043
|
+
toolCallId: request.toolCallId ?? randomUUID(),
|
|
39044
|
+
toolName: permissionToolName(request),
|
|
39045
|
+
input: request,
|
|
39046
|
+
signal: options.abortController?.signal
|
|
39047
|
+
});
|
|
39048
|
+
return decision.behavior === "allow" ? { kind: "approved" } : { kind: "reject", feedback: decision.message };
|
|
39049
|
+
} : createFilePermissionHandler(cwd),
|
|
39050
|
+
...options.toolInteraction ? {
|
|
39051
|
+
onUserInputRequest: async (request) => {
|
|
39052
|
+
const decision = await options.toolInteraction({
|
|
39053
|
+
toolCallId: randomUUID(),
|
|
39054
|
+
toolName: "ask_user_question",
|
|
39055
|
+
input: {
|
|
39056
|
+
questions: [
|
|
39057
|
+
{
|
|
39058
|
+
question: request.question,
|
|
39059
|
+
allowFreeform: request.allowFreeform,
|
|
39060
|
+
...request.choices ? {
|
|
39061
|
+
options: request.choices.map((label) => ({
|
|
39062
|
+
label
|
|
39063
|
+
}))
|
|
39064
|
+
} : {}
|
|
39065
|
+
}
|
|
39066
|
+
]
|
|
39067
|
+
},
|
|
39068
|
+
signal: options.abortController?.signal
|
|
39069
|
+
});
|
|
39070
|
+
if (decision.behavior === "deny")
|
|
39071
|
+
throw new Error(decision.message);
|
|
39072
|
+
const answer = decision.updatedInput?.answers?.[request.question];
|
|
39073
|
+
if (typeof answer !== "string")
|
|
39074
|
+
throw new Error("The client did not supply an answer.");
|
|
39075
|
+
return {
|
|
39076
|
+
answer,
|
|
39077
|
+
wasFreeform: !request.choices?.includes(answer)
|
|
39078
|
+
};
|
|
39079
|
+
}
|
|
39080
|
+
} : {}
|
|
39013
39081
|
};
|
|
39014
39082
|
session = options.resume ? await client2.resumeSession(options.resume, sessionConfig) : await client2.createSession(sessionConfig);
|
|
39015
39083
|
activeSession = session;
|
|
@@ -39042,6 +39110,14 @@ function createCopilotRunner(options) {
|
|
|
39042
39110
|
const turn = session.sendAndWait(userInput).then(() => events.close()).catch((error109) => events.fail(error109));
|
|
39043
39111
|
try {
|
|
39044
39112
|
for await (const event of events) {
|
|
39113
|
+
if (!event.agentId && event.type === "assistant.turn_start") {
|
|
39114
|
+
yield sseData2({ type: "start-step", id: event.data.turnId });
|
|
39115
|
+
continue;
|
|
39116
|
+
}
|
|
39117
|
+
if (!event.agentId && event.type === "assistant.turn_end") {
|
|
39118
|
+
yield sseData2({ type: "finish-step" });
|
|
39119
|
+
continue;
|
|
39120
|
+
}
|
|
39045
39121
|
if (event.type === "assistant.message_delta") {
|
|
39046
39122
|
const { messageId, deltaContent } = event.data;
|
|
39047
39123
|
if (!openText.has(messageId)) {
|
|
@@ -39264,8 +39340,8 @@ var AsyncQueue2 = class {
|
|
|
39264
39340
|
if (this.ended) {
|
|
39265
39341
|
return { value: void 0, done: true };
|
|
39266
39342
|
}
|
|
39267
|
-
return new Promise((
|
|
39268
|
-
this.waiters.push({ resolve:
|
|
39343
|
+
return new Promise((resolve6, reject) => {
|
|
39344
|
+
this.waiters.push({ resolve: resolve6, reject });
|
|
39269
39345
|
});
|
|
39270
39346
|
}
|
|
39271
39347
|
};
|
|
@@ -39293,9 +39369,10 @@ function usageMetadata(usage) {
|
|
|
39293
39369
|
return {
|
|
39294
39370
|
input_tokens: usage.inputTokens,
|
|
39295
39371
|
output_tokens: usage.outputTokens,
|
|
39296
|
-
|
|
39297
|
-
|
|
39298
|
-
|
|
39372
|
+
total_tokens: usage.totalTokens,
|
|
39373
|
+
...typeof usage.cachedReadTokens === "number" ? { cache_read_input_tokens: usage.cachedReadTokens } : {},
|
|
39374
|
+
...typeof usage.cachedWriteTokens === "number" ? { cache_creation_input_tokens: usage.cachedWriteTokens } : {},
|
|
39375
|
+
...typeof usage.thoughtTokens === "number" ? { reasoning_tokens: usage.thoughtTokens } : {}
|
|
39299
39376
|
};
|
|
39300
39377
|
}
|
|
39301
39378
|
async function waitForFileApproval(cwd, request) {
|
|
@@ -39323,7 +39400,7 @@ async function waitForFileApproval(cwd, request) {
|
|
|
39323
39400
|
return false;
|
|
39324
39401
|
} catch {
|
|
39325
39402
|
}
|
|
39326
|
-
await new Promise((
|
|
39403
|
+
await new Promise((resolve6) => setTimeout(resolve6, 500));
|
|
39327
39404
|
}
|
|
39328
39405
|
return false;
|
|
39329
39406
|
} finally {
|
|
@@ -39388,6 +39465,7 @@ function createAcpProcessRunner(options) {
|
|
|
39388
39465
|
startedText.clear();
|
|
39389
39466
|
};
|
|
39390
39467
|
const handleUpdate = (update) => {
|
|
39468
|
+
output2.push(sseData3({ type: "data-acp-session-update", data: update }));
|
|
39391
39469
|
if (update.sessionUpdate === "agent_message_chunk" && update.content.type === "text") {
|
|
39392
39470
|
const id = update.messageId ?? "acp-message";
|
|
39393
39471
|
if (!startedText.has(id)) {
|
|
@@ -39456,13 +39534,34 @@ function createAcpProcessRunner(options) {
|
|
|
39456
39534
|
finishReason: aborted3 ? "error" : finishReason(stopReason),
|
|
39457
39535
|
messageMetadata: {
|
|
39458
39536
|
sessionId,
|
|
39537
|
+
acpStopReason: stopReason,
|
|
39459
39538
|
usage: usageMetadata(usage)
|
|
39460
39539
|
}
|
|
39461
39540
|
}));
|
|
39462
39541
|
output2.push("data: [DONE]\n\n");
|
|
39463
39542
|
output2.close();
|
|
39464
39543
|
};
|
|
39465
|
-
const app = client({ name: "bunny-agent" }).onRequest(methods.client.session.requestPermission,
|
|
39544
|
+
const app = client({ name: "bunny-agent" }).onRequest(methods.client.session.requestPermission, async ({ params }) => {
|
|
39545
|
+
if (!options.toolInteraction || options.yolo) {
|
|
39546
|
+
return resolvePermission(cwd, options.yolo ?? false, params);
|
|
39547
|
+
}
|
|
39548
|
+
const decision = await options.toolInteraction({
|
|
39549
|
+
toolCallId: params.toolCall.toolCallId,
|
|
39550
|
+
toolName: params.toolCall.title ?? "tool",
|
|
39551
|
+
input: params.toolCall.rawInput,
|
|
39552
|
+
permission: {
|
|
39553
|
+
toolCall: params.toolCall,
|
|
39554
|
+
options: params.options,
|
|
39555
|
+
...params._meta ? { _meta: params._meta } : {}
|
|
39556
|
+
},
|
|
39557
|
+
signal: options.abortController?.signal
|
|
39558
|
+
});
|
|
39559
|
+
const wanted = decision.behavior === "allow" ? "allow_once" : "reject_once";
|
|
39560
|
+
const selected = params.options.find((option) => decision.optionId ? option.optionId === decision.optionId && (decision.behavior === "allow" ? ["allow_once", "allow_always"].includes(option.kind) : ["reject_once", "reject_always"].includes(option.kind)) : option.kind === wanted);
|
|
39561
|
+
return {
|
|
39562
|
+
outcome: selected ? { outcome: "selected", optionId: selected.optionId } : { outcome: "cancelled" }
|
|
39563
|
+
};
|
|
39564
|
+
}).onNotification(methods.client.session.update, ({ params }) => {
|
|
39466
39565
|
if (acceptingLoadedUpdates && params.sessionId === loadedSessionId) {
|
|
39467
39566
|
handleUpdate(params.update);
|
|
39468
39567
|
}
|
|
@@ -39564,7 +39663,8 @@ function createGeminiRunner(options = {}) {
|
|
|
39564
39663
|
abortController: options.abortController,
|
|
39565
39664
|
systemPrompt: options.systemPrompt,
|
|
39566
39665
|
resume: options.resume,
|
|
39567
|
-
yolo: options.yolo
|
|
39666
|
+
yolo: options.yolo,
|
|
39667
|
+
toolInteraction: options.toolInteraction
|
|
39568
39668
|
});
|
|
39569
39669
|
}
|
|
39570
39670
|
|
|
@@ -39582,7 +39682,8 @@ function createOpenCodeRunner(options = {}) {
|
|
|
39582
39682
|
abortController: options.abortController,
|
|
39583
39683
|
systemPrompt: options.systemPrompt,
|
|
39584
39684
|
resume: options.resume,
|
|
39585
|
-
yolo: options.yolo
|
|
39685
|
+
yolo: options.yolo,
|
|
39686
|
+
toolInteraction: options.toolInteraction
|
|
39586
39687
|
});
|
|
39587
39688
|
}
|
|
39588
39689
|
|
|
@@ -41045,7 +41146,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
41045
41146
|
parameters: editImageSchema,
|
|
41046
41147
|
async execute(_toolCallId, params, signal, _onUpdate) {
|
|
41047
41148
|
const { readFileSync: readFileSync8, existsSync: existsSync12 } = await import("node:fs");
|
|
41048
|
-
const { resolve:
|
|
41149
|
+
const { resolve: resolve6, basename: basename3 } = await import("node:path");
|
|
41049
41150
|
const p = params;
|
|
41050
41151
|
const imagePath = p.image;
|
|
41051
41152
|
const prompt = p.prompt;
|
|
@@ -41056,7 +41157,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
41056
41157
|
const imageSize = p.imageSize;
|
|
41057
41158
|
const rawFilename = p.filename;
|
|
41058
41159
|
const safePrompt = buildPolicySafeEditPrompt(prompt);
|
|
41059
|
-
const resolvedImage =
|
|
41160
|
+
const resolvedImage = resolve6(cwd, imagePath);
|
|
41060
41161
|
if (!existsSync12(resolvedImage)) {
|
|
41061
41162
|
return {
|
|
41062
41163
|
content: [
|
|
@@ -41100,7 +41201,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
41100
41201
|
}
|
|
41101
41202
|
];
|
|
41102
41203
|
if (maskPath) {
|
|
41103
|
-
const resolvedMask =
|
|
41204
|
+
const resolvedMask = resolve6(cwd, maskPath);
|
|
41104
41205
|
if (existsSync12(resolvedMask)) {
|
|
41105
41206
|
files.push({
|
|
41106
41207
|
name: "mask",
|
|
@@ -41759,6 +41860,7 @@ var PiAISDKStreamConverter = class {
|
|
|
41759
41860
|
this.emittedSources = /* @__PURE__ */ new Set();
|
|
41760
41861
|
this.lastEndedContentIndex = -1;
|
|
41761
41862
|
this.textInputEnded = false;
|
|
41863
|
+
this.stepNumber = 0;
|
|
41762
41864
|
this.registry = options.sourceRegistry ?? new SourceRegistry();
|
|
41763
41865
|
}
|
|
41764
41866
|
/** Ingest only against an active text part in its already selected mode. */
|
|
@@ -41781,6 +41883,10 @@ var PiAISDKStreamConverter = class {
|
|
|
41781
41883
|
if (event.type === "message_start") {
|
|
41782
41884
|
const msg = event.message;
|
|
41783
41885
|
if (msg?.role === "assistant") {
|
|
41886
|
+
chunks.push(sseData4({
|
|
41887
|
+
type: "start-step",
|
|
41888
|
+
id: `${this.messageId}:step:${++this.stepNumber}`
|
|
41889
|
+
}));
|
|
41784
41890
|
chunks.push(...this.endTextStreamIfOpen());
|
|
41785
41891
|
this.currentContentIndex = void 0;
|
|
41786
41892
|
this.lastEndedContentIndex = -1;
|
|
@@ -41788,6 +41894,12 @@ var PiAISDKStreamConverter = class {
|
|
|
41788
41894
|
return chunks;
|
|
41789
41895
|
}
|
|
41790
41896
|
if (event.type === "message_end") {
|
|
41897
|
+
if (event.message.role === "assistant") {
|
|
41898
|
+
chunks.push(sseData4({
|
|
41899
|
+
type: "finish-step",
|
|
41900
|
+
id: `${this.messageId}:step:${this.stepNumber}`
|
|
41901
|
+
}));
|
|
41902
|
+
}
|
|
41791
41903
|
if (this.options.searchContractVersion === 1 && event.message.role === "assistant") {
|
|
41792
41904
|
chunks.push(...this.endTextStreamIfOpen(aborted3 || ["length", "aborted", "error"].includes(event.message.stopReason)));
|
|
41793
41905
|
}
|
|
@@ -44663,6 +44775,25 @@ function approvalFilePath(cwd, toolCallId) {
|
|
|
44663
44775
|
return path2.join(cwd, ".bunny-agent", "approvals", approvalFileName(toolCallId));
|
|
44664
44776
|
}
|
|
44665
44777
|
async function waitForApproval(options) {
|
|
44778
|
+
if (options.toolInteraction) {
|
|
44779
|
+
const decision = await options.toolInteraction({
|
|
44780
|
+
toolCallId: options.toolCallId,
|
|
44781
|
+
toolName: options.toolName,
|
|
44782
|
+
input: options.input,
|
|
44783
|
+
signal: options.signal,
|
|
44784
|
+
timeoutMs: options.timeoutMs
|
|
44785
|
+
});
|
|
44786
|
+
if (decision.behavior === "deny")
|
|
44787
|
+
return decision;
|
|
44788
|
+
const updatedInput = decision.updatedInput ?? {};
|
|
44789
|
+
return {
|
|
44790
|
+
behavior: "allow",
|
|
44791
|
+
updatedInput: {
|
|
44792
|
+
questions: updatedInput.questions ?? options.input?.questions,
|
|
44793
|
+
answers: updatedInput.answers ?? {}
|
|
44794
|
+
}
|
|
44795
|
+
};
|
|
44796
|
+
}
|
|
44666
44797
|
const { cwd, toolCallId, toolName, input: input2, signal, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS, timeoutMs } = options;
|
|
44667
44798
|
const approvalFile = approvalFilePath(cwd, toolCallId);
|
|
44668
44799
|
const cleanup = () => {
|
|
@@ -44730,18 +44861,18 @@ async function waitForApproval(options) {
|
|
|
44730
44861
|
}
|
|
44731
44862
|
}
|
|
44732
44863
|
function sleepWithAbort(ms, signal) {
|
|
44733
|
-
return new Promise((
|
|
44864
|
+
return new Promise((resolve6) => {
|
|
44734
44865
|
if (signal?.aborted) {
|
|
44735
|
-
|
|
44866
|
+
resolve6();
|
|
44736
44867
|
return;
|
|
44737
44868
|
}
|
|
44738
44869
|
const timer = setTimeout(() => {
|
|
44739
44870
|
signal?.removeEventListener("abort", onAbort);
|
|
44740
|
-
|
|
44871
|
+
resolve6();
|
|
44741
44872
|
}, ms);
|
|
44742
44873
|
const onAbort = () => {
|
|
44743
44874
|
clearTimeout(timer);
|
|
44744
|
-
|
|
44875
|
+
resolve6();
|
|
44745
44876
|
};
|
|
44746
44877
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
44747
44878
|
});
|
|
@@ -44813,7 +44944,8 @@ function buildAskUserQuestionTool(options) {
|
|
|
44813
44944
|
input: params,
|
|
44814
44945
|
signal: signal ?? options.fallbackSignal,
|
|
44815
44946
|
pollIntervalMs: options.pollIntervalMs,
|
|
44816
|
-
timeoutMs: options.timeoutMs ?? DEFAULT_ASK_USER_QUESTION_TIMEOUT_MS2
|
|
44947
|
+
timeoutMs: options.timeoutMs ?? DEFAULT_ASK_USER_QUESTION_TIMEOUT_MS2,
|
|
44948
|
+
toolInteraction: options.toolInteraction
|
|
44817
44949
|
});
|
|
44818
44950
|
if (decision.behavior === "deny") {
|
|
44819
44951
|
throw new Error(decision.message);
|
|
@@ -44846,7 +44978,8 @@ function createToolApprovalExtension(options) {
|
|
|
44846
44978
|
input: event.input,
|
|
44847
44979
|
signal: ctx.signal ?? options.fallbackSignal,
|
|
44848
44980
|
pollIntervalMs: options.pollIntervalMs,
|
|
44849
|
-
timeoutMs: options.timeoutMs
|
|
44981
|
+
timeoutMs: options.timeoutMs,
|
|
44982
|
+
toolInteraction: options.toolInteraction
|
|
44850
44983
|
});
|
|
44851
44984
|
if (decision.behavior === "deny") {
|
|
44852
44985
|
return {
|
|
@@ -45878,10 +46011,11 @@ function createPiRunner(options = {}) {
|
|
|
45878
46011
|
const allowedTools = normalizeAllowedTools(options.allowedTools);
|
|
45879
46012
|
const toolRefDefinitions = options.toolRefs && options.toolRefs.length > 0 ? buildToolDefinitionsFromRefs(options.toolRefs) : [];
|
|
45880
46013
|
const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
|
|
45881
|
-
const bypassApproval = Boolean(options.yolo) || isRoot;
|
|
46014
|
+
const bypassApproval = Boolean(options.yolo) || isRoot && !options.toolInteraction;
|
|
45882
46015
|
const approvalGate = {
|
|
45883
46016
|
cwd,
|
|
45884
|
-
fallbackSignal: options.abortController?.signal
|
|
46017
|
+
fallbackSignal: options.abortController?.signal,
|
|
46018
|
+
toolInteraction: options.toolInteraction
|
|
45885
46019
|
};
|
|
45886
46020
|
const askUserQuestionEnabled = allowedTools === void 0 || allowedTools.includes(ASK_USER_QUESTION_TOOL_NAME);
|
|
45887
46021
|
const previousModel = sessionManager.buildSessionContext?.().model;
|
|
@@ -46007,8 +46141,8 @@ function createPiRunner(options = {}) {
|
|
|
46007
46141
|
break;
|
|
46008
46142
|
}
|
|
46009
46143
|
if (!promptSettled && !aborted3 && eventQueue.length === 0) {
|
|
46010
|
-
await new Promise((
|
|
46011
|
-
wakeConsumer =
|
|
46144
|
+
await new Promise((resolve6) => {
|
|
46145
|
+
wakeConsumer = resolve6;
|
|
46012
46146
|
});
|
|
46013
46147
|
}
|
|
46014
46148
|
}
|
|
@@ -46168,7 +46302,8 @@ function createRunner(options) {
|
|
|
46168
46302
|
yolo: options.yolo,
|
|
46169
46303
|
env,
|
|
46170
46304
|
abortController,
|
|
46171
|
-
askUserQuestionTimeoutMs: options.askUserQuestionTimeoutMs
|
|
46305
|
+
askUserQuestionTimeoutMs: options.askUserQuestionTimeoutMs,
|
|
46306
|
+
toolInteraction: options.toolInteraction
|
|
46172
46307
|
};
|
|
46173
46308
|
const input2 = options.input ? parseAgentTurnInputV1(options.input) : createLegacyAgentTurnInput(options.userInput ?? "");
|
|
46174
46309
|
const rawStream = dispatchRunner(options.runner, base, cwd, options, input2);
|
|
@@ -46232,7 +46367,8 @@ function dispatchRunner(runner, base, cwd, options, input2) {
|
|
|
46232
46367
|
abortController: base.abortController,
|
|
46233
46368
|
systemPrompt: base.systemPrompt,
|
|
46234
46369
|
resume: base.resume,
|
|
46235
|
-
yolo: base.yolo
|
|
46370
|
+
yolo: base.yolo,
|
|
46371
|
+
toolInteraction: base.toolInteraction
|
|
46236
46372
|
}).run(compiled.text);
|
|
46237
46373
|
case "pi": {
|
|
46238
46374
|
return createPiRunner({
|
|
@@ -46260,7 +46396,8 @@ function dispatchRunner(runner, base, cwd, options, input2) {
|
|
|
46260
46396
|
abortController: base.abortController,
|
|
46261
46397
|
systemPrompt: base.systemPrompt,
|
|
46262
46398
|
resume: base.resume,
|
|
46263
|
-
yolo: base.yolo
|
|
46399
|
+
yolo: base.yolo,
|
|
46400
|
+
toolInteraction: base.toolInteraction
|
|
46264
46401
|
}).run(compiled.text);
|
|
46265
46402
|
case "copilot": {
|
|
46266
46403
|
const reasoningEfforts = ["low", "medium", "high", "xhigh"];
|
|
@@ -46274,6 +46411,7 @@ function dispatchRunner(runner, base, cwd, options, input2) {
|
|
|
46274
46411
|
resume: base.resume,
|
|
46275
46412
|
yolo: base.yolo,
|
|
46276
46413
|
cwd,
|
|
46414
|
+
toolInteraction: base.toolInteraction,
|
|
46277
46415
|
env: base.env,
|
|
46278
46416
|
abortController: base.abortController,
|
|
46279
46417
|
...options.effort && reasoningEfforts.includes(options.effort) ? {
|
|
@@ -46356,21 +46494,403 @@ import { execFile } from "node:child_process";
|
|
|
46356
46494
|
import { promisify } from "node:util";
|
|
46357
46495
|
var execFileAsync = promisify(execFile);
|
|
46358
46496
|
|
|
46497
|
+
// ../../packages/server-acp/dist/tool-display.js
|
|
46498
|
+
import { isAbsolute as isAbsolute2, resolve as resolve3 } from "node:path";
|
|
46499
|
+
var recordOf = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
46500
|
+
function toolKind(name) {
|
|
46501
|
+
const key = name.toLowerCase().replace(/[\s_-]/g, "");
|
|
46502
|
+
if (/^(read|readfile|list|ls|find|glob)/.test(key))
|
|
46503
|
+
return "read";
|
|
46504
|
+
if (/^(grep|search|websearch|ripgrep)/.test(key))
|
|
46505
|
+
return "search";
|
|
46506
|
+
if (/^(write|edit|multiedit|applypatch|replace|notebookedit)/.test(key))
|
|
46507
|
+
return "edit";
|
|
46508
|
+
if (/^(delete|remove|unlink)/.test(key))
|
|
46509
|
+
return "delete";
|
|
46510
|
+
if (/^(move|rename)/.test(key))
|
|
46511
|
+
return "move";
|
|
46512
|
+
if (/^(bash|shell|execute|exec|terminal|runcommand)/.test(key))
|
|
46513
|
+
return "execute";
|
|
46514
|
+
if (/^(fetch|webfetch|browse)/.test(key))
|
|
46515
|
+
return "fetch";
|
|
46516
|
+
if (/^(todo|plan|updateplan|task|agent)/.test(key))
|
|
46517
|
+
return "think";
|
|
46518
|
+
return "other";
|
|
46519
|
+
}
|
|
46520
|
+
function toolDisplay(name, input2, cwd) {
|
|
46521
|
+
const value = recordOf(input2) ?? {};
|
|
46522
|
+
const kind = toolKind(name);
|
|
46523
|
+
const path3 = [value.file_path, value.path, value.filePath].find((candidate) => typeof candidate === "string" && candidate.length > 0);
|
|
46524
|
+
const location = path3 && (isAbsolute2(path3) ? path3 : cwd ? resolve3(cwd, path3) : void 0);
|
|
46525
|
+
const detail = path3 ?? [
|
|
46526
|
+
value.command,
|
|
46527
|
+
value.query,
|
|
46528
|
+
value.pattern,
|
|
46529
|
+
value.url,
|
|
46530
|
+
value.description
|
|
46531
|
+
].find((candidate) => typeof candidate === "string" && candidate.length > 0);
|
|
46532
|
+
const title = detail ? `${name}: ${detail.slice(0, 160)}` : name;
|
|
46533
|
+
const oldText = value.old_string ?? value.oldText;
|
|
46534
|
+
const newText = value.new_string ?? value.newText ?? value.content;
|
|
46535
|
+
const content = kind === "edit" && path3 && typeof newText === "string" ? [
|
|
46536
|
+
{
|
|
46537
|
+
type: "diff",
|
|
46538
|
+
path: location ?? path3,
|
|
46539
|
+
...typeof oldText === "string" ? { oldText } : {},
|
|
46540
|
+
newText
|
|
46541
|
+
}
|
|
46542
|
+
] : void 0;
|
|
46543
|
+
return {
|
|
46544
|
+
title,
|
|
46545
|
+
kind,
|
|
46546
|
+
...location ? { locations: [{ path: location }] } : {},
|
|
46547
|
+
...content ? { content } : {}
|
|
46548
|
+
};
|
|
46549
|
+
}
|
|
46550
|
+
function contentBlock(value) {
|
|
46551
|
+
const item = recordOf(value);
|
|
46552
|
+
if (!item)
|
|
46553
|
+
return void 0;
|
|
46554
|
+
if (item.type === "text" && typeof item.text === "string")
|
|
46555
|
+
return item;
|
|
46556
|
+
if ((item.type === "image" || item.type === "audio") && typeof item.data === "string" && typeof item.mimeType === "string")
|
|
46557
|
+
return item;
|
|
46558
|
+
if (item.type === "resource_link" && typeof item.uri === "string" && typeof item.name === "string") {
|
|
46559
|
+
return item;
|
|
46560
|
+
}
|
|
46561
|
+
if (item.type === "resource" && recordOf(item.resource))
|
|
46562
|
+
return item;
|
|
46563
|
+
return void 0;
|
|
46564
|
+
}
|
|
46565
|
+
function toolContents(output2) {
|
|
46566
|
+
const value = recordOf(output2);
|
|
46567
|
+
const candidates = Array.isArray(output2) ? output2 : Array.isArray(value?.content) ? value.content : [];
|
|
46568
|
+
const contents = candidates.flatMap((candidate) => {
|
|
46569
|
+
const item = recordOf(candidate);
|
|
46570
|
+
if (!item)
|
|
46571
|
+
return [];
|
|
46572
|
+
if (item.type === "diff" && typeof item.path === "string" && typeof item.newText === "string") {
|
|
46573
|
+
return [item];
|
|
46574
|
+
}
|
|
46575
|
+
if (item.type === "terminal" && typeof item.terminalId === "string") {
|
|
46576
|
+
return [item];
|
|
46577
|
+
}
|
|
46578
|
+
if (item.type === "content" && contentBlock(item.content))
|
|
46579
|
+
return [item];
|
|
46580
|
+
const block = contentBlock(item);
|
|
46581
|
+
return block ? [{ type: "content", content: block }] : [];
|
|
46582
|
+
});
|
|
46583
|
+
if (contents.length > 0)
|
|
46584
|
+
return contents;
|
|
46585
|
+
const text = typeof output2 === "string" ? output2 : JSON.stringify(output2 ?? null);
|
|
46586
|
+
return [{ type: "content", content: { type: "text", text } }];
|
|
46587
|
+
}
|
|
46588
|
+
function planEntries(input2) {
|
|
46589
|
+
const value = recordOf(input2);
|
|
46590
|
+
const entries = value?.todos ?? value?.plan;
|
|
46591
|
+
if (!Array.isArray(entries))
|
|
46592
|
+
return void 0;
|
|
46593
|
+
return entries.flatMap((entry) => {
|
|
46594
|
+
const item = recordOf(entry);
|
|
46595
|
+
if (!item)
|
|
46596
|
+
return [];
|
|
46597
|
+
const description = item.content ?? item.step ?? item.subject;
|
|
46598
|
+
if (typeof description !== "string")
|
|
46599
|
+
return [];
|
|
46600
|
+
const status = item.status === "completed" ? "completed" : item.status === "in_progress" ? "in_progress" : "pending";
|
|
46601
|
+
return [
|
|
46602
|
+
{
|
|
46603
|
+
content: status === "in_progress" && typeof item.activeForm === "string" ? item.activeForm : description,
|
|
46604
|
+
status,
|
|
46605
|
+
priority: item.priority === "high" || item.priority === "low" ? item.priority : "medium"
|
|
46606
|
+
}
|
|
46607
|
+
];
|
|
46608
|
+
});
|
|
46609
|
+
}
|
|
46610
|
+
|
|
46611
|
+
// ../../packages/server-acp/dist/interaction-bridge.js
|
|
46612
|
+
var BUNNY_INTERACTION_RESPOND_METHOD = "_bunny-agent/interaction/respond";
|
|
46613
|
+
var INTERACTIVE_RUNNERS = [
|
|
46614
|
+
"claude",
|
|
46615
|
+
"pi",
|
|
46616
|
+
"gemini",
|
|
46617
|
+
"opencode",
|
|
46618
|
+
"copilot"
|
|
46619
|
+
];
|
|
46620
|
+
function createAcpToolInteraction(input2) {
|
|
46621
|
+
return async (request) => {
|
|
46622
|
+
if (request.signal?.aborted)
|
|
46623
|
+
return { behavior: "deny", message: "The run was cancelled." };
|
|
46624
|
+
const isQuestion = /^(ask_user_question|AskUserQuestion)$/.test(request.toolName);
|
|
46625
|
+
const questions = isQuestion ? parseQuestions(request.input) : void 0;
|
|
46626
|
+
if (isQuestion && !input2.supportsForm) {
|
|
46627
|
+
return {
|
|
46628
|
+
behavior: "deny",
|
|
46629
|
+
message: "The connected ACP client does not support structured questions."
|
|
46630
|
+
};
|
|
46631
|
+
}
|
|
46632
|
+
const form = questions ? buildQuestionForm(questions) : void 0;
|
|
46633
|
+
const options = request.permission?.options ?? [
|
|
46634
|
+
{ optionId: "allow-once", name: "Allow once", kind: "allow_once" },
|
|
46635
|
+
{ optionId: "reject-once", name: "Reject", kind: "reject_once" }
|
|
46636
|
+
];
|
|
46637
|
+
const interaction = input2.registry.create(input2.sessionId, (reply) => {
|
|
46638
|
+
if (!["accept", "decline", "cancel"].includes(reply.action))
|
|
46639
|
+
throw new Error("Invalid interaction action.");
|
|
46640
|
+
if (form && reply.action === "accept")
|
|
46641
|
+
form.answers(reply.content ?? {});
|
|
46642
|
+
if (!form && reply.action !== "cancel" && !options.some((option) => option.optionId === reply.optionId)) {
|
|
46643
|
+
throw new Error("A permission reply must select a reported permission option.");
|
|
46644
|
+
}
|
|
46645
|
+
});
|
|
46646
|
+
const controller = new AbortController();
|
|
46647
|
+
const cancel = () => {
|
|
46648
|
+
void input2.registry.respond(input2.sessionId, interaction.id, { action: "cancel" }).catch(() => void 0);
|
|
46649
|
+
controller.abort();
|
|
46650
|
+
};
|
|
46651
|
+
request.signal?.addEventListener("abort", cancel, { once: true });
|
|
46652
|
+
if (request.signal?.aborted)
|
|
46653
|
+
cancel();
|
|
46654
|
+
const timer = request.timeoutMs === void 0 ? void 0 : setTimeout(cancel, Math.max(0, request.timeoutMs));
|
|
46655
|
+
timer?.unref?.();
|
|
46656
|
+
const meta5 = {
|
|
46657
|
+
"bunny-agent": {
|
|
46658
|
+
interactionId: interaction.id,
|
|
46659
|
+
toolCallId: request.toolCallId
|
|
46660
|
+
}
|
|
46661
|
+
};
|
|
46662
|
+
const remoteReply = form ? input2.client.request("elicitation/create", {
|
|
46663
|
+
sessionId: input2.sessionId,
|
|
46664
|
+
toolCallId: request.toolCallId,
|
|
46665
|
+
mode: "form",
|
|
46666
|
+
message: "The agent needs your answer to continue.",
|
|
46667
|
+
requestedSchema: form.schema,
|
|
46668
|
+
_meta: { ...meta5, "bunny-agent/questions": questions }
|
|
46669
|
+
}, { cancellationSignal: controller.signal }).then((reply) => ({
|
|
46670
|
+
action: reply.action,
|
|
46671
|
+
...reply.action === "accept" && reply.content ? { content: reply.content } : {}
|
|
46672
|
+
})) : permissionRequest(input2, request, options, meta5, controller.signal);
|
|
46673
|
+
void remoteReply.then((reply) => input2.registry.respond(input2.sessionId, interaction.id, reply)).catch(() => input2.registry.respond(input2.sessionId, interaction.id, { action: "cancel" }).catch(() => void 0));
|
|
46674
|
+
try {
|
|
46675
|
+
const reply = await interaction.promise;
|
|
46676
|
+
if (form) {
|
|
46677
|
+
return reply.action === "accept" ? {
|
|
46678
|
+
behavior: "allow",
|
|
46679
|
+
updatedInput: {
|
|
46680
|
+
questions,
|
|
46681
|
+
answers: form.answers(reply.content ?? {})
|
|
46682
|
+
}
|
|
46683
|
+
} : {
|
|
46684
|
+
behavior: "deny",
|
|
46685
|
+
message: reply.action === "decline" ? "The user declined to answer." : "The question was cancelled or expired."
|
|
46686
|
+
};
|
|
46687
|
+
}
|
|
46688
|
+
const selected = options.find((option) => option.optionId === reply.optionId);
|
|
46689
|
+
return selected && ["allow_once", "allow_always"].includes(selected.kind) && reply.action === "accept" ? {
|
|
46690
|
+
behavior: "allow",
|
|
46691
|
+
updatedInput: recordOf(request.input),
|
|
46692
|
+
optionId: selected.optionId
|
|
46693
|
+
} : {
|
|
46694
|
+
behavior: "deny",
|
|
46695
|
+
message: "The user did not authorize this tool.",
|
|
46696
|
+
...selected ? { optionId: selected.optionId } : {}
|
|
46697
|
+
};
|
|
46698
|
+
} finally {
|
|
46699
|
+
input2.registry.acknowledge(interaction.id);
|
|
46700
|
+
if (timer)
|
|
46701
|
+
clearTimeout(timer);
|
|
46702
|
+
request.signal?.removeEventListener("abort", cancel);
|
|
46703
|
+
controller.abort();
|
|
46704
|
+
}
|
|
46705
|
+
};
|
|
46706
|
+
}
|
|
46707
|
+
async function permissionRequest(input2, request, options, meta5, signal) {
|
|
46708
|
+
const reply = await input2.client.request("session/request_permission", {
|
|
46709
|
+
sessionId: input2.sessionId,
|
|
46710
|
+
toolCall: request.permission?.toolCall ?? {
|
|
46711
|
+
toolCallId: request.toolCallId,
|
|
46712
|
+
...toolDisplay(request.toolName, request.input, input2.cwd),
|
|
46713
|
+
status: "pending",
|
|
46714
|
+
rawInput: request.input
|
|
46715
|
+
},
|
|
46716
|
+
options,
|
|
46717
|
+
_meta: { ...request.permission?._meta, ...meta5 }
|
|
46718
|
+
}, { cancellationSignal: signal });
|
|
46719
|
+
if (reply.outcome.outcome !== "selected")
|
|
46720
|
+
return { action: "cancel" };
|
|
46721
|
+
const optionId = reply.outcome.optionId;
|
|
46722
|
+
return {
|
|
46723
|
+
// ACP's selected outcome confirms a choice, including a rejection. Tool
|
|
46724
|
+
// disposition is derived from the selected option's kind by the gate.
|
|
46725
|
+
action: "accept",
|
|
46726
|
+
optionId
|
|
46727
|
+
};
|
|
46728
|
+
}
|
|
46729
|
+
function parseQuestions(input2) {
|
|
46730
|
+
const raw = recordOf(input2)?.questions;
|
|
46731
|
+
if (!Array.isArray(raw) || raw.length === 0 || raw.length > 8)
|
|
46732
|
+
throw new Error("A survey must contain 1 to 8 questions.");
|
|
46733
|
+
return raw.map((item) => {
|
|
46734
|
+
const question = recordOf(item);
|
|
46735
|
+
if (typeof question?.question !== "string" || !question.question.trim())
|
|
46736
|
+
throw new Error("A survey question must have text.");
|
|
46737
|
+
const options = Array.isArray(question.options) ? question.options.map((option) => {
|
|
46738
|
+
const value = recordOf(option);
|
|
46739
|
+
if (typeof value?.label !== "string" || !value.label)
|
|
46740
|
+
throw new Error("Question options must have labels.");
|
|
46741
|
+
return {
|
|
46742
|
+
label: value.label,
|
|
46743
|
+
...typeof value.description === "string" ? { description: value.description } : {}
|
|
46744
|
+
};
|
|
46745
|
+
}) : void 0;
|
|
46746
|
+
return {
|
|
46747
|
+
question: question.question,
|
|
46748
|
+
...typeof question.header === "string" ? { header: question.header } : {},
|
|
46749
|
+
multiSelect: question.multiSelect === true,
|
|
46750
|
+
...question.allowFreeform === false ? { allowFreeform: false } : {},
|
|
46751
|
+
...options ? { options } : {}
|
|
46752
|
+
};
|
|
46753
|
+
});
|
|
46754
|
+
}
|
|
46755
|
+
function buildQuestionForm(questions) {
|
|
46756
|
+
const properties = {};
|
|
46757
|
+
questions.forEach((question, index) => {
|
|
46758
|
+
const key = `question_${index}`;
|
|
46759
|
+
const title = question.header ? `${question.header}: ${question.question}` : question.question;
|
|
46760
|
+
const choices = question.options?.map((option) => option.label);
|
|
46761
|
+
const selectable = choices && question.allowFreeform !== false ? [...choices, "Other"] : choices;
|
|
46762
|
+
properties[key] = choices?.length ? question.multiSelect ? {
|
|
46763
|
+
type: "array",
|
|
46764
|
+
title,
|
|
46765
|
+
items: { type: "string", enum: selectable },
|
|
46766
|
+
minItems: 1
|
|
46767
|
+
} : { type: "string", title, enum: selectable } : { type: "string", title, minLength: 1 };
|
|
46768
|
+
if (choices?.length && question.allowFreeform !== false)
|
|
46769
|
+
properties[`${key}_other`] = {
|
|
46770
|
+
type: "string",
|
|
46771
|
+
title: `Other answer: ${question.question}`
|
|
46772
|
+
};
|
|
46773
|
+
});
|
|
46774
|
+
return {
|
|
46775
|
+
schema: {
|
|
46776
|
+
type: "object",
|
|
46777
|
+
properties,
|
|
46778
|
+
required: questions.map((_, index) => `question_${index}`)
|
|
46779
|
+
},
|
|
46780
|
+
answers: (content) => Object.fromEntries(questions.map((question, index) => {
|
|
46781
|
+
const key = `question_${index}`;
|
|
46782
|
+
const supplied = content[key];
|
|
46783
|
+
const choices = question.options?.map((option) => option.label);
|
|
46784
|
+
const values = question.multiSelect && choices?.length ? Array.isArray(supplied) && supplied.every((item) => typeof item === "string") ? supplied : [] : typeof supplied === "string" && supplied.trim() ? [supplied] : [];
|
|
46785
|
+
if (values.length === 0 || choices?.length && values.some((item) => !choices.includes(item) && !(item === "Other" && question.allowFreeform !== false))) {
|
|
46786
|
+
throw new Error(`Invalid answer for ${question.question}`);
|
|
46787
|
+
}
|
|
46788
|
+
const answer = values.map((value) => {
|
|
46789
|
+
if (value !== "Other" || !choices?.length)
|
|
46790
|
+
return value;
|
|
46791
|
+
const other = content[`${key}_other`];
|
|
46792
|
+
if (typeof other !== "string" || !other.trim())
|
|
46793
|
+
throw new Error(`A custom answer is required for ${question.question}`);
|
|
46794
|
+
return other;
|
|
46795
|
+
}).join(", ");
|
|
46796
|
+
return [question.question, answer];
|
|
46797
|
+
}))
|
|
46798
|
+
};
|
|
46799
|
+
}
|
|
46800
|
+
|
|
46801
|
+
// ../../packages/server-acp/dist/interaction-registry.js
|
|
46802
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
46803
|
+
var AcpInteractionRegistry = class {
|
|
46804
|
+
pending = /* @__PURE__ */ new Map();
|
|
46805
|
+
create(sessionId, validate2) {
|
|
46806
|
+
const id = randomUUID2();
|
|
46807
|
+
let resolve6;
|
|
46808
|
+
let acknowledge;
|
|
46809
|
+
const promise3 = new Promise((done) => {
|
|
46810
|
+
resolve6 = done;
|
|
46811
|
+
});
|
|
46812
|
+
const accepted = new Promise((done) => {
|
|
46813
|
+
acknowledge = done;
|
|
46814
|
+
});
|
|
46815
|
+
this.pending.set(id, {
|
|
46816
|
+
sessionId,
|
|
46817
|
+
promise: promise3,
|
|
46818
|
+
resolve: resolve6,
|
|
46819
|
+
accepted,
|
|
46820
|
+
acknowledge,
|
|
46821
|
+
validate: validate2
|
|
46822
|
+
});
|
|
46823
|
+
return { id, promise: promise3 };
|
|
46824
|
+
}
|
|
46825
|
+
async respond(sessionId, id, reply) {
|
|
46826
|
+
const pending = this.pending.get(id);
|
|
46827
|
+
if (!pending || pending.sessionId !== sessionId)
|
|
46828
|
+
throw new Error("Interaction is unknown or expired.");
|
|
46829
|
+
pending.validate?.(reply);
|
|
46830
|
+
if (pending.reply && canonical(pending.reply) !== canonical(reply)) {
|
|
46831
|
+
throw new Error("Interaction was already resolved with a different decision.");
|
|
46832
|
+
}
|
|
46833
|
+
if (!pending.reply) {
|
|
46834
|
+
pending.reply = reply;
|
|
46835
|
+
pending.resolve(reply);
|
|
46836
|
+
}
|
|
46837
|
+
await pending.accepted;
|
|
46838
|
+
return { ok: true };
|
|
46839
|
+
}
|
|
46840
|
+
acknowledge(id) {
|
|
46841
|
+
this.pending.get(id)?.acknowledge();
|
|
46842
|
+
if (this.pending.size > 1e3) {
|
|
46843
|
+
for (const [key, pending] of this.pending) {
|
|
46844
|
+
if (pending.reply && key !== id) {
|
|
46845
|
+
this.pending.delete(key);
|
|
46846
|
+
break;
|
|
46847
|
+
}
|
|
46848
|
+
}
|
|
46849
|
+
}
|
|
46850
|
+
}
|
|
46851
|
+
};
|
|
46852
|
+
function canonical(value) {
|
|
46853
|
+
if (Array.isArray(value))
|
|
46854
|
+
return `[${value.map(canonical).join(",")}]`;
|
|
46855
|
+
if (value && typeof value === "object") {
|
|
46856
|
+
return `{${Object.entries(value).sort(([a], [b]) => a.localeCompare(b)).map(([key, item]) => `${JSON.stringify(key)}:${canonical(item)}`).join(",")}}`;
|
|
46857
|
+
}
|
|
46858
|
+
return JSON.stringify(value) ?? "undefined";
|
|
46859
|
+
}
|
|
46860
|
+
|
|
46861
|
+
// ../../packages/server-acp/dist/lifecycle.js
|
|
46862
|
+
var BUNNY_ACP_EVENT_METHOD = "_bunny-agent/session_event";
|
|
46863
|
+
|
|
46359
46864
|
// ../../packages/server-acp/dist/session-update-serializer.js
|
|
46360
|
-
var asText = (value) => typeof value === "string" ? value : JSON.stringify(value ?? null);
|
|
46361
46865
|
var AcpSessionUpdateSerializer = class {
|
|
46866
|
+
options;
|
|
46362
46867
|
startedTools = /* @__PURE__ */ new Set();
|
|
46868
|
+
terminalTools = /* @__PURE__ */ new Set();
|
|
46363
46869
|
toolTitles = /* @__PURE__ */ new Map();
|
|
46870
|
+
toolInputs = /* @__PURE__ */ new Map();
|
|
46871
|
+
completeToolInputs = /* @__PURE__ */ new Map();
|
|
46872
|
+
taskPlan = /* @__PURE__ */ new Map();
|
|
46364
46873
|
stopReasonValue = "end_turn";
|
|
46365
46874
|
errorTextValue;
|
|
46366
46875
|
sessionIdValue;
|
|
46367
46876
|
inputTokensValue = 0;
|
|
46368
46877
|
outputTokensValue = 0;
|
|
46369
|
-
|
|
46878
|
+
usageReported = false;
|
|
46879
|
+
extraUsage = {};
|
|
46880
|
+
nativePassthrough = false;
|
|
46881
|
+
stepNumber = 0;
|
|
46882
|
+
activeStepId;
|
|
46883
|
+
messageId;
|
|
46884
|
+
turnId;
|
|
46885
|
+
now;
|
|
46886
|
+
constructor(options = {}) {
|
|
46887
|
+
this.options = options;
|
|
46888
|
+
this.turnId = options.turnId ?? "turn";
|
|
46889
|
+
this.now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
46890
|
+
}
|
|
46370
46891
|
get stopReason() {
|
|
46371
|
-
return this.stopReasonValue;
|
|
46892
|
+
return this.options.signal?.aborted ? "cancelled" : this.stopReasonValue;
|
|
46372
46893
|
}
|
|
46373
|
-
/** Error text emitted by the runner, if the turn failed. */
|
|
46374
46894
|
get errorText() {
|
|
46375
46895
|
return this.errorTextValue;
|
|
46376
46896
|
}
|
|
@@ -46378,161 +46898,461 @@ var AcpSessionUpdateSerializer = class {
|
|
|
46378
46898
|
return this.sessionIdValue;
|
|
46379
46899
|
}
|
|
46380
46900
|
get usage() {
|
|
46381
|
-
|
|
46382
|
-
if (totalTokens === 0)
|
|
46901
|
+
if (!this.usageReported)
|
|
46383
46902
|
return void 0;
|
|
46384
46903
|
return {
|
|
46904
|
+
...this.extraUsage,
|
|
46385
46905
|
inputTokens: this.inputTokensValue,
|
|
46386
46906
|
outputTokens: this.outputTokensValue,
|
|
46387
|
-
totalTokens
|
|
46907
|
+
totalTokens: this.extraUsage.totalTokens ?? this.inputTokensValue + this.outputTokensValue
|
|
46388
46908
|
};
|
|
46389
46909
|
}
|
|
46910
|
+
/** Compatibility API for consumers interested only in standard ACP updates. */
|
|
46390
46911
|
async *serialize(chunks) {
|
|
46391
|
-
for await (const
|
|
46392
|
-
|
|
46912
|
+
for await (const event of this.serializeEvents(chunks)) {
|
|
46913
|
+
if (event.type === "update")
|
|
46914
|
+
yield event.update;
|
|
46915
|
+
}
|
|
46916
|
+
}
|
|
46917
|
+
async *serializeEvents(chunks) {
|
|
46918
|
+
yield this.lifecycle("turn_started");
|
|
46919
|
+
try {
|
|
46920
|
+
for await (const chunk of chunks)
|
|
46921
|
+
yield* this.convert(chunk);
|
|
46922
|
+
} catch (error109) {
|
|
46923
|
+
this.errorTextValue = error109 instanceof Error ? error109.message : String(error109);
|
|
46924
|
+
this.stopReasonValue = "refusal";
|
|
46925
|
+
throw error109;
|
|
46926
|
+
} finally {
|
|
46927
|
+
for (const id of this.startedTools) {
|
|
46928
|
+
if (this.terminalTools.has(id))
|
|
46929
|
+
continue;
|
|
46930
|
+
this.terminalTools.add(id);
|
|
46931
|
+
const message = this.stopReason === "cancelled" ? "The tool was interrupted when the turn was cancelled." : "The turn ended before this tool returned.";
|
|
46932
|
+
yield this.update({
|
|
46933
|
+
sessionUpdate: "tool_call_update",
|
|
46934
|
+
toolCallId: id,
|
|
46935
|
+
status: "failed",
|
|
46936
|
+
rawOutput: message,
|
|
46937
|
+
content: [
|
|
46938
|
+
{ type: "content", content: { type: "text", text: message } }
|
|
46939
|
+
],
|
|
46940
|
+
_meta: { "bunny-agent/interrupted": true }
|
|
46941
|
+
});
|
|
46942
|
+
}
|
|
46943
|
+
if (this.activeStepId) {
|
|
46944
|
+
yield this.lifecycle("step_finished", { stepId: this.activeStepId });
|
|
46945
|
+
this.activeStepId = void 0;
|
|
46946
|
+
}
|
|
46947
|
+
yield this.lifecycle("turn_finished", {
|
|
46948
|
+
stopReason: this.stopReason,
|
|
46949
|
+
...this.usage ? {
|
|
46950
|
+
usage: Object.fromEntries(Object.entries(this.usage).filter(([, value]) => typeof value === "number"))
|
|
46951
|
+
} : {}
|
|
46952
|
+
});
|
|
46393
46953
|
}
|
|
46394
46954
|
}
|
|
46955
|
+
lifecycle(type, fields = {}) {
|
|
46956
|
+
return {
|
|
46957
|
+
type: "lifecycle",
|
|
46958
|
+
event: {
|
|
46959
|
+
version: 1,
|
|
46960
|
+
type,
|
|
46961
|
+
turnId: this.turnId,
|
|
46962
|
+
at: this.now(),
|
|
46963
|
+
...fields
|
|
46964
|
+
}
|
|
46965
|
+
};
|
|
46966
|
+
}
|
|
46967
|
+
update(update) {
|
|
46968
|
+
return { type: "update", update };
|
|
46969
|
+
}
|
|
46970
|
+
metadata(chunk) {
|
|
46971
|
+
const value = chunk;
|
|
46972
|
+
const original = recordOf(value._meta);
|
|
46973
|
+
const providerMetadata = recordOf(value.providerMetadata);
|
|
46974
|
+
const parentToolCallId = value.parentToolCallId ?? value.parent_tool_use_id;
|
|
46975
|
+
if (!original && !providerMetadata && typeof parentToolCallId !== "string")
|
|
46976
|
+
return void 0;
|
|
46977
|
+
return {
|
|
46978
|
+
...original,
|
|
46979
|
+
...providerMetadata ? { "bunny-agent/providerMetadata": providerMetadata } : {},
|
|
46980
|
+
...typeof parentToolCallId === "string" ? { "bunny-agent/parentToolCallId": parentToolCallId } : {}
|
|
46981
|
+
};
|
|
46982
|
+
}
|
|
46395
46983
|
*convert(chunk) {
|
|
46984
|
+
const value = chunk;
|
|
46985
|
+
const meta5 = this.metadata(chunk);
|
|
46986
|
+
if (chunk.type === "data-acp-session-update") {
|
|
46987
|
+
const original = recordOf(value.data);
|
|
46988
|
+
if (typeof original?.sessionUpdate === "string") {
|
|
46989
|
+
this.nativePassthrough = true;
|
|
46990
|
+
if ((original.sessionUpdate === "tool_call" || original.sessionUpdate === "tool_call_update") && typeof original.toolCallId === "string") {
|
|
46991
|
+
this.startedTools.add(original.toolCallId);
|
|
46992
|
+
if (original.status === "completed" || original.status === "failed")
|
|
46993
|
+
this.terminalTools.add(original.toolCallId);
|
|
46994
|
+
}
|
|
46995
|
+
yield this.update(original);
|
|
46996
|
+
}
|
|
46997
|
+
return;
|
|
46998
|
+
}
|
|
46999
|
+
if (this.nativePassthrough && ![
|
|
47000
|
+
"finish",
|
|
47001
|
+
"message-metadata",
|
|
47002
|
+
"error",
|
|
47003
|
+
"step-finish",
|
|
47004
|
+
"finish-step"
|
|
47005
|
+
].includes(chunk.type))
|
|
47006
|
+
return;
|
|
46396
47007
|
switch (chunk.type) {
|
|
46397
|
-
case "text-
|
|
46398
|
-
|
|
46399
|
-
|
|
46400
|
-
|
|
46401
|
-
|
|
46402
|
-
|
|
46403
|
-
|
|
47008
|
+
case "text-start":
|
|
47009
|
+
if (typeof value.id === "string")
|
|
47010
|
+
this.messageId = value.id;
|
|
47011
|
+
return;
|
|
47012
|
+
case "text-delta":
|
|
47013
|
+
case "reasoning":
|
|
47014
|
+
case "reasoning-delta": {
|
|
47015
|
+
const text = chunk.type === "reasoning" ? value.text : value.delta;
|
|
47016
|
+
if (typeof text !== "string")
|
|
47017
|
+
return;
|
|
47018
|
+
if (chunk.type === "text-delta" && typeof value.id === "string")
|
|
47019
|
+
this.messageId = value.id;
|
|
47020
|
+
yield this.update({
|
|
47021
|
+
sessionUpdate: chunk.type === "text-delta" ? "agent_message_chunk" : "agent_thought_chunk",
|
|
47022
|
+
...typeof value.id === "string" ? { messageId: value.id } : {},
|
|
47023
|
+
content: { type: "text", text },
|
|
47024
|
+
...meta5 ? { _meta: meta5 } : {}
|
|
47025
|
+
});
|
|
46404
47026
|
return;
|
|
46405
47027
|
}
|
|
46406
|
-
case "
|
|
46407
|
-
|
|
46408
|
-
|
|
46409
|
-
|
|
46410
|
-
|
|
46411
|
-
|
|
47028
|
+
case "text-end": {
|
|
47029
|
+
if (!meta5)
|
|
47030
|
+
return;
|
|
47031
|
+
yield this.update({
|
|
47032
|
+
sessionUpdate: "agent_message_chunk",
|
|
47033
|
+
messageId: value.id,
|
|
47034
|
+
content: { type: "text", text: "" },
|
|
47035
|
+
_meta: meta5
|
|
47036
|
+
});
|
|
46412
47037
|
return;
|
|
46413
47038
|
}
|
|
46414
47039
|
case "tool-input-start": {
|
|
46415
|
-
|
|
46416
|
-
|
|
47040
|
+
if (typeof value.toolCallId !== "string")
|
|
47041
|
+
return;
|
|
47042
|
+
yield* this.openToolCall(value.toolCallId, typeof value.toolName === "string" ? value.toolName : void 0, meta5);
|
|
47043
|
+
return;
|
|
47044
|
+
}
|
|
47045
|
+
case "tool-input-delta": {
|
|
47046
|
+
if (typeof value.toolCallId !== "string" || typeof value.inputTextDelta !== "string")
|
|
47047
|
+
return;
|
|
47048
|
+
const inputText = (this.toolInputs.get(value.toolCallId) ?? "") + value.inputTextDelta;
|
|
47049
|
+
this.toolInputs.set(value.toolCallId, inputText);
|
|
47050
|
+
yield* this.openToolCall(value.toolCallId, this.toolTitles.get(value.toolCallId));
|
|
47051
|
+
yield this.update({
|
|
47052
|
+
sessionUpdate: "tool_call_update",
|
|
47053
|
+
toolCallId: value.toolCallId,
|
|
47054
|
+
_meta: { ...meta5, "bunny-agent/inputText": inputText }
|
|
47055
|
+
});
|
|
46417
47056
|
return;
|
|
46418
47057
|
}
|
|
46419
47058
|
case "tool-input-available": {
|
|
46420
|
-
|
|
46421
|
-
|
|
46422
|
-
|
|
47059
|
+
if (typeof value.toolCallId !== "string")
|
|
47060
|
+
return;
|
|
47061
|
+
const name = typeof value.toolName === "string" ? value.toolName : this.toolTitles.get(value.toolCallId) ?? "tool";
|
|
47062
|
+
this.completeToolInputs.set(value.toolCallId, value.input);
|
|
47063
|
+
yield* this.openToolCall(value.toolCallId, name, meta5);
|
|
47064
|
+
yield this.update({
|
|
46423
47065
|
sessionUpdate: "tool_call_update",
|
|
46424
|
-
toolCallId,
|
|
47066
|
+
toolCallId: value.toolCallId,
|
|
47067
|
+
...toolDisplay(name, value.input, this.options.cwd),
|
|
46425
47068
|
status: "in_progress",
|
|
46426
|
-
rawInput:
|
|
46427
|
-
|
|
47069
|
+
rawInput: value.input,
|
|
47070
|
+
...meta5 ? { _meta: meta5 } : {}
|
|
47071
|
+
});
|
|
47072
|
+
const entries = planEntries(value.input);
|
|
47073
|
+
if (entries && /todo|plan/i.test(name))
|
|
47074
|
+
yield this.update({ sessionUpdate: "plan", entries });
|
|
46428
47075
|
return;
|
|
46429
47076
|
}
|
|
46430
|
-
case "tool-output-available":
|
|
46431
|
-
|
|
46432
|
-
|
|
46433
|
-
|
|
47077
|
+
case "tool-output-available":
|
|
47078
|
+
case "tool-output-error":
|
|
47079
|
+
case "tool-input-error":
|
|
47080
|
+
case "tool-output-denied": {
|
|
47081
|
+
if (typeof value.toolCallId !== "string")
|
|
47082
|
+
return;
|
|
47083
|
+
yield* this.openToolCall(value.toolCallId, this.toolTitles.get(value.toolCallId));
|
|
47084
|
+
const failed = chunk.type !== "tool-output-available" || value.isError === true;
|
|
47085
|
+
const output2 = chunk.type === "tool-output-denied" ? "Tool execution was denied." : chunk.type === "tool-output-available" ? value.output : value.errorText;
|
|
47086
|
+
this.terminalTools.add(value.toolCallId);
|
|
47087
|
+
yield this.update({
|
|
46434
47088
|
sessionUpdate: "tool_call_update",
|
|
46435
|
-
toolCallId,
|
|
46436
|
-
status:
|
|
47089
|
+
toolCallId: value.toolCallId,
|
|
47090
|
+
status: failed ? "failed" : "completed",
|
|
46437
47091
|
rawOutput: output2,
|
|
46438
|
-
content:
|
|
46439
|
-
|
|
46440
|
-
|
|
46441
|
-
|
|
47092
|
+
content: toolContents(output2),
|
|
47093
|
+
...meta5 ? { _meta: meta5 } : {}
|
|
47094
|
+
});
|
|
47095
|
+
if (!failed) {
|
|
47096
|
+
const entries = this.updateTaskPlan(value.toolCallId, output2);
|
|
47097
|
+
if (entries)
|
|
47098
|
+
yield this.update({ sessionUpdate: "plan", entries });
|
|
47099
|
+
}
|
|
47100
|
+
return;
|
|
47101
|
+
}
|
|
47102
|
+
case "file":
|
|
47103
|
+
case "source-url":
|
|
47104
|
+
case "source-document": {
|
|
47105
|
+
const uri = value.url ?? value.uri;
|
|
47106
|
+
const name = value.filename ?? value.title ?? value.sourceId ?? "Resource";
|
|
47107
|
+
const mimeType = value.mediaType ?? value.mimeType;
|
|
47108
|
+
let content;
|
|
47109
|
+
if (typeof uri === "string") {
|
|
47110
|
+
const inline = /^data:([^;,]+);base64,(.*)$/s.exec(uri);
|
|
47111
|
+
content = inline ? inline[1]?.startsWith("image/") ? { type: "image", mimeType: inline[1], data: inline[2] ?? "" } : inline[1]?.startsWith("audio/") ? { type: "audio", mimeType: inline[1], data: inline[2] ?? "" } : {
|
|
47112
|
+
type: "resource",
|
|
47113
|
+
resource: {
|
|
47114
|
+
uri: String(name),
|
|
47115
|
+
mimeType: inline[1],
|
|
47116
|
+
blob: inline[2] ?? ""
|
|
46442
47117
|
}
|
|
46443
|
-
|
|
46444
|
-
|
|
47118
|
+
} : {
|
|
47119
|
+
type: "resource_link",
|
|
47120
|
+
uri,
|
|
47121
|
+
name: String(name),
|
|
47122
|
+
...typeof mimeType === "string" ? { mimeType } : {}
|
|
47123
|
+
};
|
|
47124
|
+
} else if (chunk.type === "source-document") {
|
|
47125
|
+
content = {
|
|
47126
|
+
type: "resource_link",
|
|
47127
|
+
uri: `bunny-source:${encodeURIComponent(String(value.sourceId ?? name))}`,
|
|
47128
|
+
name: String(name),
|
|
47129
|
+
...typeof mimeType === "string" ? { mimeType } : {}
|
|
47130
|
+
};
|
|
47131
|
+
}
|
|
47132
|
+
if (content)
|
|
47133
|
+
yield this.update({
|
|
47134
|
+
sessionUpdate: "agent_message_chunk",
|
|
47135
|
+
content,
|
|
47136
|
+
...typeof value.id === "string" ? { messageId: value.id } : this.messageId ? { messageId: this.messageId } : {},
|
|
47137
|
+
_meta: {
|
|
47138
|
+
...meta5,
|
|
47139
|
+
...value.sourceId ? { "bunny-agent/sourceId": value.sourceId } : {}
|
|
47140
|
+
}
|
|
47141
|
+
});
|
|
47142
|
+
if (chunk.type === "file" && typeof uri === "string" && !uri.startsWith("data:")) {
|
|
47143
|
+
yield this.lifecycle("resource_update", {
|
|
47144
|
+
resource: {
|
|
47145
|
+
id: String(value.id ?? uri),
|
|
47146
|
+
uri,
|
|
47147
|
+
name: String(name),
|
|
47148
|
+
...typeof mimeType === "string" ? { mimeType } : {}
|
|
47149
|
+
}
|
|
47150
|
+
});
|
|
47151
|
+
}
|
|
46445
47152
|
return;
|
|
46446
47153
|
}
|
|
46447
|
-
case "
|
|
46448
|
-
|
|
46449
|
-
|
|
46450
|
-
|
|
46451
|
-
|
|
46452
|
-
|
|
46453
|
-
status: "failed",
|
|
46454
|
-
rawOutput: errorText,
|
|
46455
|
-
content: [
|
|
46456
|
-
{ type: "content", content: { type: "text", text: errorText } }
|
|
46457
|
-
]
|
|
46458
|
-
};
|
|
47154
|
+
case "start-step":
|
|
47155
|
+
case "step-start": {
|
|
47156
|
+
if (this.activeStepId)
|
|
47157
|
+
yield this.lifecycle("step_finished", { stepId: this.activeStepId });
|
|
47158
|
+
this.activeStepId = typeof value.stepId === "string" ? value.stepId : typeof value.id === "string" ? value.id : `${this.turnId}:step:${++this.stepNumber}`;
|
|
47159
|
+
yield this.lifecycle("step_started", { stepId: this.activeStepId });
|
|
46459
47160
|
return;
|
|
46460
47161
|
}
|
|
46461
|
-
case "
|
|
46462
|
-
|
|
46463
|
-
|
|
46464
|
-
|
|
47162
|
+
case "finish-step":
|
|
47163
|
+
case "step-finish": {
|
|
47164
|
+
const usage = recordOf(value.usage);
|
|
47165
|
+
if (usage) {
|
|
47166
|
+
this.usageReported = true;
|
|
47167
|
+
this.inputTokensValue += typeof usage.inputTokens === "number" ? usage.inputTokens : 0;
|
|
47168
|
+
this.outputTokensValue += typeof usage.outputTokens === "number" ? usage.outputTokens : 0;
|
|
47169
|
+
}
|
|
47170
|
+
if (this.activeStepId)
|
|
47171
|
+
yield this.lifecycle("step_finished", { stepId: this.activeStepId });
|
|
47172
|
+
this.activeStepId = void 0;
|
|
46465
47173
|
return;
|
|
46466
47174
|
}
|
|
47175
|
+
case "error":
|
|
47176
|
+
this.errorTextValue = typeof value.errorText === "string" ? value.errorText : "Runner failed.";
|
|
47177
|
+
this.stopReasonValue = "refusal";
|
|
47178
|
+
return;
|
|
46467
47179
|
case "finish": {
|
|
46468
|
-
|
|
46469
|
-
this.captureMetadata(messageMetadata);
|
|
47180
|
+
this.captureMetadata(value.messageMetadata);
|
|
46470
47181
|
if (this.errorTextValue === void 0) {
|
|
46471
|
-
|
|
47182
|
+
const metadata = recordOf(value.messageMetadata);
|
|
47183
|
+
this.stopReasonValue = isStopReason(metadata?.acpStopReason) ? metadata.acpStopReason : mapFinishReason2(value.finishReason);
|
|
46472
47184
|
}
|
|
46473
47185
|
return;
|
|
46474
47186
|
}
|
|
46475
|
-
case "
|
|
46476
|
-
|
|
46477
|
-
this.
|
|
46478
|
-
|
|
46479
|
-
|
|
46480
|
-
|
|
46481
|
-
|
|
46482
|
-
this.captureMetadata(chunk.messageMetadata);
|
|
47187
|
+
case "message-metadata":
|
|
47188
|
+
this.captureMetadata(value.messageMetadata);
|
|
47189
|
+
yield this.update({
|
|
47190
|
+
sessionUpdate: "agent_message_chunk",
|
|
47191
|
+
content: { type: "text", text: "" },
|
|
47192
|
+
_meta: { "bunny-agent/messageMetadata": value.messageMetadata }
|
|
47193
|
+
});
|
|
46483
47194
|
return;
|
|
47195
|
+
default: {
|
|
47196
|
+
const data = recordOf(value.data);
|
|
47197
|
+
if (chunk.type === "data-artifact" && data) {
|
|
47198
|
+
const uri = data.uri ?? data.url ?? data.path;
|
|
47199
|
+
if (typeof uri === "string") {
|
|
47200
|
+
yield this.lifecycle("resource_update", {
|
|
47201
|
+
resource: {
|
|
47202
|
+
id: String(data.id ?? data.artifactId ?? uri),
|
|
47203
|
+
uri,
|
|
47204
|
+
name: String(data.name ?? data.title ?? data.artifactId ?? "Artifact"),
|
|
47205
|
+
...typeof data.mimeType === "string" ? { mimeType: data.mimeType } : {},
|
|
47206
|
+
_meta: data
|
|
47207
|
+
}
|
|
47208
|
+
});
|
|
47209
|
+
}
|
|
47210
|
+
} else if ((chunk.type === "data-job" || chunk.type === "data-agent-job") && data && typeof data.id === "string" && typeof data.status === "string") {
|
|
47211
|
+
yield this.lifecycle("job_update", {
|
|
47212
|
+
job: {
|
|
47213
|
+
id: data.id,
|
|
47214
|
+
title: typeof data.title === "string" ? data.title : "Background task",
|
|
47215
|
+
status: data.status,
|
|
47216
|
+
...typeof data.message === "string" ? { message: data.message } : {}
|
|
47217
|
+
}
|
|
47218
|
+
});
|
|
47219
|
+
}
|
|
47220
|
+
const block = contentBlock(value.content);
|
|
47221
|
+
if (block)
|
|
47222
|
+
yield this.update({
|
|
47223
|
+
sessionUpdate: "agent_message_chunk",
|
|
47224
|
+
content: block,
|
|
47225
|
+
...meta5 ? { _meta: meta5 } : {}
|
|
47226
|
+
});
|
|
47227
|
+
else if (chunk.type.startsWith("data-") || chunk.type === "compaction") {
|
|
47228
|
+
yield this.update({
|
|
47229
|
+
sessionUpdate: "agent_message_chunk",
|
|
47230
|
+
content: { type: "text", text: "" },
|
|
47231
|
+
_meta: { "bunny-agent/runnerData": value }
|
|
47232
|
+
});
|
|
47233
|
+
}
|
|
46484
47234
|
}
|
|
46485
|
-
// text-start/text-end have no ACP equivalent (agent_message_chunk carries
|
|
46486
|
-
// messageId), and tool-input-delta has no incremental-input counterpart.
|
|
46487
|
-
default:
|
|
46488
|
-
return;
|
|
46489
47235
|
}
|
|
46490
47236
|
}
|
|
46491
47237
|
captureMetadata(metadata) {
|
|
46492
|
-
|
|
47238
|
+
const value = recordOf(metadata);
|
|
47239
|
+
if (!value)
|
|
46493
47240
|
return;
|
|
46494
|
-
const value = metadata;
|
|
46495
47241
|
const sessionId = value.sessionId ?? value.session_id ?? value.sessionFile;
|
|
46496
|
-
if (typeof sessionId === "string" && sessionId.length > 0)
|
|
47242
|
+
if (typeof sessionId === "string" && sessionId.length > 0)
|
|
46497
47243
|
this.sessionIdValue = sessionId;
|
|
46498
|
-
|
|
46499
|
-
|
|
46500
|
-
if (!usage || typeof usage !== "object")
|
|
47244
|
+
const usage = recordOf(value.usage);
|
|
47245
|
+
if (!usage)
|
|
46501
47246
|
return;
|
|
46502
|
-
const
|
|
46503
|
-
|
|
46504
|
-
|
|
46505
|
-
|
|
46506
|
-
|
|
46507
|
-
|
|
46508
|
-
|
|
46509
|
-
|
|
46510
|
-
|
|
46511
|
-
|
|
47247
|
+
const input2 = usage.inputTokens ?? usage.input_tokens;
|
|
47248
|
+
const output2 = usage.outputTokens ?? usage.output_tokens;
|
|
47249
|
+
if (typeof input2 === "number") {
|
|
47250
|
+
this.inputTokensValue = Math.max(this.inputTokensValue, input2);
|
|
47251
|
+
this.usageReported = true;
|
|
47252
|
+
}
|
|
47253
|
+
if (typeof output2 === "number") {
|
|
47254
|
+
this.outputTokensValue = Math.max(this.outputTokensValue, output2);
|
|
47255
|
+
this.usageReported = true;
|
|
47256
|
+
}
|
|
47257
|
+
for (const [key, alias] of [
|
|
47258
|
+
["cachedReadTokens", "cache_read_input_tokens"],
|
|
47259
|
+
["cachedWriteTokens", "cache_creation_input_tokens"],
|
|
47260
|
+
["thoughtTokens", "reasoning_tokens"],
|
|
47261
|
+
["totalTokens", "total_tokens"]
|
|
47262
|
+
]) {
|
|
47263
|
+
const count = usage[key] ?? usage[alias];
|
|
47264
|
+
if (typeof count === "number")
|
|
47265
|
+
this.extraUsage[key] = count;
|
|
47266
|
+
}
|
|
47267
|
+
}
|
|
47268
|
+
*openToolCall(id, name, meta5) {
|
|
47269
|
+
if (name)
|
|
47270
|
+
this.toolTitles.set(id, name);
|
|
47271
|
+
if (this.startedTools.has(id))
|
|
46512
47272
|
return;
|
|
46513
|
-
this.startedTools.add(
|
|
46514
|
-
const title =
|
|
46515
|
-
this.toolTitles.set(
|
|
46516
|
-
yield {
|
|
47273
|
+
this.startedTools.add(id);
|
|
47274
|
+
const title = name ?? "tool";
|
|
47275
|
+
this.toolTitles.set(id, title);
|
|
47276
|
+
yield this.update({
|
|
46517
47277
|
sessionUpdate: "tool_call",
|
|
46518
|
-
toolCallId,
|
|
47278
|
+
toolCallId: id,
|
|
46519
47279
|
title,
|
|
46520
|
-
|
|
47280
|
+
kind: toolKind(title),
|
|
47281
|
+
status: "pending",
|
|
47282
|
+
_meta: { ...meta5, "bunny-agent/toolName": title }
|
|
47283
|
+
});
|
|
47284
|
+
}
|
|
47285
|
+
updateTaskPlan(id, output2) {
|
|
47286
|
+
const name = this.toolTitles.get(id)?.toLowerCase().replace(/[\s_-]/g, "");
|
|
47287
|
+
if (!["taskcreate", "taskupdate", "tasklist"].includes(name ?? ""))
|
|
47288
|
+
return void 0;
|
|
47289
|
+
const input2 = recordOf(this.completeToolInputs.get(id)) ?? {};
|
|
47290
|
+
let result = recordOf(output2);
|
|
47291
|
+
if (!result && typeof output2 === "string") {
|
|
47292
|
+
try {
|
|
47293
|
+
result = recordOf(JSON.parse(output2));
|
|
47294
|
+
} catch {
|
|
47295
|
+
const created = /^Task #(\S+) created successfully: (.+)$/m.exec(output2);
|
|
47296
|
+
if (created)
|
|
47297
|
+
result = { task: { id: created[1], subject: created[2] } };
|
|
47298
|
+
}
|
|
47299
|
+
}
|
|
47300
|
+
const makeEntry = (task) => {
|
|
47301
|
+
const content = task.subject ?? task.content;
|
|
47302
|
+
if (typeof content !== "string")
|
|
47303
|
+
return void 0;
|
|
47304
|
+
return {
|
|
47305
|
+
content,
|
|
47306
|
+
priority: "medium",
|
|
47307
|
+
status: task.status === "completed" ? "completed" : task.status === "in_progress" ? "in_progress" : "pending"
|
|
47308
|
+
};
|
|
46521
47309
|
};
|
|
47310
|
+
if (name === "tasklist" && Array.isArray(result?.tasks)) {
|
|
47311
|
+
this.taskPlan.clear();
|
|
47312
|
+
for (const task of result.tasks) {
|
|
47313
|
+
const value = recordOf(task);
|
|
47314
|
+
const entry = value && makeEntry(value);
|
|
47315
|
+
if (value && typeof value.id === "string" && entry)
|
|
47316
|
+
this.taskPlan.set(value.id, entry);
|
|
47317
|
+
}
|
|
47318
|
+
} else if (name === "taskcreate") {
|
|
47319
|
+
const task = recordOf(result?.task);
|
|
47320
|
+
const entry = makeEntry({ ...input2, ...task });
|
|
47321
|
+
if (typeof task?.id !== "string" || !entry)
|
|
47322
|
+
return void 0;
|
|
47323
|
+
this.taskPlan.set(task.id, entry);
|
|
47324
|
+
} else if (name === "taskupdate" && typeof input2.taskId === "string") {
|
|
47325
|
+
if (input2.status === "deleted")
|
|
47326
|
+
this.taskPlan.delete(input2.taskId);
|
|
47327
|
+
else {
|
|
47328
|
+
const previous = this.taskPlan.get(input2.taskId);
|
|
47329
|
+
const entry = makeEntry({ ...previous, ...input2 });
|
|
47330
|
+
if (!entry)
|
|
47331
|
+
return void 0;
|
|
47332
|
+
this.taskPlan.set(input2.taskId, entry);
|
|
47333
|
+
}
|
|
47334
|
+
} else
|
|
47335
|
+
return void 0;
|
|
47336
|
+
return [...this.taskPlan.values()];
|
|
46522
47337
|
}
|
|
46523
47338
|
};
|
|
46524
|
-
function
|
|
46525
|
-
|
|
46526
|
-
|
|
46527
|
-
|
|
46528
|
-
|
|
46529
|
-
|
|
46530
|
-
|
|
46531
|
-
|
|
46532
|
-
|
|
46533
|
-
|
|
46534
|
-
|
|
46535
|
-
|
|
47339
|
+
function isStopReason(value) {
|
|
47340
|
+
return typeof value === "string" && [
|
|
47341
|
+
"end_turn",
|
|
47342
|
+
"max_tokens",
|
|
47343
|
+
"max_turn_requests",
|
|
47344
|
+
"refusal",
|
|
47345
|
+
"cancelled"
|
|
47346
|
+
].includes(value);
|
|
47347
|
+
}
|
|
47348
|
+
function mapFinishReason2(reason) {
|
|
47349
|
+
if (reason === "length")
|
|
47350
|
+
return "max_tokens";
|
|
47351
|
+
if (reason === "error")
|
|
47352
|
+
return "refusal";
|
|
47353
|
+
if (reason === "abort" || reason === "cancelled")
|
|
47354
|
+
return "cancelled";
|
|
47355
|
+
return "end_turn";
|
|
46536
47356
|
}
|
|
46537
47357
|
|
|
46538
47358
|
// ../../packages/server-acp/dist/acp-agent.js
|
|
@@ -46584,17 +47404,44 @@ var mergeEnv = (...sources) => {
|
|
|
46584
47404
|
var promptToText = (prompt) => prompt.map((block) => block.type === "text" ? block.text : "").filter((text) => text.length > 0).join("\n");
|
|
46585
47405
|
function createBunnyAgentAcpApp(options = {}) {
|
|
46586
47406
|
const sessions = /* @__PURE__ */ new Map();
|
|
46587
|
-
|
|
46588
|
-
|
|
46589
|
-
|
|
46590
|
-
|
|
46591
|
-
|
|
46592
|
-
|
|
47407
|
+
const interactions = options.interactionRegistry ?? new AcpInteractionRegistry();
|
|
47408
|
+
let capabilities = {};
|
|
47409
|
+
return agent({ name: "bunny-agent" }).onRequest(methods.agent.initialize, ({ params }) => {
|
|
47410
|
+
capabilities = params.clientCapabilities ?? {};
|
|
47411
|
+
return {
|
|
47412
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
47413
|
+
agentCapabilities: {
|
|
47414
|
+
loadSession: false,
|
|
47415
|
+
promptCapabilities: {},
|
|
47416
|
+
_meta: {
|
|
47417
|
+
[BUNNY_META_KEY]: {
|
|
47418
|
+
eventStream: 1,
|
|
47419
|
+
permissionRequests: 1,
|
|
47420
|
+
elicitation: 1,
|
|
47421
|
+
interactionRespond: 1,
|
|
47422
|
+
interactiveRunners: INTERACTIVE_RUNNERS
|
|
47423
|
+
}
|
|
47424
|
+
}
|
|
47425
|
+
},
|
|
47426
|
+
agentInfo: { name: "bunny-agent", version: "0.1.0" }
|
|
47427
|
+
};
|
|
47428
|
+
}).onRequest(methods.agent.session.new, ({ params }) => {
|
|
47429
|
+
const sessionId = randomUUID3();
|
|
46593
47430
|
sessions.set(sessionId, {
|
|
46594
47431
|
cwd: params.cwd ?? options.defaultCwd ?? process.cwd(),
|
|
46595
47432
|
...readBunnyMeta(params._meta)
|
|
46596
47433
|
});
|
|
46597
|
-
|
|
47434
|
+
const runner = readBunnyMeta(params._meta).runner ?? options.defaultRunner ?? "claude";
|
|
47435
|
+
return {
|
|
47436
|
+
sessionId,
|
|
47437
|
+
_meta: {
|
|
47438
|
+
[BUNNY_META_KEY]: {
|
|
47439
|
+
runner,
|
|
47440
|
+
permissionRequests: INTERACTIVE_RUNNERS.includes(runner) ? 1 : 0,
|
|
47441
|
+
elicitation: ["claude", "pi", "copilot"].includes(runner) ? 1 : 0
|
|
47442
|
+
}
|
|
47443
|
+
}
|
|
47444
|
+
};
|
|
46598
47445
|
}).onRequest(methods.agent.session.prompt, async ({ params, client: client2, signal }) => {
|
|
46599
47446
|
const session = sessions.get(params.sessionId);
|
|
46600
47447
|
if (!session) {
|
|
@@ -46608,12 +47455,20 @@ function createBunnyAgentAcpApp(options = {}) {
|
|
|
46608
47455
|
abort.abort();
|
|
46609
47456
|
else
|
|
46610
47457
|
signal.addEventListener("abort", onTransportAbort, { once: true });
|
|
46611
|
-
const
|
|
47458
|
+
const turnId = randomUUID3();
|
|
47459
|
+
const serializer = new AcpSessionUpdateSerializer({
|
|
47460
|
+
turnId,
|
|
47461
|
+
cwd: session.cwd,
|
|
47462
|
+
signal: abort.signal
|
|
47463
|
+
});
|
|
47464
|
+
const runner = turn.runner ?? session.runner ?? options.defaultRunner ?? "claude";
|
|
47465
|
+
const extension = recordOf(recordOf(capabilities._meta)?.[BUNNY_META_KEY]);
|
|
47466
|
+
const eventStream = extension?.eventStream === 1;
|
|
46612
47467
|
try {
|
|
46613
47468
|
let chunks;
|
|
46614
47469
|
try {
|
|
46615
47470
|
chunks = parseRunnerStream(createRunner({
|
|
46616
|
-
runner
|
|
47471
|
+
runner,
|
|
46617
47472
|
model: turn.model ?? session.model ?? options.defaultModel ?? DEFAULT_MODEL,
|
|
46618
47473
|
...turn.input ? { input: turn.input } : { userInput: promptToText(params.prompt) },
|
|
46619
47474
|
systemPrompt: turn.systemPrompt ?? session.systemPrompt,
|
|
@@ -46629,6 +47484,15 @@ function createBunnyAgentAcpApp(options = {}) {
|
|
|
46629
47484
|
mcpConfig: turn.mcpConfig ?? session.mcpConfig,
|
|
46630
47485
|
effort: turn.effort ?? session.effort,
|
|
46631
47486
|
askUserQuestionTimeoutMs: turn.askUserQuestionTimeoutMs ?? session.askUserQuestionTimeoutMs,
|
|
47487
|
+
...INTERACTIVE_RUNNERS.includes(runner) ? {
|
|
47488
|
+
toolInteraction: createAcpToolInteraction({
|
|
47489
|
+
sessionId: params.sessionId,
|
|
47490
|
+
client: client2,
|
|
47491
|
+
registry: interactions,
|
|
47492
|
+
supportsForm: capabilities.elicitation?.form != null,
|
|
47493
|
+
cwd: session.cwd
|
|
47494
|
+
})
|
|
47495
|
+
} : {},
|
|
46632
47496
|
abortController: abort,
|
|
46633
47497
|
// Caller owns session/resume; don't touch cwd/.bunny-agent.
|
|
46634
47498
|
autoInject: false
|
|
@@ -46636,11 +47500,18 @@ function createBunnyAgentAcpApp(options = {}) {
|
|
|
46636
47500
|
} catch (error109) {
|
|
46637
47501
|
throw RequestError.invalidParams(void 0, error109 instanceof Error ? error109.message : String(error109));
|
|
46638
47502
|
}
|
|
46639
|
-
for await (const
|
|
46640
|
-
|
|
46641
|
-
|
|
46642
|
-
|
|
46643
|
-
|
|
47503
|
+
for await (const event of serializer.serializeEvents(chunks)) {
|
|
47504
|
+
if (event.type === "update") {
|
|
47505
|
+
await client2.notify(methods.client.session.update, {
|
|
47506
|
+
sessionId: params.sessionId,
|
|
47507
|
+
update: event.update
|
|
47508
|
+
});
|
|
47509
|
+
} else if (eventStream) {
|
|
47510
|
+
await client2.notify(BUNNY_ACP_EVENT_METHOD, {
|
|
47511
|
+
sessionId: params.sessionId,
|
|
47512
|
+
event: event.event
|
|
47513
|
+
});
|
|
47514
|
+
}
|
|
46644
47515
|
}
|
|
46645
47516
|
} finally {
|
|
46646
47517
|
signal.removeEventListener("abort", onTransportAbort);
|
|
@@ -46648,13 +47519,27 @@ function createBunnyAgentAcpApp(options = {}) {
|
|
|
46648
47519
|
}
|
|
46649
47520
|
const runnerMeta = {
|
|
46650
47521
|
...serializer.sessionId ? { sessionId: serializer.sessionId } : {},
|
|
46651
|
-
...serializer.errorText ? { errorText: serializer.errorText } : {}
|
|
47522
|
+
...serializer.errorText && !abort.signal.aborted ? { errorText: serializer.errorText } : {}
|
|
46652
47523
|
};
|
|
46653
47524
|
return {
|
|
46654
47525
|
stopReason: serializer.stopReason,
|
|
46655
47526
|
...serializer.usage ? { usage: serializer.usage } : {},
|
|
46656
47527
|
...Object.keys(runnerMeta).length > 0 ? { _meta: { [BUNNY_META_KEY]: runnerMeta } } : {}
|
|
46657
47528
|
};
|
|
47529
|
+
}).onRequest(BUNNY_INTERACTION_RESPOND_METHOD, { parse: (value) => recordOf(value) ?? {} }, async ({ params }) => {
|
|
47530
|
+
const value = recordOf(params);
|
|
47531
|
+
if (typeof value?.sessionId !== "string" || typeof value.requestId !== "string" || !["accept", "decline", "cancel"].includes(String(value.action))) {
|
|
47532
|
+
throw RequestError.invalidParams(void 0, "Invalid interaction response.");
|
|
47533
|
+
}
|
|
47534
|
+
try {
|
|
47535
|
+
return await interactions.respond(value.sessionId, value.requestId, {
|
|
47536
|
+
action: value.action,
|
|
47537
|
+
...recordOf(value.content) ? { content: value.content } : {},
|
|
47538
|
+
...typeof value.optionId === "string" ? { optionId: value.optionId } : {}
|
|
47539
|
+
});
|
|
47540
|
+
} catch (error109) {
|
|
47541
|
+
throw RequestError.invalidParams(void 0, error109 instanceof Error ? error109.message : String(error109));
|
|
47542
|
+
}
|
|
46658
47543
|
}).onNotification(methods.agent.session.cancel, ({ params }) => {
|
|
46659
47544
|
sessions.get(params.sessionId)?.abort?.abort();
|
|
46660
47545
|
});
|
|
@@ -46704,17 +47589,17 @@ import {
|
|
|
46704
47589
|
statSync as statSync3,
|
|
46705
47590
|
writeFileSync as writeFileSync10
|
|
46706
47591
|
} from "node:fs";
|
|
46707
|
-
import { basename as basename2, dirname as dirname5, join as join15, resolve as
|
|
47592
|
+
import { basename as basename2, dirname as dirname5, join as join15, resolve as resolve4 } from "node:path";
|
|
46708
47593
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
46709
47594
|
function getPackageRoot() {
|
|
46710
47595
|
const thisDir = dirname5(fileURLToPath2(import.meta.url));
|
|
46711
|
-
return
|
|
47596
|
+
return resolve4(thisDir, "..");
|
|
46712
47597
|
}
|
|
46713
47598
|
function getShippedDockerfile() {
|
|
46714
47599
|
const packageRoot = getPackageRoot();
|
|
46715
47600
|
const candidates = [
|
|
46716
47601
|
join15(packageRoot, "Dockerfile"),
|
|
46717
|
-
|
|
47602
|
+
resolve4(
|
|
46718
47603
|
packageRoot,
|
|
46719
47604
|
"..",
|
|
46720
47605
|
"..",
|
|
@@ -46722,7 +47607,7 @@ function getShippedDockerfile() {
|
|
|
46722
47607
|
"bunny-agent-claude",
|
|
46723
47608
|
"Dockerfile"
|
|
46724
47609
|
),
|
|
46725
|
-
|
|
47610
|
+
resolve4(process.cwd(), "docker", "bunny-agent-claude", "Dockerfile")
|
|
46726
47611
|
];
|
|
46727
47612
|
for (const p of candidates) {
|
|
46728
47613
|
if (existsSync11(p)) return p;
|
|
@@ -46745,7 +47630,7 @@ function ensureDocker() {
|
|
|
46745
47630
|
}
|
|
46746
47631
|
}
|
|
46747
47632
|
function resolveTemplatePath(template) {
|
|
46748
|
-
const abs =
|
|
47633
|
+
const abs = resolve4(process.cwd(), template);
|
|
46749
47634
|
if (!existsSync11(abs)) {
|
|
46750
47635
|
console.error(`\u274C Template directory not found: ${abs}`);
|
|
46751
47636
|
process.exit(1);
|
|
@@ -46897,9 +47782,9 @@ async function runAgent(options) {
|
|
|
46897
47782
|
}
|
|
46898
47783
|
|
|
46899
47784
|
// src/cli.ts
|
|
46900
|
-
config3({ path:
|
|
46901
|
-
config3({ path:
|
|
46902
|
-
config3({ path:
|
|
47785
|
+
config3({ path: resolve5(process.cwd(), ".env"), quiet: true });
|
|
47786
|
+
config3({ path: resolve5(process.cwd(), "../.env"), quiet: true });
|
|
47787
|
+
config3({ path: resolve5(process.cwd(), "../../.env"), quiet: true });
|
|
46903
47788
|
function getSubcommand() {
|
|
46904
47789
|
for (let i = 2; i < process.argv.length; i++) {
|
|
46905
47790
|
const a = process.argv[i];
|