fix: expand reply cwd (~) and document AGENTS

This commit is contained in:
Peter Steinberger
2025-12-14 02:59:31 +00:00
parent 5ace7c9c66
commit 507f5623f4
8 changed files with 105 additions and 7 deletions

View File

@@ -16,6 +16,7 @@ import { getChildLogger } from "../logging.js";
import { splitMediaFromOutput } from "../media/parse.js";
import { enqueueCommand } from "../process/command-queue.js";
import { runPiRpc } from "../process/tau-rpc.js";
import { resolveUserPath } from "../utils.js";
import { applyTemplate, type TemplateContext } from "./templating.js";
import {
formatToolAggregate,
@@ -357,6 +358,11 @@ export async function runCommandReply(
onPartialReply,
} = params;
const resolvedCwd =
typeof reply.cwd === "string" && reply.cwd.trim()
? resolveUserPath(reply.cwd)
: undefined;
if (!reply.command?.length) {
throw new Error("reply.command is required for mode=command");
}
@@ -499,14 +505,14 @@ export async function runCommandReply(
}
logVerbose(
`Running command auto-reply: ${rpcArgv.join(" ")}${reply.cwd ? ` (cwd: ${reply.cwd})` : ""}`,
`Running command auto-reply: ${rpcArgv.join(" ")}${resolvedCwd ? ` (cwd: ${resolvedCwd})` : ""}`,
);
logger.info(
{
agent: agentKind,
sessionId: templatingCtx.SessionId,
newSession: isNewSession,
cwd: reply.cwd,
cwd: resolvedCwd,
command: rpcArgv.slice(0, -1), // omit body to reduce noise
},
"command auto-reply start",
@@ -593,7 +599,7 @@ export async function runCommandReply(
const rpcResult = await runPiRpc({
argv: rpcArgvForRun,
cwd: reply.cwd,
cwd: resolvedCwd,
prompt: body,
timeoutMs,
onEvent: (line: string) => {
@@ -758,7 +764,7 @@ export async function runCommandReply(
signal: signalUsed,
killed: killedUsed,
argv: finalArgv,
cwd: reply.cwd,
cwd: resolvedCwd,
stdout: truncate(rawStdout),
stderr: truncate(stderrUsed),
},
@@ -888,7 +894,7 @@ export async function runCommandReply(
const elapsed = Date.now() - started;
verboseLog(`Command auto-reply finished in ${elapsed}ms`);
logger.info(
{ durationMs: elapsed, agent: agentKind, cwd: reply.cwd },
{ durationMs: elapsed, agent: agentKind, cwd: resolvedCwd },
"command auto-reply finished",
);
if ((codeUsed ?? 0) !== 0) {
@@ -995,7 +1001,7 @@ export async function runCommandReply(
} catch (err) {
const elapsed = Date.now() - started;
logger.info(
{ durationMs: elapsed, agent: agentKind, cwd: reply.cwd },
{ durationMs: elapsed, agent: agentKind, cwd: resolvedCwd },
"command auto-reply failed",
);
const anyErr = err as { killed?: boolean; signal?: string };
@@ -1010,7 +1016,7 @@ export async function runCommandReply(
);
const baseMsg =
"Command timed out after " +
`${timeoutSeconds}s${reply.cwd ? ` (cwd: ${reply.cwd})` : ""}. Try a shorter prompt or split the request.`;
`${timeoutSeconds}s${resolvedCwd ? ` (cwd: ${resolvedCwd})` : ""}. Try a shorter prompt or split the request.`;
const partial =
extractRpcAssistantText(errorObj.stdout ?? "") ||
extractAssistantTextLoosely(errorObj.stdout ?? "") ||

View File

@@ -9,6 +9,7 @@ import {
jidToE164,
normalizeE164,
normalizePath,
resolveUserPath,
sleep,
toWhatsappJid,
withWhatsAppPrefix,
@@ -85,3 +86,19 @@ describe("jidToE164", () => {
spy.mockRestore();
});
});
describe("resolveUserPath", () => {
it("expands ~ to home dir", () => {
expect(resolveUserPath("~")).toBe(path.resolve(os.homedir()));
});
it("expands ~/ to home dir", () => {
expect(resolveUserPath("~/clawd")).toBe(
path.resolve(os.homedir(), "clawd"),
);
});
it("resolves relative paths", () => {
expect(resolveUserPath("tmp/dir")).toBe(path.resolve("tmp/dir"));
});
});

View File

@@ -71,5 +71,14 @@ export function sleep(ms: number) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export function resolveUserPath(input: string): string {
const trimmed = input.trim();
if (!trimmed) return trimmed;
if (trimmed.startsWith("~")) {
return path.resolve(trimmed.replace("~", os.homedir()));
}
return path.resolve(trimmed);
}
// Fixed configuration root; legacy ~/.clawdis is no longer used.
export const CONFIG_DIR = path.join(os.homedir(), ".clawdis");