feat(web,server): unify nav naming, panel width and the update entry (#130)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Yaowei ZhengandClaude Opus 5 authored and GitHub committed 2026-07-30 17:25:50 +08:00
1 parent 97852f43b8
commit 385d506e77
32 files changed
+1135 -557

No files matched your search

@@ -33,8 +33,19 @@ import { sessionShell } from "./shell.js";
/** Process-group semantics are available on POSIX; Windows falls back to signaling the child process directly. */
const SUPPORTS_PROCESS_GROUP = process.platform !== "win32";
/** Extra wait cap (ms) after the command exits to collect trailing output: enough to drain the last flush, without hanging. */
const POST_EXIT_DRAIN_MS = 50;
/**
* Extra wait cap (ms) after the command exits to collect trailing output: enough to drain the
* last flush, without hanging.
*
* Windows gets a far larger budget. `exit` fires on process termination without waiting for
* pipe EOF (see the listener below), so this window is the only thing standing between a
* fast-exiting command and losing its output — and Git-Bash pipe delivery on Windows routinely
* misses a 50ms window that POSIX pipes never come close to. Symptom when it is too tight: a
* command that ran fine reports empty or truncated output, intermittently and under load. The
* cost of the larger cap is bounded and only paid on Windows, and only when a command exits
* with its pipe still draining: the loop breaks as soon as the buffer goes quiet.
*/
const POST_EXIT_DRAIN_MS = process.platform === "win32" ? 500 : 50;
/** Capacity cap (characters) for a single session's unread output: prevents a chatty background process from blowing up memory. */
const OUTPUT_BUFFER_CAP = 1024 * 1024; // 1 MiB
/**
+27 -3
View File
@@ -130,6 +130,28 @@ async function collectRun(
return all;
}
/**
* Reads a file the shell just wrote, retrying briefly until it holds `expected`.
*
* A tool completes when its shell process exits, which does not promise the write is visible to
* this process yet — on Windows CI it intermittently is not, surfacing as ENOENT or stale
* content. Retrying asserts the same exact content; it only stops the assertion racing the
* filesystem, and a genuinely wrong write still fails one timeout later.
*/
async function readFileEventually(
file: string,
expected: string,
timeoutMs = 2000,
): Promise<string> {
const deadline = Date.now() + timeoutMs;
let last = "";
for (;;) {
last = await readFile(file, "utf8").catch(() => "");
if (last === expected || Date.now() >= deadline) return last;
await new Promise((r) => setTimeout(r, 25));
}
}
describe("ContextEngine ReAct loop (mock LLM, approve callback)", () => {
let workspace: string;
let traces: string;
@@ -167,7 +189,9 @@ describe("ContextEngine ReAct loop (mock LLM, approve callback)", () => {
(m) => (m.payload as { type?: string }).type === "tool_call_output",
),
).toBe(true);
expect(await readFile(join(workspace, "hello.txt"), "utf8")).toBe("Hello, Penguin");
expect(await readFileEventually(join(workspace, "hello.txt"), "Hello, Penguin")).toBe(
"Hello, Penguin",
);
const types = collected.map((m) => (m.payload as { type?: string }).type);
expect(types).toContain("tool_call_output");
@@ -988,8 +1012,8 @@ describe("ContextEngine async/incremental tool calls (overlapping execution)", (
expect(firstCompleteAt["t2"]!).toBeLessThan(firstCompleteAt["t1"]!);
}
expect(await readFile(join(workspace, "a.txt"), "utf8")).toBe("one");
expect(await readFile(join(workspace, "b.txt"), "utf8")).toBe("two");
expect(await readFileEventually(join(workspace, "a.txt"), "one")).toBe("one");
expect(await readFileEventually(join(workspace, "b.txt"), "two")).toBe("two");
// Both tool outputs are fed back into the second turn, producing the final reply.
expect(
all.some(
+24 -3
View File
@@ -45,6 +45,28 @@ async function collect(gen: AsyncGenerator<OmniMessage>): Promise<OmniMessage[]>
return out;
}
/**
* Reads a file the shell just wrote, retrying briefly until it holds `expected`.
*
* The tool completes when the shell process exits, which does not promise the write is visible
* to this process yet — on Windows CI it intermittently is not. Retrying asserts the same exact
* content, it just stops the assertion from racing the filesystem; a genuinely wrong write
* still fails, one timeout later, with the last value read.
*/
async function readFileEventually(
file: string,
expected: string,
timeoutMs = 2000,
): Promise<string> {
const deadline = Date.now() + timeoutMs;
let last = "";
for (;;) {
last = await readFile(file, "utf8").catch(() => "");
if (last === expected || Date.now() >= deadline) return last;
await new Promise((r) => setTimeout(r, 25));
}
}
function payloadTypes(messages: OmniMessage[]): string[] {
return messages.map((m) => (m.payload as { type?: string }).type ?? "");
}
@@ -152,7 +174,7 @@ describe("Environment.executeTool — basic file write", () => {
expect(outPayload.tool_call_id).toBe("call_write");
expect(outPayload.stop_reason).toBe("completed");
const written = await readFile(path.join(tmp, "note.txt"), "utf8");
const written = await readFileEventually(path.join(tmp, "note.txt"), "Hello, Penguin");
expect(written).toBe("Hello, Penguin");
});
});
@@ -224,8 +246,7 @@ describe("Environment.executeTool — edit file", () => {
}),
);
const written = await readFile(path.join(tmp, "note.txt"), "utf8");
expect(written).toBe("Hello!");
expect(await readFileEventually(path.join(tmp, "note.txt"), "Hello!")).toBe("Hello!");
});
});