mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-09 05:19:32 +08:00
Add cwd option for command replies
This commit is contained in:
@@ -2,7 +2,11 @@
|
||||
|
||||
## [Unreleased] 0.1.3
|
||||
|
||||
_Add notes here for the next release._
|
||||
### Features
|
||||
- Added `cwd` option to command reply config for setting the working directory where commands execute. Essential for Claude Code to have proper project context.
|
||||
|
||||
### Developer notes
|
||||
- Command auto-replies now pass `{ timeoutMs, cwd }` into the command runner; custom runners/tests that stub `runCommandWithTimeout` should accept the options object as well as the legacy numeric timeout.
|
||||
|
||||
## 0.1.2 — 2025-11-25
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ warelay reads `~/.warelay/warelay.json` (JSON5 accepted). Add a command-mode rep
|
||||
allowFrom: ["+15551234567"],
|
||||
reply: {
|
||||
mode: "command",
|
||||
// Working directory for command execution (useful for Claude Code project context).
|
||||
cwd: "/Users/you/Projects/my-project",
|
||||
// Prepended before the inbound body; good for system prompts.
|
||||
bodyPrefix: "You are a concise WhatsApp assistant. Keep replies under 1500 characters.\n\n",
|
||||
// Claude CLI argv; the final element is the prompt/body provided by warelay.
|
||||
@@ -38,6 +40,7 @@ warelay reads `~/.warelay/warelay.json` (JSON5 accepted). Add a command-mode rep
|
||||
```
|
||||
|
||||
Notes on this configuration:
|
||||
- `cwd` sets the working directory where the command runs. This is essential for Claude Code to have the right project context—Claude will see the project's `CLAUDE.md`, have access to project files, and understand the codebase structure.
|
||||
- warelay automatically injects a Claude identity prefix and the correct `--output-format`/`-p` flags when `command[0]` is `claude` and `claudeOutputFormat` is set.
|
||||
- Sessions are stored in `~/.warelay/sessions.json`; `scope: per-sender` keeps separate threads for each contact.
|
||||
- `bodyPrefix` is added before the inbound message body that reaches Claude. The string above mirrors the built-in 1500-character WhatsApp guardrail.
|
||||
|
||||
@@ -288,11 +288,13 @@ export async function getReplyFromConfig(
|
||||
[CLAUDE_IDENTITY_PREFIX, existingBody].filter(Boolean).join("\n\n"),
|
||||
];
|
||||
}
|
||||
logVerbose(`Running command auto-reply: ${finalArgv.join(" ")}`);
|
||||
logVerbose(
|
||||
`Running command auto-reply: ${finalArgv.join(" ")}${reply.cwd ? ` (cwd: ${reply.cwd})` : ""}`,
|
||||
);
|
||||
const started = Date.now();
|
||||
try {
|
||||
const { stdout, stderr, code, signal, killed } = await enqueueCommand(
|
||||
() => commandRunner(finalArgv, timeoutMs),
|
||||
() => commandRunner(finalArgv, { timeoutMs, cwd: reply.cwd }),
|
||||
{
|
||||
onWait: (waitMs, queuedAhead) => {
|
||||
if (isVerbose()) {
|
||||
|
||||
@@ -26,6 +26,7 @@ export type WarelayConfig = {
|
||||
mode: ReplyMode;
|
||||
text?: string; // for mode=text, can contain {{Body}}
|
||||
command?: string[]; // for mode=command, argv with templates
|
||||
cwd?: string; // working directory for command execution
|
||||
template?: string; // prepend template string when building command/prompt
|
||||
timeoutSeconds?: number; // optional command timeout; defaults to 600s
|
||||
bodyPrefix?: string; // optional string prepended to Body before templating
|
||||
@@ -43,6 +44,7 @@ const ReplySchema = z
|
||||
mode: z.union([z.literal("text"), z.literal("command")]),
|
||||
text: z.string().optional(),
|
||||
command: z.array(z.string()).optional(),
|
||||
cwd: z.string().optional(),
|
||||
template: z.string().optional(),
|
||||
timeoutSeconds: z.number().int().positive().optional(),
|
||||
bodyPrefix: z.string().optional(),
|
||||
|
||||
@@ -43,14 +43,26 @@ export type SpawnResult = {
|
||||
killed: boolean;
|
||||
};
|
||||
|
||||
export type CommandOptions = {
|
||||
timeoutMs: number;
|
||||
cwd?: string;
|
||||
};
|
||||
|
||||
export async function runCommandWithTimeout(
|
||||
argv: string[],
|
||||
timeoutMs: number,
|
||||
optionsOrTimeout: number | CommandOptions,
|
||||
): Promise<SpawnResult> {
|
||||
const options: CommandOptions =
|
||||
typeof optionsOrTimeout === "number"
|
||||
? { timeoutMs: optionsOrTimeout }
|
||||
: optionsOrTimeout;
|
||||
const { timeoutMs, cwd } = options;
|
||||
|
||||
// Spawn with inherited stdin (TTY) so tools like `claude` don't hang.
|
||||
return await new Promise((resolve, reject) => {
|
||||
const child = spawn(argv[0], argv.slice(1), {
|
||||
stdio: ["inherit", "pipe", "pipe"],
|
||||
cwd,
|
||||
});
|
||||
let stdout = "";
|
||||
let stderr = "";
|
||||
|
||||
Reference in New Issue
Block a user