更新大量 tsx 原始文件; 已经迁移 login panel; 部分 (#121)

* style(B1-1): 格式化 ink/buddy/cli/context/screens/tasks/services/keybindings/state (43 files)

纯格式化:移除分号、React Compiler import、import 多行展开。
修复了 Box.tsx 和 ScrollBox.tsx 中无效的 global.d.ts import。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-2): 格式化 commands (79 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-3): 格式化 components/messages,permissions,mcp,sandbox,shell (104 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-4): 格式化 components/PromptInput,FeedbackSurvey,tasks,agents,skills,design-system,wizard (73 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-5): 格式化 components其余 + hooks + tools (232 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* style(B1-6): 格式化 main/entrypoints/utils/moreright (21 files)

纯格式化:移除分号、React Compiler import、import 多行展开。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: 更新 README,新增 Run.ps1/TODO.md,删除 V6.md

- README.md: 大幅重写,更详细版本历史和配置示例
- Run.ps1: 新增 Windows 启动脚本
- TODO.md: 新增包完成清单
- V6.md: 删除(架构重构规划已不适用)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: 修复以前的问题

* fix: 修复 login 面板的问题

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
claude-code-best
2026-04-04 23:24:27 +08:00
committed by GitHub
parent 02694918b5
commit 5b1a52b8e0
559 changed files with 103807 additions and 101817 deletions

View File

@@ -1,22 +1,22 @@
import { c as _c } from "react/compiler-runtime";
import type { StructuredPatchHunk } from 'diff';
import * as React from 'react';
import { memo } from 'react';
import { useSettings } from '../hooks/useSettings.js';
import { Box, NoSelect, RawAnsi, useTheme } from '../ink.js';
import { isFullscreenEnvEnabled } from '../utils/fullscreen.js';
import sliceAnsi from '../utils/sliceAnsi.js';
import { expectColorDiff } from './StructuredDiff/colorDiff.js';
import { StructuredDiffFallback } from './StructuredDiff/Fallback.js';
import type { StructuredPatchHunk } from 'diff'
import * as React from 'react'
import { memo } from 'react'
import { useSettings } from '../hooks/useSettings.js'
import { Box, NoSelect, RawAnsi, useTheme } from '../ink.js'
import { isFullscreenEnvEnabled } from '../utils/fullscreen.js'
import sliceAnsi from '../utils/sliceAnsi.js'
import { expectColorDiff } from './StructuredDiff/colorDiff.js'
import { StructuredDiffFallback } from './StructuredDiff/Fallback.js'
type Props = {
patch: StructuredPatchHunk;
dim: boolean;
filePath: string; // File path for language detection
firstLine: string | null; // First line of file for shebang detection
fileContent?: string; // Full file content for syntax context (multiline strings, etc.)
width: number;
skipHighlighting?: boolean; // Skip syntax highlighting
};
patch: StructuredPatchHunk
dim: boolean
filePath: string // File path for language detection
firstLine: string | null // First line of file for shebang detection
fileContent?: string // Full file content for syntax context (multiline strings, etc.)
width: number
skipHighlighting?: boolean // Skip syntax highlighting
}
// REPL.tsx renders <Messages> at two disjoint tree positions (transcript
// early-return vs prompt-mode nested in FullscreenLayout), so ctrl+o
@@ -30,160 +30,157 @@ type Props = {
// reactivating the per-line <DiffLine> branch that PR #20378 had bypassed.
// Caching the split here restores the O(1)-leaves-per-diff invariant.
type CachedRender = {
lines: string[];
lines: string[]
// Two RawAnsi columns replace what was N DiffLine rows. sliceAnsi work
// moves from per-remount to cold-cache-only; parseToSpans is eliminated
// entirely (RawAnsi bypasses Ansi parsing).
gutterWidth: number;
gutters: string[] | null;
contents: string[] | null;
};
const RENDER_CACHE = new WeakMap<StructuredPatchHunk, Map<string, CachedRender>>();
gutterWidth: number
gutters: string[] | null
contents: string[] | null
}
const RENDER_CACHE = new WeakMap<
StructuredPatchHunk,
Map<string, CachedRender>
>()
// Gutter width matches the Rust module's layout: marker (1) + space +
// right-aligned line number (max_digits) + space. Depends only on patch
// identity (the WeakMap key), so it's cacheable alongside the NAPI output.
function computeGutterWidth(patch: StructuredPatchHunk): number {
const maxLineNumber = Math.max(patch.oldStart + patch.oldLines - 1, patch.newStart + patch.newLines - 1, 1);
return maxLineNumber.toString().length + 3; // marker + 2 padding spaces
const maxLineNumber = Math.max(
patch.oldStart + patch.oldLines - 1,
patch.newStart + patch.newLines - 1,
1,
)
return maxLineNumber.toString().length + 3 // marker + 2 padding spaces
}
function renderColorDiff(patch: StructuredPatchHunk, firstLine: string | null, filePath: string, fileContent: string | null, theme: string, width: number, dim: boolean, splitGutter: boolean): CachedRender | null {
const ColorDiff = expectColorDiff();
if (!ColorDiff) return null;
function renderColorDiff(
patch: StructuredPatchHunk,
firstLine: string | null,
filePath: string,
fileContent: string | null,
theme: string,
width: number,
dim: boolean,
splitGutter: boolean,
): CachedRender | null {
const ColorDiff = expectColorDiff()
if (!ColorDiff) return null
// Defensive: if the gutter would eat the whole render width (narrow
// terminal), skip the split. Rust already wraps to `width` so the
// single-column output stays correct; we just lose noSelect. Without
// this, sliceAnsi(line, gutterWidth) would return empty content and
// RawAnsi(width<=0) is untested.
const rawGutterWidth = splitGutter ? computeGutterWidth(patch) : 0;
const gutterWidth = rawGutterWidth > 0 && rawGutterWidth < width ? rawGutterWidth : 0;
const key = `${theme}|${width}|${dim ? 1 : 0}|${gutterWidth}|${firstLine ?? ''}|${filePath}`;
let perHunk = RENDER_CACHE.get(patch);
const hit = perHunk?.get(key);
if (hit) return hit;
const lines = new ColorDiff(patch, firstLine, filePath, fileContent).render(theme, width, dim);
if (lines === null) return null;
const rawGutterWidth = splitGutter ? computeGutterWidth(patch) : 0
const gutterWidth =
rawGutterWidth > 0 && rawGutterWidth < width ? rawGutterWidth : 0
const key = `${theme}|${width}|${dim ? 1 : 0}|${gutterWidth}|${firstLine ?? ''}|${filePath}`
let perHunk = RENDER_CACHE.get(patch)
const hit = perHunk?.get(key)
if (hit) return hit
const lines = new ColorDiff(patch, firstLine, filePath, fileContent).render(
theme,
width,
dim,
)
if (lines === null) return null
// Pre-split the gutter column once (cold-cache). sliceAnsi preserves
// styles across the cut; the Rust module already pads the gutter to
// gutterWidth so the narrow RawAnsi column's width matches its cells.
let gutters: string[] | null = null;
let contents: string[] | null = null;
let gutters: string[] | null = null
let contents: string[] | null = null
if (gutterWidth > 0) {
gutters = lines.map(l => sliceAnsi(l, 0, gutterWidth));
contents = lines.map(l => sliceAnsi(l, gutterWidth));
gutters = lines.map(l => sliceAnsi(l, 0, gutterWidth))
contents = lines.map(l => sliceAnsi(l, gutterWidth))
}
const entry: CachedRender = {
lines,
gutterWidth,
gutters,
contents
};
const entry: CachedRender = { lines, gutterWidth, gutters, contents }
if (!perHunk) {
perHunk = new Map();
RENDER_CACHE.set(patch, perHunk);
perHunk = new Map()
RENDER_CACHE.set(patch, perHunk)
}
// Cap the inner map: width is part of the key, so terminal resize while a
// diff is visible accumulates a full render copy per distinct width. Four
// variants (two widths × dim on/off) covers the steady state; beyond that
// the user is actively resizing and old widths are stale.
if (perHunk.size >= 4) perHunk.clear();
perHunk.set(key, entry);
return entry;
if (perHunk.size >= 4) perHunk.clear()
perHunk.set(key, entry)
return entry
}
export const StructuredDiff = memo(function StructuredDiff(t0: Props) {
const $ = _c(26);
const {
patch,
dim,
filePath,
firstLine,
fileContent,
width,
skipHighlighting: t1
} = t0;
const skipHighlighting = t1 === undefined ? false : t1;
const [theme] = useTheme();
const settings = useSettings();
const syntaxHighlightingDisabled = settings.syntaxHighlightingDisabled ?? false;
const safeWidth = Math.max(1, Math.floor(width));
let t2;
if ($[0] !== dim || $[1] !== fileContent || $[2] !== filePath || $[3] !== firstLine || $[4] !== patch || $[5] !== safeWidth || $[6] !== skipHighlighting || $[7] !== syntaxHighlightingDisabled || $[8] !== theme) {
const splitGutter = isFullscreenEnvEnabled();
t2 = skipHighlighting || syntaxHighlightingDisabled ? null : renderColorDiff(patch, firstLine, filePath, fileContent ?? null, theme, safeWidth, dim, splitGutter);
$[0] = dim;
$[1] = fileContent;
$[2] = filePath;
$[3] = firstLine;
$[4] = patch;
$[5] = safeWidth;
$[6] = skipHighlighting;
$[7] = syntaxHighlightingDisabled;
$[8] = theme;
$[9] = t2;
} else {
t2 = $[9];
}
const cached = t2;
export const StructuredDiff = memo(function StructuredDiff({
patch,
dim,
filePath,
firstLine,
fileContent,
width,
skipHighlighting = false,
}: Props): React.ReactNode {
const [theme] = useTheme()
const settings = useSettings()
const syntaxHighlightingDisabled =
settings.syntaxHighlightingDisabled ?? false
// Ensure width is at least 1 to prevent crashes in the Rust NAPI module
// which expects u32 (can't handle negative numbers)
const safeWidth = Math.max(1, Math.floor(width))
// Only split out a noSelect gutter in fullscreen mode — terminal native
// selection is used otherwise and noSelect is meaningless. Both branches
// are now O(1) Yoga leaves per diff on remount (2 vs 1), so this gate
// only saves cold-cache sliceAnsi work when fullscreen is off.
const splitGutter = isFullscreenEnvEnabled()
const cached =
skipHighlighting || syntaxHighlightingDisabled
? null
: renderColorDiff(
patch,
firstLine,
filePath,
fileContent ?? null,
theme,
safeWidth,
dim,
splitGutter,
)
if (!cached) {
let t3;
if ($[10] !== dim || $[11] !== patch || $[12] !== width) {
t3 = <Box><StructuredDiffFallback patch={patch} dim={dim} width={width} /></Box>;
$[10] = dim;
$[11] = patch;
$[12] = width;
$[13] = t3;
} else {
t3 = $[13];
}
return t3;
return (
<Box>
<StructuredDiffFallback patch={patch} dim={dim} width={width} />
</Box>
)
}
const {
lines,
gutterWidth,
gutters,
contents
} = cached;
const { lines, gutterWidth, gutters, contents } = cached
// Two-column layout: gutter (noSelect) + content. NoSelect marks the
// Box's computed bounds non-selectable; RawAnsi's measure func sets
// rawHeight=lines.length, so one tall leaf gets the same noSelect
// coverage N per-row Boxes would — without the per-row Yoga cost.
if (gutterWidth > 0 && gutters && contents) {
let t3;
if ($[14] !== gutterWidth || $[15] !== gutters) {
t3 = <NoSelect fromLeftEdge={true}><RawAnsi lines={gutters} width={gutterWidth} /></NoSelect>;
$[14] = gutterWidth;
$[15] = gutters;
$[16] = t3;
} else {
t3 = $[16];
}
const t4 = safeWidth - gutterWidth;
let t5;
if ($[17] !== contents || $[18] !== t4) {
t5 = <RawAnsi lines={contents} width={t4} />;
$[17] = contents;
$[18] = t4;
$[19] = t5;
} else {
t5 = $[19];
}
let t6;
if ($[20] !== t3 || $[21] !== t5) {
t6 = <Box flexDirection="row">{t3}{t5}</Box>;
$[20] = t3;
$[21] = t5;
$[22] = t6;
} else {
t6 = $[22];
}
return t6;
return (
<Box flexDirection="row">
<NoSelect fromLeftEdge>
<RawAnsi lines={gutters} width={gutterWidth} />
</NoSelect>
<RawAnsi lines={contents} width={safeWidth - gutterWidth} />
</Box>
)
}
let t3;
if ($[23] !== lines || $[24] !== safeWidth) {
t3 = <Box><RawAnsi lines={lines} width={safeWidth} /></Box>;
$[23] = lines;
$[24] = safeWidth;
$[25] = t3;
} else {
t3 = $[25];
}
return t3;
});
return (
<Box>
<RawAnsi lines={lines} width={safeWidth} />
</Box>
)
})