Compare commits

..

6 Commits

Author SHA1 Message Date
nntrivi2001 81b3cbda65 chore: v2.8.56 — new tab / split pane starts in the Session defaults 2026-11-02 13:34:36 +07:00
nntrivi2001 0a99eed369 fix(workspace): a new tab or split pane starts in the account's Session defaults
newTabBody sent only prompt/tool/model, so a Claude tab opened from the tab
bar + or a split menu always started in auto mode even with Bypass
permissions set as the default; a Codex one ignored its sandbox, approval
and YOLO defaults. It now sends the same defaults the workspace home's
prompt box starts from.
2026-11-02 13:34:10 +07:00
nntrivi2001 1ec9f2e592 chore: v2.8.55 — chat + menu no longer covered by the controls under the prompt box 2026-11-02 13:30:33 +07:00
nntrivi2001 a401a318c5 fix(chat): + menu paints above the controls row under the prompt box
Opened downward, the panel had no z-index, so the AI Proxy / Permission /
Local selects (positioned, later in the DOM) drew over its first rows.
2026-11-02 13:29:08 +07:00
nntrivi2001 5caad0df2d chore: v2.8.54 — chat Stop shows while Claude thinks
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 13:29:05 +07:00
nntrivi2001 01e66ba122 fix(chat): Stop shows while Claude thinks, not only while its footer says "esc to interrupt"
The chat's live line said "Thinking… 21s" while the box offered Send, so the
turn could not be stopped. Stop shows only when a hook marked main "working"
or the pane's busy line matched, and Claude Code 2.1.3xx writes
"esc to interrupt" only in its footer, which a narrow pane, a tip or a notice
replaces. Claude's busy line now also matches its spinner (verb… (41s · …)),
which the line a finished turn leaves ("Cooked for 1m 2s") does not; and the
chat re-reads "working" on transcript_changed, so a hook that reached another
dashboard on the same database no longer leaves Stop hidden.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 13:29:05 +07:00
10 changed files with 61 additions and 16 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
# Claude Code Working Guide
_Last synced: v2.8.53 (2026-11-02) — chat + menu opens downward when there is no room above._ A change that makes any statement in this file, `AGENTS.md`, or a README wrong — a moved path, a new or changed extension point, a retired rule — updates that file in the same change-set and bumps this marker. **Bump = replace the version/date and a ≤ 1-line summary; never append a changelog here** — details belong in the commit message and `docs/`, because this whole file is loaded into every session.
_Last synced: v2.8.56 (2026-11-02) — a new tab or split pane starts in the account's Session defaults (bypass included)._ A change that makes any statement in this file, `AGENTS.md`, or a README wrong — a moved path, a new or changed extension point, a retired rule — updates that file in the same change-set and bumps this marker. **Bump = replace the version/date and a ≤ 1-line summary; never append a changelog here** — details belong in the commit message and `docs/`, because this whole file is loaded into every session.
## Project mission
- Maintain a reliable local-first dashboard for Claude Code session monitoring.
+1 -1
View File
@@ -78,7 +78,7 @@ function loadLists(cwd: string): Promise<Lists> {
}
const PANEL =
"absolute w-60 rounded-xl border border-border bg-surface-1 py-1 shadow-lg animate-fade-in";
"absolute z-40 w-60 rounded-xl border border-border bg-surface-1 py-1 shadow-lg animate-fade-in";
/** Room the menu and its tallest submenu (Project files: search + list) need. */
const MENU_ROOM = 380;
+13 -5
View File
@@ -16,8 +16,9 @@
* keys, Home and End move between tabs (one tab stop, APG). Errors are
* toasts. The `+` menu opens a new tab in the free slot the server picks
* (`slot: "auto"`) — a plain shell (`POST /api/lanes/:id/start {shell: true}`)
* or an installed, enabled AI tool started bare on its default model, no
* prompt (a prompt, proxy or worktree is still the workspace home's prompt
* or an installed, enabled AI tool started bare on its default model and
* the account's Session defaults (permission mode, Codex sandbox/approval/
* bypass), no prompt (a prompt, proxy or worktree is still the workspace home's prompt
* box) — plus a link to Settings → Agents. Ten sessions is the server's limit
* (`MAX_PANE_SLOT`). The bar is the console's only header: Home (the
* workspace's home) at its left end, `actions` (the single pane's split menus)
@@ -72,6 +73,7 @@ import {
type GroupsUpdate,
} from "./PaneGrid";
import { insertionIndex } from "../../lib/laneOrderStorage";
import { readCodexDefaults, readDefaultMode } from "../../lib/sessionDefaults";
import {
type PaneGroups,
MAX_PANES,
@@ -140,15 +142,21 @@ export function newTabTools(lane: Lane, aiTools: AiToolsState): string[] {
];
}
/** The start body of a bare tool on its default model, no prompt. Only a
* different tool is named, as the home does: the workspace's own keeps
* starting even once disabled. */
/** The start body of a bare tool on its default model, no prompt, in the
* account's Session defaults (Claude's permission mode, Codex's sandbox,
* approval and bypass) — the same ones the workspace home's prompt box starts
* from. Only a different tool is named, as the home does: the workspace's own
* keeps starting even once disabled. */
export function newTabBody(id: string, lane: Lane, aiTools: AiToolsState) {
const model = aiTools.byId(id)?.defaultModel;
const codex = id === "codex" ? readCodexDefaults() : null;
return {
prompt: "",
...(id !== lane.tool ? { tool: id } : {}),
...(model ? { model } : {}),
...(id === "claude" ? { permissionMode: readDefaultMode() } : {}),
...(codex ? { sandbox: codex.sandbox, approval: codex.approval } : {}),
...(codex?.bypass && aiTools.byId(id)?.bypass ? { bypass: true } : {}),
};
}
+4 -1
View File
@@ -689,8 +689,11 @@ export const PaneChat = memo(function PaneChat({
// another dashboard on the same database, or the socket dropped) would
// otherwise leave Stop up after the turn ended.
intervalMs: working || waiting ? 5000 : undefined,
// The transcript growing re-reads it too: a hook that reached another
// dashboard on the same database sends this one no agent_updated, and
// without a poll Stop never showed for a turn the chat calls Thinking….
match: (msg) =>
msg.type === "agent_updated" &&
(msg.type === "agent_updated" || msg.type === "transcript_changed") &&
(msg.data as { session_id?: string } | undefined)?.session_id === sessionId,
});
@@ -432,6 +432,14 @@ describe("readRunBusy", () => {
let rows = ["✻ Thinking… (4s · ↓ 120 tokens · esc to interrupt)"];
const off = registerPane("agenthub-lane-8", () => {}, () => true, undefined, undefined, () => rows);
expect(readRunBusy("agenthub-lane-8", "claude")).toBe(true);
// Claude's spinner with the footer's hint gone (a narrow pane, a tip).
rows = ["✶ Skedaddling… (41s · ↓ 2.8k tokens · thought for 2s)", " ⏵⏵ auto mode on"];
expect(readRunBusy("agenthub-lane-8", "claude")).toBe(true);
rows = ["✻ Thinking… (1m 3s)"];
expect(readRunBusy("agenthub-lane-8", "claude")).toBe(true);
// The line a finished turn leaves is not.
rows = ["✻ Cooked for 1m 2s", "❯ "];
expect(readRunBusy("agenthub-lane-8", "claude")).toBe(false);
// Claude's permission footer is not a turn at work.
rows = ["Esc to cancel · Tab to amend"];
expect(readRunBusy("agenthub-lane-8", "claude")).toBe(false);
+8 -3
View File
@@ -368,10 +368,15 @@ function typeRow(options: PaneMenuOption[]): number {
/** The status line a tool's TUI shows only while a turn runs, read off its
* binary's own strings: Claude's and Codex's `esc to interrupt`, agy's
* `Thinking… (3s · esc to cancel)` — in parentheses after an ellipsis, so
* Claude's permission footer (`Esc to cancel · Tab to amend`) is not it. A
* tool missing here (omp, Cursor) has no line we know. */
* Claude's permission footer (`Esc to cancel · Tab to amend`) is not it.
* Claude ≥ 2.1.3xx keeps `esc to interrupt` only in its footer, which a
* narrow pane, a tip or a notice replaces, so its spinner line counts too:
* a verb, an ellipsis and the turn's time in parentheses
* (`✶ Skedaddling… (41s · ↓ 2.8k tokens)`) — the line a finished turn leaves
* (`✻ Cooked for 1m 2s`) has neither. A tool missing here (omp, Cursor) has
* no line we know. */
export const BUSY_LINE: Readonly<Record<string, RegExp>> = {
claude: /\besc to interrupt\b/i,
claude: /\besc to interrupt\b|…\s*\(\s*\d+[smh]\b/i,
codex: /\besc to interrupt\b/i,
antigravity: /…\s*\([^)]*\besc to cancel\)/i,
};
+22 -1
View File
@@ -1053,7 +1053,28 @@ describe("split panes", () => {
const user = userEvent.setup();
await user.click(screen.getByTestId("pane-split-right-1"));
await user.click(screen.getByTestId("pane-split-new-right-1-claude"));
expect(api.lanes.action).toHaveBeenCalledWith(1, "start", { slot: "auto", prompt: "" });
expect(api.lanes.action).toHaveBeenCalledWith(1, "start", {
slot: "auto",
prompt: "",
permissionMode: "auto",
});
});
it("a new AI pane starts in the account's Session defaults (bypass included)", async () => {
localStorage.setItem("agenthub.permissionMode", "bypassPermissions");
lanesToReturn = lanesToReturn.map((l) => ({ ...l, tool: "claude" }));
withRuns([live(0), live(1)]);
await open("/workspace?lane=1&run=agenthub-lane-1");
await ctrlClick(screen.getByTestId("console-tab-1"));
const user = userEvent.setup();
await user.click(screen.getByTestId("pane-split-right-1"));
await user.click(screen.getByTestId("pane-split-new-right-1-claude"));
expect(api.lanes.action).toHaveBeenCalledWith(1, "start", {
slot: "auto",
prompt: "",
permissionMode: "bypassPermissions",
});
localStorage.removeItem("agenthub.permissionMode");
});
it("with one pane, the split menus sit beside Tools and split it", async () => {
@@ -7316,7 +7316,7 @@ exports[`screen snapshots > Settings — about 1`] = `
<span
class="text-status-warning/90"
>
UI build v2.8.53 (rebuild client to match)
UI build v2.8.56 (rebuild client to match)
</span>
</p>
</div>
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "agenthub",
"version": "2.8.53",
"version": "2.8.56",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "agenthub",
"version": "2.8.53",
"version": "2.8.56",
"hasInstallScript": true,
"license": "UNLICENSED",
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "agenthub",
"version": "2.8.53",
"version": "2.8.56",
"bin": {
"agenthub": "bin/agenthub.js"
},