@hachej/boring-agent 0.1.61 → 0.1.63
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/front/styles.css +2 -0
- package/dist/server/index.d.ts +60 -0
- package/dist/server/index.js +196 -4
- package/package.json +2 -2
package/dist/front/styles.css
CHANGED
package/dist/server/index.d.ts
CHANGED
|
@@ -444,6 +444,62 @@ interface ModeContext {
|
|
|
444
444
|
requestId?: string;
|
|
445
445
|
telemetry?: TelemetrySink;
|
|
446
446
|
}
|
|
447
|
+
interface RuntimeFilesystemBindingOperations {
|
|
448
|
+
read(descriptor: {
|
|
449
|
+
filesystem: string;
|
|
450
|
+
path: string;
|
|
451
|
+
}): Promise<{
|
|
452
|
+
content: string;
|
|
453
|
+
metadata?: unknown;
|
|
454
|
+
}>;
|
|
455
|
+
list(descriptor: {
|
|
456
|
+
filesystem: string;
|
|
457
|
+
path: string;
|
|
458
|
+
}): Promise<{
|
|
459
|
+
entries: string[];
|
|
460
|
+
metadata?: unknown;
|
|
461
|
+
}>;
|
|
462
|
+
find(descriptor: {
|
|
463
|
+
filesystem: string;
|
|
464
|
+
path: string;
|
|
465
|
+
}, pattern: string, options?: {
|
|
466
|
+
limit?: number;
|
|
467
|
+
offset?: number;
|
|
468
|
+
}): Promise<{
|
|
469
|
+
paths: string[];
|
|
470
|
+
metadata?: unknown;
|
|
471
|
+
}>;
|
|
472
|
+
grep(descriptor: {
|
|
473
|
+
filesystem: string;
|
|
474
|
+
path: string;
|
|
475
|
+
}, pattern: string, options?: {
|
|
476
|
+
limit?: number;
|
|
477
|
+
offset?: number;
|
|
478
|
+
}): Promise<{
|
|
479
|
+
matches: Array<{
|
|
480
|
+
path: string;
|
|
481
|
+
line: number;
|
|
482
|
+
text: string;
|
|
483
|
+
}>;
|
|
484
|
+
metadata?: unknown;
|
|
485
|
+
}>;
|
|
486
|
+
stat(descriptor: {
|
|
487
|
+
filesystem: string;
|
|
488
|
+
path: string;
|
|
489
|
+
}): Promise<{
|
|
490
|
+
isDirectory: boolean;
|
|
491
|
+
metadata?: unknown;
|
|
492
|
+
}>;
|
|
493
|
+
rejectMutation(operation: string, descriptor: {
|
|
494
|
+
filesystem: string;
|
|
495
|
+
path: string;
|
|
496
|
+
}): never;
|
|
497
|
+
}
|
|
498
|
+
interface RuntimeFilesystemBinding {
|
|
499
|
+
readonly filesystem: string;
|
|
500
|
+
readonly access: 'readonly';
|
|
501
|
+
readonly operations: RuntimeFilesystemBindingOperations;
|
|
502
|
+
}
|
|
447
503
|
interface RuntimeBundle {
|
|
448
504
|
runtimeContext?: WorkspaceRuntimeContext;
|
|
449
505
|
/**
|
|
@@ -461,6 +517,8 @@ interface RuntimeBundle {
|
|
|
461
517
|
bash?: RuntimeBashStrategy;
|
|
462
518
|
/** Runtime-owned filesystem strategy, consumed by the agent filesystem tool builder. */
|
|
463
519
|
filesystem?: RuntimeFilesystemStrategy;
|
|
520
|
+
/** Optional filesystem bindings prepared for this runtime/session. */
|
|
521
|
+
filesystemBindings?: RuntimeFilesystemBinding[];
|
|
464
522
|
}
|
|
465
523
|
|
|
466
524
|
declare const REMOTE_WORKER_RUNTIME_CWD = "/workspace";
|
|
@@ -608,6 +666,8 @@ declare function createRemoteWorkerSandbox(client: RemoteWorkerClient): Sandbox;
|
|
|
608
666
|
declare function fileRoutes(app: FastifyInstance, opts: {
|
|
609
667
|
workspace?: Workspace;
|
|
610
668
|
getWorkspace?: (request: FastifyRequest) => Workspace | Promise<Workspace>;
|
|
669
|
+
filesystemBindings?: RuntimeFilesystemBinding[];
|
|
670
|
+
getFilesystemBindings?: (request: FastifyRequest) => RuntimeFilesystemBinding[] | undefined | Promise<RuntimeFilesystemBinding[] | undefined>;
|
|
611
671
|
}, done: (err?: Error) => void): void;
|
|
612
672
|
|
|
613
673
|
interface RuntimeTemplateContribution {
|
package/dist/server/index.js
CHANGED
|
@@ -2656,6 +2656,9 @@ var BORING_SETTINGS_PATH = ".boring/settings";
|
|
|
2656
2656
|
var DEFAULT_MARKDOWN_IMAGE_UPLOAD_DIR = "assets/images";
|
|
2657
2657
|
var DEFAULT_FILE_UPLOAD_DIR = "assets/uploads";
|
|
2658
2658
|
var MAX_UPLOAD_BYTES = 10 * 1024 * 1024;
|
|
2659
|
+
var USER_FILESYSTEM_ID = "user";
|
|
2660
|
+
var ERROR_CODE_NOT_FOUND_OR_DENIED = "not_found_or_denied";
|
|
2661
|
+
var ERROR_CODE_READONLY = "readonly";
|
|
2659
2662
|
var IMAGE_UPLOAD_EXTENSIONS = /* @__PURE__ */ new Set(["avif", "gif", "jpg", "jpeg", "png", "webp"]);
|
|
2660
2663
|
var SAFE_UNKNOWN_FILE_EXTENSIONS = /* @__PURE__ */ new Set(["csv", "doc", "docx", "json", "md", "pdf", "ppt", "pptx", "rtf", "txt", "xls", "xlsx", "zip"]);
|
|
2661
2664
|
var MIME_UPLOAD_EXTENSIONS = {
|
|
@@ -2723,6 +2726,14 @@ function classifyError(err, reply, subject) {
|
|
|
2723
2726
|
error: { code: ERROR_CODE_INTERNAL, message }
|
|
2724
2727
|
});
|
|
2725
2728
|
}
|
|
2729
|
+
function requestedFilesystem(value) {
|
|
2730
|
+
return typeof value === "string" && value.length > 0 ? value : USER_FILESYSTEM_ID;
|
|
2731
|
+
}
|
|
2732
|
+
function sendNotFoundOrDenied(reply) {
|
|
2733
|
+
return reply.code(404).send({
|
|
2734
|
+
error: { code: ERROR_CODE_NOT_FOUND_OR_DENIED, message: "not found or denied" }
|
|
2735
|
+
});
|
|
2736
|
+
}
|
|
2726
2737
|
function requireStringParam(value, field, reply) {
|
|
2727
2738
|
if (typeof value !== "string" || value.length === 0) {
|
|
2728
2739
|
reply.code(400).send({
|
|
@@ -2842,16 +2853,49 @@ function sendValidationError(reply, message, field) {
|
|
|
2842
2853
|
error: { code: ERROR_CODE_VALIDATION_ERROR, message, ...field ? { field } : {} }
|
|
2843
2854
|
});
|
|
2844
2855
|
}
|
|
2856
|
+
function sendFilesystemBindingMutationDenied(reply, filesystem, access5) {
|
|
2857
|
+
return reply.code(403).send({
|
|
2858
|
+
error: { code: ERROR_CODE_READONLY, message: `${filesystem} binding is ${access5}` }
|
|
2859
|
+
});
|
|
2860
|
+
}
|
|
2845
2861
|
function fileRoutes(app, opts, done) {
|
|
2846
2862
|
async function resolveWorkspace(request) {
|
|
2847
2863
|
if (opts.getWorkspace) return await opts.getWorkspace(request);
|
|
2848
2864
|
if (opts.workspace) return opts.workspace;
|
|
2849
2865
|
throw new Error("file route requires workspace or getWorkspace");
|
|
2850
2866
|
}
|
|
2867
|
+
async function resolveFilesystemBindings(request) {
|
|
2868
|
+
if (opts.getFilesystemBindings) return await opts.getFilesystemBindings(request) ?? [];
|
|
2869
|
+
if (opts.filesystemBindings) return opts.filesystemBindings;
|
|
2870
|
+
return [];
|
|
2871
|
+
}
|
|
2872
|
+
async function resolveFilesystemBinding(request, filesystem) {
|
|
2873
|
+
return (await resolveFilesystemBindings(request)).find((binding) => binding.filesystem === filesystem);
|
|
2874
|
+
}
|
|
2875
|
+
async function rejectUnsupportedFilesystemMutation(request, reply, filesystem) {
|
|
2876
|
+
const binding = await resolveFilesystemBinding(request, filesystem);
|
|
2877
|
+
if (!binding) return sendNotFoundOrDenied(reply);
|
|
2878
|
+
if (binding.access === "readonly") return sendFilesystemBindingMutationDenied(reply, filesystem, binding.access);
|
|
2879
|
+
return reply.code(501).send({
|
|
2880
|
+
error: { code: ERROR_CODE_INTERNAL, message: `${filesystem} binding access is not supported by this route` }
|
|
2881
|
+
});
|
|
2882
|
+
}
|
|
2851
2883
|
app.get("/api/v1/files/raw", async (request, reply) => {
|
|
2852
2884
|
const query = request.query;
|
|
2853
2885
|
const path4 = requireStringParam(query.path, "path", reply);
|
|
2854
2886
|
if (path4 === null) return;
|
|
2887
|
+
const filesystem = requestedFilesystem(query.filesystem);
|
|
2888
|
+
if (filesystem !== USER_FILESYSTEM_ID) {
|
|
2889
|
+
try {
|
|
2890
|
+
const binding = await resolveFilesystemBinding(request, filesystem);
|
|
2891
|
+
if (!binding || binding.access !== "readonly") return sendNotFoundOrDenied(reply);
|
|
2892
|
+
const result = await binding.operations.read({ filesystem, path: path4 });
|
|
2893
|
+
const bytes = Buffer.from(result.content, "utf8");
|
|
2894
|
+
return reply.header("content-type", contentTypeForPath(path4)).header("content-length", String(bytes.byteLength)).header("cache-control", "no-store").header("x-content-type-options", "nosniff").send(bytes);
|
|
2895
|
+
} catch {
|
|
2896
|
+
return sendNotFoundOrDenied(reply);
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2855
2899
|
try {
|
|
2856
2900
|
const workspace = await resolveWorkspace(request);
|
|
2857
2901
|
if (!workspace.readBinaryFile) {
|
|
@@ -2905,6 +2949,17 @@ function fileRoutes(app, opts, done) {
|
|
|
2905
2949
|
const query = request.query;
|
|
2906
2950
|
const path4 = requireStringParam(query.path, "path", reply);
|
|
2907
2951
|
if (path4 === null) return;
|
|
2952
|
+
const filesystem = requestedFilesystem(query.filesystem);
|
|
2953
|
+
if (filesystem !== USER_FILESYSTEM_ID) {
|
|
2954
|
+
try {
|
|
2955
|
+
const binding = await resolveFilesystemBinding(request, filesystem);
|
|
2956
|
+
if (!binding || binding.access !== "readonly") return sendNotFoundOrDenied(reply);
|
|
2957
|
+
const result = await binding.operations.read({ filesystem, path: path4 });
|
|
2958
|
+
return { content: result.content };
|
|
2959
|
+
} catch {
|
|
2960
|
+
return sendNotFoundOrDenied(reply);
|
|
2961
|
+
}
|
|
2962
|
+
}
|
|
2908
2963
|
try {
|
|
2909
2964
|
if (isReadonlySkillFilePath(path4)) {
|
|
2910
2965
|
const { content: content2, stat: stat13 } = await readReadonlySkillFile(path4);
|
|
@@ -2936,6 +2991,8 @@ function fileRoutes(app, opts, done) {
|
|
|
2936
2991
|
error: { code: ERROR_CODE_VALIDATION_ERROR, message: "content is required", field: "content" }
|
|
2937
2992
|
});
|
|
2938
2993
|
}
|
|
2994
|
+
const filesystem = requestedFilesystem(body.filesystem);
|
|
2995
|
+
if (filesystem !== USER_FILESYSTEM_ID) return await rejectUnsupportedFilesystemMutation(request, reply, filesystem);
|
|
2939
2996
|
const expectedMtimeMs = typeof body.expectedMtimeMs === "number" ? body.expectedMtimeMs : null;
|
|
2940
2997
|
const shouldReturnMtimeMs = body.returnMtimeMs !== false || expectedMtimeMs !== null;
|
|
2941
2998
|
try {
|
|
@@ -3069,6 +3126,8 @@ function fileRoutes(app, opts, done) {
|
|
|
3069
3126
|
const query = request.query;
|
|
3070
3127
|
const path4 = requireStringParam(query.path, "path", reply);
|
|
3071
3128
|
if (path4 === null) return;
|
|
3129
|
+
const filesystem = requestedFilesystem(query.filesystem);
|
|
3130
|
+
if (filesystem !== USER_FILESYSTEM_ID) return await rejectUnsupportedFilesystemMutation(request, reply, filesystem);
|
|
3072
3131
|
try {
|
|
3073
3132
|
const workspace = await resolveWorkspace(request);
|
|
3074
3133
|
await workspace.unlink(path4);
|
|
@@ -3083,6 +3142,8 @@ function fileRoutes(app, opts, done) {
|
|
|
3083
3142
|
if (from === null) return;
|
|
3084
3143
|
const to = requireStringParam(body?.to, "to", reply);
|
|
3085
3144
|
if (to === null) return;
|
|
3145
|
+
const filesystem = requestedFilesystem(body.filesystem);
|
|
3146
|
+
if (filesystem !== USER_FILESYSTEM_ID) return await rejectUnsupportedFilesystemMutation(request, reply, filesystem);
|
|
3086
3147
|
try {
|
|
3087
3148
|
const workspace = await resolveWorkspace(request);
|
|
3088
3149
|
await workspace.rename(from, to);
|
|
@@ -3096,6 +3157,8 @@ function fileRoutes(app, opts, done) {
|
|
|
3096
3157
|
const path4 = requireStringParam(body?.path, "path", reply);
|
|
3097
3158
|
if (path4 === null) return;
|
|
3098
3159
|
const recursive = body.recursive === true;
|
|
3160
|
+
const filesystem = requestedFilesystem(body.filesystem);
|
|
3161
|
+
if (filesystem !== USER_FILESYSTEM_ID) return await rejectUnsupportedFilesystemMutation(request, reply, filesystem);
|
|
3099
3162
|
try {
|
|
3100
3163
|
const workspace = await resolveWorkspace(request);
|
|
3101
3164
|
await workspace.mkdir(path4, { recursive });
|
|
@@ -3108,6 +3171,17 @@ function fileRoutes(app, opts, done) {
|
|
|
3108
3171
|
const query = request.query;
|
|
3109
3172
|
const path4 = requireStringParam(query.path, "path", reply);
|
|
3110
3173
|
if (path4 === null) return;
|
|
3174
|
+
const filesystem = requestedFilesystem(query.filesystem);
|
|
3175
|
+
if (filesystem !== USER_FILESYSTEM_ID) {
|
|
3176
|
+
try {
|
|
3177
|
+
const binding = await resolveFilesystemBinding(request, filesystem);
|
|
3178
|
+
if (!binding || binding.access !== "readonly") return sendNotFoundOrDenied(reply);
|
|
3179
|
+
const result = await binding.operations.stat({ filesystem, path: path4 });
|
|
3180
|
+
return result.isDirectory ? { kind: "dir" } : { kind: "file", size: 0 };
|
|
3181
|
+
} catch {
|
|
3182
|
+
return sendNotFoundOrDenied(reply);
|
|
3183
|
+
}
|
|
3184
|
+
}
|
|
3111
3185
|
try {
|
|
3112
3186
|
if (isReadonlySkillFilePath(path4)) {
|
|
3113
3187
|
return await statReadonlySkillFile(path4);
|
|
@@ -8327,17 +8401,135 @@ function buildRemoteWorkspaceFilesystemAgentTools(bundle, pathOptions) {
|
|
|
8327
8401
|
function isTextContent2(content) {
|
|
8328
8402
|
return content.type === "text" && typeof content.text === "string";
|
|
8329
8403
|
}
|
|
8404
|
+
function filesystemBindings(bundle) {
|
|
8405
|
+
return bundle.filesystemBindings ?? [];
|
|
8406
|
+
}
|
|
8407
|
+
function filesystemIds(bundle) {
|
|
8408
|
+
return filesystemBindings(bundle).map((binding) => binding.filesystem);
|
|
8409
|
+
}
|
|
8410
|
+
function withFilesystemParameter(parameters, filesystemIds2) {
|
|
8411
|
+
const schema = parameters && typeof parameters === "object" ? { ...parameters } : { type: "object" };
|
|
8412
|
+
const properties = schema.properties && typeof schema.properties === "object" ? { ...schema.properties } : {};
|
|
8413
|
+
return {
|
|
8414
|
+
...schema,
|
|
8415
|
+
properties: {
|
|
8416
|
+
...properties,
|
|
8417
|
+
filesystem: {
|
|
8418
|
+
type: "string",
|
|
8419
|
+
description: filesystemIds2.length > 0 ? "Logical filesystem to use. Omit or use user for workspace files; use an advertised named filesystem for bound readonly context." : "Logical filesystem to use. Omit or use user for workspace files.",
|
|
8420
|
+
enum: ["user", ...filesystemIds2]
|
|
8421
|
+
}
|
|
8422
|
+
}
|
|
8423
|
+
};
|
|
8424
|
+
}
|
|
8425
|
+
function requestedFilesystem2(params) {
|
|
8426
|
+
const value = params.filesystem;
|
|
8427
|
+
return typeof value === "string" && value.length > 0 ? value : "user";
|
|
8428
|
+
}
|
|
8429
|
+
function withoutFilesystem(params) {
|
|
8430
|
+
const { filesystem: _filesystem, ...rest } = params;
|
|
8431
|
+
return rest;
|
|
8432
|
+
}
|
|
8433
|
+
function boundFilesystemPath(params) {
|
|
8434
|
+
const value = params.path;
|
|
8435
|
+
return typeof value === "string" && value.length > 0 ? value : "/";
|
|
8436
|
+
}
|
|
8437
|
+
function assertNotFilesystemPathSpoof(path4, filesystemIds2) {
|
|
8438
|
+
const normalized = path4.replace(/\\/g, "/");
|
|
8439
|
+
if (normalized.includes(":/") || filesystemIds2.some((filesystem) => normalized === `/${filesystem}` || normalized.startsWith(`/${filesystem}/`))) {
|
|
8440
|
+
throw new Error("filesystem prefixes are not valid path strings; use the filesystem parameter");
|
|
8441
|
+
}
|
|
8442
|
+
}
|
|
8443
|
+
function filesystemBinding(bundle, filesystem) {
|
|
8444
|
+
return filesystemBindings(bundle).find((binding) => binding.filesystem === filesystem);
|
|
8445
|
+
}
|
|
8446
|
+
function boundOperations(bundle, filesystem) {
|
|
8447
|
+
const binding = filesystemBinding(bundle, filesystem);
|
|
8448
|
+
if (!binding) throw new Error(`No filesystem binding is available for ${filesystem}`);
|
|
8449
|
+
return binding.operations;
|
|
8450
|
+
}
|
|
8451
|
+
function formatBoundRead(content) {
|
|
8452
|
+
return { content: [{ type: "text", text: content }] };
|
|
8453
|
+
}
|
|
8454
|
+
function formatBoundList(entries) {
|
|
8455
|
+
return { content: [{ type: "text", text: entries.join("\n") }] };
|
|
8456
|
+
}
|
|
8457
|
+
function formatBoundFind(paths) {
|
|
8458
|
+
return { content: [{ type: "text", text: paths.join("\n") }] };
|
|
8459
|
+
}
|
|
8460
|
+
function formatBoundGrep(matches) {
|
|
8461
|
+
return { content: [{ type: "text", text: matches.map((match) => `${match.path}:${match.line}:${match.text}`).join("\n") }] };
|
|
8462
|
+
}
|
|
8463
|
+
async function executeBoundFilesystemTool(toolName, filesystem, params, bundle) {
|
|
8464
|
+
const path4 = boundFilesystemPath(params);
|
|
8465
|
+
assertNotFilesystemPathSpoof(path4, filesystemIds(bundle));
|
|
8466
|
+
const operations = boundOperations(bundle, filesystem);
|
|
8467
|
+
if (toolName === "read") {
|
|
8468
|
+
const result = await operations.read({ filesystem, path: path4 });
|
|
8469
|
+
return { ...formatBoundRead(result.content), details: { metadata: result.metadata } };
|
|
8470
|
+
}
|
|
8471
|
+
if (toolName === "ls") {
|
|
8472
|
+
const result = await operations.list({ filesystem, path: path4 });
|
|
8473
|
+
return { ...formatBoundList(result.entries), details: { metadata: result.metadata } };
|
|
8474
|
+
}
|
|
8475
|
+
if (toolName === "find") {
|
|
8476
|
+
const pattern = typeof params.pattern === "string" ? params.pattern : "*";
|
|
8477
|
+
const limit = typeof params.limit === "number" ? params.limit : void 0;
|
|
8478
|
+
const result = await operations.find({ filesystem, path: path4 }, pattern, { limit });
|
|
8479
|
+
return { ...formatBoundFind(result.paths), details: { metadata: result.metadata } };
|
|
8480
|
+
}
|
|
8481
|
+
if (toolName === "grep") {
|
|
8482
|
+
const pattern = typeof params.pattern === "string" ? params.pattern : "";
|
|
8483
|
+
const limit = typeof params.limit === "number" ? params.limit : void 0;
|
|
8484
|
+
const result = await operations.grep({ filesystem, path: path4 }, pattern, { limit });
|
|
8485
|
+
return { ...formatBoundGrep(result.matches), details: { metadata: result.metadata } };
|
|
8486
|
+
}
|
|
8487
|
+
if (toolName === "write" || toolName === "edit") {
|
|
8488
|
+
operations.rejectMutation(toolName, { filesystem, path: path4 });
|
|
8489
|
+
}
|
|
8490
|
+
throw new Error(`Tool ${toolName} does not support filesystem ${filesystem}`);
|
|
8491
|
+
}
|
|
8492
|
+
function withBoundFilesystemPromptGuidance(promptSnippet, filesystemIds2) {
|
|
8493
|
+
if (filesystemIds2.length === 0) return promptSnippet;
|
|
8494
|
+
const guidance = [
|
|
8495
|
+
"Named filesystem bindings: file tools default to the user workspace when filesystem is omitted.",
|
|
8496
|
+
`Use the filesystem parameter explicitly for bound readonly context (${filesystemIds2.join(", ")}), and start browsing at / unless told otherwise.`,
|
|
8497
|
+
"Readonly filesystem bindings reject writes; do not use path prefixes like filesystem:/x to switch filesystem."
|
|
8498
|
+
].join("\n");
|
|
8499
|
+
return [promptSnippet, guidance].filter(Boolean).join("\n");
|
|
8500
|
+
}
|
|
8501
|
+
function withFilesystemRouting(tool, bundle) {
|
|
8502
|
+
const ids = filesystemIds(bundle);
|
|
8503
|
+
return {
|
|
8504
|
+
...tool,
|
|
8505
|
+
promptSnippet: withBoundFilesystemPromptGuidance(tool.promptSnippet, ids),
|
|
8506
|
+
parameters: withFilesystemParameter(tool.parameters, ids),
|
|
8507
|
+
async execute(params, ctx) {
|
|
8508
|
+
const filesystem = requestedFilesystem2(params);
|
|
8509
|
+
if (filesystem !== "user") {
|
|
8510
|
+
const result = await executeBoundFilesystemTool(tool.name, filesystem, params, bundle);
|
|
8511
|
+
const textContent = (result.content ?? []).filter(isTextContent2).map((c) => ({ type: "text", text: c.text }));
|
|
8512
|
+
return {
|
|
8513
|
+
content: textContent.length > 0 ? textContent : [{ type: "text", text: "" }],
|
|
8514
|
+
isError: false,
|
|
8515
|
+
details: result.details
|
|
8516
|
+
};
|
|
8517
|
+
}
|
|
8518
|
+
return await tool.execute(withoutFilesystem(params), ctx);
|
|
8519
|
+
}
|
|
8520
|
+
};
|
|
8521
|
+
}
|
|
8330
8522
|
function adaptPiTool2(piTool) {
|
|
8331
8523
|
return {
|
|
8332
8524
|
name: piTool.name,
|
|
8333
8525
|
readinessRequirements: ["workspace-fs"],
|
|
8334
8526
|
description: piTool.description,
|
|
8335
8527
|
promptSnippet: piTool.promptSnippet,
|
|
8336
|
-
parameters: piTool.parameters,
|
|
8528
|
+
parameters: piTool.parameters && typeof piTool.parameters === "object" ? { ...piTool.parameters } : { type: "object" },
|
|
8337
8529
|
async execute(params, ctx) {
|
|
8338
8530
|
const result = await piTool.execute(
|
|
8339
8531
|
ctx.toolCallId,
|
|
8340
|
-
params,
|
|
8532
|
+
withoutFilesystem(params),
|
|
8341
8533
|
ctx.abortSignal,
|
|
8342
8534
|
ctx.onUpdate ? (update) => {
|
|
8343
8535
|
const text = update.content?.filter(isTextContent2).map((c) => c.text).join("");
|
|
@@ -8361,7 +8553,7 @@ function buildFilesystemAgentTools(bundle) {
|
|
|
8361
8553
|
const cwd = bundle.workspace.root;
|
|
8362
8554
|
const strategy = bundle.filesystem ?? defaultFilesystemStrategyForBundle(bundle);
|
|
8363
8555
|
if (strategy.kind === "remote-workspace") {
|
|
8364
|
-
return buildRemoteWorkspaceFilesystemAgentTools(bundle, strategy.pathOptions);
|
|
8556
|
+
return buildRemoteWorkspaceFilesystemAgentTools(bundle, strategy.pathOptions).map((tool) => withFilesystemRouting(tool, bundle));
|
|
8365
8557
|
}
|
|
8366
8558
|
const storageRoot = getRuntimeBundleStorageRoot(bundle);
|
|
8367
8559
|
const ops = boundFs(storageRoot, { runtimeRoot: cwd });
|
|
@@ -8372,7 +8564,7 @@ function buildFilesystemAgentTools(bundle) {
|
|
|
8372
8564
|
adaptPiTool2(createFindToolDefinition2(cwd, { operations: ops.find })),
|
|
8373
8565
|
adaptPiTool2(createGrepToolDefinition2(cwd, { operations: ops.grep })),
|
|
8374
8566
|
adaptPiTool2(createLsToolDefinition2(cwd, { operations: ops.ls }))
|
|
8375
|
-
];
|
|
8567
|
+
].map((tool) => withFilesystemRouting(tool, bundle));
|
|
8376
8568
|
}
|
|
8377
8569
|
|
|
8378
8570
|
// src/server/tools/harness/index.ts
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hachej/boring-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.63",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Pane-embeddable coding agent. Ships direct/local/vercel-sandbox execution modes behind one interface.",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"use-stick-to-bottom": "^1.1.3",
|
|
75
75
|
"yaml": "^2.8.3",
|
|
76
76
|
"zod": "^3.25.76",
|
|
77
|
-
"@hachej/boring-ui-kit": "0.1.
|
|
77
|
+
"@hachej/boring-ui-kit": "0.1.63"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@antithesishq/bombadil": "0.5.0",
|