更新大量 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,69 +1,97 @@
import type { ContentBlockParam } from '@anthropic-ai/sdk/resources';
import { randomUUID } from 'crypto';
import * as React from 'react';
import { BashModeProgress } from 'src/components/BashModeProgress.js';
import type { SetToolJSXFn } from 'src/Tool.js';
import { BashTool } from 'src/tools/BashTool/BashTool.js';
import type { AttachmentMessage, SystemMessage, UserMessage } from 'src/types/message.js';
import type { ShellProgress } from 'src/types/tools.js';
import { logEvent } from '../../services/analytics/index.js';
import { errorMessage, ShellError } from '../errors.js';
import { createSyntheticUserCaveatMessage, createUserInterruptionMessage, createUserMessage, prepareUserContent } from '../messages.js';
import { resolveDefaultShell } from '../shell/resolveDefaultShell.js';
import { isPowerShellToolEnabled } from '../shell/shellToolUtils.js';
import { processToolResultBlock } from '../toolResultStorage.js';
import { escapeXml } from '../xml.js';
import type { ProcessUserInputContext } from './processUserInput.js';
export async function processBashCommand(inputString: string, precedingInputBlocks: ContentBlockParam[], attachmentMessages: AttachmentMessage[], context: ProcessUserInputContext, setToolJSX: SetToolJSXFn): Promise<{
messages: (UserMessage | AttachmentMessage | SystemMessage)[];
shouldQuery: boolean;
import type { ContentBlockParam } from '@anthropic-ai/sdk/resources'
import { randomUUID } from 'crypto'
import * as React from 'react'
import { BashModeProgress } from 'src/components/BashModeProgress.js'
import type { SetToolJSXFn } from 'src/Tool.js'
import { BashTool } from 'src/tools/BashTool/BashTool.js'
import type {
AttachmentMessage,
SystemMessage,
UserMessage,
} from 'src/types/message.js'
import type { ShellProgress } from 'src/types/tools.js'
import { logEvent } from '../../services/analytics/index.js'
import { errorMessage, ShellError } from '../errors.js'
import {
createSyntheticUserCaveatMessage,
createUserInterruptionMessage,
createUserMessage,
prepareUserContent,
} from '../messages.js'
import { resolveDefaultShell } from '../shell/resolveDefaultShell.js'
import { isPowerShellToolEnabled } from '../shell/shellToolUtils.js'
import { processToolResultBlock } from '../toolResultStorage.js'
import { escapeXml } from '../xml.js'
import type { ProcessUserInputContext } from './processUserInput.js'
export async function processBashCommand(
inputString: string,
precedingInputBlocks: ContentBlockParam[],
attachmentMessages: AttachmentMessage[],
context: ProcessUserInputContext,
setToolJSX: SetToolJSXFn,
): Promise<{
messages: (UserMessage | AttachmentMessage | SystemMessage)[]
shouldQuery: boolean
}> {
// Shell routing (docs/design/ps-shell-selection.md §5.2): consult
// defaultShell, fall back to bash. isPowerShellToolEnabled() applies the
// same platform + env-var gate as tools.ts so input-box routing matches
// tool-list visibility. Computed up front so telemetry records the
// actual shell, not the raw setting.
const usePowerShell = isPowerShellToolEnabled() && resolveDefaultShell() === 'powershell';
logEvent('tengu_input_bash', {
powershell: usePowerShell
});
const usePowerShell =
isPowerShellToolEnabled() && resolveDefaultShell() === 'powershell'
logEvent('tengu_input_bash', { powershell: usePowerShell })
const userMessage = createUserMessage({
content: prepareUserContent({
inputString: `<bash-input>${inputString}</bash-input>`,
precedingInputBlocks
})
});
precedingInputBlocks,
}),
})
// ctrl+b to background indicator
let jsx: React.ReactNode;
let jsx: React.ReactNode
// Just show initial UI
setToolJSX({
jsx: <BashModeProgress input={inputString} progress={null} verbose={context.options.verbose} />,
shouldHidePromptInput: false
});
jsx: (
<BashModeProgress
input={inputString}
progress={null}
verbose={context.options.verbose}
/>
),
shouldHidePromptInput: false,
})
try {
const bashModeContext: ProcessUserInputContext = {
...context,
// TODO: Clean up this hack
setToolJSX: _ => {
jsx = _?.jsx;
}
};
jsx = _?.jsx
},
}
// Progress UI — shared across both shell backends (both emit ShellProgress)
const onProgress = (progress: {
data: ShellProgress;
}) => {
const onProgress = (progress: { data: ShellProgress }) => {
setToolJSX({
jsx: <>
<BashModeProgress input={inputString!} progress={progress.data} verbose={context.options.verbose} />
jsx: (
<>
<BashModeProgress
input={inputString!}
progress={progress.data}
verbose={context.options.verbose}
/>
{jsx}
</>,
</>
),
shouldHidePromptInput: false,
showSpinner: false
});
};
showSpinner: false,
})
}
// User-initiated `!` commands run outside sandbox. Both shell tools honor
// dangerouslyDisableSandbox (checked against areUnsandboxedCommandsAllowed()
@@ -71,69 +99,107 @@ export async function processBashCommand(inputString: string, precedingInputBloc
// native, shouldUseSandbox() returns false regardless (unsupported platform).
// Lazy-require PowerShellTool so its ~300KB chunk only loads when the
// user has actually selected the powershell default shell.
type PSMod = typeof import('src/tools/PowerShellTool/PowerShellTool.js');
let PowerShellTool: PSMod['PowerShellTool'] | null = null;
type PSMod = typeof import('src/tools/PowerShellTool/PowerShellTool.js')
let PowerShellTool: PSMod['PowerShellTool'] | null = null
if (usePowerShell) {
/* eslint-disable @typescript-eslint/no-require-imports */
PowerShellTool = (require('src/tools/PowerShellTool/PowerShellTool.js') as PSMod).PowerShellTool;
PowerShellTool = (
require('src/tools/PowerShellTool/PowerShellTool.js') as PSMod
).PowerShellTool
/* eslint-enable @typescript-eslint/no-require-imports */
}
const shellTool = PowerShellTool ?? BashTool;
const response = PowerShellTool ? await PowerShellTool.call({
command: inputString,
dangerouslyDisableSandbox: true
}, bashModeContext, undefined, undefined, onProgress) : await BashTool.call({
command: inputString,
dangerouslyDisableSandbox: true
}, bashModeContext, undefined, undefined, onProgress);
const data = response.data;
const shellTool = PowerShellTool ?? BashTool
const response = PowerShellTool
? await PowerShellTool.call(
{ command: inputString, dangerouslyDisableSandbox: true },
bashModeContext,
undefined,
undefined,
onProgress,
)
: await BashTool.call(
{
command: inputString,
dangerouslyDisableSandbox: true,
},
bashModeContext,
undefined,
undefined,
onProgress,
)
const data = response.data
if (!data) {
throw new Error('No result received from shell command');
throw new Error('No result received from shell command')
}
const stderr = data.stderr;
const stderr = data.stderr
// Reuse the same formatting pipeline as inline !`cmd` bash (promptShellExecution)
// and model-initiated Bash. When BashTool.call() persists large output to disk,
// data.persistedOutputPath is set and the formatter wraps in <persisted-output>.
// Pass stderr:'' to keep it separate for the <bash-stderr> UI tag.
const mapped = await processToolResultBlock(shellTool, {
...data,
stderr: ''
}, randomUUID());
const mapped = await processToolResultBlock(
shellTool,
{ ...data, stderr: '' },
randomUUID(),
)
// mapped.content may contain our own <persisted-output> wrapper (trusted
// XML from buildLargeToolResultMessage). Escaping it would turn structural
// tags into &lt;persisted-output&gt;, breaking the model's parse and
// UserBashOutputMessage's extractTag. Escape the raw fallback only.
const stdout = typeof mapped.content === 'string' ? mapped.content : escapeXml(data.stdout);
const stdout =
typeof mapped.content === 'string'
? mapped.content
: escapeXml(data.stdout)
return {
messages: [createSyntheticUserCaveatMessage(), userMessage, ...attachmentMessages, createUserMessage({
content: `<bash-stdout>${stdout}</bash-stdout><bash-stderr>${escapeXml(stderr)}</bash-stderr>`
})],
shouldQuery: false
};
messages: [
createSyntheticUserCaveatMessage(),
userMessage,
...attachmentMessages,
createUserMessage({
content: `<bash-stdout>${stdout}</bash-stdout><bash-stderr>${escapeXml(stderr)}</bash-stderr>`,
}),
],
shouldQuery: false,
}
} catch (e) {
if (e instanceof ShellError) {
if (e.interrupted) {
return {
messages: [createSyntheticUserCaveatMessage(), userMessage, createUserInterruptionMessage({
toolUse: false
}), ...attachmentMessages],
shouldQuery: false
};
messages: [
createSyntheticUserCaveatMessage(),
userMessage,
createUserInterruptionMessage({ toolUse: false }),
...attachmentMessages,
],
shouldQuery: false,
}
}
return {
messages: [createSyntheticUserCaveatMessage(), userMessage, ...attachmentMessages, createUserMessage({
content: `<bash-stdout>${escapeXml(e.stdout)}</bash-stdout><bash-stderr>${escapeXml(e.stderr)}</bash-stderr>`
})],
shouldQuery: false
};
messages: [
createSyntheticUserCaveatMessage(),
userMessage,
...attachmentMessages,
createUserMessage({
content: `<bash-stdout>${escapeXml(e.stdout)}</bash-stdout><bash-stderr>${escapeXml(e.stderr)}</bash-stderr>`,
}),
],
shouldQuery: false,
}
}
return {
messages: [createSyntheticUserCaveatMessage(), userMessage, ...attachmentMessages, createUserMessage({
content: `<bash-stderr>Command failed: ${escapeXml(errorMessage(e))}</bash-stderr>`
})],
shouldQuery: false
};
messages: [
createSyntheticUserCaveatMessage(),
userMessage,
...attachmentMessages,
createUserMessage({
content: `<bash-stderr>Command failed: ${escapeXml(errorMessage(e))}</bash-stderr>`,
}),
],
shouldQuery: false,
}
} finally {
setToolJSX(null);
setToolJSX(null)
}
}

File diff suppressed because it is too large Load Diff