更新大量 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,104 +1,146 @@
import * as React from 'react';
import { MessageResponse } from '../../components/MessageResponse.js';
import { supportsHyperlinks } from '../../ink/supports-hyperlinks.js';
import { Link, Text } from '../../ink.js';
import { renderToolResultMessage as renderDefaultMCPToolResultMessage } from '../../tools/MCPTool/UI.js';
import type { MCPToolResult } from '../../utils/mcpValidation.js';
import { truncateToWidth } from '../format.js';
import { trackClaudeInChromeTabId } from './common.js';
export type { Tool } from '@modelcontextprotocol/sdk/types.js';
import * as React from 'react'
import { MessageResponse } from '../../components/MessageResponse.js'
import { supportsHyperlinks } from '../../ink/supports-hyperlinks.js'
import { Link, Text } from '../../ink.js'
import { renderToolResultMessage as renderDefaultMCPToolResultMessage } from '../../tools/MCPTool/UI.js'
import type { MCPToolResult } from '../../utils/mcpValidation.js'
import { truncateToWidth } from '../format.js'
import { trackClaudeInChromeTabId } from './common.js'
export type { Tool } from '@modelcontextprotocol/sdk/types.js'
/**
* All tool names from BROWSER_TOOLS in @ant/claude-for-chrome-mcp.
* Keep in sync with the package's BROWSER_TOOLS array.
*/
export type ChromeToolName = 'javascript_tool' | 'read_page' | 'find' | 'form_input' | 'computer' | 'navigate' | 'resize_window' | 'gif_creator' | 'upload_image' | 'get_page_text' | 'tabs_context_mcp' | 'tabs_create_mcp' | 'update_plan' | 'read_console_messages' | 'read_network_requests' | 'shortcuts_list' | 'shortcuts_execute';
const CHROME_EXTENSION_FOCUS_TAB_URL_BASE = 'https://clau.de/chrome/tab/';
function renderChromeToolUseMessage(input: Record<string, unknown>, toolName: ChromeToolName, verbose: boolean): React.ReactNode {
const tabId = input.tabId;
export type ChromeToolName =
| 'javascript_tool'
| 'read_page'
| 'find'
| 'form_input'
| 'computer'
| 'navigate'
| 'resize_window'
| 'gif_creator'
| 'upload_image'
| 'get_page_text'
| 'tabs_context_mcp'
| 'tabs_create_mcp'
| 'update_plan'
| 'read_console_messages'
| 'read_network_requests'
| 'shortcuts_list'
| 'shortcuts_execute'
const CHROME_EXTENSION_FOCUS_TAB_URL_BASE = 'https://clau.de/chrome/tab/'
function renderChromeToolUseMessage(
input: Record<string, unknown>,
toolName: ChromeToolName,
verbose: boolean,
): React.ReactNode {
const tabId = input.tabId
if (typeof tabId === 'number') {
trackClaudeInChromeTabId(tabId);
trackClaudeInChromeTabId(tabId)
}
// Build secondary info based on tool type and input
const secondaryInfo: string[] = [];
const secondaryInfo: string[] = []
switch (toolName) {
case 'navigate':
if (typeof input.url === 'string') {
try {
const url = new URL(input.url);
secondaryInfo.push(url.hostname);
const url = new URL(input.url)
secondaryInfo.push(url.hostname)
} catch {
secondaryInfo.push(truncateToWidth(input.url, 30));
secondaryInfo.push(truncateToWidth(input.url, 30))
}
}
break;
break
case 'find':
if (typeof input.query === 'string') {
secondaryInfo.push(`pattern: ${truncateToWidth(input.query, 30)}`);
secondaryInfo.push(`pattern: ${truncateToWidth(input.query, 30)}`)
}
break;
break
case 'computer':
if (typeof input.action === 'string') {
const action = input.action;
if (action === 'left_click' || action === 'right_click' || action === 'double_click' || action === 'middle_click') {
const action = input.action
if (
action === 'left_click' ||
action === 'right_click' ||
action === 'double_click' ||
action === 'middle_click'
) {
if (typeof input.ref === 'string') {
secondaryInfo.push(`${action} on ${input.ref}`);
secondaryInfo.push(`${action} on ${input.ref}`)
} else if (Array.isArray(input.coordinate)) {
secondaryInfo.push(`${action} at (${input.coordinate.join(', ')})`);
secondaryInfo.push(`${action} at (${input.coordinate.join(', ')})`)
} else {
secondaryInfo.push(action);
secondaryInfo.push(action)
}
} else if (action === 'type' && typeof input.text === 'string') {
secondaryInfo.push(`type "${truncateToWidth(input.text, 15)}"`);
secondaryInfo.push(`type "${truncateToWidth(input.text, 15)}"`)
} else if (action === 'key' && typeof input.text === 'string') {
secondaryInfo.push(`key ${input.text}`);
} else if (action === 'scroll' && typeof input.scroll_direction === 'string') {
secondaryInfo.push(`scroll ${input.scroll_direction}`);
secondaryInfo.push(`key ${input.text}`)
} else if (
action === 'scroll' &&
typeof input.scroll_direction === 'string'
) {
secondaryInfo.push(`scroll ${input.scroll_direction}`)
} else if (action === 'wait' && typeof input.duration === 'number') {
secondaryInfo.push(`wait ${input.duration}s`);
secondaryInfo.push(`wait ${input.duration}s`)
} else if (action === 'left_click_drag') {
secondaryInfo.push('drag');
secondaryInfo.push('drag')
} else {
secondaryInfo.push(action);
secondaryInfo.push(action)
}
}
break;
break
case 'gif_creator':
if (typeof input.action === 'string') {
secondaryInfo.push(`${input.action}`);
secondaryInfo.push(`${input.action}`)
}
break;
break
case 'resize_window':
if (typeof input.width === 'number' && typeof input.height === 'number') {
secondaryInfo.push(`${input.width}x${input.height}`);
secondaryInfo.push(`${input.width}x${input.height}`)
}
break;
break
case 'read_console_messages':
if (typeof input.pattern === 'string') {
secondaryInfo.push(`pattern: ${truncateToWidth(input.pattern, 20)}`);
secondaryInfo.push(`pattern: ${truncateToWidth(input.pattern, 20)}`)
}
if (input.onlyErrors === true) {
secondaryInfo.push('errors only');
secondaryInfo.push('errors only')
}
break;
break
case 'read_network_requests':
if (typeof input.urlPattern === 'string') {
secondaryInfo.push(`pattern: ${truncateToWidth(input.urlPattern, 20)}`);
secondaryInfo.push(`pattern: ${truncateToWidth(input.urlPattern, 20)}`)
}
break;
break
case 'shortcuts_execute':
if (typeof input.shortcutId === 'string') {
secondaryInfo.push(`shortcut_id: ${input.shortcutId}`);
secondaryInfo.push(`shortcut_id: ${input.shortcutId}`)
}
break;
break
case 'javascript_tool':
// In verbose mode, show the full code
if (verbose && typeof input.text === 'string') {
return input.text;
return input.text
}
// In non-verbose mode, return empty string to preserve View Tab layout
return '';
return ''
case 'tabs_create_mcp':
case 'tabs_context_mcp':
case 'form_input':
@@ -109,9 +151,10 @@ function renderChromeToolUseMessage(input: Record<string, unknown>, toolName: Ch
case 'update_plan':
// These tools don't have meaningful secondary info to show inline.
// Return empty string (not null) to ensure tool header still renders.
return '';
return ''
}
return secondaryInfo.join(', ') || null;
return secondaryInfo.join(', ') || null
}
/**
@@ -123,22 +166,29 @@ function renderChromeToolUseMessage(input: Record<string, unknown>, toolName: Ch
*/
function renderChromeViewTabLink(input: unknown): React.ReactNode {
if (!supportsHyperlinks()) {
return null;
return null
}
if (typeof input !== 'object' || input === null || !('tabId' in input)) {
return null;
return null
}
const tabId = typeof input.tabId === 'number' ? input.tabId : typeof input.tabId === 'string' ? parseInt(input.tabId, 10) : NaN;
const tabId =
typeof input.tabId === 'number'
? input.tabId
: typeof input.tabId === 'string'
? parseInt(input.tabId, 10)
: NaN
if (isNaN(tabId)) {
return null;
return null
}
const linkUrl = `${CHROME_EXTENSION_FOCUS_TAB_URL_BASE}${tabId}`;
return <Text>
const linkUrl = `${CHROME_EXTENSION_FOCUS_TAB_URL_BASE}${tabId}`
return (
<Text>
{' '}
<Link url={linkUrl}>
<Text color="subtle">[View Tab]</Text>
</Link>
</Text>;
</Text>
)
}
/**
@@ -146,72 +196,79 @@ function renderChromeViewTabLink(input: unknown): React.ReactNode {
* Shows a brief summary for successful results. Errors are handled by
* the default renderToolUseErrorMessage when is_error is set.
*/
export function renderChromeToolResultMessage(output: MCPToolResult, toolName: ChromeToolName, verbose: boolean): React.ReactNode {
export function renderChromeToolResultMessage(
output: MCPToolResult,
toolName: ChromeToolName,
verbose: boolean,
): React.ReactNode {
if (verbose) {
return renderDefaultMCPToolResultMessage(output, [], {
verbose
});
return renderDefaultMCPToolResultMessage(output, [], { verbose })
}
let summary: string | null = null;
let summary: string | null = null
switch (toolName) {
case 'navigate':
summary = 'Navigation completed';
break;
summary = 'Navigation completed'
break
case 'tabs_create_mcp':
summary = 'Tab created';
break;
summary = 'Tab created'
break
case 'tabs_context_mcp':
summary = 'Tabs read';
break;
summary = 'Tabs read'
break
case 'form_input':
summary = 'Input completed';
break;
summary = 'Input completed'
break
case 'computer':
summary = 'Action completed';
break;
summary = 'Action completed'
break
case 'resize_window':
summary = 'Window resized';
break;
summary = 'Window resized'
break
case 'find':
summary = 'Search completed';
break;
summary = 'Search completed'
break
case 'gif_creator':
summary = 'GIF action completed';
break;
summary = 'GIF action completed'
break
case 'read_console_messages':
summary = 'Console messages retrieved';
break;
summary = 'Console messages retrieved'
break
case 'read_network_requests':
summary = 'Network requests retrieved';
break;
summary = 'Network requests retrieved'
break
case 'shortcuts_list':
summary = 'Shortcuts retrieved';
break;
summary = 'Shortcuts retrieved'
break
case 'shortcuts_execute':
summary = 'Shortcut executed';
break;
summary = 'Shortcut executed'
break
case 'javascript_tool':
summary = 'Script executed';
break;
summary = 'Script executed'
break
case 'read_page':
summary = 'Page read';
break;
summary = 'Page read'
break
case 'upload_image':
summary = 'Image uploaded';
break;
summary = 'Image uploaded'
break
case 'get_page_text':
summary = 'Page text retrieved';
break;
summary = 'Page text retrieved'
break
case 'update_plan':
summary = 'Plan updated';
break;
summary = 'Plan updated'
break
}
if (summary) {
return <MessageResponse height={1}>
return (
<MessageResponse height={1}>
<Text dimColor>{summary}</Text>
</MessageResponse>;
</MessageResponse>
)
}
return null;
return null
}
/**
@@ -219,43 +276,56 @@ export function renderChromeToolResultMessage(output: MCPToolResult, toolName: C
* rendering for chrome tools in a single spread operation.
*/
export function getClaudeInChromeMCPToolOverrides(toolName: string): {
userFacingName: (input?: Record<string, unknown>) => string;
renderToolUseMessage: (input: Record<string, unknown>, options: {
verbose: boolean;
}) => React.ReactNode;
renderToolUseTag: (input: Partial<Record<string, unknown>>) => React.ReactNode;
renderToolResultMessage: (output: string | MCPToolResult, progressMessagesForMessage: unknown[], options: {
verbose: boolean;
}) => React.ReactNode;
userFacingName: (input?: Record<string, unknown>) => string
renderToolUseMessage: (
input: Record<string, unknown>,
options: { verbose: boolean },
) => React.ReactNode
renderToolUseTag: (input: Partial<Record<string, unknown>>) => React.ReactNode
renderToolResultMessage: (
output: string | MCPToolResult,
progressMessagesForMessage: unknown[],
options: { verbose: boolean },
) => React.ReactNode
} {
return {
userFacingName(_input?: Record<string, unknown>) {
// Trim the _mcp postfix that show up in some of the tool names
const displayName = toolName.replace(/_mcp$/, '');
return `Claude in Chrome[${displayName}]`;
const displayName = toolName.replace(/_mcp$/, '')
return `Claude in Chrome[${displayName}]`
},
renderToolUseMessage(input: Record<string, unknown>, {
verbose
}: {
verbose: boolean;
}): React.ReactNode {
return renderChromeToolUseMessage(input, toolName as ChromeToolName, verbose);
renderToolUseMessage(
input: Record<string, unknown>,
{ verbose }: { verbose: boolean },
): React.ReactNode {
return renderChromeToolUseMessage(
input,
toolName as ChromeToolName,
verbose,
)
},
renderToolUseTag(input: Partial<Record<string, unknown>>): React.ReactNode {
return renderChromeViewTabLink(input);
return renderChromeViewTabLink(input)
},
renderToolResultMessage(output: string | MCPToolResult, _progressMessagesForMessage: unknown[], {
verbose
}: {
verbose: boolean;
}): React.ReactNode {
renderToolResultMessage(
output: string | MCPToolResult,
_progressMessagesForMessage: unknown[],
{ verbose }: { verbose: boolean },
): React.ReactNode {
if (!isMCPToolResult(output)) {
return null;
return null
}
return renderChromeToolResultMessage(output, toolName as ChromeToolName, verbose);
}
};
return renderChromeToolResultMessage(
output,
toolName as ChromeToolName,
verbose,
)
},
}
}
function isMCPToolResult(output: string | MCPToolResult): output is MCPToolResult {
return typeof output === 'object' && output !== null;
function isMCPToolResult(
output: string | MCPToolResult,
): output is MCPToolResult {
return typeof output === 'object' && output !== null
}