@bunny-agent/manager 0.9.62 → 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/__tests__/tool-output.test.d.ts +2 -0
- package/dist/__tests__/tool-output.test.d.ts.map +1 -0
- package/dist/__tests__/tool-output.test.js +77 -0
- package/dist/__tests__/tool-output.test.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/tool-output.d.ts +22 -0
- package/dist/tool-output.d.ts.map +1 -0
- package/dist/tool-output.js +68 -0
- package/dist/tool-output.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-output.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/tool-output.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { mkdtemp, readdir, readFile, rm, stat, writeFile, } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { guardToolOutput, TOOL_OUTPUT_MAX_BYTES, TOOL_OUTPUT_MAX_LINES, } from "../tool-output.js";
|
|
6
|
+
vi.mock("node:os", async (importOriginal) => {
|
|
7
|
+
const actual = await importOriginal();
|
|
8
|
+
return { ...actual, tmpdir: vi.fn(actual.tmpdir) };
|
|
9
|
+
});
|
|
10
|
+
const systemTempDirectory = tmpdir();
|
|
11
|
+
describe("guardToolOutput", () => {
|
|
12
|
+
let tempDirectory;
|
|
13
|
+
beforeEach(async () => {
|
|
14
|
+
tempDirectory = await mkdtemp(join(systemTempDirectory, "bunny-tool-output-test-"));
|
|
15
|
+
vi.mocked(tmpdir).mockReturnValue(tempDirectory);
|
|
16
|
+
});
|
|
17
|
+
afterEach(async () => {
|
|
18
|
+
vi.restoreAllMocks();
|
|
19
|
+
await rm(tempDirectory, { recursive: true, force: true });
|
|
20
|
+
});
|
|
21
|
+
it.each([
|
|
22
|
+
"",
|
|
23
|
+
" unchanged\n",
|
|
24
|
+
"x".repeat(TOOL_OUTPUT_MAX_BYTES),
|
|
25
|
+
"\n".repeat(TOOL_OUTPUT_MAX_LINES - 1),
|
|
26
|
+
])("leaves outputs within both limits unchanged without writing files (%#)", async (text) => {
|
|
27
|
+
expect(await guardToolOutput(text)).toEqual({ text });
|
|
28
|
+
expect(await readdir(tempDirectory)).toEqual([]);
|
|
29
|
+
});
|
|
30
|
+
it.each([
|
|
31
|
+
"x".repeat(TOOL_OUTPUT_MAX_BYTES + 1),
|
|
32
|
+
"event\n".repeat(TOOL_OUTPUT_MAX_LINES),
|
|
33
|
+
"\u4e2d\u6587\ud83d\ude42".repeat(20_000),
|
|
34
|
+
JSON.stringify({
|
|
35
|
+
content: [
|
|
36
|
+
{
|
|
37
|
+
type: "text",
|
|
38
|
+
text: JSON.stringify({ report: "work log\\n".repeat(400_000) }),
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
}),
|
|
42
|
+
])("bounds previews and saves the entire original response (%#)", async (text) => {
|
|
43
|
+
const result = await guardToolOutput(text);
|
|
44
|
+
expect(Buffer.byteLength(result.text)).toBeLessThanOrEqual(TOOL_OUTPUT_MAX_BYTES);
|
|
45
|
+
expect(result.text.split("\n").length).toBeLessThanOrEqual(TOOL_OUTPUT_MAX_LINES);
|
|
46
|
+
expect(result.text).not.toContain("\ufffd");
|
|
47
|
+
expect(result.text).toContain("Tool output truncated:");
|
|
48
|
+
expect(result.text).toContain("Use read with offset/limit");
|
|
49
|
+
expect(result.outputGuard).toMatchObject({
|
|
50
|
+
truncated: true,
|
|
51
|
+
originalBytes: Buffer.byteLength(text),
|
|
52
|
+
originalLines: text.split("\n").length,
|
|
53
|
+
});
|
|
54
|
+
const path = result.outputGuard.fullOutputPath;
|
|
55
|
+
expect(path.startsWith(join(tempDirectory, "bunny-tool-output-"))).toBe(true);
|
|
56
|
+
expect(result.text).toContain(JSON.stringify(path));
|
|
57
|
+
expect(await readFile(path, "utf8")).toBe(text);
|
|
58
|
+
expect((await stat(path)).mode & 0o777).toBe(0o600);
|
|
59
|
+
});
|
|
60
|
+
it("keeps concurrent responses in distinct files", async () => {
|
|
61
|
+
const texts = Array.from({ length: 5 }, (_, index) => `${index}:${"x".repeat(100_000)}`);
|
|
62
|
+
const results = await Promise.all(texts.map((text) => guardToolOutput(text)));
|
|
63
|
+
const paths = results.map((result) => result.outputGuard.fullOutputPath);
|
|
64
|
+
expect(new Set(paths).size).toBe(5);
|
|
65
|
+
expect(await Promise.all(paths.map((path) => readFile(path, "utf8")))).toEqual(texts);
|
|
66
|
+
});
|
|
67
|
+
it("still bounds output and reports when the temporary directory cannot store the full response", async () => {
|
|
68
|
+
const blocked = join(tempDirectory, "blocked");
|
|
69
|
+
await writeFile(blocked, "not a directory");
|
|
70
|
+
vi.mocked(tmpdir).mockReturnValue(blocked);
|
|
71
|
+
const result = await guardToolOutput("x".repeat(100_000));
|
|
72
|
+
expect(Buffer.byteLength(result.text)).toBeLessThanOrEqual(TOOL_OUTPUT_MAX_BYTES);
|
|
73
|
+
expect(result.text).toContain("Full output could not be saved");
|
|
74
|
+
expect(result.outputGuard).not.toHaveProperty("fullOutputPath");
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
//# sourceMappingURL=tool-output.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-output.test.js","sourceRoot":"","sources":["../../src/__tests__/tool-output.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export { buildRunnerEnv } from "./env.js";
|
|
|
11
11
|
export type { SandboxExecErrorCode } from "./sandbox-exec-error.js";
|
|
12
12
|
export { ExecDiagnostics, SandboxExecError, validateExecInput, } from "./sandbox-exec-error.js";
|
|
13
13
|
export { posixShellQuote } from "./shell-escape.js";
|
|
14
|
+
export type { GuardedToolOutput, ToolOutputGuardDetails, } from "./tool-output.js";
|
|
15
|
+
export { guardToolOutput, TOOL_OUTPUT_MAX_BYTES, TOOL_OUTPUT_MAX_LINES, } from "./tool-output.js";
|
|
14
16
|
export { ConsoleTranscriptWriter, JsonlTranscriptWriter, MemoryTranscriptWriter, MultiTranscriptWriter, } from "./transcript.js";
|
|
15
17
|
export type { BunnyAgentCodingRunBody, BunnyAgentOptions, ExecOptions, McpConfig, McpHttpServerConfig, McpLifecycle, McpServerConfig, McpServerOptions, McpSettings, McpStdioServerConfig, Message, RunnerSpec, SandboxAdapter, SandboxHandle, StreamInput, ToolInputSchema, ToolRef, ToolRuntime, TranscriptEntry, TranscriptWriter, Volume, } from "./types.js";
|
|
16
18
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,sCAAsC,EACtC,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAChE,YAAY,EAAE,gCAAgC,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AACjE,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,sCAAsC,EACtC,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAChE,YAAY,EAAE,gCAAgC,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,YAAY,EACV,iBAAiB,EACjB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAM1B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,uBAAuB,EACvB,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,oBAAoB,EACpB,OAAO,EACP,UAAU,EACV,cAAc,EACd,aAAa,EACb,WAAW,EACX,eAAe,EACf,OAAO,EACP,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,MAAM,GACP,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ export { ExecDiagnostics, SandboxExecError, validateExecInput, } from "./sandbox
|
|
|
10
10
|
// Shared POSIX shell quoting for adapters that must build a shell command
|
|
11
11
|
// string instead of using independent argv/env channels.
|
|
12
12
|
export { posixShellQuote } from "./shell-escape.js";
|
|
13
|
+
export { guardToolOutput, TOOL_OUTPUT_MAX_BYTES, TOOL_OUTPUT_MAX_LINES, } from "./tool-output.js";
|
|
13
14
|
// Local adapters live in their own packages, mirroring the cloud adapters:
|
|
14
15
|
// @bunny-agent/sandbox-local (LocalMachine — NO isolation) and
|
|
15
16
|
// @bunny-agent/sandbox-srt (SrtSandbox — OS-level isolation via
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,sCAAsC,EACtC,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,cAAc;AACd,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AACjC,0EAA0E;AAC1E,yDAAyD;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE9C,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,sCAAsC,EACtC,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,8BAA8B,EAAE,MAAM,gBAAgB,CAAC;AAEhE,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,cAAc;AACd,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC;AACjC,0EAA0E;AAC1E,yDAAyD;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAKpD,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,2EAA2E;AAC3E,+DAA+D;AAC/D,gEAAgE;AAChE,iEAAiE;AACjE,oCAAoC;AACpC,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const TOOL_OUTPUT_MAX_BYTES: number;
|
|
2
|
+
export declare const TOOL_OUTPUT_MAX_LINES = 2000;
|
|
3
|
+
/** Size and retrieval information for a truncated external tool response. */
|
|
4
|
+
export interface ToolOutputGuardDetails {
|
|
5
|
+
truncated: true;
|
|
6
|
+
originalBytes: number;
|
|
7
|
+
originalLines: number;
|
|
8
|
+
fullOutputPath?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Model-visible text and optional metadata; never contains the full spilled response. */
|
|
11
|
+
export interface GuardedToolOutput {
|
|
12
|
+
text: string;
|
|
13
|
+
outputGuard?: ToolOutputGuardDetails;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Bound external tool text to 50 KiB / 2,000 lines, including the retrieval notice.
|
|
17
|
+
* Oversized responses are saved verbatim in the OS temporary directory, matching
|
|
18
|
+
* Pi's native output-file lifecycle. Storage failures still return bounded text
|
|
19
|
+
* and explicitly report that the full output could not be saved.
|
|
20
|
+
*/
|
|
21
|
+
export declare function guardToolOutput(text: string): Promise<GuardedToolOutput>;
|
|
22
|
+
//# sourceMappingURL=tool-output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-output.d.ts","sourceRoot":"","sources":["../src/tool-output.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,qBAAqB,QAAY,CAAC;AAC/C,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C,6EAA6E;AAC7E,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,IAAI,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,0FAA0F;AAC1F,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,sBAAsB,CAAC;CACtC;AA2BD;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,CAAC,CAyC5B"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
export const TOOL_OUTPUT_MAX_BYTES = 50 * 1024;
|
|
6
|
+
export const TOOL_OUTPUT_MAX_LINES = 2_000;
|
|
7
|
+
function countLines(text) {
|
|
8
|
+
let lines = 1;
|
|
9
|
+
for (let index = 0; index < text.length; index++) {
|
|
10
|
+
if (text[index] === "\n")
|
|
11
|
+
lines++;
|
|
12
|
+
}
|
|
13
|
+
return lines;
|
|
14
|
+
}
|
|
15
|
+
function previewText(text, maxBytes, maxLines) {
|
|
16
|
+
// Slice before encoding to avoid allocating another copy of a multi-MB response.
|
|
17
|
+
const buffer = Buffer.from(text.slice(0, maxBytes), "utf8");
|
|
18
|
+
let end = Math.min(buffer.length, maxBytes);
|
|
19
|
+
while (end > 0 && end < buffer.length && (buffer[end] & 0xc0) === 0x80) {
|
|
20
|
+
end--;
|
|
21
|
+
}
|
|
22
|
+
const prefix = buffer.subarray(0, end).toString("utf8");
|
|
23
|
+
let lines = 1;
|
|
24
|
+
for (let index = 0; index < prefix.length; index++) {
|
|
25
|
+
if (prefix[index] === "\n" && ++lines > maxLines) {
|
|
26
|
+
return prefix.slice(0, index);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return prefix;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Bound external tool text to 50 KiB / 2,000 lines, including the retrieval notice.
|
|
33
|
+
* Oversized responses are saved verbatim in the OS temporary directory, matching
|
|
34
|
+
* Pi's native output-file lifecycle. Storage failures still return bounded text
|
|
35
|
+
* and explicitly report that the full output could not be saved.
|
|
36
|
+
*/
|
|
37
|
+
export async function guardToolOutput(text) {
|
|
38
|
+
const originalBytes = Buffer.byteLength(text, "utf8");
|
|
39
|
+
const originalLines = countLines(text);
|
|
40
|
+
if (originalBytes <= TOOL_OUTPUT_MAX_BYTES &&
|
|
41
|
+
originalLines <= TOOL_OUTPUT_MAX_LINES) {
|
|
42
|
+
return { text };
|
|
43
|
+
}
|
|
44
|
+
let fullOutputPath;
|
|
45
|
+
try {
|
|
46
|
+
const path = join(tmpdir(), `bunny-tool-output-${randomBytes(8).toString("hex")}.txt`);
|
|
47
|
+
await writeFile(path, text, { encoding: "utf8", mode: 0o600, flag: "wx" });
|
|
48
|
+
fullOutputPath = path;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// A storage error must not let the original oversized response reach the model.
|
|
52
|
+
}
|
|
53
|
+
const retrieval = fullOutputPath
|
|
54
|
+
? `Full output saved to: ${JSON.stringify(fullOutputPath)}. Use read with offset/limit or bash to extract a bounded fragment.`
|
|
55
|
+
: "Full output could not be saved. Retry with a narrower query or fewer fields.";
|
|
56
|
+
const notice = `\n\n[Tool output truncated: original ${originalBytes} bytes / ${originalLines} lines; preview limit ${TOOL_OUTPUT_MAX_BYTES} bytes / ${TOOL_OUTPUT_MAX_LINES} lines. ${retrieval}]`;
|
|
57
|
+
const preview = previewText(text, TOOL_OUTPUT_MAX_BYTES - Buffer.byteLength(notice, "utf8"), TOOL_OUTPUT_MAX_LINES - countLines(notice) + 1);
|
|
58
|
+
return {
|
|
59
|
+
text: `${preview}${notice}`,
|
|
60
|
+
outputGuard: {
|
|
61
|
+
truncated: true,
|
|
62
|
+
originalBytes,
|
|
63
|
+
originalLines,
|
|
64
|
+
...(fullOutputPath ? { fullOutputPath } : {}),
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=tool-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-output.js","sourceRoot":"","sources":["../src/tool-output.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED