From 46e3899945698768d10c60528d42c385e3a2ff06 Mon Sep 17 00:00:00 2001 From: nntrivi2001 Date: Mon, 12 Oct 2026 15:40:47 +0700 Subject: [PATCH] =?UTF-8?q?fix:=20v2.7.4=20=E2=80=94=20Changes=20matches?= =?UTF-8?q?=20JetBrains=20(#72),=20the=20chat=20says=20when=20Claude=20wai?= =?UTF-8?q?ts=20on=20a=20trust=20prompt=20(#73),=20Vietnamese=20Telex=20in?= =?UTF-8?q?=20Safari?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Changes (#72): a file git reports `MM` whose working copy equals HEAD again (a staged change since undone on disk) is no longer listed — JetBrains' GitChangesCollector drops it the same way. Mode-only changes stay listed. statusCounts (the dirty-tree safety checks) is unchanged. - Chat (#73): Claude Code runs no hook before a folder is trusted, so a new pane's session has no row; the chat now says the session has not started, offers Open terminal, and asks before typing a message or /model //effort into the pane (an Enter would pick the trust prompt's "No, exit"). - Terminal: Safari + macOS's own Vietnamese Telex replaces the whole word on each key (insertReplacementText), which xterm.js ignores — only each word's first letter reached the pane. The edit is now sent as DELs + the new tail. - Also: Ctrl+V pastes a screenshot into the terminal as a file path; the folder browser fallback lists files for a file field (`files=1`); the macOS native picker opens in front of the browser; a hidden tab is marked while a chat waits or once a turn ended; chat live line shows running calls, turn time and tokens, and "Done in …". --- CLAUDE.md | 2 +- client/src/components/PathPickButton.tsx | 24 +- client/src/components/SplashScreen.tsx | 89 +---- .../__tests__/PathPickButton.test.tsx | 35 +- .../conversation/ConversationView.tsx | 62 ++- .../components/conversation/MessageList.tsx | 375 +++++++++++++++--- .../ConversationView.notYet.test.tsx | 25 +- .../__tests__/MessageList.images.test.tsx | 38 +- .../__tests__/MessageList.sender.test.tsx | 116 +++++- .../components/lanes/FolderBrowseModal.tsx | 53 ++- .../components/onboarding/OnboardingTour.tsx | 10 +- client/src/components/run/ChatOutline.tsx | 39 +- client/src/components/run/PaneChat.tsx | 154 ++++++- client/src/components/run/PaneGrid.tsx | 27 +- client/src/components/run/RunSetup.tsx | 2 +- client/src/components/run/TerminalView.tsx | 70 +++- .../run/__tests__/ChatOutline.test.tsx | 4 + .../run/__tests__/PaneChat.test.tsx | 82 +++- .../run/__tests__/TerminalView.test.tsx | 75 +++- client/src/i18n/locales/en/lanes.json | 1 - client/src/i18n/locales/en/run.json | 8 + client/src/i18n/locales/en/sessions.json | 12 +- client/src/i18n/locales/vi/lanes.json | 1 - client/src/i18n/locales/vi/run.json | 8 + client/src/i18n/locales/vi/sessions.json | 12 +- client/src/index.css | 25 ++ client/src/lib/api.ts | 14 +- client/src/lib/tabBadge.ts | 49 +++ .../screens.snapshot.test.tsx.snap | 2 +- docs/API.md | 16 +- docs/LANES.md | 8 +- openapi.yaml | 2 +- package-lock.json | 4 +- package.json | 2 +- server/README.md | 2 +- server/__tests__/git-diff-ops.test.js | 28 ++ server/__tests__/lane-lifecycle.test.js | 19 + server/__tests__/native-dialog.test.js | 7 + server/__tests__/server-s3-review5.test.js | 50 ++- server/lib/git-diff.js | 8 +- server/lib/native-dialog.js | 4 + server/routes/lanes.js | 15 +- server/routes/run.js | 27 +- server/routes/sessions.js | 20 +- 44 files changed, 1329 insertions(+), 297 deletions(-) create mode 100644 client/src/lib/tabBadge.ts diff --git a/CLAUDE.md b/CLAUDE.md index 5899138d..6d09fa82 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # Claude Code Working Guide -_Last synced: v2.7.3 (2026-10-12) — Update now restarts through our own service unit; a start refuses a missing folder (ENOCWD)._ 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.7.4 (2026-10-12) — Changes hides a staged change undone on disk (#72); chat says when the session has not started (#73)._ 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. diff --git a/client/src/components/PathPickButton.tsx b/client/src/components/PathPickButton.tsx index 9f5048a0..02f8a90a 100644 --- a/client/src/components/PathPickButton.tsx +++ b/client/src/components/PathPickButton.tsx @@ -6,9 +6,9 @@ * user chose. A browser's picker cannot give a page that path, so the dialog * opens on the server's desktop — which is only this user's screen when the * browser runs on the same machine. Anywhere else (a LAN browser, a server - * with no desktop or no zenity/kdialog) a folder falls back to the in-app - * `FolderBrowseModal` (as it does on any other failure), and a file to typing - * the path. + * with no desktop or no zenity/kdialog) it falls back to the in-app + * `FolderBrowseModal` (as it does on any other failure) — for a file field + * too, which then lists files and picks one on click. * @author Nguyễn Ngọc Trí Vĩ */ @@ -16,12 +16,8 @@ import { useState, type Ref } from "react"; import { useTranslation } from "react-i18next"; import { FolderOpen } from "lucide-react"; import { api } from "../lib/api"; -import { toast } from "../lib/toast"; import { FolderBrowseModal } from "./lanes/FolderBrowseModal"; -/** Server answers that mean "no native picker for this browser" — not a fault. */ -const FALLBACK = new Set(["EREMOTE", "EBADORIGIN", "ENODIALOG"]); - export function PathPickButton({ kind = "dir", start, @@ -47,15 +43,10 @@ export function PathPickButton({ try { const r = await api.lanes.pickPath(kind, start?.trim() || undefined); if (r.path) onPick(r.path); - } catch (err) { - const code = (err as { code?: string }).code; - // A folder always has the in-app browser to fall back on, whatever went - // wrong with the native one (a crashed dialog, one already open). - if (kind === "dir") setFallback(true); - else if (code && FALLBACK.has(code)) toast.info(t("browse.typePath")); - else { - toast.error(err instanceof Error ? err.message : String(err)); - } + } catch { + // The in-app browser is the fallback whatever went wrong with the + // native one: a LAN browser (EREMOTE), no desktop, a crashed dialog. + setFallback(true); } finally { setBusy(false); } @@ -80,6 +71,7 @@ export function PathPickButton({
e.stopPropagation()}> setFallback(false)} diff --git a/client/src/components/SplashScreen.tsx b/client/src/components/SplashScreen.tsx index 06049720..585278a4 100644 --- a/client/src/components/SplashScreen.tsx +++ b/client/src/components/SplashScreen.tsx @@ -1,7 +1,7 @@ /** * @file SplashScreen.tsx * @description Branding splash shown once per browser session on app load. A - * dark-tech "constellation" overlay built around the node-graph brand mark: + * dark-tech "constellation" overlay built around the SmartGift brand mark: * a time-aware greeting, a bold (localized) tagline, and two subtexts reveal * in a staggered cascade. The tagline and the subtext pair are picked at * random (per mount) from localized pools in `splash.json`, so the copy is @@ -143,7 +143,7 @@ export function SplashScreen() {