mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 07:40:44 +00:00
fix: restore codex verbose full output
This commit is contained in:
@@ -27,6 +27,7 @@ Docs: https://docs.openclaw.ai
|
||||
### Fixes
|
||||
|
||||
- Web fetch: add a documented `tools.web.fetch.ssrfPolicy.allowIpv6UniqueLocalRange` opt-in and thread it through cache keys and DNS/IP checks so trusted fake-IP proxy stacks using `fc00::/7` can work without broad private-network access. Fixes #74351. Thanks @jeffrey701.
|
||||
- OpenAI Codex: restore `/verbose full` persistence and app-server tool-output forwarding, and retry Gateway E2E temp-home cleanup so debug runs do not regress on stale validation or cleanup flakes. Thanks @vincentkoc.
|
||||
- Anthropic/Meridian: preserve text and thinking content seeded on `content_block_start` in anthropic-messages streams, so `[thinking, text]` replies no longer persist as empty turns or trigger empty-response fallbacks. Fixes #74410. Thanks @vyctorbrzezowski.
|
||||
- Channels/Matrix: complete the cross-signing handshake on `openclaw matrix verify confirm-sas` so the operator's other Matrix device clears its `Verifying…` loop instead of staying stuck after the agent confirms. (#74542) Thanks @nklock.
|
||||
- CLI/status: honor channel-specific model context-window overrides when reporting effective context, so channel-scoped sessions reflect the active window in `openclaw status`. Thanks @HemantSudarshan.
|
||||
|
||||
@@ -636,6 +636,65 @@ describe("runCodexAppServerAttempt", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("forwards Codex app-server verbose tool summaries and completed output", async () => {
|
||||
const onToolResult = vi.fn();
|
||||
const sessionFile = path.join(tempDir, "session.jsonl");
|
||||
const workspaceDir = path.join(tempDir, "workspace");
|
||||
const harness = createStartedThreadHarness();
|
||||
const params = createParams(sessionFile, workspaceDir);
|
||||
params.verboseLevel = "full";
|
||||
params.onToolResult = onToolResult;
|
||||
|
||||
const run = runCodexAppServerAttempt(params);
|
||||
await harness.waitForMethod("turn/start");
|
||||
await harness.notify({
|
||||
method: "item/started",
|
||||
params: {
|
||||
threadId: "thread-1",
|
||||
turnId: "turn-1",
|
||||
item: {
|
||||
type: "dynamicToolCall",
|
||||
id: "tool-1",
|
||||
namespace: null,
|
||||
tool: "read",
|
||||
arguments: { path: "README.md" },
|
||||
status: "inProgress",
|
||||
contentItems: null,
|
||||
success: null,
|
||||
durationMs: null,
|
||||
},
|
||||
},
|
||||
});
|
||||
await harness.notify({
|
||||
method: "item/completed",
|
||||
params: {
|
||||
threadId: "thread-1",
|
||||
turnId: "turn-1",
|
||||
item: {
|
||||
type: "dynamicToolCall",
|
||||
id: "tool-1",
|
||||
namespace: null,
|
||||
tool: "read",
|
||||
arguments: { path: "README.md" },
|
||||
status: "completed",
|
||||
contentItems: [{ type: "inputText", text: "file contents" }],
|
||||
success: true,
|
||||
durationMs: 12,
|
||||
},
|
||||
},
|
||||
});
|
||||
await harness.completeTurn({ threadId: "thread-1", turnId: "turn-1" });
|
||||
await run;
|
||||
|
||||
expect(onToolResult).toHaveBeenCalledTimes(2);
|
||||
expect(onToolResult).toHaveBeenNthCalledWith(1, {
|
||||
text: "📖 Read: `from README.md`",
|
||||
});
|
||||
expect(onToolResult).toHaveBeenNthCalledWith(2, {
|
||||
text: "📖 Read: `from README.md`\n```txt\nfile contents\n```",
|
||||
});
|
||||
});
|
||||
|
||||
it("registers native hook relay config for an enabled Codex turn and cleans it up", async () => {
|
||||
const sessionFile = path.join(tempDir, "session.jsonl");
|
||||
const workspaceDir = path.join(tempDir, "workspace");
|
||||
|
||||
@@ -298,7 +298,12 @@ module.exports = {
|
||||
expect(afterCount).toBe(beforeCount);
|
||||
} finally {
|
||||
await server.close({ reason: "http tools workspace test complete" });
|
||||
await fs.rm(tempHome, { recursive: true, force: true });
|
||||
await fs.rm(tempHome, {
|
||||
recursive: true,
|
||||
force: true,
|
||||
maxRetries: 10,
|
||||
retryDelay: 50,
|
||||
});
|
||||
envSnapshot.restore();
|
||||
}
|
||||
},
|
||||
@@ -505,7 +510,12 @@ module.exports = {
|
||||
expect(parsed.plugins?.entries?.discord).toBeUndefined();
|
||||
} finally {
|
||||
await server.close({ reason: "minimal gateway auto-enable verify" });
|
||||
await fs.rm(tempHome, { recursive: true, force: true });
|
||||
await fs.rm(tempHome, {
|
||||
recursive: true,
|
||||
force: true,
|
||||
maxRetries: 10,
|
||||
retryDelay: 50,
|
||||
});
|
||||
envSnapshot.restore();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -186,6 +186,22 @@ describe("gateway sessions patch", () => {
|
||||
expect(entry.fastMode).toBeUndefined();
|
||||
});
|
||||
|
||||
test("persists verboseLevel=full", async () => {
|
||||
const entry = expectPatchOk(
|
||||
await runPatch({
|
||||
patch: { key: MAIN_SESSION_KEY, verboseLevel: "full" },
|
||||
}),
|
||||
);
|
||||
expect(entry.verboseLevel).toBe("full");
|
||||
});
|
||||
|
||||
test("rejects invalid verboseLevel values with all valid choices in the error", async () => {
|
||||
const result = await runPatch({
|
||||
patch: { key: MAIN_SESSION_KEY, verboseLevel: "maybe" },
|
||||
});
|
||||
expectPatchError(result, 'invalid verboseLevel (use "on"|"off"|"full")');
|
||||
});
|
||||
|
||||
test("persists elevatedLevel=off (does not clear)", async () => {
|
||||
const entry = expectPatchOk(
|
||||
await runPatch({
|
||||
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
} from "../auto-reply/thinking.js";
|
||||
import type { SessionEntry } from "../config/sessions.js";
|
||||
|
||||
const INVALID_VERBOSE_LEVEL_ERROR = 'invalid verboseLevel (use "on"|"off"|"full")';
|
||||
|
||||
export function parseVerboseOverride(
|
||||
raw: unknown,
|
||||
): { ok: true; value: VerboseLevel | null | undefined } | { ok: false; error: string } {
|
||||
@@ -16,11 +18,11 @@ export function parseVerboseOverride(
|
||||
return { ok: true, value: undefined };
|
||||
}
|
||||
if (typeof raw !== "string") {
|
||||
return { ok: false, error: 'invalid verboseLevel (use "on"|"off")' };
|
||||
return { ok: false, error: INVALID_VERBOSE_LEVEL_ERROR };
|
||||
}
|
||||
const normalized = normalizeVerboseLevel(raw);
|
||||
if (!normalized) {
|
||||
return { ok: false, error: 'invalid verboseLevel (use "on"|"off")' };
|
||||
return { ok: false, error: INVALID_VERBOSE_LEVEL_ERROR };
|
||||
}
|
||||
return { ok: true, value: normalized };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user