@bunny-agent/runner-cli 0.9.62-release.2 → 0.9.63-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 +208 -237
- package/package.json +5 -5
package/dist/bundle.mjs
CHANGED
|
@@ -39551,10 +39551,10 @@ function createMcpExtension(config4) {
|
|
|
39551
39551
|
}
|
|
39552
39552
|
|
|
39553
39553
|
// ../../packages/runner-pi/dist/pi-runner.js
|
|
39554
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
39555
|
-
import { join as
|
|
39554
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync8, unlinkSync as unlinkSync7 } from "node:fs";
|
|
39555
|
+
import { isAbsolute, join as join12, resolve as resolve2 } from "node:path";
|
|
39556
39556
|
import { getBuiltinModel } from "@earendil-works/pi-ai/providers/all";
|
|
39557
|
-
import { createAgentSession,
|
|
39557
|
+
import { CONFIG_DIR_NAME, createAgentSession, DefaultResourceLoader, getAgentDir, ModelRuntime, SessionManager as SessionManager2, SettingsManager } from "@earendil-works/pi-coding-agent";
|
|
39558
39558
|
|
|
39559
39559
|
// ../../packages/runner-pi/dist/apply-patch-shim.js
|
|
39560
39560
|
import { chmodSync, existsSync as existsSync5, mkdirSync as mkdirSync4, renameSync, writeFileSync as writeFileSync5 } from "node:fs";
|
|
@@ -39848,105 +39848,9 @@ function buildApplyPatchTool(cwd) {
|
|
|
39848
39848
|
};
|
|
39849
39849
|
}
|
|
39850
39850
|
|
|
39851
|
-
// ../../packages/runner-pi/dist/bunny-agent-resource-loader.js
|
|
39852
|
-
import { existsSync as existsSync7 } from "node:fs";
|
|
39853
|
-
import { homedir } from "node:os";
|
|
39854
|
-
import { isAbsolute, join as join9, resolve as resolve2 } from "node:path";
|
|
39855
|
-
import { DefaultResourceLoader, loadSkills } from "@earendil-works/pi-coding-agent";
|
|
39856
|
-
var LOG_PREFIX = "[bunny-agent:pi]";
|
|
39857
|
-
function logSkillLoad(cwd, agentDir, skillPaths, result) {
|
|
39858
|
-
const lines = [
|
|
39859
|
-
`${LOG_PREFIX} loadSkills`,
|
|
39860
|
-
` cwd: ${cwd}`,
|
|
39861
|
-
` agentDir: ${agentDir}`,
|
|
39862
|
-
` extra skillPaths (${skillPaths.length}):`
|
|
39863
|
-
];
|
|
39864
|
-
for (const raw of skillPaths) {
|
|
39865
|
-
const abs = isAbsolute(raw) ? raw : resolve2(cwd, raw);
|
|
39866
|
-
lines.push(` ${raw} -> ${abs} (exists: ${existsSync7(abs) ? "yes" : "no"})`);
|
|
39867
|
-
}
|
|
39868
|
-
lines.push(` loaded skills: ${result.skills.length}`);
|
|
39869
|
-
if (result.skills.length > 0) {
|
|
39870
|
-
lines.push(` skill names: ${result.skills.map((s) => s.name).join(", ")}`);
|
|
39871
|
-
}
|
|
39872
|
-
if (result.diagnostics.length > 0) {
|
|
39873
|
-
lines.push(` diagnostics (${result.diagnostics.length}):`);
|
|
39874
|
-
for (const d of result.diagnostics) {
|
|
39875
|
-
const pathPart = d.path !== void 0 ? ` path=${d.path}` : "";
|
|
39876
|
-
lines.push(` [${d.type}] ${d.message}${pathPart}`);
|
|
39877
|
-
}
|
|
39878
|
-
}
|
|
39879
|
-
console.error(lines.join("\n"));
|
|
39880
|
-
}
|
|
39881
|
-
var BunnyAgentResourceLoader = class {
|
|
39882
|
-
constructor(options = {}) {
|
|
39883
|
-
this.cwd = options.cwd ?? process.cwd();
|
|
39884
|
-
this.agentDir = options.agentDir ?? join9(homedir(), ".bunny", "agent");
|
|
39885
|
-
this.skillPaths = options.skillPaths ?? [];
|
|
39886
|
-
this.extraAppendPrompt = options.appendSystemPrompt;
|
|
39887
|
-
this.delegate = new DefaultResourceLoader({
|
|
39888
|
-
cwd: this.cwd,
|
|
39889
|
-
agentDir: this.agentDir,
|
|
39890
|
-
settingsManager: options.settingsManager,
|
|
39891
|
-
extensionFactories: options.extensionFactories
|
|
39892
|
-
});
|
|
39893
|
-
}
|
|
39894
|
-
async reload() {
|
|
39895
|
-
await this.delegate.reload();
|
|
39896
|
-
this.cachedSkills = void 0;
|
|
39897
|
-
}
|
|
39898
|
-
getSkills() {
|
|
39899
|
-
if (!this.cachedSkills) {
|
|
39900
|
-
this.cachedSkills = loadSkills({
|
|
39901
|
-
cwd: this.cwd,
|
|
39902
|
-
agentDir: this.agentDir,
|
|
39903
|
-
skillPaths: this.skillPaths,
|
|
39904
|
-
includeDefaults: true
|
|
39905
|
-
});
|
|
39906
|
-
if (this.skillPaths.length > 0) {
|
|
39907
|
-
logSkillLoad(this.cwd, this.agentDir, this.skillPaths, this.cachedSkills);
|
|
39908
|
-
}
|
|
39909
|
-
}
|
|
39910
|
-
return this.cachedSkills;
|
|
39911
|
-
}
|
|
39912
|
-
// Delegate all other methods
|
|
39913
|
-
getExtensions() {
|
|
39914
|
-
return this.delegate.getExtensions();
|
|
39915
|
-
}
|
|
39916
|
-
getPrompts() {
|
|
39917
|
-
return this.delegate.getPrompts();
|
|
39918
|
-
}
|
|
39919
|
-
getThemes() {
|
|
39920
|
-
return this.delegate.getThemes();
|
|
39921
|
-
}
|
|
39922
|
-
getAgentsFiles() {
|
|
39923
|
-
return this.delegate.getAgentsFiles();
|
|
39924
|
-
}
|
|
39925
|
-
getSystemPrompt() {
|
|
39926
|
-
return this.delegate.getSystemPrompt();
|
|
39927
|
-
}
|
|
39928
|
-
getSystemPromptSource() {
|
|
39929
|
-
return this.delegate.getSystemPromptSource();
|
|
39930
|
-
}
|
|
39931
|
-
getAppendSystemPromptSources() {
|
|
39932
|
-
return this.delegate.getAppendSystemPromptSources();
|
|
39933
|
-
}
|
|
39934
|
-
getAppendSystemPrompt() {
|
|
39935
|
-
const base = this.delegate.getAppendSystemPrompt();
|
|
39936
|
-
if (this.extraAppendPrompt) {
|
|
39937
|
-
console.error(`${LOG_PREFIX} getAppendSystemPrompt: appending extra prompt (${this.extraAppendPrompt.length} chars)`);
|
|
39938
|
-
return [...base, this.extraAppendPrompt];
|
|
39939
|
-
}
|
|
39940
|
-
return base;
|
|
39941
|
-
}
|
|
39942
|
-
extendResources(paths) {
|
|
39943
|
-
this.delegate.extendResources(paths);
|
|
39944
|
-
}
|
|
39945
|
-
};
|
|
39946
|
-
|
|
39947
39851
|
// ../../packages/runner-pi/dist/image-tools.js
|
|
39948
39852
|
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync7 } from "node:fs";
|
|
39949
|
-
import { dirname as dirname3, extname, join as
|
|
39853
|
+
import { dirname as dirname3, extname, join as join9 } from "node:path";
|
|
39950
39854
|
var generateImageSchema = {
|
|
39951
39855
|
type: "object",
|
|
39952
39856
|
properties: {
|
|
@@ -40207,7 +40111,7 @@ function buildImageGenerateTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
40207
40111
|
const imageSize = p.imageSize;
|
|
40208
40112
|
const rawFilename = p.filename;
|
|
40209
40113
|
const filename = rawFilename ? extname(rawFilename) ? rawFilename : `${rawFilename}.png` : `image_${Date.now()}.png`;
|
|
40210
|
-
const filePath =
|
|
40114
|
+
const filePath = join9(cwd, filename.replace(/[^a-zA-Z0-9_\-./]/g, "_"));
|
|
40211
40115
|
try {
|
|
40212
40116
|
const url3 = `${baseUrl.replace(/\/$/, "")}/v1/images/generations`;
|
|
40213
40117
|
const res = await fetch(url3, {
|
|
@@ -40355,7 +40259,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
40355
40259
|
// biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
|
|
40356
40260
|
parameters: editImageSchema,
|
|
40357
40261
|
async execute(_toolCallId, params, signal, _onUpdate) {
|
|
40358
|
-
const { readFileSync: readFileSync8, existsSync:
|
|
40262
|
+
const { readFileSync: readFileSync8, existsSync: existsSync12 } = await import("node:fs");
|
|
40359
40263
|
const { resolve: resolve5, basename: basename3 } = await import("node:path");
|
|
40360
40264
|
const p = params;
|
|
40361
40265
|
const imagePath = p.image;
|
|
@@ -40368,7 +40272,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
40368
40272
|
const rawFilename = p.filename;
|
|
40369
40273
|
const safePrompt = buildPolicySafeEditPrompt(prompt);
|
|
40370
40274
|
const resolvedImage = resolve5(cwd, imagePath);
|
|
40371
|
-
if (!
|
|
40275
|
+
if (!existsSync12(resolvedImage)) {
|
|
40372
40276
|
return {
|
|
40373
40277
|
content: [
|
|
40374
40278
|
{
|
|
@@ -40380,7 +40284,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
40380
40284
|
};
|
|
40381
40285
|
}
|
|
40382
40286
|
const filename = rawFilename ? extname(rawFilename) ? rawFilename : `${rawFilename}.png` : `edited_${Date.now()}.png`;
|
|
40383
|
-
const filePath =
|
|
40287
|
+
const filePath = join9(cwd, filename.replace(/[^a-zA-Z0-9_\-./]/g, "_"));
|
|
40384
40288
|
try {
|
|
40385
40289
|
const imageBuffer = readFileSync8(resolvedImage);
|
|
40386
40290
|
const fields = [
|
|
@@ -40412,7 +40316,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
40412
40316
|
];
|
|
40413
40317
|
if (maskPath) {
|
|
40414
40318
|
const resolvedMask = resolve5(cwd, maskPath);
|
|
40415
|
-
if (
|
|
40319
|
+
if (existsSync12(resolvedMask)) {
|
|
40416
40320
|
files.push({
|
|
40417
40321
|
name: "mask",
|
|
40418
40322
|
filename: basename3(resolvedMask),
|
|
@@ -40479,7 +40383,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
40479
40383
|
|
|
40480
40384
|
// ../../packages/runner-pi/dist/session-utils.js
|
|
40481
40385
|
import { closeSync, fstatSync, openSync, readdirSync, readSync, statSync } from "node:fs";
|
|
40482
|
-
import { join as
|
|
40386
|
+
import { join as join10 } from "node:path";
|
|
40483
40387
|
import { SessionManager } from "@earendil-works/pi-coding-agent";
|
|
40484
40388
|
var MAX_SESSION_FILE_BYTES = Number(process.env.SANDAGENT_MAX_SESSION_BYTES) || 10 * 1024 * 1024;
|
|
40485
40389
|
function resolveSessionPathById(cwd, sessionIdOrPath) {
|
|
@@ -40490,7 +40394,7 @@ function resolveSessionPathById(cwd, sessionIdOrPath) {
|
|
|
40490
40394
|
try {
|
|
40491
40395
|
const suffix = `_${sessionIdOrPath}.jsonl`;
|
|
40492
40396
|
const match = readdirSync(sessionsDir).find((f) => f.endsWith(suffix));
|
|
40493
|
-
return match ?
|
|
40397
|
+
return match ? join10(sessionsDir, match) : void 0;
|
|
40494
40398
|
} catch {
|
|
40495
40399
|
return void 0;
|
|
40496
40400
|
}
|
|
@@ -43629,37 +43533,37 @@ function buildAskUserQuestionTool(options) {
|
|
|
43629
43533
|
}
|
|
43630
43534
|
};
|
|
43631
43535
|
}
|
|
43632
|
-
function
|
|
43536
|
+
function createToolApprovalExtension(options) {
|
|
43633
43537
|
return {
|
|
43634
|
-
name: tool
|
|
43635
|
-
|
|
43636
|
-
|
|
43637
|
-
|
|
43638
|
-
|
|
43639
|
-
|
|
43640
|
-
|
|
43641
|
-
|
|
43642
|
-
|
|
43643
|
-
|
|
43644
|
-
|
|
43645
|
-
|
|
43646
|
-
|
|
43538
|
+
name: "bunny-agent-tool-approval",
|
|
43539
|
+
factory: (pi) => {
|
|
43540
|
+
pi.on("tool_call", async (event, ctx) => {
|
|
43541
|
+
if (isAskUserQuestionToolName(event.toolName) || event.parentToolCallId !== void 0) {
|
|
43542
|
+
return void 0;
|
|
43543
|
+
}
|
|
43544
|
+
const decision = await waitForApproval({
|
|
43545
|
+
cwd: options.cwd,
|
|
43546
|
+
toolCallId: event.toolCallId,
|
|
43547
|
+
toolName: event.toolName,
|
|
43548
|
+
input: event.input,
|
|
43549
|
+
signal: ctx.signal ?? options.fallbackSignal,
|
|
43550
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
43551
|
+
timeoutMs: options.timeoutMs
|
|
43552
|
+
});
|
|
43553
|
+
if (decision.behavior === "deny") {
|
|
43554
|
+
return {
|
|
43555
|
+
block: true,
|
|
43556
|
+
reason: `Tool "${event.toolName}" was not approved: ${decision.message}`
|
|
43557
|
+
};
|
|
43558
|
+
}
|
|
43559
|
+
return void 0;
|
|
43647
43560
|
});
|
|
43648
|
-
if (decision.behavior === "deny") {
|
|
43649
|
-
throw new Error(`Tool "${tool.name}" was not approved: ${decision.message}`);
|
|
43650
|
-
}
|
|
43651
|
-
return tool.execute(toolCallId, params, signal, onUpdate, ctx);
|
|
43652
43561
|
}
|
|
43653
43562
|
};
|
|
43654
43563
|
}
|
|
43655
|
-
function gateToolsForApproval(tools, bypass, options) {
|
|
43656
|
-
if (bypass)
|
|
43657
|
-
return tools;
|
|
43658
|
-
return tools.map((tool) => wrapToolWithApproval(tool, options));
|
|
43659
|
-
}
|
|
43660
43564
|
|
|
43661
43565
|
// ../../packages/runner-pi/dist/tool-overrides.js
|
|
43662
|
-
import {
|
|
43566
|
+
import { createBashToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
43663
43567
|
|
|
43664
43568
|
// ../../packages/runner-pi/dist/web-tools.js
|
|
43665
43569
|
var braveProvider = {
|
|
@@ -44081,11 +43985,11 @@ function buildWebFetchTool() {
|
|
|
44081
43985
|
|
|
44082
43986
|
// ../../packages/runner-pi/dist/tool-overrides.js
|
|
44083
43987
|
function redactSecrets(text, secrets) {
|
|
44084
|
-
|
|
43988
|
+
const values = secretValues(secrets).filter((v) => text.includes(v));
|
|
43989
|
+
if (values.length === 0)
|
|
44085
43990
|
return text;
|
|
44086
43991
|
let result = text;
|
|
44087
43992
|
const escapeRegex3 = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
44088
|
-
const values = Object.values(secrets).filter((v) => v.length >= 8).filter((v) => !/^\//.test(v) && !/^[A-Za-z]:[/\\]/.test(v)).sort((a, b) => b.length - a.length);
|
|
44089
43993
|
for (const v of values) {
|
|
44090
43994
|
const ev = escapeRegex3(v);
|
|
44091
43995
|
result = result.replace(new RegExp(`^\\S+=.*${ev}.*$\\n?`, "gm"), "");
|
|
@@ -44095,19 +43999,61 @@ function redactSecrets(text, secrets) {
|
|
|
44095
43999
|
result = result.replace(/\n{3,}/g, "\n\n");
|
|
44096
44000
|
return result.trim();
|
|
44097
44001
|
}
|
|
44098
|
-
function
|
|
44099
|
-
|
|
44100
|
-
|
|
44002
|
+
function secretValues(secrets) {
|
|
44003
|
+
return Object.values(secrets).filter((v) => v.length >= 8).filter((v) => !/^\//.test(v) && !/^[A-Za-z]:[/\\]/.test(v)).sort((a, b) => b.length - a.length);
|
|
44004
|
+
}
|
|
44005
|
+
function maskSecrets(value, values) {
|
|
44006
|
+
if (typeof value === "string") {
|
|
44007
|
+
let masked = value;
|
|
44008
|
+
for (const v of values)
|
|
44009
|
+
masked = masked.split(v).join("***");
|
|
44010
|
+
return masked;
|
|
44011
|
+
}
|
|
44012
|
+
if (Array.isArray(value)) {
|
|
44013
|
+
const next = value.map((item) => maskSecrets(item, values));
|
|
44014
|
+
return next.some((item, i) => item !== value[i]) ? next : value;
|
|
44015
|
+
}
|
|
44016
|
+
if (value !== null && typeof value === "object") {
|
|
44017
|
+
let changed = false;
|
|
44018
|
+
const next = {};
|
|
44019
|
+
for (const [key, item] of Object.entries(value)) {
|
|
44020
|
+
next[key] = maskSecrets(item, values);
|
|
44021
|
+
if (next[key] !== item)
|
|
44022
|
+
changed = true;
|
|
44023
|
+
}
|
|
44024
|
+
return changed ? next : value;
|
|
44101
44025
|
}
|
|
44026
|
+
return value;
|
|
44102
44027
|
}
|
|
44028
|
+
var ENV_OPTIONS_WITH_VALUE = /* @__PURE__ */ new Set([
|
|
44029
|
+
"-u",
|
|
44030
|
+
"--unset",
|
|
44031
|
+
"-C",
|
|
44032
|
+
"--chdir",
|
|
44033
|
+
"-S",
|
|
44034
|
+
"--split-string"
|
|
44035
|
+
]);
|
|
44103
44036
|
function isEnvDumpCommand(command) {
|
|
44104
44037
|
const cmd = command.replace(/\s+/g, " ").trim();
|
|
44105
|
-
|
|
44038
|
+
if (/(?:^|[|;&])\s*(?:printenv|export\s+-p|declare\s+-x)\b/.test(cmd)) {
|
|
44039
|
+
return true;
|
|
44040
|
+
}
|
|
44041
|
+
for (const match of cmd.matchAll(/(?:^|[|;&])\s*env(?=$|[\s|;&>])([^|;&>]*)/g)) {
|
|
44042
|
+
const words = match[1].trim().split(" ").filter(Boolean);
|
|
44043
|
+
let i = 0;
|
|
44044
|
+
while (i < words.length && (words[i].startsWith("-") || /^[A-Za-z_]\w*=/.test(words[i]))) {
|
|
44045
|
+
i += ENV_OPTIONS_WITH_VALUE.has(words[i]) ? 2 : 1;
|
|
44046
|
+
}
|
|
44047
|
+
if (i >= words.length || isEnvDumpCommand(words.slice(i).join(" "))) {
|
|
44048
|
+
return true;
|
|
44049
|
+
}
|
|
44050
|
+
}
|
|
44051
|
+
return false;
|
|
44106
44052
|
}
|
|
44107
|
-
function buildEnvInjectedBashTool(cwd,
|
|
44053
|
+
function buildEnvInjectedBashTool(cwd, opts = {}) {
|
|
44108
44054
|
const safeEnv = opts.systemEnv ?? {};
|
|
44109
44055
|
const pathPrepend = opts.pathPrepend;
|
|
44110
|
-
|
|
44056
|
+
return createBashToolDefinition(cwd, {
|
|
44111
44057
|
spawnHook: (ctx) => {
|
|
44112
44058
|
const env = {
|
|
44113
44059
|
...ctx.env,
|
|
@@ -44120,50 +44066,45 @@ function buildEnvInjectedBashTool(cwd, extraEnv, opts = {}) {
|
|
|
44120
44066
|
return { ...ctx, env };
|
|
44121
44067
|
}
|
|
44122
44068
|
});
|
|
44123
|
-
return {
|
|
44124
|
-
name: bashAgentTool.name,
|
|
44125
|
-
label: bashAgentTool.label ?? "bash",
|
|
44126
|
-
description: bashAgentTool.description,
|
|
44127
|
-
// biome-ignore lint/suspicious/noExplicitAny: TypeBox schema from pi internals
|
|
44128
|
-
parameters: bashAgentTool.parameters,
|
|
44129
|
-
async execute(toolCallId, params, signal, onUpdate) {
|
|
44130
|
-
const command = params.command ?? "";
|
|
44131
|
-
if (isEnvDumpCommand(command)) {
|
|
44132
|
-
return {
|
|
44133
|
-
content: [
|
|
44134
|
-
{
|
|
44135
|
-
type: "text",
|
|
44136
|
-
text: "Command blocked: printing or redirecting environment variables is not allowed."
|
|
44137
|
-
}
|
|
44138
|
-
],
|
|
44139
|
-
details: void 0
|
|
44140
|
-
};
|
|
44141
|
-
}
|
|
44142
|
-
const result = await bashAgentTool.execute(toolCallId, params, signal, onUpdate);
|
|
44143
|
-
redactResultContent(result, extraEnv);
|
|
44144
|
-
return result;
|
|
44145
|
-
}
|
|
44146
|
-
};
|
|
44147
44069
|
}
|
|
44148
|
-
|
|
44149
|
-
|
|
44070
|
+
var ENV_DUMP_BLOCKED_MESSAGE = "Command blocked: printing or redirecting environment variables is not allowed.";
|
|
44071
|
+
function createSecretGuardExtension(secrets) {
|
|
44150
44072
|
return {
|
|
44151
|
-
name:
|
|
44152
|
-
|
|
44153
|
-
|
|
44154
|
-
|
|
44155
|
-
|
|
44156
|
-
|
|
44157
|
-
|
|
44158
|
-
|
|
44159
|
-
|
|
44073
|
+
name: "bunny-agent-secret-guard",
|
|
44074
|
+
factory: (pi) => {
|
|
44075
|
+
pi.on("tool_call", (event) => {
|
|
44076
|
+
if (event.toolName === "bash" && typeof event.input.command === "string" && isEnvDumpCommand(event.input.command)) {
|
|
44077
|
+
return { block: true, reason: ENV_DUMP_BLOCKED_MESSAGE };
|
|
44078
|
+
}
|
|
44079
|
+
return void 0;
|
|
44080
|
+
});
|
|
44081
|
+
const values = secretValues(secrets);
|
|
44082
|
+
pi.on("tool_result", (event) => {
|
|
44083
|
+
if (values.length === 0)
|
|
44084
|
+
return void 0;
|
|
44085
|
+
let contentChanged = false;
|
|
44086
|
+
const content = event.content.map((part) => {
|
|
44087
|
+
if (part.type !== "text")
|
|
44088
|
+
return part;
|
|
44089
|
+
const text = redactSecrets(part.text, secrets);
|
|
44090
|
+
if (text === part.text)
|
|
44091
|
+
return part;
|
|
44092
|
+
contentChanged = true;
|
|
44093
|
+
return { ...part, text };
|
|
44094
|
+
});
|
|
44095
|
+
const details = maskSecrets(event.details, values);
|
|
44096
|
+
const structuredContent = maskSecrets(event.structuredContent, values);
|
|
44097
|
+
if (!contentChanged && details === event.details && structuredContent === event.structuredContent) {
|
|
44098
|
+
return void 0;
|
|
44099
|
+
}
|
|
44100
|
+
return { content, details, structuredContent };
|
|
44101
|
+
});
|
|
44160
44102
|
}
|
|
44161
44103
|
};
|
|
44162
44104
|
}
|
|
44163
44105
|
function buildSecretAwareTools(cwd, secrets, opts = {}) {
|
|
44164
44106
|
const tools = [
|
|
44165
|
-
buildEnvInjectedBashTool(cwd,
|
|
44166
|
-
buildSecretRedactingReadTool(cwd, secrets),
|
|
44107
|
+
buildEnvInjectedBashTool(cwd, opts),
|
|
44167
44108
|
buildWebFetchTool()
|
|
44168
44109
|
];
|
|
44169
44110
|
if (resolveSearchProvider(secrets)) {
|
|
@@ -44275,7 +44216,7 @@ function serializeResult2(result) {
|
|
|
44275
44216
|
}
|
|
44276
44217
|
|
|
44277
44218
|
// ../../packages/runner-pi/dist/pi-runner.js
|
|
44278
|
-
var
|
|
44219
|
+
var LOG_PREFIX = "[bunny-agent:pi]";
|
|
44279
44220
|
var DEFAULT_DYNAMIC_MODEL_PROFILE = {
|
|
44280
44221
|
contextWindow: 128e3,
|
|
44281
44222
|
maxTokens: 16384,
|
|
@@ -44403,8 +44344,8 @@ function traceRawMessage(debugCwd, data, reset = false, optionsEnv) {
|
|
|
44403
44344
|
if (!enabled)
|
|
44404
44345
|
return;
|
|
44405
44346
|
try {
|
|
44406
|
-
const file3 =
|
|
44407
|
-
if (reset &&
|
|
44347
|
+
const file3 = join12(debugCwd, "pi-message-stream-debug.json");
|
|
44348
|
+
if (reset && existsSync8(file3))
|
|
44408
44349
|
unlinkSync7(file3);
|
|
44409
44350
|
const type = data !== null && typeof data === "object" ? data.type : void 0;
|
|
44410
44351
|
let payload = data;
|
|
@@ -44418,6 +44359,39 @@ function traceRawMessage(debugCwd, data, reset = false, optionsEnv) {
|
|
|
44418
44359
|
} catch {
|
|
44419
44360
|
}
|
|
44420
44361
|
}
|
|
44362
|
+
async function createPiResourceLoader(options) {
|
|
44363
|
+
const { systemPrompt } = options;
|
|
44364
|
+
const defaultSkillDirs = [
|
|
44365
|
+
join12(options.agentDir, "skills"),
|
|
44366
|
+
join12(options.cwd, CONFIG_DIR_NAME, "skills")
|
|
44367
|
+
].filter((dir) => existsSync8(dir));
|
|
44368
|
+
const loader = new DefaultResourceLoader({
|
|
44369
|
+
cwd: options.cwd,
|
|
44370
|
+
agentDir: options.agentDir,
|
|
44371
|
+
settingsManager: options.settingsManager,
|
|
44372
|
+
noSkills: true,
|
|
44373
|
+
additionalSkillPaths: [...defaultSkillDirs, ...options.skillPaths ?? []],
|
|
44374
|
+
appendSystemPromptOverride: systemPrompt ? (base) => [...base, systemPrompt] : void 0,
|
|
44375
|
+
extensionFactories: options.extensionFactories
|
|
44376
|
+
});
|
|
44377
|
+
await loader.reload();
|
|
44378
|
+
if (options.skillPaths && options.skillPaths.length > 0) {
|
|
44379
|
+
logSkillLoad(options.cwd, options.skillPaths, loader.getSkills());
|
|
44380
|
+
}
|
|
44381
|
+
return loader;
|
|
44382
|
+
}
|
|
44383
|
+
function logSkillLoad(cwd, skillPaths, result) {
|
|
44384
|
+
const lines = [`${LOG_PREFIX} loadSkills cwd=${cwd}`];
|
|
44385
|
+
for (const raw of skillPaths) {
|
|
44386
|
+
const abs = isAbsolute(raw) ? raw : resolve2(cwd, raw);
|
|
44387
|
+
lines.push(` ${raw} -> ${abs} (exists: ${existsSync8(abs) ? "yes" : "no"})`);
|
|
44388
|
+
}
|
|
44389
|
+
lines.push(` loaded skills (${result.skills.length}): ${result.skills.map((s) => s.name).join(", ")}`);
|
|
44390
|
+
for (const d of result.diagnostics) {
|
|
44391
|
+
lines.push(` [${d.type}] ${d.message}${d.path !== void 0 ? ` path=${d.path}` : ""}`);
|
|
44392
|
+
}
|
|
44393
|
+
console.error(lines.join("\n"));
|
|
44394
|
+
}
|
|
44421
44395
|
function createPiRunner(options = {}) {
|
|
44422
44396
|
const modelSpec = options.model;
|
|
44423
44397
|
if (modelSpec == null || modelSpec.trim() === "") {
|
|
@@ -44431,6 +44405,8 @@ function createPiRunner(options = {}) {
|
|
|
44431
44405
|
const mcpExtension = shouldEnableMcp(options.mcpConfig, options.allowedTools) ? createMcpExtension(options.mcpConfig) : void 0;
|
|
44432
44406
|
return {
|
|
44433
44407
|
async *run(userInput) {
|
|
44408
|
+
const agentDir = getAgentDir();
|
|
44409
|
+
const settingsManager = SettingsManager.create(cwd, agentDir);
|
|
44434
44410
|
const modelRuntime = await ModelRuntime.create({
|
|
44435
44411
|
modelsPath: null,
|
|
44436
44412
|
allowModelNetwork: false
|
|
@@ -44477,7 +44453,7 @@ function createPiRunner(options = {}) {
|
|
|
44477
44453
|
const sessionManager = await (async () => {
|
|
44478
44454
|
if (forkFrom) {
|
|
44479
44455
|
const sourcePath = resolveSessionPathById(cwd, forkFrom);
|
|
44480
|
-
console.error(`${
|
|
44456
|
+
console.error(`${LOG_PREFIX} fork: sourceId=${forkFrom} sourcePath=${sourcePath ?? "(not found)"}`);
|
|
44481
44457
|
if (!sourcePath) {
|
|
44482
44458
|
throw new Error(`Pi runner: forkFrom source session not found: ${forkFrom}`);
|
|
44483
44459
|
}
|
|
@@ -44485,11 +44461,11 @@ function createPiRunner(options = {}) {
|
|
|
44485
44461
|
}
|
|
44486
44462
|
if (resume) {
|
|
44487
44463
|
const sessionPath2 = resolveSessionPathById(cwd, resume);
|
|
44488
|
-
console.error(`${
|
|
44464
|
+
console.error(`${LOG_PREFIX} resume: id=${resume} path=${sessionPath2 ?? "(not found)"}`);
|
|
44489
44465
|
if (sessionPath2) {
|
|
44490
44466
|
if (isSessionFileTooLarge(sessionPath2)) {
|
|
44491
44467
|
const context = extractSessionContext(sessionPath2);
|
|
44492
|
-
console.error(`${
|
|
44468
|
+
console.error(`${LOG_PREFIX} session file too large, starting fresh${context ? " (with context)" : ""}`);
|
|
44493
44469
|
const newMgr = SessionManager2.create(cwd);
|
|
44494
44470
|
if (context) {
|
|
44495
44471
|
const firstId = newMgr.getEntries()[0]?.id ?? "";
|
|
@@ -44503,24 +44479,14 @@ function createPiRunner(options = {}) {
|
|
|
44503
44479
|
}
|
|
44504
44480
|
return SessionManager2.create(cwd);
|
|
44505
44481
|
})();
|
|
44506
|
-
const resourceLoader = options.skillPaths || options.systemPrompt || mcpExtension ? new BunnyAgentResourceLoader({
|
|
44507
|
-
cwd,
|
|
44508
|
-
skillPaths: options.skillPaths,
|
|
44509
|
-
appendSystemPrompt: options.systemPrompt,
|
|
44510
|
-
extensionFactories: mcpExtension ? [mcpExtension] : void 0
|
|
44511
|
-
}) : void 0;
|
|
44512
|
-
if (options.skillPaths && options.skillPaths.length > 0) {
|
|
44513
|
-
console.error(`${LOG_PREFIX2} runner: cwd=${cwd} skillPaths=${JSON.stringify(options.skillPaths)}`);
|
|
44514
|
-
}
|
|
44515
|
-
if (resourceLoader) {
|
|
44516
|
-
await resourceLoader.reload();
|
|
44517
|
-
}
|
|
44518
44482
|
const applyPatchShimDir = ensureApplyPatchShim();
|
|
44519
44483
|
const customTools = options.env && Object.keys(options.env).length > 0 ? buildSecretAwareTools(cwd, options.env, {
|
|
44520
44484
|
systemEnv: options.systemEnv,
|
|
44521
44485
|
pathPrepend: applyPatchShimDir
|
|
44522
44486
|
}) : applyPatchShimDir ? [
|
|
44523
|
-
buildEnvInjectedBashTool(cwd, {
|
|
44487
|
+
buildEnvInjectedBashTool(cwd, {
|
|
44488
|
+
pathPrepend: applyPatchShimDir
|
|
44489
|
+
})
|
|
44524
44490
|
] : [];
|
|
44525
44491
|
if (provider === "openai") {
|
|
44526
44492
|
customTools.push(buildApplyPatchTool(cwd));
|
|
@@ -44541,29 +44507,34 @@ function createPiRunner(options = {}) {
|
|
|
44541
44507
|
cwd,
|
|
44542
44508
|
fallbackSignal: options.abortController?.signal
|
|
44543
44509
|
};
|
|
44544
|
-
let regularTools = [
|
|
44545
|
-
...applyAllowedTools(customTools, allowedTools),
|
|
44546
|
-
...toolRefDefinitions
|
|
44547
|
-
];
|
|
44548
|
-
if (!bypassApproval) {
|
|
44549
|
-
const overriddenNames = new Set(regularTools.map((tool) => tool.name));
|
|
44550
|
-
const builtinTools = applyAllowedTools(createCodingTools(cwd), allowedTools).filter((tool) => !overriddenNames.has(tool.name));
|
|
44551
|
-
regularTools = [...regularTools, ...builtinTools];
|
|
44552
|
-
}
|
|
44553
|
-
const gatedTools = gateToolsForApproval(regularTools, bypassApproval, approvalGate);
|
|
44554
44510
|
const askUserQuestionEnabled = allowedTools === void 0 || allowedTools.includes(ASK_USER_QUESTION_TOOL_NAME);
|
|
44555
44511
|
const previousModel = sessionManager.buildSessionContext?.().model;
|
|
44556
44512
|
const thinkingLevel = resolveInitialThinkingLevel(options.effort, previousModel, model);
|
|
44513
|
+
const resourceLoader = await createPiResourceLoader({
|
|
44514
|
+
cwd,
|
|
44515
|
+
agentDir,
|
|
44516
|
+
settingsManager,
|
|
44517
|
+
skillPaths: options.skillPaths,
|
|
44518
|
+
systemPrompt: options.systemPrompt,
|
|
44519
|
+
extensionFactories: [
|
|
44520
|
+
createSecretGuardExtension(options.env ?? {}),
|
|
44521
|
+
...bypassApproval ? [] : [createToolApprovalExtension(approvalGate)],
|
|
44522
|
+
...mcpExtension ? [mcpExtension] : []
|
|
44523
|
+
]
|
|
44524
|
+
});
|
|
44557
44525
|
const { session } = await createAgentSession({
|
|
44558
44526
|
cwd,
|
|
44527
|
+
agentDir,
|
|
44559
44528
|
model,
|
|
44560
44529
|
sessionManager,
|
|
44530
|
+
settingsManager,
|
|
44561
44531
|
modelRuntime,
|
|
44562
44532
|
resourceLoader,
|
|
44563
44533
|
thinkingLevel,
|
|
44564
44534
|
tools: allowedTools,
|
|
44565
44535
|
customTools: [
|
|
44566
|
-
...
|
|
44536
|
+
...applyAllowedTools(customTools, allowedTools),
|
|
44537
|
+
...toolRefDefinitions,
|
|
44567
44538
|
...askUserQuestionEnabled ? [
|
|
44568
44539
|
buildAskUserQuestionTool({
|
|
44569
44540
|
...approvalGate,
|
|
@@ -44696,17 +44667,17 @@ function createPiRunner(options = {}) {
|
|
|
44696
44667
|
}
|
|
44697
44668
|
|
|
44698
44669
|
// ../../packages/runner-harness/dist/session.js
|
|
44699
|
-
import { existsSync as
|
|
44700
|
-
import { join as
|
|
44670
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync6, writeFileSync as writeFileSync9 } from "node:fs";
|
|
44671
|
+
import { join as join13 } from "node:path";
|
|
44701
44672
|
var DIR = ".bunny-agent";
|
|
44702
44673
|
var FILE = "session-id";
|
|
44703
44674
|
function sessionPath(cwd) {
|
|
44704
|
-
return
|
|
44675
|
+
return join13(cwd, DIR, FILE);
|
|
44705
44676
|
}
|
|
44706
44677
|
function readSessionId(cwd) {
|
|
44707
44678
|
try {
|
|
44708
44679
|
const p = sessionPath(cwd);
|
|
44709
|
-
if (!
|
|
44680
|
+
if (!existsSync9(p))
|
|
44710
44681
|
return void 0;
|
|
44711
44682
|
return readFileSync6(p, "utf8").trim() || void 0;
|
|
44712
44683
|
} catch {
|
|
@@ -44715,28 +44686,28 @@ function readSessionId(cwd) {
|
|
|
44715
44686
|
}
|
|
44716
44687
|
function writeSessionId(cwd, id) {
|
|
44717
44688
|
try {
|
|
44718
|
-
mkdirSync8(
|
|
44689
|
+
mkdirSync8(join13(cwd, DIR), { recursive: true });
|
|
44719
44690
|
writeFileSync9(sessionPath(cwd), id, "utf8");
|
|
44720
44691
|
} catch {
|
|
44721
44692
|
}
|
|
44722
44693
|
}
|
|
44723
44694
|
|
|
44724
44695
|
// ../../packages/runner-harness/dist/skills.js
|
|
44725
|
-
import { existsSync as
|
|
44726
|
-
import { homedir
|
|
44727
|
-
import { join as
|
|
44696
|
+
import { existsSync as existsSync10, readdirSync as readdirSync2, statSync as statSync2 } from "node:fs";
|
|
44697
|
+
import { homedir } from "node:os";
|
|
44698
|
+
import { join as join14 } from "node:path";
|
|
44728
44699
|
function discoverSkillPaths(cwd) {
|
|
44729
44700
|
const paths = [];
|
|
44730
44701
|
for (const base of [
|
|
44731
|
-
|
|
44732
|
-
|
|
44702
|
+
join14(cwd, "skills"),
|
|
44703
|
+
join14(homedir(), ".bunny-agent", "skills")
|
|
44733
44704
|
]) {
|
|
44734
|
-
if (!
|
|
44705
|
+
if (!existsSync10(base))
|
|
44735
44706
|
continue;
|
|
44736
44707
|
try {
|
|
44737
44708
|
for (const entry of readdirSync2(base)) {
|
|
44738
|
-
const full =
|
|
44739
|
-
if (statSync2(full).isDirectory() &&
|
|
44709
|
+
const full = join14(base, entry);
|
|
44710
|
+
if (statSync2(full).isDirectory() && existsSync10(join14(full, "SKILL.md"))) {
|
|
44740
44711
|
paths.push(full);
|
|
44741
44712
|
}
|
|
44742
44713
|
}
|
|
@@ -45270,14 +45241,14 @@ async function runAcpAgent(options) {
|
|
|
45270
45241
|
import { execSync } from "node:child_process";
|
|
45271
45242
|
import {
|
|
45272
45243
|
copyFileSync,
|
|
45273
|
-
existsSync as
|
|
45244
|
+
existsSync as existsSync11,
|
|
45274
45245
|
mkdirSync as mkdirSync9,
|
|
45275
45246
|
readdirSync as readdirSync3,
|
|
45276
45247
|
readFileSync as readFileSync7,
|
|
45277
45248
|
statSync as statSync3,
|
|
45278
45249
|
writeFileSync as writeFileSync10
|
|
45279
45250
|
} from "node:fs";
|
|
45280
|
-
import { basename as basename2, dirname as dirname5, join as
|
|
45251
|
+
import { basename as basename2, dirname as dirname5, join as join15, resolve as resolve3 } from "node:path";
|
|
45281
45252
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
45282
45253
|
function getPackageRoot() {
|
|
45283
45254
|
const thisDir = dirname5(fileURLToPath2(import.meta.url));
|
|
@@ -45286,7 +45257,7 @@ function getPackageRoot() {
|
|
|
45286
45257
|
function getShippedDockerfile() {
|
|
45287
45258
|
const packageRoot = getPackageRoot();
|
|
45288
45259
|
const candidates = [
|
|
45289
|
-
|
|
45260
|
+
join15(packageRoot, "Dockerfile"),
|
|
45290
45261
|
resolve3(
|
|
45291
45262
|
packageRoot,
|
|
45292
45263
|
"..",
|
|
@@ -45298,7 +45269,7 @@ function getShippedDockerfile() {
|
|
|
45298
45269
|
resolve3(process.cwd(), "docker", "bunny-agent-claude", "Dockerfile")
|
|
45299
45270
|
];
|
|
45300
45271
|
for (const p of candidates) {
|
|
45301
|
-
if (
|
|
45272
|
+
if (existsSync11(p)) return p;
|
|
45302
45273
|
}
|
|
45303
45274
|
console.error(
|
|
45304
45275
|
`\u274C Dockerfile not found. Searched:
|
|
@@ -45319,7 +45290,7 @@ function ensureDocker() {
|
|
|
45319
45290
|
}
|
|
45320
45291
|
function resolveTemplatePath(template) {
|
|
45321
45292
|
const abs = resolve3(process.cwd(), template);
|
|
45322
|
-
if (!
|
|
45293
|
+
if (!existsSync11(abs)) {
|
|
45323
45294
|
console.error(`\u274C Template directory not found: ${abs}`);
|
|
45324
45295
|
process.exit(1);
|
|
45325
45296
|
}
|
|
@@ -45328,8 +45299,8 @@ function resolveTemplatePath(template) {
|
|
|
45328
45299
|
function copyDirSync(src, dest) {
|
|
45329
45300
|
mkdirSync9(dest, { recursive: true });
|
|
45330
45301
|
for (const entry of readdirSync3(src)) {
|
|
45331
|
-
const srcPath =
|
|
45332
|
-
const destPath =
|
|
45302
|
+
const srcPath = join15(src, entry);
|
|
45303
|
+
const destPath = join15(dest, entry);
|
|
45333
45304
|
if (statSync3(srcPath).isDirectory()) {
|
|
45334
45305
|
copyDirSync(srcPath, destPath);
|
|
45335
45306
|
} else {
|
|
@@ -45349,23 +45320,23 @@ async function buildImage(opts) {
|
|
|
45349
45320
|
console.log(` Push: ${opts.push}`);
|
|
45350
45321
|
console.log("");
|
|
45351
45322
|
ensureDocker();
|
|
45352
|
-
const buildContext =
|
|
45323
|
+
const buildContext = join15(process.cwd(), ".docker-staging");
|
|
45353
45324
|
mkdirSync9(buildContext, { recursive: true });
|
|
45354
45325
|
let dockerfile = readFileSync7(getShippedDockerfile(), "utf8");
|
|
45355
45326
|
if (templatePath && templateName) {
|
|
45356
|
-
const destDir =
|
|
45327
|
+
const destDir = join15(buildContext, "templates", templateName);
|
|
45357
45328
|
mkdirSync9(destDir, { recursive: true });
|
|
45358
|
-
const claudeMd =
|
|
45359
|
-
if (
|
|
45360
|
-
copyFileSync(claudeMd,
|
|
45361
|
-
const claudeDir =
|
|
45362
|
-
if (
|
|
45329
|
+
const claudeMd = join15(templatePath, "CLAUDE.md");
|
|
45330
|
+
if (existsSync11(claudeMd))
|
|
45331
|
+
copyFileSync(claudeMd, join15(destDir, "CLAUDE.md"));
|
|
45332
|
+
const claudeDir = join15(templatePath, ".claude");
|
|
45333
|
+
if (existsSync11(claudeDir)) copyDirSync(claudeDir, join15(destDir, ".claude"));
|
|
45363
45334
|
let copyLines = "\n# Template files\nRUN mkdir -p /opt/bunny-agent/templates";
|
|
45364
|
-
if (
|
|
45335
|
+
if (existsSync11(join15(destDir, "CLAUDE.md"))) {
|
|
45365
45336
|
copyLines += `
|
|
45366
45337
|
COPY templates/${templateName}/CLAUDE.md /opt/bunny-agent/templates/CLAUDE.md`;
|
|
45367
45338
|
}
|
|
45368
|
-
if (
|
|
45339
|
+
if (existsSync11(join15(destDir, ".claude"))) {
|
|
45369
45340
|
copyLines += `
|
|
45370
45341
|
COPY templates/${templateName}/.claude /opt/bunny-agent/templates/.claude`;
|
|
45371
45342
|
}
|
|
@@ -45374,10 +45345,10 @@ COPY templates/${templateName}/.claude /opt/bunny-agent/templates/.claude`;
|
|
|
45374
45345
|
CMD `);
|
|
45375
45346
|
console.log("\u{1F9E9} Injected template files into Dockerfile");
|
|
45376
45347
|
}
|
|
45377
|
-
writeFileSync10(
|
|
45348
|
+
writeFileSync10(join15(buildContext, "Dockerfile"), dockerfile);
|
|
45378
45349
|
console.log("\u{1F433} Building Docker image...");
|
|
45379
45350
|
run(
|
|
45380
|
-
`docker build --platform=${opts.platform} -t ${localImage} -f ${
|
|
45351
|
+
`docker build --platform=${opts.platform} -t ${localImage} -f ${join15(buildContext, "Dockerfile")} ${buildContext}`
|
|
45381
45352
|
);
|
|
45382
45353
|
console.log(`
|
|
45383
45354
|
\u2705 Image built: ${localImage}`);
|
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.63-beta.2",
|
|
4
4
|
"description": "BunnyAgent Runner CLI - Like gemini-cli or claude-code, runs in your local terminal with AI SDK UI streaming",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -60,14 +60,14 @@
|
|
|
60
60
|
"typescript": "^5.3.0",
|
|
61
61
|
"vitest": "^1.6.1",
|
|
62
62
|
"@bunny-agent/apply-patch": "0.1.0",
|
|
63
|
-
"@bunny-agent/runner-claude": "0.6.2",
|
|
64
63
|
"@bunny-agent/runner-codex": "0.6.2",
|
|
65
|
-
"@bunny-agent/runner-
|
|
64
|
+
"@bunny-agent/runner-claude": "0.6.2",
|
|
66
65
|
"@bunny-agent/runner-gemini": "0.6.2",
|
|
67
|
-
"@bunny-agent/runner-opencode": "0.6.2",
|
|
68
66
|
"@bunny-agent/runner-harness": "0.1.1-beta.0",
|
|
69
|
-
"@bunny-agent/
|
|
67
|
+
"@bunny-agent/runner-copilot": "0.1.0",
|
|
68
|
+
"@bunny-agent/runner-opencode": "0.6.2",
|
|
70
69
|
"@bunny-agent/runner-pi": "0.6.4-beta.0",
|
|
70
|
+
"@bunny-agent/manager": "0.9.63-beta.2",
|
|
71
71
|
"@bunny-agent/server-acp": "0.1.0"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|