Files
zesdex/apps/packages/infrastructure/src/tools/bash_tools.ts
T

65 lines
1.9 KiB
TypeScript
Raw Normal View History

/**
* Background bash process output and kill tools.
* Mirrors `tools/bash_tools.rs`.
*/
import * as fs from "node:fs";
import * as path from "node:path";
import type { JsonValue } from "@zesdex/domain";
import { type Tool, type ToolCtx } from "./mod.ts";
import { argStr } from "./util.ts";
/** Get the output of a background bash job by ID. */
export class BashOutput implements Tool {
name = "bash_output";
description = "Get the output of a background bash job by ID";
parameters = {
type: "object",
properties: {
job_id: { type: "string", description: "Background job ID" },
},
required: ["job_id"],
};
run(ctx: ToolCtx, args: JsonValue): string {
const jobId = argStr(args, "job_id");
// Prevent path traversal
if (jobId.includes("/") || jobId.includes("\\") || jobId.includes("..")) {
throw new Error(`invalid job_id '${jobId}': must not contain path separators`);
}
const outputDir = path.join(ctx.sessionDir, "bash-outputs");
const outputFile = path.join(outputDir, jobId);
if (fs.existsSync(outputFile)) {
try {
const content = fs.readFileSync(outputFile, "utf8");
return `Output for job '${jobId}':\n${content}`;
} catch (e) {
return `Error reading output: ${(e as Error).message}`;
}
}
return `No output found for job '${jobId}'. The job may still be running.`;
}
}
/** Kill a background bash job by ID. */
export class BashKill implements Tool {
name = "bash_kill";
description = "Kill a background bash job by ID";
parameters = {
type: "object",
properties: {
job_id: { type: "string", description: "Background job ID to kill" },
},
required: ["job_id"],
};
run(_ctx: ToolCtx, args: JsonValue): string {
const jobId = argStr(args, "job_id");
// Background job control is a global registry — not yet ported (bgbash 3g).
throw new Error(`no active background job found with ID '${jobId}'`);
}
}