mirror of
https://github.com/moltbot/moltbot.git
synced 2026-04-21 05:32:53 +00:00
fix: harden ACP spawn workspace resolution
This commit is contained in:
@@ -53,6 +53,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Telegram/replies: preserve explicit topic targets when `replyTo` is present while still inheriting the current topic for same-chat replies without an explicit topic. (#59634) Thanks @dashhuang.
|
||||
- Telegram/reactions: preserve `reactionNotifications: "own"` across gateway restarts by persisting sent-message ownership state instead of treating cold cache as a permissive fallback. (#59207) Thanks @samzong.
|
||||
- Telegram/media: preserve `<media:...>` placeholders and `file_id` in captioned messages when Bot API downloads fail, so agents still receive media context. (#59948) Thanks @v1p0r.
|
||||
- ACP/agents: inherit the target agent workspace for cross-agent ACP spawns, keep missing target workspaces on the backend default cwd path, and surface real access errors instead of silently running in the wrong tree. (#58438) Thanks @zssggle-rgb.
|
||||
- Telegram/media: keep inbound image attachments readable on upgraded installs where legacy state roots still differ from the managed config-dir media cache. (#59971) Thanks @neeravmakwana.
|
||||
- Telegram/local Bot API: thread `channels.telegram.apiRoot` through buffered reply-media and album downloads so self-hosted Bot API file paths stop falling back to `api.telegram.org` and 404ing. (#59544) Thanks @SARAMALI15792.
|
||||
- Telegram/media: add `channels.telegram.network.dangerouslyAllowPrivateNetwork` for trusted fake-IP or transparent-proxy environments where Telegram media downloads resolve `api.telegram.org` to private/internal/special-use addresses.
|
||||
|
||||
@@ -646,6 +646,62 @@ describe("spawnAcpDirect", () => {
|
||||
}
|
||||
});
|
||||
|
||||
it("surfaces non-missing target workspace access failures instead of silently dropping cwd", async () => {
|
||||
const workspaceRoot = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-acp-spawn-"));
|
||||
const accessSpy = vi.spyOn(fs, "access");
|
||||
try {
|
||||
const mainWorkspace = path.join(workspaceRoot, "main");
|
||||
const targetWorkspace = path.join(workspaceRoot, "claude-code");
|
||||
await fs.mkdir(mainWorkspace, { recursive: true });
|
||||
await fs.mkdir(targetWorkspace, { recursive: true });
|
||||
|
||||
replaceSpawnConfig({
|
||||
...hoisted.state.cfg,
|
||||
acp: {
|
||||
...hoisted.state.cfg.acp,
|
||||
allowedAgents: ["codex", "claude-code"],
|
||||
},
|
||||
agents: {
|
||||
list: [
|
||||
{
|
||||
id: "main",
|
||||
default: true,
|
||||
workspace: mainWorkspace,
|
||||
},
|
||||
{
|
||||
id: "claude-code",
|
||||
workspace: targetWorkspace,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
accessSpy.mockRejectedValueOnce(
|
||||
Object.assign(new Error("permission denied"), { code: "EACCES" }),
|
||||
);
|
||||
|
||||
const result = await spawnAcpDirect(
|
||||
{
|
||||
task: "Inspect the queue owner state",
|
||||
agentId: "claude-code",
|
||||
mode: "run",
|
||||
},
|
||||
{
|
||||
agentSessionKey: "agent:main:main",
|
||||
},
|
||||
);
|
||||
|
||||
expect(result).toEqual({
|
||||
status: "error",
|
||||
error: "permission denied",
|
||||
});
|
||||
expect(hoisted.initializeSessionMock).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
accessSpy.mockRestore();
|
||||
await fs.rm(workspaceRoot, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
it("binds LINE ACP sessions to the current conversation when the channel has no native threads", async () => {
|
||||
enableLineCurrentConversationBindings();
|
||||
hoisted.sessionBindingBindMock.mockImplementationOnce(
|
||||
|
||||
@@ -382,8 +382,12 @@ async function resolveRuntimeCwdForAcpSpawn(params: {
|
||||
try {
|
||||
await fs.access(params.resolvedCwd);
|
||||
return params.resolvedCwd;
|
||||
} catch {
|
||||
return undefined;
|
||||
} catch (error) {
|
||||
const code = error instanceof Error ? (error as NodeJS.ErrnoException).code : undefined;
|
||||
if (code === "ENOENT" || code === "ENOTDIR") {
|
||||
return undefined;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user