更新大量 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,289 +1,230 @@
import { c as _c } from "react/compiler-runtime";
import { homedir } from 'os';
import React from 'react';
import { logEvent } from 'src/services/analytics/index.js';
import { setSessionTrustAccepted } from '../../bootstrap/state.js';
import type { Command } from '../../commands.js';
import { useExitOnCtrlCDWithKeybindings } from '../../hooks/useExitOnCtrlCDWithKeybindings.js';
import { Box, Link, Text } from '../../ink.js';
import { useKeybinding } from '../../keybindings/useKeybinding.js';
import { getMcpConfigsByScope } from '../../services/mcp/config.js';
import { BASH_TOOL_NAME } from '../../tools/BashTool/toolName.js';
import { checkHasTrustDialogAccepted, saveCurrentProjectConfig } from '../../utils/config.js';
import { getCwd } from '../../utils/cwd.js';
import { getFsImplementation } from '../../utils/fsOperations.js';
import { gracefulShutdownSync } from '../../utils/gracefulShutdown.js';
import { Select } from '../CustomSelect/index.js';
import { PermissionDialog } from '../permissions/PermissionDialog.js';
import { getApiKeyHelperSources, getAwsCommandsSources, getBashPermissionSources, getDangerousEnvVarsSources, getGcpCommandsSources, getHooksSources, getOtelHeadersHelperSources } from './utils.js';
import { homedir } from 'os'
import React from 'react'
import { logEvent } from 'src/services/analytics/index.js'
import { setSessionTrustAccepted } from '../../bootstrap/state.js'
import type { Command } from '../../commands.js'
import { useExitOnCtrlCDWithKeybindings } from '../../hooks/useExitOnCtrlCDWithKeybindings.js'
import { Box, Link, Text } from '../../ink.js'
import { useKeybinding } from '../../keybindings/useKeybinding.js'
import { getMcpConfigsByScope } from '../../services/mcp/config.js'
import { BASH_TOOL_NAME } from '../../tools/BashTool/toolName.js'
import {
checkHasTrustDialogAccepted,
saveCurrentProjectConfig,
} from '../../utils/config.js'
import { getCwd } from '../../utils/cwd.js'
import { getFsImplementation } from '../../utils/fsOperations.js'
import { gracefulShutdownSync } from '../../utils/gracefulShutdown.js'
import { Select } from '../CustomSelect/index.js'
import { PermissionDialog } from '../permissions/PermissionDialog.js'
import {
getApiKeyHelperSources,
getAwsCommandsSources,
getBashPermissionSources,
getDangerousEnvVarsSources,
getGcpCommandsSources,
getHooksSources,
getOtelHeadersHelperSources,
} from './utils.js'
type Props = {
onDone(): void;
commands?: Command[];
};
export function TrustDialog(t0) {
const $ = _c(33);
const {
onDone,
commands
} = t0;
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t1 = getMcpConfigsByScope("project");
$[0] = t1;
} else {
t1 = $[0];
onDone(): void
commands?: Command[]
}
export function TrustDialog({ onDone, commands }: Props): React.ReactNode {
const { servers: projectServers } = getMcpConfigsByScope('project')
// In all cases, we generally check only the project-level and
// project-local-level settings, which we assume that users do not configure
// directly compared to user-level settings.
// Check for MCPs
const hasMcpServers = Object.keys(projectServers).length > 0
// Check for hooks
const hooksSettingSources = getHooksSources()
const hasHooks = hooksSettingSources.length > 0
// Check whether code execution is allowed in permissions and slash commands
const bashSettingSources = getBashPermissionSources()
// Check for apiKeyHelper which executes arbitrary commands
const apiKeyHelperSources = getApiKeyHelperSources()
const hasApiKeyHelper = apiKeyHelperSources.length > 0
// Check for AWS commands which execute arbitrary commands
const awsCommandsSources = getAwsCommandsSources()
const hasAwsCommands = awsCommandsSources.length > 0
// Check for GCP commands which execute arbitrary commands
const gcpCommandsSources = getGcpCommandsSources()
const hasGcpCommands = gcpCommandsSources.length > 0
// Check for otelHeadersHelper which executes arbitrary commands
const otelHeadersHelperSources = getOtelHeadersHelperSources()
const hasOtelHeadersHelper = otelHeadersHelperSources.length > 0
// Check for dangerous environment variables (not in SAFE_ENV_VARS)
const dangerousEnvVarsSources = getDangerousEnvVarsSources()
const hasDangerousEnvVars = dangerousEnvVarsSources.length > 0
const hasSlashCommandBash =
commands?.some(
command =>
command.type === 'prompt' &&
command.loadedFrom === 'commands_DEPRECATED' &&
(command.source === 'projectSettings' ||
command.source === 'localSettings') &&
command.allowedTools?.some(
(tool: string) =>
tool === BASH_TOOL_NAME || tool.startsWith(BASH_TOOL_NAME + '('),
),
) ?? false
const hasSkillsBash =
commands?.some(
command =>
command.type === 'prompt' &&
(command.loadedFrom === 'skills' || command.loadedFrom === 'plugin') &&
(command.source === 'projectSettings' ||
command.source === 'localSettings' ||
command.source === 'plugin') &&
command.allowedTools?.some(
(tool: string) =>
tool === BASH_TOOL_NAME || tool.startsWith(BASH_TOOL_NAME + '('),
),
) ?? false
const hasAnyBashExecution =
bashSettingSources.length > 0 || hasSlashCommandBash || hasSkillsBash
const hasTrustDialogAccepted = checkHasTrustDialogAccepted()
React.useEffect(() => {
const isHomeDir = homedir() === getCwd()
logEvent('tengu_trust_dialog_shown', {
isHomeDir,
hasMcpServers,
hasHooks,
hasBashExecution: hasAnyBashExecution,
hasApiKeyHelper,
hasAwsCommands,
hasGcpCommands,
hasOtelHeadersHelper,
hasDangerousEnvVars,
})
}, [
hasMcpServers,
hasHooks,
hasAnyBashExecution,
hasApiKeyHelper,
hasAwsCommands,
hasGcpCommands,
hasOtelHeadersHelper,
hasDangerousEnvVars,
])
function onChange(value: 'enable_all' | 'exit') {
if (value === 'exit') {
gracefulShutdownSync(1)
return
}
const isHomeDir = homedir() === getCwd()
logEvent('tengu_trust_dialog_accept', {
isHomeDir,
hasMcpServers,
hasHooks,
hasBashExecution: hasAnyBashExecution,
hasApiKeyHelper,
hasAwsCommands,
hasGcpCommands,
hasOtelHeadersHelper,
hasDangerousEnvVars,
})
if (isHomeDir) {
// For home directory, store trust in session memory only (not persisted to disk)
// This allows hooks and other trust-requiring features to work during this session
// while preserving the security intent of not permanently trusting home dir
setSessionTrustAccepted(true)
} else {
saveCurrentProjectConfig(current => ({
...current,
hasTrustDialogAccepted: true,
}))
}
// Do NOT write MCP server settings here. handleMcpjsonServerApprovals in
// interactiveHelpers.tsx runs right after this dialog and shows the per-server approval
// UI. Writing enabledMcpjsonServers/enableAllProjectMcpServers here would
// mark every server 'approved' and silently skip that dialog. See #15558.
onDone()
}
const {
servers: projectServers
} = t1;
let t2;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t2 = Object.keys(projectServers);
$[1] = t2;
} else {
t2 = $[1];
}
const hasMcpServers = t2.length > 0;
let t3;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t3 = getHooksSources();
$[2] = t3;
} else {
t3 = $[2];
}
const hooksSettingSources = t3;
const hasHooks = hooksSettingSources.length > 0;
let t4;
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
t4 = getBashPermissionSources();
$[3] = t4;
} else {
t4 = $[3];
}
const bashSettingSources = t4;
let t5;
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
t5 = getApiKeyHelperSources();
$[4] = t5;
} else {
t5 = $[4];
}
const apiKeyHelperSources = t5;
const hasApiKeyHelper = apiKeyHelperSources.length > 0;
let t6;
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
t6 = getAwsCommandsSources();
$[5] = t6;
} else {
t6 = $[5];
}
const awsCommandsSources = t6;
const hasAwsCommands = awsCommandsSources.length > 0;
let t7;
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
t7 = getGcpCommandsSources();
$[6] = t7;
} else {
t7 = $[6];
}
const gcpCommandsSources = t7;
const hasGcpCommands = gcpCommandsSources.length > 0;
let t8;
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
t8 = getOtelHeadersHelperSources();
$[7] = t8;
} else {
t8 = $[7];
}
const otelHeadersHelperSources = t8;
const hasOtelHeadersHelper = otelHeadersHelperSources.length > 0;
let t9;
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
t9 = getDangerousEnvVarsSources();
$[8] = t9;
} else {
t9 = $[8];
}
const dangerousEnvVarsSources = t9;
const hasDangerousEnvVars = dangerousEnvVarsSources.length > 0;
let t10;
if ($[9] !== commands) {
t10 = commands?.some(_temp2) ?? false;
$[9] = commands;
$[10] = t10;
} else {
t10 = $[10];
}
const hasSlashCommandBash = t10;
let t11;
if ($[11] !== commands) {
t11 = commands?.some(_temp4) ?? false;
$[11] = commands;
$[12] = t11;
} else {
t11 = $[12];
}
const hasSkillsBash = t11;
const hasAnyBashExecution = bashSettingSources.length > 0 || hasSlashCommandBash || hasSkillsBash;
const hasTrustDialogAccepted = checkHasTrustDialogAccepted();
let t12;
let t13;
if ($[13] !== hasAnyBashExecution) {
t12 = () => {
const isHomeDir = homedir() === getCwd();
logEvent("tengu_trust_dialog_shown", {
isHomeDir,
hasMcpServers,
hasHooks,
hasBashExecution: hasAnyBashExecution,
hasApiKeyHelper,
hasAwsCommands,
hasGcpCommands,
hasOtelHeadersHelper,
hasDangerousEnvVars
});
};
t13 = [hasMcpServers, hasHooks, hasAnyBashExecution, hasApiKeyHelper, hasAwsCommands, hasGcpCommands, hasOtelHeadersHelper, hasDangerousEnvVars];
$[13] = hasAnyBashExecution;
$[14] = t12;
$[15] = t13;
} else {
t12 = $[14];
t13 = $[15];
}
React.useEffect(t12, t13);
let t14;
if ($[16] !== hasAnyBashExecution || $[17] !== onDone) {
t14 = function onChange(value) {
if (value === "exit") {
gracefulShutdownSync(1);
return;
}
const isHomeDir_0 = homedir() === getCwd();
logEvent("tengu_trust_dialog_accept", {
isHomeDir: isHomeDir_0,
hasMcpServers,
hasHooks,
hasBashExecution: hasAnyBashExecution,
hasApiKeyHelper,
hasAwsCommands,
hasGcpCommands,
hasOtelHeadersHelper,
hasDangerousEnvVars
});
if (isHomeDir_0) {
setSessionTrustAccepted(true);
} else {
saveCurrentProjectConfig(_temp5);
}
onDone();
};
$[16] = hasAnyBashExecution;
$[17] = onDone;
$[18] = t14;
} else {
t14 = $[18];
}
const onChange = t14;
const exitState = useExitOnCtrlCDWithKeybindings(_temp6);
let t15;
if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
t15 = {
context: "Confirmation"
};
$[19] = t15;
} else {
t15 = $[19];
}
useKeybinding("confirm:no", _temp7, t15);
// Default onExit is useApp().exit() → Ink.unmount(), which tears down the
// React tree but never calls onDone(). showSetupScreens() in
// interactiveHelpers.tsx awaits a Promise that only resolves via onDone,
// so the default would hang the await forever. With keybinding
// customization enabled, the chokidar watcher (persistent: true) keeps the
// event loop alive and the process freezes. Explicitly exit 1 like "No".
const exitState = useExitOnCtrlCDWithKeybindings(() =>
gracefulShutdownSync(1),
)
// Use configurable keybinding for ESC to cancel/exit
useKeybinding(
'confirm:no',
() => {
gracefulShutdownSync(0)
},
{ context: 'Confirmation' },
)
// Automatically resolve the trust dialog if there is nothing to be shown.
if (hasTrustDialogAccepted) {
setTimeout(onDone);
return null;
setTimeout(onDone)
return null
}
let t16;
let t17;
let t18;
if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
t16 = <Text bold={true}>{getFsImplementation().cwd()}</Text>;
t17 = <Text>Quick safety check: Is this a project you created or one you trust? (Like your own code, a well-known open source project, or work from your team). If not, take a moment to review what{"'"}s in this folder first.</Text>;
t18 = <Text>Claude Code{"'"}ll be able to read, edit, and execute files here.</Text>;
$[20] = t16;
$[21] = t17;
$[22] = t18;
} else {
t16 = $[20];
t17 = $[21];
t18 = $[22];
}
let t19;
if ($[23] === Symbol.for("react.memo_cache_sentinel")) {
t19 = <Text dimColor={true}><Link url="https://code.claude.com/docs/en/security">Security guide</Link></Text>;
$[23] = t19;
} else {
t19 = $[23];
}
let t20;
if ($[24] === Symbol.for("react.memo_cache_sentinel")) {
t20 = [{
label: "Yes, I trust this folder",
value: "enable_all"
}, {
label: "No, exit",
value: "exit"
}];
$[24] = t20;
} else {
t20 = $[24];
}
let t21;
if ($[25] !== onChange) {
t21 = <Select options={t20} onChange={value_0 => onChange(value_0 as 'enable_all' | 'exit')} onCancel={() => onChange("exit")} />;
$[25] = onChange;
$[26] = t21;
} else {
t21 = $[26];
}
let t22;
if ($[27] !== exitState.keyName || $[28] !== exitState.pending) {
t22 = <Text dimColor={true}>{exitState.pending ? <>Press {exitState.keyName} again to exit</> : <>Enter to confirm · Esc to cancel</>}</Text>;
$[27] = exitState.keyName;
$[28] = exitState.pending;
$[29] = t22;
} else {
t22 = $[29];
}
let t23;
if ($[30] !== t21 || $[31] !== t22) {
t23 = <PermissionDialog color="warning" titleColor="warning" title="Accessing workspace:"><Box flexDirection="column" gap={1} paddingTop={1}>{t16}{t17}{t18}{t19}{t21}{t22}</Box></PermissionDialog>;
$[30] = t21;
$[31] = t22;
$[32] = t23;
} else {
t23 = $[32];
}
return t23;
}
function _temp7() {
gracefulShutdownSync(0);
}
function _temp6() {
return gracefulShutdownSync(1);
}
function _temp5(current) {
return {
...current,
hasTrustDialogAccepted: true
};
}
function _temp4(command_0) {
return command_0.type === "prompt" && (command_0.loadedFrom === "skills" || command_0.loadedFrom === "plugin") && (command_0.source === "projectSettings" || command_0.source === "localSettings" || command_0.source === "plugin") && command_0.allowedTools?.some(_temp3);
}
function _temp3(tool_0) {
return tool_0 === BASH_TOOL_NAME || tool_0.startsWith(BASH_TOOL_NAME + "(");
}
function _temp2(command) {
return command.type === "prompt" && command.loadedFrom === "commands_DEPRECATED" && (command.source === "projectSettings" || command.source === "localSettings") && command.allowedTools?.some(_temp);
}
function _temp(tool) {
return tool === BASH_TOOL_NAME || tool.startsWith(BASH_TOOL_NAME + "(");
return (
<PermissionDialog
color="warning"
titleColor="warning"
title="Accessing workspace:"
>
<Box flexDirection="column" gap={1} paddingTop={1}>
<Text bold>{getFsImplementation().cwd()}</Text>
<Text>
Quick safety check: Is this a project you created or one you trust?
(Like your own code, a well-known open source project, or work from
your team). If not, take a moment to review what{"'"}s in this folder
first.
</Text>
<Text>
Claude Code{"'"}ll be able to read, edit, and execute files here.
</Text>
<Text dimColor>
<Link url="https://code.claude.com/docs/en/security">
Security guide
</Link>
</Text>
<Select
options={[
{ label: 'Yes, I trust this folder', value: 'enable_all' },
{ label: 'No, exit', value: 'exit' },
]}
onChange={value => onChange(value as 'enable_all' | 'exit')}
onCancel={() => onChange('exit')}
/>
<Text dimColor>
{exitState.pending ? (
<>Press {exitState.keyName} again to exit</>
) : (
<>Enter to confirm · Esc to cancel</>
)}
</Text>
</Box>
</PermissionDialog>
)
}