fix: guard bash pty cwd
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { type ChildProcessWithoutNullStreams, spawn } from "node:child_process";
|
import { type ChildProcessWithoutNullStreams, spawn } from "node:child_process";
|
||||||
import { randomUUID } from "node:crypto";
|
import { randomUUID } from "node:crypto";
|
||||||
import { existsSync } from "node:fs";
|
import { existsSync, statSync } from "node:fs";
|
||||||
|
import { homedir } from "node:os";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core";
|
import type { AgentTool, AgentToolResult } from "@mariozechner/pi-agent-core";
|
||||||
import { Type } from "@sinclair/typebox";
|
import { Type } from "@sinclair/typebox";
|
||||||
@@ -160,7 +161,11 @@ export function createBashTool(
|
|||||||
const maxOutput = DEFAULT_MAX_OUTPUT;
|
const maxOutput = DEFAULT_MAX_OUTPUT;
|
||||||
const startedAt = Date.now();
|
const startedAt = Date.now();
|
||||||
const sessionId = randomUUID();
|
const sessionId = randomUUID();
|
||||||
const workdir = params.workdir?.trim() || process.cwd();
|
const warnings: string[] = [];
|
||||||
|
const workdir = resolveWorkdir(
|
||||||
|
params.workdir?.trim() || process.cwd(),
|
||||||
|
warnings,
|
||||||
|
);
|
||||||
|
|
||||||
const { shell, args: shellArgs } = getShellConfig();
|
const { shell, args: shellArgs } = getShellConfig();
|
||||||
const env = params.env ? { ...process.env, ...params.env } : process.env;
|
const env = params.env ? { ...process.env, ...params.env } : process.env;
|
||||||
@@ -230,6 +235,8 @@ export function createBashTool(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (warning) warnings.push(warning);
|
||||||
|
|
||||||
const session = {
|
const session = {
|
||||||
id: sessionId,
|
id: sessionId,
|
||||||
command: params.command,
|
command: params.command,
|
||||||
@@ -286,7 +293,7 @@ export function createBashTool(
|
|||||||
const emitUpdate = () => {
|
const emitUpdate = () => {
|
||||||
if (!onUpdate) return;
|
if (!onUpdate) return;
|
||||||
const tailText = session.tail || session.aggregated;
|
const tailText = session.tail || session.aggregated;
|
||||||
const warningText = warning ? `${warning}\n\n` : "";
|
const warningText = warnings.length ? `${warnings.join("\n")}\n\n` : "";
|
||||||
onUpdate({
|
onUpdate({
|
||||||
content: [{ type: "text", text: warningText + (tailText || "") }],
|
content: [{ type: "text", text: warningText + (tailText || "") }],
|
||||||
details: {
|
details: {
|
||||||
@@ -336,7 +343,7 @@ export function createBashTool(
|
|||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
text:
|
text:
|
||||||
`${warning ? `${warning}\n\n` : ""}` +
|
`${warnings.length ? `${warnings.join("\n")}\n\n` : ""}` +
|
||||||
`Command still running (session ${sessionId}, pid ${session.pid ?? "n/a"}). ` +
|
`Command still running (session ${sessionId}, pid ${session.pid ?? "n/a"}). ` +
|
||||||
"Use process (list/poll/log/write/kill/clear/remove) for follow-up.",
|
"Use process (list/poll/log/write/kill/clear/remove) for follow-up.",
|
||||||
},
|
},
|
||||||
@@ -410,7 +417,7 @@ export function createBashTool(
|
|||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
text:
|
text:
|
||||||
`${warning ? `${warning}\n\n` : ""}` +
|
`${warnings.length ? `${warnings.join("\n")}\n\n` : ""}` +
|
||||||
(aggregated || "(no output)"),
|
(aggregated || "(no output)"),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -915,6 +922,30 @@ function killSession(session: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveWorkdir(workdir: string, warnings: string[]) {
|
||||||
|
const current = safeCwd();
|
||||||
|
const fallback = current ?? homedir();
|
||||||
|
try {
|
||||||
|
const stats = statSync(workdir);
|
||||||
|
if (stats.isDirectory()) return workdir;
|
||||||
|
} catch {
|
||||||
|
// ignore, fallback below
|
||||||
|
}
|
||||||
|
warnings.push(
|
||||||
|
`Warning: workdir "${workdir}" is unavailable; using "${fallback}".`,
|
||||||
|
);
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
function safeCwd() {
|
||||||
|
try {
|
||||||
|
const cwd = process.cwd();
|
||||||
|
return existsSync(cwd) ? cwd : null;
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function ensurePath(env: Record<string, string>) {
|
function ensurePath(env: Record<string, string>) {
|
||||||
if (!env.PATH?.trim()) {
|
if (!env.PATH?.trim()) {
|
||||||
env.PATH = DEFAULT_PATH;
|
env.PATH = DEFAULT_PATH;
|
||||||
|
|||||||
Reference in New Issue
Block a user