@bunny-agent/runner-cli 0.9.41 → 0.9.42

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.
Files changed (2) hide show
  1. package/dist/bundle.mjs +40 -321
  2. package/package.json +3 -3
package/dist/bundle.mjs CHANGED
@@ -1277,283 +1277,16 @@ function createOpenCodeRunner(options = {}) {
1277
1277
  };
1278
1278
  }
1279
1279
 
1280
- // ../../packages/runner-pi/dist/ask-user-question-tool.js
1281
- import { createHash } from "node:crypto";
1282
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync3 } from "node:fs";
1283
- import { join as join5 } from "node:path";
1284
- var TOOL_NAME = "ask_user_question";
1285
- var APPROVAL_DIR = join5(".bunny-agent", "approvals");
1286
- var ASK_USER_QUESTION_TIMEOUT_MS = 12e4;
1287
- var ASK_USER_QUESTION_POLL_MS = 500;
1288
- var MAX_QUESTIONS = 4;
1289
- var MIN_OPTIONS = 2;
1290
- var MAX_OPTIONS = 4;
1291
- var MAX_HEADER_LEN = 12;
1292
- var MAX_QUESTION_LEN = 500;
1293
- var MAX_OPTION_LABEL_LEN = 80;
1294
- var MAX_OPTION_DESCRIPTION_LEN = 240;
1295
- var ESC = String.fromCharCode(27);
1296
- var CSI = String.fromCharCode(155);
1297
- var ST = String.fromCharCode(156);
1298
- var OSC = String.fromCharCode(157);
1299
- var BEL = String.fromCharCode(7);
1300
- var ANSI_OSC_RE = new RegExp(`(?:${ESC}\\]|${OSC})[^${ESC}${ST}${BEL}]*(?:${BEL}|${ESC}\\\\|${ST})`, "g");
1301
- var ANSI_CTL_RE = new RegExp(`(?:${ESC}\\[[0-?]*[ -/]*[@-~]|${CSI}[0-?]*[ -/]*[@-~]|${ESC}[@-Z\\\\\\-_])`, "g");
1302
- var CTL_CHAR_RE = new RegExp(`[${String.fromCharCode(0)}-${String.fromCharCode(31)}${String.fromCharCode(127)}-${String.fromCharCode(159)}]+`, "g");
1303
- var askUserQuestionSchema = {
1304
- type: "object",
1305
- required: ["questions"],
1306
- properties: {
1307
- questions: {
1308
- type: "array",
1309
- minItems: 1,
1310
- maxItems: MAX_QUESTIONS,
1311
- description: `Between 1 and ${MAX_QUESTIONS} questions to ask the user.`,
1312
- items: {
1313
- type: "object",
1314
- required: ["question", "header", "multiSelect", "options"],
1315
- properties: {
1316
- question: {
1317
- type: "string",
1318
- description: "The full question to ask the user. Should be specific, end with a question mark, and avoid jargon the user has not used."
1319
- },
1320
- header: {
1321
- type: "string",
1322
- description: `Short label (max ${MAX_HEADER_LEN} chars) shown as a chip/tag in the UI. Examples: "Library", "Auth method", "Approach".`
1323
- },
1324
- multiSelect: {
1325
- type: "boolean",
1326
- description: "Set true when the choices are not mutually exclusive and the user may select more than one."
1327
- },
1328
- options: {
1329
- type: "array",
1330
- minItems: MIN_OPTIONS,
1331
- maxItems: MAX_OPTIONS,
1332
- description: `Between ${MIN_OPTIONS} and ${MAX_OPTIONS} mutually exclusive options. Do not add an "Other" option \u2014 the host adds one automatically.`,
1333
- items: {
1334
- type: "object",
1335
- required: ["label", "description"],
1336
- properties: {
1337
- label: {
1338
- type: "string",
1339
- description: "Display text for the option (1-5 words). Should clearly describe the choice."
1340
- },
1341
- description: {
1342
- type: "string",
1343
- description: "What this option means or what happens if chosen \u2014 call out trade-offs."
1344
- }
1345
- }
1346
- }
1347
- }
1348
- }
1349
- }
1350
- }
1351
- }
1352
- };
1353
- var TOOL_DESCRIPTION = `Ask the user one or more multiple-choice questions when the task is genuinely ambiguous and you need user input to proceed (choosing between libraries, design approaches, trade-offs, etc.). Each question carries 2-${MAX_OPTIONS} options; up to ${MAX_QUESTIONS} questions per call. The user can also select an automatically-provided "Other" option to give free-form input. Use sparingly \u2014 prefer making a sensible default choice when the task is clear.`;
1354
- function sanitizeText(value) {
1355
- if (typeof value !== "string")
1356
- return "";
1357
- return value.replace(ANSI_OSC_RE, "").replace(ANSI_CTL_RE, "").replace(CTL_CHAR_RE, " ").replace(/\s+/g, " ").trim();
1358
- }
1359
- function truncate(value, max) {
1360
- return value.length <= max ? value : `${value.slice(0, Math.max(0, max - 3))}...`;
1361
- }
1362
- function sanitizeQuestions(questions) {
1363
- return questions.map((q) => ({
1364
- question: truncate(sanitizeText(q.question), MAX_QUESTION_LEN),
1365
- header: truncate(sanitizeText(q.header), MAX_HEADER_LEN),
1366
- multiSelect: !!q.multiSelect,
1367
- options: q.options.map((o) => ({
1368
- label: truncate(sanitizeText(o.label), MAX_OPTION_LABEL_LEN),
1369
- description: truncate(sanitizeText(o.description), MAX_OPTION_DESCRIPTION_LEN)
1370
- }))
1371
- }));
1372
- }
1373
- function readApproval(file) {
1374
- try {
1375
- const raw = readFileSync3(file, "utf-8");
1376
- return JSON.parse(raw);
1377
- } catch {
1378
- return void 0;
1379
- }
1380
- }
1381
- var TOOL_CALL_ID_PREFIX_LEN = 32;
1382
- var TOOL_CALL_ID_HASH_LEN = 16;
1383
- function sanitizeToolCallId(toolCallId) {
1384
- const safePrefix = toolCallId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, TOOL_CALL_ID_PREFIX_LEN);
1385
- const hash = createHash("sha1").update(toolCallId).digest("hex").slice(0, TOOL_CALL_ID_HASH_LEN);
1386
- return `${safePrefix}-${hash}`;
1387
- }
1388
- function safeUnlink(file) {
1389
- try {
1390
- if (existsSync4(file))
1391
- unlinkSync3(file);
1392
- } catch {
1393
- }
1394
- }
1395
- async function pollApprovalFile(approvalFile, signal, options = {}) {
1396
- const timeoutMs = options.timeoutMs ?? ASK_USER_QUESTION_TIMEOUT_MS;
1397
- const pollMs = options.pollMs ?? ASK_USER_QUESTION_POLL_MS;
1398
- const deadline = Date.now() + timeoutMs;
1399
- let lastApproval;
1400
- while (true) {
1401
- if (signal?.aborted) {
1402
- return { kind: "aborted", answers: lastApproval?.answers ?? {} };
1403
- }
1404
- const approval = readApproval(approvalFile);
1405
- if (approval)
1406
- lastApproval = approval;
1407
- if (approval && approval.status !== "pending") {
1408
- const answers = approval.answers ?? {};
1409
- if (approval.status === "completed" && Object.keys(answers).length > 0) {
1410
- return { kind: "answered", answers };
1411
- }
1412
- if (approval.status === "declined") {
1413
- return { kind: "declined", answers, reason: approval.reason };
1414
- }
1415
- if (approval.status === "cancelled") {
1416
- return { kind: "cancelled", answers, reason: approval.reason };
1417
- }
1418
- return {
1419
- kind: "declined",
1420
- answers,
1421
- reason: approval.reason ?? "no_answer_provided"
1422
- };
1423
- }
1424
- if (Date.now() >= deadline) {
1425
- const partial = lastApproval?.answers ?? {};
1426
- return {
1427
- kind: Object.keys(partial).length > 0 ? "answered" : "timeout",
1428
- answers: partial
1429
- };
1430
- }
1431
- await sleepWithAbort(Math.min(pollMs, Math.max(0, deadline - Date.now())), signal);
1432
- }
1433
- }
1434
- function sleepWithAbort(ms, signal) {
1435
- return new Promise((resolve4) => {
1436
- if (ms <= 0) {
1437
- resolve4();
1438
- return;
1439
- }
1440
- if (signal?.aborted) {
1441
- resolve4();
1442
- return;
1443
- }
1444
- const onAbort = () => {
1445
- clearTimeout(timer);
1446
- resolve4();
1447
- };
1448
- const timer = setTimeout(() => {
1449
- signal?.removeEventListener("abort", onAbort);
1450
- resolve4();
1451
- }, ms);
1452
- signal?.addEventListener("abort", onAbort, { once: true });
1453
- });
1454
- }
1455
- function formatAcceptedText(questions, answers) {
1456
- const lines = ["User answered:"];
1457
- for (const q of questions) {
1458
- const raw = answers[q.question];
1459
- const formatted = Array.isArray(raw) ? raw.join(", ") : typeof raw === "string" && raw.length > 0 ? raw : "(no answer)";
1460
- lines.push(`Q: ${q.question}`);
1461
- lines.push(`A: ${formatted}`);
1462
- }
1463
- return lines.join("\n");
1464
- }
1465
- function formatDeclinedText(reason, partial) {
1466
- const partialNote = Object.keys(partial).length > 0 ? ` Partial answers received: ${JSON.stringify(partial)}.` : "";
1467
- return `User did not answer the questions (reason: ${reason}). Make a sensible default choice and continue, or ask again if the choice is genuinely required.${partialNote}`;
1468
- }
1469
- function buildAskUserQuestionTool(opts) {
1470
- const { cwd, timeoutMs, pollMs } = opts;
1471
- return {
1472
- name: TOOL_NAME,
1473
- label: "ask_user_question",
1474
- description: TOOL_DESCRIPTION,
1475
- promptSnippet: "ask_user_question: ask the user 1-4 multiple-choice questions when the task is genuinely ambiguous.",
1476
- promptGuidelines: [
1477
- "Use ask_user_question only when the task is genuinely ambiguous and a user choice is required to proceed; otherwise pick a sensible default.",
1478
- "Each question must carry 2-4 mutually exclusive options. Do not add an 'Other' option \u2014 the host adds one automatically."
1479
- ],
1480
- // Pause other tool calls while a user prompt is open; otherwise pi may
1481
- // surface output the user has not yet had a chance to react to.
1482
- executionMode: "sequential",
1483
- // biome-ignore lint/suspicious/noExplicitAny: TypeBox accepts plain JSON Schema literals here, see image-tools.ts.
1484
- parameters: askUserQuestionSchema,
1485
- async execute(toolCallId, params, signal) {
1486
- const raw = params.questions ?? [];
1487
- const sanitized = sanitizeQuestions(raw);
1488
- const sanitizedInput = { questions: sanitized };
1489
- const approvalDir = join5(cwd, APPROVAL_DIR);
1490
- const approvalFile = join5(approvalDir, `${sanitizeToolCallId(toolCallId)}.json`);
1491
- try {
1492
- mkdirSync2(approvalDir, { recursive: true });
1493
- const pending = {
1494
- status: "pending",
1495
- toolName: TOOL_NAME,
1496
- input: sanitizedInput,
1497
- questions: sanitized,
1498
- answers: {}
1499
- };
1500
- writeFileSync3(approvalFile, JSON.stringify(pending));
1501
- } catch (error) {
1502
- const message = error instanceof Error ? error.message : "Unknown error";
1503
- return {
1504
- content: [
1505
- {
1506
- type: "text",
1507
- text: `ask_user_question failed to create approval file: ${message}`
1508
- }
1509
- ],
1510
- details: void 0
1511
- };
1512
- }
1513
- let outcome;
1514
- try {
1515
- outcome = await pollApprovalFile(approvalFile, signal, {
1516
- timeoutMs,
1517
- pollMs
1518
- });
1519
- } finally {
1520
- safeUnlink(approvalFile);
1521
- }
1522
- if (outcome.kind === "answered") {
1523
- return {
1524
- content: [
1525
- {
1526
- type: "text",
1527
- text: formatAcceptedText(sanitized, outcome.answers)
1528
- }
1529
- ],
1530
- details: void 0
1531
- };
1532
- }
1533
- const reason = outcome.kind === "timeout" ? "timeout" : outcome.kind === "aborted" ? "run_aborted" : outcome.reason ?? outcome.kind;
1534
- return {
1535
- content: [
1536
- {
1537
- type: "text",
1538
- text: formatDeclinedText(reason, outcome.answers)
1539
- }
1540
- ],
1541
- details: void 0
1542
- };
1543
- }
1544
- };
1545
- }
1546
-
1547
1280
  // ../../packages/runner-pi/dist/pi-runner.js
1548
- import { appendFileSync as appendFileSync2, existsSync as existsSync6, unlinkSync as unlinkSync4 } from "node:fs";
1549
- import { join as join9 } from "node:path";
1281
+ import { appendFileSync as appendFileSync2, existsSync as existsSync5, unlinkSync as unlinkSync3 } from "node:fs";
1282
+ import { join as join8 } from "node:path";
1550
1283
  import { getModel } from "@earendil-works/pi-ai";
1551
1284
  import { AuthStorage, createAgentSession, ModelRegistry, SessionManager as SessionManager2 } from "@earendil-works/pi-coding-agent";
1552
1285
 
1553
1286
  // ../../packages/runner-pi/dist/bunny-agent-resource-loader.js
1554
- import { existsSync as existsSync5 } from "node:fs";
1287
+ import { existsSync as existsSync4 } from "node:fs";
1555
1288
  import { homedir } from "node:os";
1556
- import { isAbsolute, join as join6, resolve as resolve2 } from "node:path";
1289
+ import { isAbsolute, join as join5, resolve as resolve2 } from "node:path";
1557
1290
  import { DefaultResourceLoader, loadSkills } from "@earendil-works/pi-coding-agent";
1558
1291
  var LOG_PREFIX = "[bunny-agent:pi]";
1559
1292
  function logSkillLoad(cwd, agentDir, skillPaths, result) {
@@ -1565,7 +1298,7 @@ function logSkillLoad(cwd, agentDir, skillPaths, result) {
1565
1298
  ];
1566
1299
  for (const raw of skillPaths) {
1567
1300
  const abs = isAbsolute(raw) ? raw : resolve2(cwd, raw);
1568
- lines.push(` ${raw} -> ${abs} (exists: ${existsSync5(abs) ? "yes" : "no"})`);
1301
+ lines.push(` ${raw} -> ${abs} (exists: ${existsSync4(abs) ? "yes" : "no"})`);
1569
1302
  }
1570
1303
  lines.push(` loaded skills: ${result.skills.length}`);
1571
1304
  if (result.skills.length > 0) {
@@ -1583,7 +1316,7 @@ function logSkillLoad(cwd, agentDir, skillPaths, result) {
1583
1316
  var BunnyAgentResourceLoader = class {
1584
1317
  constructor(options = {}) {
1585
1318
  this.cwd = options.cwd ?? process.cwd();
1586
- this.agentDir = options.agentDir ?? join6(homedir(), ".bunny", "agent");
1319
+ this.agentDir = options.agentDir ?? join5(homedir(), ".bunny", "agent");
1587
1320
  this.skillPaths = options.skillPaths ?? [];
1588
1321
  this.extraAppendPrompt = options.appendSystemPrompt;
1589
1322
  this.delegate = new DefaultResourceLoader({
@@ -1640,8 +1373,8 @@ var BunnyAgentResourceLoader = class {
1640
1373
  };
1641
1374
 
1642
1375
  // ../../packages/runner-pi/dist/image-tools.js
1643
- import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "node:fs";
1644
- import { dirname as dirname3, extname, join as join7 } from "node:path";
1376
+ import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
1377
+ import { dirname as dirname3, extname, join as join6 } from "node:path";
1645
1378
  var generateImageSchema = {
1646
1379
  type: "object",
1647
1380
  properties: {
@@ -1874,8 +1607,8 @@ async function saveImageItem(item, filePath, apiKey) {
1874
1607
  const b64 = await resolveB64(item, apiKey);
1875
1608
  if (!b64)
1876
1609
  return void 0;
1877
- mkdirSync3(dirname3(filePath), { recursive: true });
1878
- writeFileSync4(filePath, Buffer.from(b64, "base64"));
1610
+ mkdirSync2(dirname3(filePath), { recursive: true });
1611
+ writeFileSync3(filePath, Buffer.from(b64, "base64"));
1879
1612
  return filePath;
1880
1613
  }
1881
1614
  function buildImageGenerateTool(cwd, imageModelId, baseUrl, apiKey) {
@@ -1902,7 +1635,7 @@ function buildImageGenerateTool(cwd, imageModelId, baseUrl, apiKey) {
1902
1635
  const imageSize = p.imageSize;
1903
1636
  const rawFilename = p.filename;
1904
1637
  const filename = rawFilename ? extname(rawFilename) ? rawFilename : `${rawFilename}.png` : `image_${Date.now()}.png`;
1905
- const filePath = join7(cwd, filename.replace(/[^a-zA-Z0-9_\-./]/g, "_"));
1638
+ const filePath = join6(cwd, filename.replace(/[^a-zA-Z0-9_\-./]/g, "_"));
1906
1639
  try {
1907
1640
  const url = `${baseUrl.replace(/\/$/, "")}/v1/images/generations`;
1908
1641
  const res = await fetch(url, {
@@ -2050,7 +1783,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
2050
1783
  // biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
2051
1784
  parameters: editImageSchema,
2052
1785
  async execute(_toolCallId, params, signal, _onUpdate) {
2053
- const { readFileSync: readFileSync5, existsSync: existsSync9 } = await import("node:fs");
1786
+ const { readFileSync: readFileSync4, existsSync: existsSync8 } = await import("node:fs");
2054
1787
  const { resolve: resolve4, basename: basename2 } = await import("node:path");
2055
1788
  const p = params;
2056
1789
  const imagePath = p.image;
@@ -2063,7 +1796,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
2063
1796
  const rawFilename = p.filename;
2064
1797
  const safePrompt = buildPolicySafeEditPrompt(prompt);
2065
1798
  const resolvedImage = resolve4(cwd, imagePath);
2066
- if (!existsSync9(resolvedImage)) {
1799
+ if (!existsSync8(resolvedImage)) {
2067
1800
  return {
2068
1801
  content: [
2069
1802
  {
@@ -2075,9 +1808,9 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
2075
1808
  };
2076
1809
  }
2077
1810
  const filename = rawFilename ? extname(rawFilename) ? rawFilename : `${rawFilename}.png` : `edited_${Date.now()}.png`;
2078
- const filePath = join7(cwd, filename.replace(/[^a-zA-Z0-9_\-./]/g, "_"));
1811
+ const filePath = join6(cwd, filename.replace(/[^a-zA-Z0-9_\-./]/g, "_"));
2079
1812
  try {
2080
- const imageBuffer = readFileSync5(resolvedImage);
1813
+ const imageBuffer = readFileSync4(resolvedImage);
2081
1814
  const fields = [
2082
1815
  { name: "model", value: imageModelId },
2083
1816
  { name: "prompt", value: safePrompt.prompt },
@@ -2107,11 +1840,11 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
2107
1840
  ];
2108
1841
  if (maskPath) {
2109
1842
  const resolvedMask = resolve4(cwd, maskPath);
2110
- if (existsSync9(resolvedMask)) {
1843
+ if (existsSync8(resolvedMask)) {
2111
1844
  files.push({
2112
1845
  name: "mask",
2113
1846
  filename: basename2(resolvedMask),
2114
- buffer: readFileSync5(resolvedMask),
1847
+ buffer: readFileSync4(resolvedMask),
2115
1848
  mime: detectImageMime(resolvedMask)
2116
1849
  });
2117
1850
  }
@@ -2174,7 +1907,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
2174
1907
 
2175
1908
  // ../../packages/runner-pi/dist/session-utils.js
2176
1909
  import { closeSync, fstatSync, openSync, readdirSync as readdirSync2, readSync, statSync as statSync2 } from "node:fs";
2177
- import { join as join8 } from "node:path";
1910
+ import { join as join7 } from "node:path";
2178
1911
  import { SessionManager } from "@earendil-works/pi-coding-agent";
2179
1912
  var MAX_SESSION_FILE_BYTES = Number(process.env.SANDAGENT_MAX_SESSION_BYTES) || 10 * 1024 * 1024;
2180
1913
  function resolveSessionPathById(cwd, sessionId) {
@@ -2183,7 +1916,7 @@ function resolveSessionPathById(cwd, sessionId) {
2183
1916
  try {
2184
1917
  const suffix = `_${sessionId}.jsonl`;
2185
1918
  const match = readdirSync2(sessionsDir).find((f) => f.endsWith(suffix));
2186
- return match ? join8(sessionsDir, match) : void 0;
1919
+ return match ? join7(sessionsDir, match) : void 0;
2187
1920
  } catch {
2188
1921
  return void 0;
2189
1922
  }
@@ -2363,16 +2096,15 @@ var PiAISDKStreamConverter = class {
2363
2096
  }
2364
2097
  if (event.type === "tool_execution_start") {
2365
2098
  chunks.push(...this.endTextStreamIfOpen());
2366
- const toolCallId = sanitizeToolCallId(event.toolCallId);
2367
2099
  chunks.push(sseData({
2368
2100
  type: "tool-input-start",
2369
- toolCallId,
2101
+ toolCallId: event.toolCallId,
2370
2102
  toolName: event.toolName,
2371
2103
  dynamic: true,
2372
2104
  providerExecuted: true
2373
2105
  }), sseData({
2374
2106
  type: "tool-input-available",
2375
- toolCallId,
2107
+ toolCallId: event.toolCallId,
2376
2108
  toolName: event.toolName,
2377
2109
  input: event.args,
2378
2110
  dynamic: true,
@@ -2385,11 +2117,10 @@ var PiAISDKStreamConverter = class {
2385
2117
  const raw = event.result?.details?.usage?.raw;
2386
2118
  if (raw != null)
2387
2119
  accumulateToolUsage(this.toolUsageTally, raw);
2388
- const toolCallId = sanitizeToolCallId(event.toolCallId);
2389
2120
  if (event.isError) {
2390
2121
  chunks.push(sseData({
2391
2122
  type: "tool-output-error",
2392
- toolCallId,
2123
+ toolCallId: event.toolCallId,
2393
2124
  errorText: output,
2394
2125
  dynamic: true,
2395
2126
  providerExecuted: true
@@ -2397,7 +2128,7 @@ var PiAISDKStreamConverter = class {
2397
2128
  } else {
2398
2129
  chunks.push(sseData({
2399
2130
  type: "tool-output-available",
2400
- toolCallId,
2131
+ toolCallId: event.toolCallId,
2401
2132
  output,
2402
2133
  dynamic: true,
2403
2134
  providerExecuted: true
@@ -5620,12 +5351,6 @@ function resolveImageModelName(chatProvider, env) {
5620
5351
  function getEnvValue(optionsEnv, name) {
5621
5352
  return optionsEnv?.[name] ?? process.env[name];
5622
5353
  }
5623
- function parsePositiveInt(value) {
5624
- if (value === void 0 || value === "")
5625
- return void 0;
5626
- const n = Number(value);
5627
- return Number.isFinite(n) && n > 0 ? Math.floor(n) : void 0;
5628
- }
5629
5354
  function applyModelOverrides(model, provider, optionsEnv) {
5630
5355
  if (model == null)
5631
5356
  return;
@@ -5655,9 +5380,9 @@ function traceRawMessage(debugCwd, data, reset = false, optionsEnv) {
5655
5380
  if (!enabled)
5656
5381
  return;
5657
5382
  try {
5658
- const file = join9(debugCwd, "pi-message-stream-debug.json");
5659
- if (reset && existsSync6(file))
5660
- unlinkSync4(file);
5383
+ const file = join8(debugCwd, "pi-message-stream-debug.json");
5384
+ if (reset && existsSync5(file))
5385
+ unlinkSync3(file);
5661
5386
  const type = data !== null && typeof data === "object" ? data.type : void 0;
5662
5387
  let payload = data;
5663
5388
  try {
@@ -5760,12 +5485,6 @@ function createPiRunner(options = {}) {
5760
5485
  customTools.push(buildImageGenerateTool(cwd, imageModelName, model.baseUrl, apiKey), buildImageEditTool(cwd, imageModelName, model.baseUrl, apiKey));
5761
5486
  }
5762
5487
  const toolRefDefinitions = options.toolRefs && options.toolRefs.length > 0 ? buildToolDefinitionsFromRefs(options.toolRefs) : [];
5763
- const askTimeoutSeconds = parsePositiveInt(getEnvValue(options.env, "ASK_USER_QUESTION_TOOL_TIMEOUT"));
5764
- const askUserQuestionTool = buildAskUserQuestionTool({
5765
- cwd,
5766
- timeoutMs: askTimeoutSeconds !== void 0 ? askTimeoutSeconds * 1e3 : void 0
5767
- });
5768
- customTools.push(askUserQuestionTool);
5769
5488
  const { session } = await createAgentSession({
5770
5489
  cwd,
5771
5490
  model,
@@ -5874,47 +5593,47 @@ function createPiRunner(options = {}) {
5874
5593
  }
5875
5594
 
5876
5595
  // ../../packages/runner-harness/dist/session.js
5877
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync5 } from "node:fs";
5878
- import { join as join10 } from "node:path";
5596
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
5597
+ import { join as join9 } from "node:path";
5879
5598
  var DIR = ".bunny-agent";
5880
5599
  var FILE = "session-id";
5881
5600
  function sessionPath(cwd) {
5882
- return join10(cwd, DIR, FILE);
5601
+ return join9(cwd, DIR, FILE);
5883
5602
  }
5884
5603
  function readSessionId(cwd) {
5885
5604
  try {
5886
5605
  const p = sessionPath(cwd);
5887
- if (!existsSync7(p))
5606
+ if (!existsSync6(p))
5888
5607
  return void 0;
5889
- return readFileSync4(p, "utf8").trim() || void 0;
5608
+ return readFileSync3(p, "utf8").trim() || void 0;
5890
5609
  } catch {
5891
5610
  return void 0;
5892
5611
  }
5893
5612
  }
5894
5613
  function writeSessionId(cwd, id) {
5895
5614
  try {
5896
- mkdirSync4(join10(cwd, DIR), { recursive: true });
5897
- writeFileSync5(sessionPath(cwd), id, "utf8");
5615
+ mkdirSync3(join9(cwd, DIR), { recursive: true });
5616
+ writeFileSync4(sessionPath(cwd), id, "utf8");
5898
5617
  } catch {
5899
5618
  }
5900
5619
  }
5901
5620
 
5902
5621
  // ../../packages/runner-harness/dist/skills.js
5903
- import { existsSync as existsSync8, readdirSync as readdirSync3, statSync as statSync3 } from "node:fs";
5622
+ import { existsSync as existsSync7, readdirSync as readdirSync3, statSync as statSync3 } from "node:fs";
5904
5623
  import { homedir as homedir2 } from "node:os";
5905
- import { join as join11 } from "node:path";
5624
+ import { join as join10 } from "node:path";
5906
5625
  function discoverSkillPaths(cwd) {
5907
5626
  const paths = [];
5908
5627
  for (const base of [
5909
- join11(cwd, "skills"),
5910
- join11(homedir2(), ".bunny-agent", "skills")
5628
+ join10(cwd, "skills"),
5629
+ join10(homedir2(), ".bunny-agent", "skills")
5911
5630
  ]) {
5912
- if (!existsSync8(base))
5631
+ if (!existsSync7(base))
5913
5632
  continue;
5914
5633
  try {
5915
5634
  for (const entry of readdirSync3(base)) {
5916
- const full = join11(base, entry);
5917
- if (statSync3(full).isDirectory() && existsSync8(join11(full, "SKILL.md"))) {
5635
+ const full = join10(base, entry);
5636
+ if (statSync3(full).isDirectory() && existsSync7(join10(full, "SKILL.md"))) {
5918
5637
  paths.push(full);
5919
5638
  }
5920
5639
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunny-agent/runner-cli",
3
- "version": "0.9.41",
3
+ "version": "0.9.42",
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": {
@@ -53,10 +53,10 @@
53
53
  "esbuild": "^0.27.2",
54
54
  "typescript": "^5.3.0",
55
55
  "vitest": "^1.6.1",
56
- "@bunny-agent/runner-claude": "0.6.2",
57
56
  "@bunny-agent/runner-codex": "0.6.2",
58
- "@bunny-agent/runner-gemini": "0.6.2",
57
+ "@bunny-agent/runner-claude": "0.6.2",
59
58
  "@bunny-agent/runner-harness": "0.1.1-beta.0",
59
+ "@bunny-agent/runner-gemini": "0.6.2",
60
60
  "@bunny-agent/runner-opencode": "0.6.2",
61
61
  "@bunny-agent/runner-pi": "0.6.4-beta.0"
62
62
  },