@bunny-agent/runner-cli 0.9.29-beta.0 → 0.9.29-beta.11
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/build-image.d.ts.map +1 -1
- package/dist/build-image.js +2 -0
- package/dist/build-image.js.map +1 -1
- package/dist/bundle.mjs +410 -245
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-image.d.ts","sourceRoot":"","sources":["../src/build-image.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,iBAAiB;IAChC,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,IAAI,EAAE,OAAO,CAAC;CACf;
|
|
1
|
+
{"version":3,"file":"build-image.d.ts","sourceRoot":"","sources":["../src/build-image.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,iBAAiB;IAChC,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,QAAQ,EAAE,MAAM,CAAC;IACjB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,IAAI,EAAE,OAAO,CAAC;CACf;AA6ED,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2EvE"}
|
package/dist/build-image.js
CHANGED
|
@@ -13,10 +13,12 @@ function getShippedDockerfile() {
|
|
|
13
13
|
// Look for Dockerfile in several locations:
|
|
14
14
|
// 1. Package root (apps/runner-cli/Dockerfile) — shipped with npm package
|
|
15
15
|
// 2. docker/bunny-agent-claude/Dockerfile — monorepo development
|
|
16
|
+
// 3. CWD-relative docker/bunny-agent-claude/Dockerfile — global install invoked from repo root
|
|
16
17
|
const packageRoot = getPackageRoot();
|
|
17
18
|
const candidates = [
|
|
18
19
|
join(packageRoot, "Dockerfile"),
|
|
19
20
|
resolve(packageRoot, "..", "..", "docker", "bunny-agent-claude", "Dockerfile"),
|
|
21
|
+
resolve(process.cwd(), "docker", "bunny-agent-claude", "Dockerfile"),
|
|
20
22
|
];
|
|
21
23
|
for (const p of candidates) {
|
|
22
24
|
if (existsSync(p))
|
package/dist/build-image.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-image.js","sourceRoot":"","sources":["../src/build-image.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EACL,YAAY,EACZ,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,aAAa,GACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAiBzC,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,SAAS,cAAc;IACrB,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACxD,OAAO,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,oBAAoB;IAC3B,4CAA4C;IAC5C,0EAA0E;IAC1E,iEAAiE;IACjE,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;IACrC,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC;QAC/B,OAAO,CACL,WAAW,EACX,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,oBAAoB,EACpB,YAAY,CACb;
|
|
1
|
+
{"version":3,"file":"build-image.js","sourceRoot":"","sources":["../src/build-image.ts"],"names":[],"mappings":"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"}
|
package/dist/bundle.mjs
CHANGED
|
@@ -33,7 +33,8 @@ function getShippedDockerfile() {
|
|
|
33
33
|
"docker",
|
|
34
34
|
"bunny-agent-claude",
|
|
35
35
|
"Dockerfile"
|
|
36
|
-
)
|
|
36
|
+
),
|
|
37
|
+
resolve(process.cwd(), "docker", "bunny-agent-claude", "Dockerfile")
|
|
37
38
|
];
|
|
38
39
|
for (const p of candidates) {
|
|
39
40
|
if (existsSync(p)) return p;
|
|
@@ -1273,9 +1274,9 @@ function createOpenCodeRunner(options = {}) {
|
|
|
1273
1274
|
|
|
1274
1275
|
// ../../packages/runner-pi/dist/pi-runner.js
|
|
1275
1276
|
import { appendFileSync as appendFileSync2, existsSync as existsSync5, unlinkSync as unlinkSync3 } from "node:fs";
|
|
1276
|
-
import { join as
|
|
1277
|
+
import { join as join8 } from "node:path";
|
|
1277
1278
|
import { getModel } from "@mariozechner/pi-ai";
|
|
1278
|
-
import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "@mariozechner/pi-coding-agent";
|
|
1279
|
+
import { AuthStorage, createAgentSession, ModelRegistry, SessionManager as SessionManager2 } from "@mariozechner/pi-coding-agent";
|
|
1279
1280
|
|
|
1280
1281
|
// ../../packages/runner-pi/dist/bunny-agent-resource-loader.js
|
|
1281
1282
|
import { existsSync as existsSync4 } from "node:fs";
|
|
@@ -1399,8 +1400,8 @@ var generateImageSchema = {
|
|
|
1399
1400
|
},
|
|
1400
1401
|
quality: {
|
|
1401
1402
|
type: "string",
|
|
1402
|
-
enum: ["
|
|
1403
|
-
description: "Image quality
|
|
1403
|
+
enum: ["low", "medium", "high", "auto"],
|
|
1404
|
+
description: "Image quality. Defaults to auto."
|
|
1404
1405
|
}
|
|
1405
1406
|
},
|
|
1406
1407
|
required: ["prompt"],
|
|
@@ -1558,11 +1559,11 @@ function buildImageGenerateTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
1558
1559
|
],
|
|
1559
1560
|
// biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
|
|
1560
1561
|
parameters: generateImageSchema,
|
|
1561
|
-
async execute(_toolCallId, params,
|
|
1562
|
+
async execute(_toolCallId, params, signal, _onUpdate) {
|
|
1562
1563
|
const p = params;
|
|
1563
1564
|
const prompt = p.prompt;
|
|
1564
1565
|
const size = p.size ?? "1024x1024";
|
|
1565
|
-
const quality = p.quality ?? "
|
|
1566
|
+
const quality = p.quality ?? "auto";
|
|
1566
1567
|
const rawFilename = p.filename;
|
|
1567
1568
|
const filename = rawFilename ? extname(rawFilename) ? rawFilename : `${rawFilename}.png` : `image_${Date.now()}.png`;
|
|
1568
1569
|
const filePath = join6(cwd, filename.replace(/[^a-zA-Z0-9_\-./]/g, "_"));
|
|
@@ -1582,7 +1583,8 @@ function buildImageGenerateTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
1582
1583
|
quality,
|
|
1583
1584
|
response_format: "b64_json",
|
|
1584
1585
|
output_format: "png"
|
|
1585
|
-
})
|
|
1586
|
+
}),
|
|
1587
|
+
signal
|
|
1586
1588
|
});
|
|
1587
1589
|
if (!res.ok) {
|
|
1588
1590
|
throw new Error(`Image generation failed (${res.status}): ${await res.text()}`);
|
|
@@ -1599,6 +1601,7 @@ function buildImageGenerateTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
1599
1601
|
],
|
|
1600
1602
|
details: {
|
|
1601
1603
|
filePath: savedPath,
|
|
1604
|
+
...json.usage != null ? { usage: { raw: { [imageModelId]: json.usage } } } : {},
|
|
1602
1605
|
response: json
|
|
1603
1606
|
}
|
|
1604
1607
|
};
|
|
@@ -1687,7 +1690,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
1687
1690
|
],
|
|
1688
1691
|
// biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
|
|
1689
1692
|
parameters: editImageSchema,
|
|
1690
|
-
async execute(_toolCallId, params,
|
|
1693
|
+
async execute(_toolCallId, params, signal, _onUpdate) {
|
|
1691
1694
|
const { readFileSync: readFileSync4, existsSync: existsSync8 } = await import("node:fs");
|
|
1692
1695
|
const { resolve: resolve4, basename: basename2 } = await import("node:path");
|
|
1693
1696
|
const p = params;
|
|
@@ -1755,7 +1758,8 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
1755
1758
|
"Content-Type": type,
|
|
1756
1759
|
Authorization: `Bearer ${apiKey}`
|
|
1757
1760
|
},
|
|
1758
|
-
body
|
|
1761
|
+
body,
|
|
1762
|
+
signal
|
|
1759
1763
|
});
|
|
1760
1764
|
if (!res.ok) {
|
|
1761
1765
|
throw new Error(`Image edit failed (${res.status}): ${await res.text()}`);
|
|
@@ -1785,6 +1789,7 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
1785
1789
|
],
|
|
1786
1790
|
details: {
|
|
1787
1791
|
filePath: savedPath,
|
|
1792
|
+
...json.usage != null ? { usage: { raw: { [imageModelId]: json.usage } } } : {},
|
|
1788
1793
|
response: json
|
|
1789
1794
|
}
|
|
1790
1795
|
};
|
|
@@ -1801,6 +1806,310 @@ function buildImageEditTool(cwd, imageModelId, baseUrl, apiKey) {
|
|
|
1801
1806
|
};
|
|
1802
1807
|
}
|
|
1803
1808
|
|
|
1809
|
+
// ../../packages/runner-pi/dist/session-utils.js
|
|
1810
|
+
import { closeSync, fstatSync, openSync, readdirSync as readdirSync2, readSync, statSync as statSync2 } from "node:fs";
|
|
1811
|
+
import { join as join7 } from "node:path";
|
|
1812
|
+
import { SessionManager } from "@mariozechner/pi-coding-agent";
|
|
1813
|
+
var MAX_SESSION_FILE_BYTES = Number(process.env.SANDAGENT_MAX_SESSION_BYTES) || 10 * 1024 * 1024;
|
|
1814
|
+
function resolveSessionPathById(cwd, sessionId) {
|
|
1815
|
+
const tempMgr = SessionManager.create(cwd);
|
|
1816
|
+
const sessionsDir = tempMgr.getSessionDir();
|
|
1817
|
+
try {
|
|
1818
|
+
const suffix = `_${sessionId}.jsonl`;
|
|
1819
|
+
const match = readdirSync2(sessionsDir).find((f) => f.endsWith(suffix));
|
|
1820
|
+
return match ? join7(sessionsDir, match) : void 0;
|
|
1821
|
+
} catch {
|
|
1822
|
+
return void 0;
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
function isSessionFileTooLarge(sessionPath2) {
|
|
1826
|
+
try {
|
|
1827
|
+
return statSync2(sessionPath2).size > MAX_SESSION_FILE_BYTES;
|
|
1828
|
+
} catch {
|
|
1829
|
+
return false;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
function readTailEntries(sessionPath2, tailBytes = 1024 * 1024) {
|
|
1833
|
+
let fd;
|
|
1834
|
+
try {
|
|
1835
|
+
fd = openSync(sessionPath2, "r");
|
|
1836
|
+
} catch {
|
|
1837
|
+
return [];
|
|
1838
|
+
}
|
|
1839
|
+
try {
|
|
1840
|
+
const fileSize = fstatSync(fd).size;
|
|
1841
|
+
const readStart = Math.max(0, fileSize - tailBytes);
|
|
1842
|
+
const readLen = fileSize - readStart;
|
|
1843
|
+
const buf = Buffer.alloc(readLen);
|
|
1844
|
+
readSync(fd, buf, 0, readLen, readStart);
|
|
1845
|
+
const tail = buf.toString("utf8");
|
|
1846
|
+
const entries = [];
|
|
1847
|
+
for (const line of tail.split("\n")) {
|
|
1848
|
+
const trimmed = line.trim();
|
|
1849
|
+
if (!trimmed)
|
|
1850
|
+
continue;
|
|
1851
|
+
try {
|
|
1852
|
+
entries.push(JSON.parse(trimmed));
|
|
1853
|
+
} catch {
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
return entries;
|
|
1857
|
+
} finally {
|
|
1858
|
+
closeSync(fd);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
function extractSessionContext(sessionPath2) {
|
|
1862
|
+
const entries = readTailEntries(sessionPath2);
|
|
1863
|
+
if (entries.length === 0)
|
|
1864
|
+
return void 0;
|
|
1865
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
1866
|
+
const e = entries[i];
|
|
1867
|
+
if (e.type === "compaction" && typeof e.summary === "string") {
|
|
1868
|
+
return e.summary;
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
const recentMessages = [];
|
|
1872
|
+
const MAX_MESSAGES = 6;
|
|
1873
|
+
for (let i = entries.length - 1; i >= 0 && recentMessages.length < MAX_MESSAGES; i--) {
|
|
1874
|
+
const e = entries[i];
|
|
1875
|
+
if (e.type !== "message")
|
|
1876
|
+
continue;
|
|
1877
|
+
const msg = e.message;
|
|
1878
|
+
if (!msg)
|
|
1879
|
+
continue;
|
|
1880
|
+
if (msg.role !== "user" && msg.role !== "assistant")
|
|
1881
|
+
continue;
|
|
1882
|
+
let text = "";
|
|
1883
|
+
if (typeof msg.content === "string") {
|
|
1884
|
+
text = msg.content;
|
|
1885
|
+
} else if (Array.isArray(msg.content)) {
|
|
1886
|
+
text = msg.content.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n");
|
|
1887
|
+
}
|
|
1888
|
+
if (text) {
|
|
1889
|
+
recentMessages.unshift(`[${msg.role}]: ${text}`);
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
if (recentMessages.length === 0)
|
|
1893
|
+
return void 0;
|
|
1894
|
+
return "## Previous Session Context (auto-extracted)\n\nThe following is the tail of the previous conversation:\n\n" + recentMessages.join("\n\n");
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
// ../../packages/runner-pi/dist/usage-metadata.js
|
|
1898
|
+
function usageToMessageMetadata(usage) {
|
|
1899
|
+
return {
|
|
1900
|
+
input_tokens: usage.input,
|
|
1901
|
+
output_tokens: usage.output,
|
|
1902
|
+
cache_read_input_tokens: usage.cacheRead,
|
|
1903
|
+
cache_creation_input_tokens: usage.cacheWrite
|
|
1904
|
+
};
|
|
1905
|
+
}
|
|
1906
|
+
function accumulateToolUsage(tally, raw) {
|
|
1907
|
+
for (const [key, row] of Object.entries(raw)) {
|
|
1908
|
+
const existing = tally[key];
|
|
1909
|
+
if (existing) {
|
|
1910
|
+
for (const [field, val] of Object.entries(row)) {
|
|
1911
|
+
if (typeof val === "number")
|
|
1912
|
+
existing[field] = (existing[field] ?? 0) + val;
|
|
1913
|
+
}
|
|
1914
|
+
} else {
|
|
1915
|
+
const nums = {};
|
|
1916
|
+
for (const [field, val] of Object.entries(row)) {
|
|
1917
|
+
if (typeof val === "number")
|
|
1918
|
+
nums[field] = val;
|
|
1919
|
+
}
|
|
1920
|
+
tally[key] = nums;
|
|
1921
|
+
}
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
function getUsageFromAgentEndMessages(messages) {
|
|
1925
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
1926
|
+
const m = messages[i];
|
|
1927
|
+
if (m.role === "assistant" && m.usage != null)
|
|
1928
|
+
return m.usage;
|
|
1929
|
+
}
|
|
1930
|
+
return void 0;
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
// ../../packages/runner-pi/dist/stream-converter.js
|
|
1934
|
+
function emitStreamError(errorText) {
|
|
1935
|
+
const errorLine = "data: " + JSON.stringify({ type: "error", errorText }) + "\n\n";
|
|
1936
|
+
const finishLine = "data: " + JSON.stringify({ type: "finish", finishReason: "error" }) + "\n\n";
|
|
1937
|
+
return [errorLine, finishLine, "data: [DONE]\n\n"];
|
|
1938
|
+
}
|
|
1939
|
+
function extractToolResultText(result) {
|
|
1940
|
+
if (result !== null && typeof result === "object") {
|
|
1941
|
+
const r = result;
|
|
1942
|
+
if (Array.isArray(r.content) && r.content.length > 0) {
|
|
1943
|
+
const text = r.content.filter((c) => c.type === "text" && typeof c.text === "string").map((c) => c.text).join("\n");
|
|
1944
|
+
if (text.length > 0)
|
|
1945
|
+
return text;
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
if (typeof result === "string")
|
|
1949
|
+
return result;
|
|
1950
|
+
try {
|
|
1951
|
+
return JSON.stringify(result);
|
|
1952
|
+
} catch {
|
|
1953
|
+
return String(result);
|
|
1954
|
+
}
|
|
1955
|
+
}
|
|
1956
|
+
function sseData(obj) {
|
|
1957
|
+
return "data: " + JSON.stringify(obj) + "\n\n";
|
|
1958
|
+
}
|
|
1959
|
+
var PiAISDKStreamConverter = class {
|
|
1960
|
+
constructor(options) {
|
|
1961
|
+
this.options = options;
|
|
1962
|
+
this.messageId = "msg_" + Date.now() + "_" + Math.random().toString(36).slice(2);
|
|
1963
|
+
this.toolUsageTally = {};
|
|
1964
|
+
this.activeTextPartId = null;
|
|
1965
|
+
this.hasStarted = false;
|
|
1966
|
+
this.hasFinished = false;
|
|
1967
|
+
}
|
|
1968
|
+
get finished() {
|
|
1969
|
+
return this.hasFinished;
|
|
1970
|
+
}
|
|
1971
|
+
forceError(errorText) {
|
|
1972
|
+
if (this.hasFinished)
|
|
1973
|
+
return [];
|
|
1974
|
+
return [...this.ensureStart(), ...this.finishError(errorText)];
|
|
1975
|
+
}
|
|
1976
|
+
handleEvent(event, aborted) {
|
|
1977
|
+
if (this.hasFinished)
|
|
1978
|
+
return [];
|
|
1979
|
+
const chunks = [...this.ensureStart()];
|
|
1980
|
+
if (event.type === "message_start") {
|
|
1981
|
+
const msg = event.message;
|
|
1982
|
+
if (msg?.role === "assistant")
|
|
1983
|
+
chunks.push(...this.endTextStreamIfOpen());
|
|
1984
|
+
return chunks;
|
|
1985
|
+
}
|
|
1986
|
+
if (event.type === "message_end")
|
|
1987
|
+
return chunks;
|
|
1988
|
+
if (event.type === "message_update") {
|
|
1989
|
+
const sub = event.assistantMessageEvent;
|
|
1990
|
+
if (sub.type === "text_start")
|
|
1991
|
+
chunks.push(...this.endTextStreamIfOpen(), ...this.openTextStream());
|
|
1992
|
+
else if (sub.type === "text_delta")
|
|
1993
|
+
chunks.push(...this.emitTextDelta(sub.delta));
|
|
1994
|
+
else if (sub.type === "toolcall_start")
|
|
1995
|
+
chunks.push(...this.endTextStreamIfOpen());
|
|
1996
|
+
return chunks;
|
|
1997
|
+
}
|
|
1998
|
+
if (event.type === "tool_execution_start") {
|
|
1999
|
+
chunks.push(...this.endTextStreamIfOpen());
|
|
2000
|
+
chunks.push(sseData({
|
|
2001
|
+
type: "tool-input-start",
|
|
2002
|
+
toolCallId: event.toolCallId,
|
|
2003
|
+
toolName: event.toolName,
|
|
2004
|
+
dynamic: true,
|
|
2005
|
+
providerExecuted: true
|
|
2006
|
+
}), sseData({
|
|
2007
|
+
type: "tool-input-available",
|
|
2008
|
+
toolCallId: event.toolCallId,
|
|
2009
|
+
toolName: event.toolName,
|
|
2010
|
+
input: event.args,
|
|
2011
|
+
dynamic: true,
|
|
2012
|
+
providerExecuted: true
|
|
2013
|
+
}));
|
|
2014
|
+
return chunks;
|
|
2015
|
+
}
|
|
2016
|
+
if (event.type === "tool_execution_end") {
|
|
2017
|
+
const output = this.options.redactText(this.options.normalizeToolOutput(event.result));
|
|
2018
|
+
const raw = event.result?.details?.usage?.raw;
|
|
2019
|
+
if (raw != null)
|
|
2020
|
+
accumulateToolUsage(this.toolUsageTally, raw);
|
|
2021
|
+
chunks.push(sseData({
|
|
2022
|
+
type: "tool-output-available",
|
|
2023
|
+
toolCallId: event.toolCallId,
|
|
2024
|
+
output,
|
|
2025
|
+
isError: event.isError,
|
|
2026
|
+
dynamic: true,
|
|
2027
|
+
providerExecuted: true
|
|
2028
|
+
}));
|
|
2029
|
+
return chunks;
|
|
2030
|
+
}
|
|
2031
|
+
if (event.type === "agent_end") {
|
|
2032
|
+
if (aborted) {
|
|
2033
|
+
chunks.push(...this.finishError("Run aborted by signal."));
|
|
2034
|
+
} else {
|
|
2035
|
+
const errorMsg = this.options.getErrorFromAgentEndMessages(event.messages);
|
|
2036
|
+
if (errorMsg)
|
|
2037
|
+
chunks.push(...this.finishError(errorMsg));
|
|
2038
|
+
else
|
|
2039
|
+
chunks.push(...this.finishSuccess(this.options.getUsageFromAgentEndMessages(event.messages)));
|
|
2040
|
+
}
|
|
2041
|
+
return chunks;
|
|
2042
|
+
}
|
|
2043
|
+
return chunks;
|
|
2044
|
+
}
|
|
2045
|
+
ensureStart() {
|
|
2046
|
+
if (this.hasStarted)
|
|
2047
|
+
return [];
|
|
2048
|
+
this.hasStarted = true;
|
|
2049
|
+
return [
|
|
2050
|
+
sseData({ type: "start", messageId: this.messageId }),
|
|
2051
|
+
sseData({
|
|
2052
|
+
type: "message-metadata",
|
|
2053
|
+
messageMetadata: { sessionId: this.options.sessionId }
|
|
2054
|
+
})
|
|
2055
|
+
];
|
|
2056
|
+
}
|
|
2057
|
+
newTextPartId() {
|
|
2058
|
+
return "text_" + Date.now() + "_" + Math.random().toString(36).slice(2) + "_" + Math.random().toString(36).slice(2);
|
|
2059
|
+
}
|
|
2060
|
+
openTextStream() {
|
|
2061
|
+
this.activeTextPartId = this.newTextPartId();
|
|
2062
|
+
return [sseData({ type: "text-start", id: this.activeTextPartId })];
|
|
2063
|
+
}
|
|
2064
|
+
emitTextDelta(rawDelta) {
|
|
2065
|
+
const delta = rawDelta ? this.options.redactText(rawDelta) : void 0;
|
|
2066
|
+
if (!delta)
|
|
2067
|
+
return [];
|
|
2068
|
+
const startChunk = this.activeTextPartId == null ? this.openTextStream() : [];
|
|
2069
|
+
return [
|
|
2070
|
+
...startChunk,
|
|
2071
|
+
sseData({ type: "text-delta", id: this.activeTextPartId, delta })
|
|
2072
|
+
];
|
|
2073
|
+
}
|
|
2074
|
+
endTextStreamIfOpen() {
|
|
2075
|
+
if (this.activeTextPartId == null)
|
|
2076
|
+
return [];
|
|
2077
|
+
const id = this.activeTextPartId;
|
|
2078
|
+
this.activeTextPartId = null;
|
|
2079
|
+
return [sseData({ type: "text-end", id })];
|
|
2080
|
+
}
|
|
2081
|
+
finishSuccess(usage) {
|
|
2082
|
+
const chunks = [...this.endTextStreamIfOpen()];
|
|
2083
|
+
const raw = {};
|
|
2084
|
+
let chatUsage;
|
|
2085
|
+
if (usage) {
|
|
2086
|
+
const { id } = this.options.model;
|
|
2087
|
+
chatUsage = {
|
|
2088
|
+
type: "chat",
|
|
2089
|
+
...usageToMessageMetadata(usage)
|
|
2090
|
+
};
|
|
2091
|
+
raw[id] = chatUsage;
|
|
2092
|
+
}
|
|
2093
|
+
for (const [key, tally] of Object.entries(this.toolUsageTally)) {
|
|
2094
|
+
raw[key] = { ...tally };
|
|
2095
|
+
}
|
|
2096
|
+
const finishPayload = {
|
|
2097
|
+
type: "finish",
|
|
2098
|
+
finishReason: "stop"
|
|
2099
|
+
};
|
|
2100
|
+
if (usage) {
|
|
2101
|
+
finishPayload.messageMetadata = { usage: { ...chatUsage, raw } };
|
|
2102
|
+
}
|
|
2103
|
+
chunks.push(sseData(finishPayload), "data: [DONE]\n\n");
|
|
2104
|
+
this.hasFinished = true;
|
|
2105
|
+
return chunks;
|
|
2106
|
+
}
|
|
2107
|
+
finishError(errorText) {
|
|
2108
|
+
this.hasFinished = true;
|
|
2109
|
+
return emitStreamError(errorText);
|
|
2110
|
+
}
|
|
2111
|
+
};
|
|
2112
|
+
|
|
1804
2113
|
// ../../packages/runner-pi/dist/tool-overrides.js
|
|
1805
2114
|
import { createBashTool, createReadTool } from "@mariozechner/pi-coding-agent";
|
|
1806
2115
|
|
|
@@ -1809,7 +2118,7 @@ var braveProvider = {
|
|
|
1809
2118
|
id: "brave",
|
|
1810
2119
|
label: "Brave Search",
|
|
1811
2120
|
envKeys: ["BRAVE_API_KEY"],
|
|
1812
|
-
async search({ apiKey, query, count, country, freshness }) {
|
|
2121
|
+
async search({ apiKey, query, count, country, freshness, signal }) {
|
|
1813
2122
|
const params = new URLSearchParams({
|
|
1814
2123
|
q: query,
|
|
1815
2124
|
count: String(Math.min(count, 20))
|
|
@@ -1823,7 +2132,8 @@ var braveProvider = {
|
|
|
1823
2132
|
Accept: "application/json",
|
|
1824
2133
|
"Accept-Encoding": "gzip",
|
|
1825
2134
|
"X-Subscription-Token": apiKey
|
|
1826
|
-
}
|
|
2135
|
+
},
|
|
2136
|
+
signal
|
|
1827
2137
|
});
|
|
1828
2138
|
if (!res.ok) {
|
|
1829
2139
|
const body = await res.text().catch(() => "");
|
|
@@ -1844,14 +2154,14 @@ ${body}`);
|
|
|
1844
2154
|
});
|
|
1845
2155
|
}
|
|
1846
2156
|
}
|
|
1847
|
-
return results;
|
|
2157
|
+
return { results };
|
|
1848
2158
|
}
|
|
1849
2159
|
};
|
|
1850
2160
|
var tavilyProvider = {
|
|
1851
2161
|
id: "tavily",
|
|
1852
2162
|
label: "Tavily",
|
|
1853
2163
|
envKeys: ["TAVILY_API_KEY"],
|
|
1854
|
-
async search({ apiKey, query, count }) {
|
|
2164
|
+
async search({ apiKey, query, count, signal }) {
|
|
1855
2165
|
const res = await fetch("https://api.tavily.com/search", {
|
|
1856
2166
|
method: "POST",
|
|
1857
2167
|
headers: { "Content-Type": "application/json" },
|
|
@@ -1860,7 +2170,8 @@ var tavilyProvider = {
|
|
|
1860
2170
|
query,
|
|
1861
2171
|
max_results: Math.min(count, 10),
|
|
1862
2172
|
include_answer: false
|
|
1863
|
-
})
|
|
2173
|
+
}),
|
|
2174
|
+
signal
|
|
1864
2175
|
});
|
|
1865
2176
|
if (!res.ok) {
|
|
1866
2177
|
const body = await res.text().catch(() => "");
|
|
@@ -1878,7 +2189,7 @@ ${body}`);
|
|
|
1878
2189
|
});
|
|
1879
2190
|
}
|
|
1880
2191
|
}
|
|
1881
|
-
return results;
|
|
2192
|
+
return { results };
|
|
1882
2193
|
}
|
|
1883
2194
|
};
|
|
1884
2195
|
var AUTO_DETECT_ORDER = [braveProvider, tavilyProvider];
|
|
@@ -1913,9 +2224,12 @@ var BROWSER_UA = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/53
|
|
|
1913
2224
|
function htmlToText(html) {
|
|
1914
2225
|
return html.replace(/<(script|style|noscript)[^>]*>[\s\S]*?<\/\1>/gi, "").replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|div|h[1-6]|li|tr)>/gi, "\n").replace(/<(p|div|h[1-6]|li|tr)[^>]*>/gi, "\n").replace(/<[^>]+>/g, "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/'/g, "'").replace(/ /g, " ").replace(/[ \t]+/g, " ").replace(/\n{3,}/g, "\n\n").trim();
|
|
1915
2226
|
}
|
|
1916
|
-
async function fetchPageContent(url) {
|
|
2227
|
+
async function fetchPageContent(url, externalSignal) {
|
|
1917
2228
|
const controller = new AbortController();
|
|
1918
2229
|
const timeout = setTimeout(() => controller.abort(), 15e3);
|
|
2230
|
+
externalSignal?.addEventListener("abort", () => controller.abort(), {
|
|
2231
|
+
once: true
|
|
2232
|
+
});
|
|
1919
2233
|
try {
|
|
1920
2234
|
const res = await fetch(url, {
|
|
1921
2235
|
headers: {
|
|
@@ -2012,7 +2326,7 @@ function buildWebSearchTool(env) {
|
|
|
2012
2326
|
],
|
|
2013
2327
|
// biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
|
|
2014
2328
|
parameters: webSearchSchema,
|
|
2015
|
-
async execute(_toolCallId, params,
|
|
2329
|
+
async execute(_toolCallId, params, signal, _onUpdate) {
|
|
2016
2330
|
const p = params;
|
|
2017
2331
|
const query = p.query;
|
|
2018
2332
|
const count = p.count ?? 5;
|
|
@@ -2022,18 +2336,29 @@ function buildWebSearchTool(env) {
|
|
|
2022
2336
|
let lastError;
|
|
2023
2337
|
for (const { provider, apiKey } of providers) {
|
|
2024
2338
|
try {
|
|
2025
|
-
const results = await provider.search({
|
|
2339
|
+
const { results } = await provider.search({
|
|
2026
2340
|
apiKey,
|
|
2027
2341
|
query,
|
|
2028
2342
|
count,
|
|
2029
2343
|
country,
|
|
2030
|
-
freshness
|
|
2344
|
+
freshness,
|
|
2345
|
+
signal
|
|
2031
2346
|
});
|
|
2347
|
+
let fetchedPages = 0;
|
|
2032
2348
|
if (shouldFetchContent) {
|
|
2033
2349
|
for (const r of results) {
|
|
2034
|
-
r.content = await fetchPageContent(r.link);
|
|
2350
|
+
r.content = await fetchPageContent(r.link, signal);
|
|
2351
|
+
fetchedPages += 1;
|
|
2035
2352
|
}
|
|
2036
2353
|
}
|
|
2354
|
+
const usage = {
|
|
2355
|
+
raw: {
|
|
2356
|
+
[provider.id]: {
|
|
2357
|
+
requests: 1,
|
|
2358
|
+
fetchedPages
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
};
|
|
2037
2362
|
return {
|
|
2038
2363
|
content: [
|
|
2039
2364
|
{
|
|
@@ -2041,7 +2366,9 @@ function buildWebSearchTool(env) {
|
|
|
2041
2366
|
text: formatSearchResults(results, provider.label)
|
|
2042
2367
|
}
|
|
2043
2368
|
],
|
|
2044
|
-
details:
|
|
2369
|
+
details: {
|
|
2370
|
+
usage
|
|
2371
|
+
}
|
|
2045
2372
|
};
|
|
2046
2373
|
} catch (e) {
|
|
2047
2374
|
lastError = e;
|
|
@@ -2077,11 +2404,11 @@ function buildWebFetchTool() {
|
|
|
2077
2404
|
],
|
|
2078
2405
|
// biome-ignore lint/suspicious/noExplicitAny: plain JSON Schema compatible with TypeBox TSchema
|
|
2079
2406
|
parameters: webFetchSchema,
|
|
2080
|
-
async execute(_toolCallId, params,
|
|
2407
|
+
async execute(_toolCallId, params, signal, _onUpdate) {
|
|
2081
2408
|
const p = params;
|
|
2082
2409
|
const url = p.url;
|
|
2083
2410
|
try {
|
|
2084
|
-
const content = await fetchPageContent(url);
|
|
2411
|
+
const content = await fetchPageContent(url, signal);
|
|
2085
2412
|
return {
|
|
2086
2413
|
content: [{ type: "text", text: content }],
|
|
2087
2414
|
details: void 0
|
|
@@ -2224,52 +2551,6 @@ function applyModelOverrides(model, provider, optionsEnv) {
|
|
|
2224
2551
|
model.baseUrl = anthropicBaseUrl;
|
|
2225
2552
|
}
|
|
2226
2553
|
}
|
|
2227
|
-
function emitStreamError(errorText) {
|
|
2228
|
-
return [
|
|
2229
|
-
`data: ${JSON.stringify({ type: "error", errorText })}
|
|
2230
|
-
|
|
2231
|
-
`,
|
|
2232
|
-
`data: ${JSON.stringify({ type: "finish", finishReason: "error" })}
|
|
2233
|
-
|
|
2234
|
-
`,
|
|
2235
|
-
"data: [DONE]\n\n"
|
|
2236
|
-
];
|
|
2237
|
-
}
|
|
2238
|
-
function extractToolResultText(result) {
|
|
2239
|
-
if (result !== null && typeof result === "object") {
|
|
2240
|
-
const r = result;
|
|
2241
|
-
if (Array.isArray(r.content) && r.content.length > 0) {
|
|
2242
|
-
const text = r.content.filter((c) => c.type === "text" && typeof c.text === "string").map((c) => c.text).join("\n");
|
|
2243
|
-
if (text.length > 0) {
|
|
2244
|
-
return text;
|
|
2245
|
-
}
|
|
2246
|
-
}
|
|
2247
|
-
}
|
|
2248
|
-
if (typeof result === "string")
|
|
2249
|
-
return result;
|
|
2250
|
-
try {
|
|
2251
|
-
return JSON.stringify(result);
|
|
2252
|
-
} catch {
|
|
2253
|
-
return String(result);
|
|
2254
|
-
}
|
|
2255
|
-
}
|
|
2256
|
-
function usageToMessageMetadata(usage) {
|
|
2257
|
-
return {
|
|
2258
|
-
input_tokens: usage.input,
|
|
2259
|
-
output_tokens: usage.output,
|
|
2260
|
-
cache_read_input_tokens: usage.cacheRead,
|
|
2261
|
-
cache_creation_input_tokens: usage.cacheWrite
|
|
2262
|
-
};
|
|
2263
|
-
}
|
|
2264
|
-
function getUsageFromAgentEndMessages(messages) {
|
|
2265
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2266
|
-
const m = messages[i];
|
|
2267
|
-
if (m.role === "assistant" && m.usage != null) {
|
|
2268
|
-
return m.usage;
|
|
2269
|
-
}
|
|
2270
|
-
}
|
|
2271
|
-
return void 0;
|
|
2272
|
-
}
|
|
2273
2554
|
function getErrorFromAgentEndMessages(messages) {
|
|
2274
2555
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
2275
2556
|
const m = messages[i];
|
|
@@ -2285,7 +2566,7 @@ function traceRawMessage(debugCwd, data, reset = false, optionsEnv) {
|
|
|
2285
2566
|
if (!enabled)
|
|
2286
2567
|
return;
|
|
2287
2568
|
try {
|
|
2288
|
-
const file =
|
|
2569
|
+
const file = join8(debugCwd, "pi-message-stream-debug.json");
|
|
2289
2570
|
if (reset && existsSync5(file))
|
|
2290
2571
|
unlinkSync3(file);
|
|
2291
2572
|
const type = data !== null && typeof data === "object" ? data.type : void 0;
|
|
@@ -2352,13 +2633,26 @@ function createPiRunner(options = {}) {
|
|
|
2352
2633
|
const sessionManager = await (async () => {
|
|
2353
2634
|
if (resume !== void 0 && resume !== "") {
|
|
2354
2635
|
if (resume.includes("/")) {
|
|
2355
|
-
return
|
|
2636
|
+
return SessionManager2.open(resume);
|
|
2356
2637
|
}
|
|
2357
|
-
const
|
|
2358
|
-
|
|
2359
|
-
|
|
2638
|
+
const sessionPath2 = resolveSessionPathById(cwd, resume);
|
|
2639
|
+
console.error(`${LOG_PREFIX2} resume: id=${resume} path=${sessionPath2 ?? "(not found)"}`);
|
|
2640
|
+
if (sessionPath2) {
|
|
2641
|
+
if (isSessionFileTooLarge(sessionPath2)) {
|
|
2642
|
+
const context = extractSessionContext(sessionPath2);
|
|
2643
|
+
console.error(`${LOG_PREFIX2} session file too large, starting fresh${context ? " (with context)" : ""}`);
|
|
2644
|
+
const newMgr = SessionManager2.create(cwd);
|
|
2645
|
+
if (context) {
|
|
2646
|
+
const firstId = newMgr.getEntries()[0]?.id ?? "";
|
|
2647
|
+
newMgr.appendCompaction(context, firstId, 0);
|
|
2648
|
+
}
|
|
2649
|
+
return newMgr;
|
|
2650
|
+
}
|
|
2651
|
+
return SessionManager2.open(sessionPath2);
|
|
2652
|
+
}
|
|
2653
|
+
return SessionManager2.create(cwd);
|
|
2360
2654
|
}
|
|
2361
|
-
return
|
|
2655
|
+
return SessionManager2.create(cwd);
|
|
2362
2656
|
})();
|
|
2363
2657
|
const resourceLoader = options.skillPaths ? new BunnyAgentResourceLoader({
|
|
2364
2658
|
cwd,
|
|
@@ -2414,165 +2708,34 @@ function createPiRunner(options = {}) {
|
|
|
2414
2708
|
}
|
|
2415
2709
|
try {
|
|
2416
2710
|
traceRawMessage(cwd, null, true, options.env);
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
if (imageParts.length > 0) {
|
|
2426
|
-
images = imageParts.map((p) => ({
|
|
2427
|
-
type: "image",
|
|
2428
|
-
data: p.data,
|
|
2429
|
-
mimeType: p.mimeType
|
|
2430
|
-
}));
|
|
2431
|
-
}
|
|
2711
|
+
const promptText = userInput;
|
|
2712
|
+
const promptPromise = session.prompt(promptText);
|
|
2713
|
+
const streamConverter = new PiAISDKStreamConverter({
|
|
2714
|
+
sessionId: session.sessionId,
|
|
2715
|
+
model,
|
|
2716
|
+
redactText: (value) => {
|
|
2717
|
+
if (options.env && Object.keys(options.env).length > 0) {
|
|
2718
|
+
return redactSecrets(value, options.env);
|
|
2432
2719
|
}
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
let hasFinished = false;
|
|
2440
|
-
const imageToolUsage = { input_tokens: 0, output_tokens: 0 };
|
|
2441
|
-
const newTextPartId = () => `text_${Date.now()}_${Math.random().toString(36).slice(2)}_${Math.random().toString(36).slice(2)}`;
|
|
2442
|
-
let activeTextPartId = null;
|
|
2443
|
-
let textStreamOpen = false;
|
|
2444
|
-
const endTextStreamIfOpen = function* () {
|
|
2445
|
-
if (textStreamOpen && activeTextPartId != null) {
|
|
2446
|
-
yield `data: ${JSON.stringify({ type: "text-end", id: activeTextPartId })}
|
|
2447
|
-
|
|
2448
|
-
`;
|
|
2449
|
-
textStreamOpen = false;
|
|
2450
|
-
activeTextPartId = null;
|
|
2451
|
-
}
|
|
2452
|
-
};
|
|
2453
|
-
const beginTextStream = function* () {
|
|
2454
|
-
activeTextPartId = newTextPartId();
|
|
2455
|
-
yield `data: ${JSON.stringify({ type: "text-start", id: activeTextPartId })}
|
|
2456
|
-
|
|
2457
|
-
`;
|
|
2458
|
-
textStreamOpen = true;
|
|
2459
|
-
};
|
|
2460
|
-
const ensureStartEvent = async function* () {
|
|
2461
|
-
if (!hasStarted) {
|
|
2462
|
-
yield `data: ${JSON.stringify({ type: "start", messageId })}
|
|
2463
|
-
|
|
2464
|
-
`;
|
|
2465
|
-
yield `data: ${JSON.stringify({
|
|
2466
|
-
type: "message-metadata",
|
|
2467
|
-
messageMetadata: { sessionId: session.sessionId }
|
|
2468
|
-
})}
|
|
2469
|
-
|
|
2470
|
-
`;
|
|
2471
|
-
hasStarted = true;
|
|
2472
|
-
}
|
|
2473
|
-
};
|
|
2474
|
-
const finishSuccess = async function* (usage) {
|
|
2475
|
-
yield* endTextStreamIfOpen();
|
|
2476
|
-
const finishPayload = { type: "finish", finishReason: "stop" };
|
|
2477
|
-
const hasImageUsage = imageToolUsage.input_tokens > 0 || imageToolUsage.output_tokens > 0;
|
|
2478
|
-
if (usage != null || hasImageUsage) {
|
|
2479
|
-
const base = usage != null ? usageToMessageMetadata(usage) : {};
|
|
2480
|
-
finishPayload.messageMetadata = {
|
|
2481
|
-
usage: {
|
|
2482
|
-
...base,
|
|
2483
|
-
input_tokens: (base.input_tokens ?? 0) + imageToolUsage.input_tokens,
|
|
2484
|
-
output_tokens: (base.output_tokens ?? 0) + imageToolUsage.output_tokens
|
|
2485
|
-
}
|
|
2486
|
-
};
|
|
2487
|
-
}
|
|
2488
|
-
yield `data: ${JSON.stringify(finishPayload)}
|
|
2489
|
-
|
|
2490
|
-
`;
|
|
2491
|
-
yield "data: [DONE]\n\n";
|
|
2492
|
-
hasFinished = true;
|
|
2493
|
-
};
|
|
2494
|
-
const finishError = async function* (errorText) {
|
|
2495
|
-
for (const chunk of emitStreamError(errorText)) {
|
|
2496
|
-
yield chunk;
|
|
2497
|
-
}
|
|
2498
|
-
hasFinished = true;
|
|
2499
|
-
};
|
|
2720
|
+
return value;
|
|
2721
|
+
},
|
|
2722
|
+
normalizeToolOutput: extractToolResultText,
|
|
2723
|
+
getUsageFromAgentEndMessages,
|
|
2724
|
+
getErrorFromAgentEndMessages
|
|
2725
|
+
});
|
|
2500
2726
|
while (!isComplete || eventQueue.length > 0) {
|
|
2501
2727
|
while (eventQueue.length > 0) {
|
|
2502
2728
|
const event = eventQueue.shift();
|
|
2503
2729
|
traceRawMessage(cwd, event, false, options.env);
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
if (msg?.role === "assistant") {
|
|
2508
|
-
yield* endTextStreamIfOpen();
|
|
2509
|
-
}
|
|
2510
|
-
} else if (event.type === "message_update") {
|
|
2511
|
-
const sub = event.assistantMessageEvent;
|
|
2512
|
-
if (sub.type === "text_start") {
|
|
2513
|
-
yield* endTextStreamIfOpen();
|
|
2514
|
-
yield* beginTextStream();
|
|
2515
|
-
} else if (sub.type === "text_delta") {
|
|
2516
|
-
let delta = sub.delta;
|
|
2517
|
-
if (delta) {
|
|
2518
|
-
if (options.env && Object.keys(options.env).length > 0) {
|
|
2519
|
-
delta = redactSecrets(delta, options.env);
|
|
2520
|
-
}
|
|
2521
|
-
if (!textStreamOpen) {
|
|
2522
|
-
yield* beginTextStream();
|
|
2523
|
-
}
|
|
2524
|
-
yield `data: ${JSON.stringify({
|
|
2525
|
-
type: "text-delta",
|
|
2526
|
-
id: activeTextPartId,
|
|
2527
|
-
delta
|
|
2528
|
-
})}
|
|
2529
|
-
|
|
2530
|
-
`;
|
|
2531
|
-
}
|
|
2532
|
-
} else if (sub.type === "toolcall_start") {
|
|
2533
|
-
yield* endTextStreamIfOpen();
|
|
2534
|
-
}
|
|
2535
|
-
} else if (event.type === "tool_execution_start") {
|
|
2536
|
-
yield* endTextStreamIfOpen();
|
|
2537
|
-
yield `data: ${JSON.stringify({ type: "tool-input-start", toolCallId: event.toolCallId, toolName: event.toolName, dynamic: true, providerExecuted: true })}
|
|
2538
|
-
|
|
2539
|
-
`;
|
|
2540
|
-
yield `data: ${JSON.stringify({ type: "tool-input-available", toolCallId: event.toolCallId, toolName: event.toolName, input: event.args, dynamic: true, providerExecuted: true })}
|
|
2541
|
-
|
|
2542
|
-
`;
|
|
2543
|
-
} else if (event.type === "tool_execution_end") {
|
|
2544
|
-
let output = extractToolResultText(event.result);
|
|
2545
|
-
if (options.env && Object.keys(options.env).length > 0) {
|
|
2546
|
-
output = redactSecrets(output, options.env);
|
|
2547
|
-
}
|
|
2548
|
-
if ((event.toolName === "generate_image" || event.toolName === "edit_image") && event.result !== null && typeof event.result === "object") {
|
|
2549
|
-
const details = event.result.details;
|
|
2550
|
-
const u = details?.response?.usage;
|
|
2551
|
-
if (u) {
|
|
2552
|
-
imageToolUsage.input_tokens += u.input_tokens ?? 0;
|
|
2553
|
-
imageToolUsage.output_tokens += u.output_tokens ?? 0;
|
|
2554
|
-
}
|
|
2555
|
-
}
|
|
2556
|
-
yield `data: ${JSON.stringify({ type: "tool-output-available", toolCallId: event.toolCallId, output, isError: event.isError, dynamic: true, providerExecuted: true })}
|
|
2557
|
-
|
|
2558
|
-
`;
|
|
2559
|
-
} else if (event.type === "agent_end") {
|
|
2560
|
-
if (aborted) {
|
|
2561
|
-
yield* finishError("Run aborted by signal.");
|
|
2562
|
-
} else {
|
|
2563
|
-
const errorMsg = getErrorFromAgentEndMessages(event.messages);
|
|
2564
|
-
if (errorMsg) {
|
|
2565
|
-
yield* finishError(errorMsg);
|
|
2566
|
-
} else {
|
|
2567
|
-
const usage = getUsageFromAgentEndMessages(event.messages);
|
|
2568
|
-
yield* finishSuccess(usage);
|
|
2569
|
-
}
|
|
2570
|
-
}
|
|
2730
|
+
const chunks = streamConverter.handleEvent(event, aborted);
|
|
2731
|
+
for (const chunk of chunks) {
|
|
2732
|
+
yield chunk;
|
|
2571
2733
|
}
|
|
2572
2734
|
}
|
|
2573
|
-
if (aborted && !
|
|
2574
|
-
|
|
2575
|
-
|
|
2735
|
+
if (aborted && !streamConverter.finished) {
|
|
2736
|
+
for (const chunk of streamConverter.forceError("Run aborted by signal.")) {
|
|
2737
|
+
yield chunk;
|
|
2738
|
+
}
|
|
2576
2739
|
break;
|
|
2577
2740
|
}
|
|
2578
2741
|
if (!isComplete && eventQueue.length === 0) {
|
|
@@ -2581,22 +2744,24 @@ function createPiRunner(options = {}) {
|
|
|
2581
2744
|
});
|
|
2582
2745
|
}
|
|
2583
2746
|
}
|
|
2584
|
-
if (
|
|
2747
|
+
if (streamConverter.finished) {
|
|
2585
2748
|
return;
|
|
2586
2749
|
}
|
|
2587
2750
|
try {
|
|
2588
2751
|
await promptPromise;
|
|
2589
2752
|
} catch (error) {
|
|
2590
|
-
if (!
|
|
2591
|
-
yield* ensureStartEvent();
|
|
2753
|
+
if (!streamConverter.finished) {
|
|
2592
2754
|
const message = error instanceof Error ? error.message : "Pi agent run failed.";
|
|
2593
|
-
|
|
2755
|
+
for (const chunk of streamConverter.forceError(message)) {
|
|
2756
|
+
yield chunk;
|
|
2757
|
+
}
|
|
2594
2758
|
}
|
|
2595
2759
|
return;
|
|
2596
2760
|
}
|
|
2597
|
-
if (!
|
|
2598
|
-
|
|
2599
|
-
|
|
2761
|
+
if (!streamConverter.finished && session.agent.state.error) {
|
|
2762
|
+
for (const chunk of streamConverter.forceError(session.agent.state.error)) {
|
|
2763
|
+
yield chunk;
|
|
2764
|
+
}
|
|
2600
2765
|
}
|
|
2601
2766
|
} finally {
|
|
2602
2767
|
if (abortSignal) {
|
|
@@ -2616,11 +2781,11 @@ function createPiRunner(options = {}) {
|
|
|
2616
2781
|
|
|
2617
2782
|
// ../../packages/runner-harness/dist/session.js
|
|
2618
2783
|
import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
2619
|
-
import { join as
|
|
2784
|
+
import { join as join9 } from "node:path";
|
|
2620
2785
|
var DIR = ".bunny-agent";
|
|
2621
2786
|
var FILE = "session-id";
|
|
2622
2787
|
function sessionPath(cwd) {
|
|
2623
|
-
return
|
|
2788
|
+
return join9(cwd, DIR, FILE);
|
|
2624
2789
|
}
|
|
2625
2790
|
function readSessionId(cwd) {
|
|
2626
2791
|
try {
|
|
@@ -2634,28 +2799,28 @@ function readSessionId(cwd) {
|
|
|
2634
2799
|
}
|
|
2635
2800
|
function writeSessionId(cwd, id) {
|
|
2636
2801
|
try {
|
|
2637
|
-
mkdirSync3(
|
|
2802
|
+
mkdirSync3(join9(cwd, DIR), { recursive: true });
|
|
2638
2803
|
writeFileSync4(sessionPath(cwd), id, "utf8");
|
|
2639
2804
|
} catch {
|
|
2640
2805
|
}
|
|
2641
2806
|
}
|
|
2642
2807
|
|
|
2643
2808
|
// ../../packages/runner-harness/dist/skills.js
|
|
2644
|
-
import { existsSync as existsSync7, readdirSync as
|
|
2809
|
+
import { existsSync as existsSync7, readdirSync as readdirSync3, statSync as statSync3 } from "node:fs";
|
|
2645
2810
|
import { homedir as homedir2 } from "node:os";
|
|
2646
|
-
import { join as
|
|
2811
|
+
import { join as join10 } from "node:path";
|
|
2647
2812
|
function discoverSkillPaths(cwd) {
|
|
2648
2813
|
const paths = [];
|
|
2649
2814
|
for (const base of [
|
|
2650
|
-
|
|
2651
|
-
|
|
2815
|
+
join10(cwd, "skills"),
|
|
2816
|
+
join10(homedir2(), ".bunny-agent", "skills")
|
|
2652
2817
|
]) {
|
|
2653
2818
|
if (!existsSync7(base))
|
|
2654
2819
|
continue;
|
|
2655
2820
|
try {
|
|
2656
|
-
for (const entry of
|
|
2657
|
-
const full =
|
|
2658
|
-
if (
|
|
2821
|
+
for (const entry of readdirSync3(base)) {
|
|
2822
|
+
const full = join10(base, entry);
|
|
2823
|
+
if (statSync3(full).isDirectory() && existsSync7(join10(full, "SKILL.md"))) {
|
|
2659
2824
|
paths.push(full);
|
|
2660
2825
|
}
|
|
2661
2826
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bunny-agent/runner-cli",
|
|
3
|
-
"version": "0.9.29-beta.
|
|
3
|
+
"version": "0.9.29-beta.11",
|
|
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,12 +53,12 @@
|
|
|
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
|
-
"@bunny-agent/runner-codex": "0.6.2",
|
|
58
56
|
"@bunny-agent/runner-harness": "0.1.1-beta.0",
|
|
59
|
-
"@bunny-agent/runner-
|
|
57
|
+
"@bunny-agent/runner-claude": "0.6.2",
|
|
58
|
+
"@bunny-agent/runner-gemini": "0.6.2",
|
|
60
59
|
"@bunny-agent/runner-pi": "0.6.4-beta.0",
|
|
61
|
-
"@bunny-agent/runner-
|
|
60
|
+
"@bunny-agent/runner-opencode": "0.6.2",
|
|
61
|
+
"@bunny-agent/runner-codex": "0.6.2"
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
64
|
"build": "tsc && pnpm bundle",
|