mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
acp: add regression coverage and smoke-test docs
This commit is contained in:
committed by
mbelinky
parent
4aebff78bc
commit
d06138ac3d
@@ -246,6 +246,46 @@ Interface details:
|
||||
- `streamTo` (optional): `"parent"` streams initial ACP run progress summaries back to the requester session as system events.
|
||||
- When available, accepted responses include `streamLogPath` pointing to a session-scoped JSONL log (`<sessionId>.acp-stream.jsonl`) you can tail for full relay history.
|
||||
|
||||
### Operator smoke test
|
||||
|
||||
Use this after a gateway deploy when you want a quick live check that ACP spawn
|
||||
is actually working end-to-end, not just passing unit tests.
|
||||
|
||||
Recommended gate:
|
||||
|
||||
1. Verify the deployed gateway version/commit on the target host.
|
||||
2. Confirm the deployed source includes the ACP lineage acceptance in
|
||||
`src/gateway/sessions-patch.ts` (`subagent:* or acp:* sessions`).
|
||||
3. Open a temporary ACPX bridge session to a live agent (for example
|
||||
`razor(main)` on `jpclawhq`).
|
||||
4. Ask that agent to call `sessions_spawn` with:
|
||||
- `runtime: "acp"`
|
||||
- `agentId: "codex"`
|
||||
- `mode: "run"`
|
||||
- task: `Reply with exactly LIVE-ACP-SPAWN-OK`
|
||||
5. Verify the agent reports:
|
||||
- `accepted=yes`
|
||||
- a real `childSessionKey`
|
||||
- no validator error
|
||||
6. Clean up the temporary ACPX bridge session.
|
||||
|
||||
Example prompt to the live agent:
|
||||
|
||||
```text
|
||||
Use the sessions_spawn tool now with runtime: "acp", agentId: "codex", and mode: "run".
|
||||
Set the task to: "Reply with exactly LIVE-ACP-SPAWN-OK".
|
||||
Then report only: accepted=<yes/no>; childSessionKey=<value or none>; error=<exact text or none>.
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
- Keep this smoke test on `mode: "run"` unless you are intentionally testing
|
||||
thread-bound persistent ACP sessions.
|
||||
- Do not require `streamTo: "parent"` for the basic gate. That path depends on
|
||||
requester/session capabilities and is a separate integration check.
|
||||
- Treat thread-bound `mode: "session"` testing as a second, richer integration
|
||||
pass from a real Discord thread or Telegram topic.
|
||||
|
||||
## Sandbox compatibility
|
||||
|
||||
ACP sessions currently run on the host runtime, not inside the OpenClaw sandbox.
|
||||
|
||||
@@ -127,6 +127,40 @@ describe("AcpxRuntime", () => {
|
||||
expect(promptArgs).toContain("--approve-all");
|
||||
});
|
||||
|
||||
it("serializes text plus image attachments into ACP prompt blocks", async () => {
|
||||
const { runtime, logPath } = await createMockRuntimeFixture();
|
||||
|
||||
const handle = await runtime.ensureSession({
|
||||
sessionKey: "agent:codex:acp:with-image",
|
||||
agent: "codex",
|
||||
mode: "persistent",
|
||||
});
|
||||
|
||||
for await (const _event of runtime.runTurn({
|
||||
handle,
|
||||
text: "describe this image",
|
||||
attachments: [{ mediaType: "image/png", data: "aW1hZ2UtYnl0ZXM=" }],
|
||||
mode: "prompt",
|
||||
requestId: "req-image",
|
||||
})) {
|
||||
// Consume stream to completion so prompt logging is finalized.
|
||||
}
|
||||
|
||||
const logs = await readMockRuntimeLogEntries(logPath);
|
||||
const prompt = logs.find(
|
||||
(entry) =>
|
||||
entry.kind === "prompt" &&
|
||||
String(entry.sessionName ?? "") === "agent:codex:acp:with-image",
|
||||
);
|
||||
expect(prompt).toBeDefined();
|
||||
|
||||
const stdinBlocks = JSON.parse(String(prompt?.stdinText ?? ""));
|
||||
expect(stdinBlocks).toEqual([
|
||||
{ type: "text", text: "describe this image" },
|
||||
{ type: "image", mimeType: "image/png", data: "aW1hZ2UtYnl0ZXM=" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("preserves leading spaces across streamed text deltas", async () => {
|
||||
const runtime = sharedFixture?.runtime;
|
||||
expect(runtime).toBeDefined();
|
||||
|
||||
@@ -463,6 +463,18 @@ describe("gateway server sessions", () => {
|
||||
expect(spawnedPatched.ok).toBe(true);
|
||||
expect(spawnedPatched.payload?.entry.spawnedBy).toBe("agent:main:main");
|
||||
|
||||
const acpPatched = await rpcReq<{
|
||||
ok: true;
|
||||
entry: { spawnedBy?: string; spawnDepth?: number };
|
||||
}>(ws, "sessions.patch", {
|
||||
key: "agent:main:acp:child",
|
||||
spawnedBy: "agent:main:main",
|
||||
spawnDepth: 1,
|
||||
});
|
||||
expect(acpPatched.ok).toBe(true);
|
||||
expect(acpPatched.payload?.entry.spawnedBy).toBe("agent:main:main");
|
||||
expect(acpPatched.payload?.entry.spawnDepth).toBe(1);
|
||||
|
||||
const spawnedPatchedInvalidKey = await rpcReq(ws, "sessions.patch", {
|
||||
key: "agent:main:main",
|
||||
spawnedBy: "agent:main:main",
|
||||
|
||||
Reference in New Issue
Block a user