mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-21 15:55:50 +00:00
更新大量 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:
@@ -1,31 +1,39 @@
|
||||
import * as React from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from 'src/services/analytics/index.js';
|
||||
import { ConfigurableShortcutHint } from '../../components/ConfigurableShortcutHint.js';
|
||||
import { Byline } from '../../components/design-system/Byline.js';
|
||||
import { KeyboardShortcutHint } from '../../components/design-system/KeyboardShortcutHint.js';
|
||||
import { Spinner } from '../../components/Spinner.js';
|
||||
import TextInput from '../../components/TextInput.js';
|
||||
import { Box, Text } from '../../ink.js';
|
||||
import { toError } from '../../utils/errors.js';
|
||||
import { logError } from '../../utils/log.js';
|
||||
import { clearAllCaches } from '../../utils/plugins/cacheUtils.js';
|
||||
import { addMarketplaceSource, saveMarketplaceToSettings } from '../../utils/plugins/marketplaceManager.js';
|
||||
import { parseMarketplaceInput } from '../../utils/plugins/parseMarketplaceInput.js';
|
||||
import type { ViewState } from './types.js';
|
||||
import * as React from 'react'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import {
|
||||
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
logEvent,
|
||||
} from 'src/services/analytics/index.js'
|
||||
import { ConfigurableShortcutHint } from '../../components/ConfigurableShortcutHint.js'
|
||||
import { Byline } from '../../components/design-system/Byline.js'
|
||||
import { KeyboardShortcutHint } from '../../components/design-system/KeyboardShortcutHint.js'
|
||||
import { Spinner } from '../../components/Spinner.js'
|
||||
import TextInput from '../../components/TextInput.js'
|
||||
import { Box, Text } from '../../ink.js'
|
||||
import { toError } from '../../utils/errors.js'
|
||||
import { logError } from '../../utils/log.js'
|
||||
import { clearAllCaches } from '../../utils/plugins/cacheUtils.js'
|
||||
import {
|
||||
addMarketplaceSource,
|
||||
saveMarketplaceToSettings,
|
||||
} from '../../utils/plugins/marketplaceManager.js'
|
||||
import { parseMarketplaceInput } from '../../utils/plugins/parseMarketplaceInput.js'
|
||||
import type { ViewState } from './types.js'
|
||||
|
||||
type Props = {
|
||||
inputValue: string;
|
||||
setInputValue: (value: string) => void;
|
||||
cursorOffset: number;
|
||||
setCursorOffset: (offset: number) => void;
|
||||
error: string | null;
|
||||
setError: (error: string | null) => void;
|
||||
result: string | null;
|
||||
setResult: (result: string | null) => void;
|
||||
setViewState: (state: ViewState) => void;
|
||||
onAddComplete?: () => void | Promise<void>;
|
||||
cliMode?: boolean;
|
||||
};
|
||||
inputValue: string
|
||||
setInputValue: (value: string) => void
|
||||
cursorOffset: number
|
||||
setCursorOffset: (offset: number) => void
|
||||
error: string | null
|
||||
setError: (error: string | null) => void
|
||||
result: string | null
|
||||
setResult: (result: string | null) => void
|
||||
setViewState: (state: ViewState) => void
|
||||
onAddComplete?: () => void | Promise<void>
|
||||
cliMode?: boolean
|
||||
}
|
||||
|
||||
export function AddMarketplace({
|
||||
inputValue,
|
||||
setInputValue,
|
||||
@@ -37,90 +45,100 @@ export function AddMarketplace({
|
||||
setResult,
|
||||
setViewState,
|
||||
onAddComplete,
|
||||
cliMode = false
|
||||
cliMode = false,
|
||||
}: Props): React.ReactNode {
|
||||
const hasAttemptedAutoAdd = useRef(false);
|
||||
const [isLoading, setLoading] = useState(false);
|
||||
const [progressMessage, setProgressMessage] = useState<string>('');
|
||||
const hasAttemptedAutoAdd = useRef(false)
|
||||
const [isLoading, setLoading] = useState(false)
|
||||
const [progressMessage, setProgressMessage] = useState<string>('')
|
||||
|
||||
const handleAdd = async () => {
|
||||
const input = inputValue.trim();
|
||||
const input = inputValue.trim()
|
||||
if (!input) {
|
||||
setError('Please enter a marketplace source');
|
||||
return;
|
||||
setError('Please enter a marketplace source')
|
||||
return
|
||||
}
|
||||
const parsed = await parseMarketplaceInput(input);
|
||||
|
||||
const parsed = await parseMarketplaceInput(input)
|
||||
if (!parsed) {
|
||||
setError('Invalid marketplace source format. Try: owner/repo, https://..., or ./path');
|
||||
return;
|
||||
setError(
|
||||
'Invalid marketplace source format. Try: owner/repo, https://..., or ./path',
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Check if parseMarketplaceInput returned an error
|
||||
if ('error' in parsed) {
|
||||
setError(parsed.error);
|
||||
return;
|
||||
setError(parsed.error)
|
||||
return
|
||||
}
|
||||
setError(null);
|
||||
|
||||
setError(null)
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
setProgressMessage('');
|
||||
const {
|
||||
name,
|
||||
resolvedSource
|
||||
} = await addMarketplaceSource(parsed, message => {
|
||||
setProgressMessage(message);
|
||||
});
|
||||
saveMarketplaceToSettings(name, {
|
||||
source: resolvedSource
|
||||
});
|
||||
clearAllCaches();
|
||||
let sourceType = parsed.source;
|
||||
setLoading(true)
|
||||
setProgressMessage('')
|
||||
const { name, resolvedSource } = await addMarketplaceSource(
|
||||
parsed,
|
||||
message => {
|
||||
setProgressMessage(message)
|
||||
},
|
||||
)
|
||||
saveMarketplaceToSettings(name, { source: resolvedSource })
|
||||
clearAllCaches()
|
||||
|
||||
let sourceType = parsed.source
|
||||
if (parsed.source === 'github') {
|
||||
sourceType = parsed.repo as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS;
|
||||
sourceType =
|
||||
parsed.repo as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
|
||||
}
|
||||
|
||||
logEvent('tengu_marketplace_added', {
|
||||
source_type: sourceType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
|
||||
});
|
||||
source_type:
|
||||
sourceType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
})
|
||||
|
||||
if (onAddComplete) {
|
||||
await onAddComplete();
|
||||
await onAddComplete()
|
||||
}
|
||||
setProgressMessage('');
|
||||
setLoading(false);
|
||||
|
||||
setProgressMessage('')
|
||||
setLoading(false)
|
||||
|
||||
if (cliMode) {
|
||||
// In CLI mode, set result to trigger completion
|
||||
setResult(`Successfully added marketplace: ${name}`);
|
||||
setResult(`Successfully added marketplace: ${name}`)
|
||||
} else {
|
||||
// In interactive mode, switch to browse view
|
||||
setViewState({
|
||||
type: 'browse-marketplace',
|
||||
targetMarketplace: name
|
||||
});
|
||||
setViewState({ type: 'browse-marketplace', targetMarketplace: name })
|
||||
}
|
||||
} catch (err) {
|
||||
const error = toError(err);
|
||||
logError(error);
|
||||
setError(error.message);
|
||||
setProgressMessage('');
|
||||
setLoading(false);
|
||||
const error = toError(err)
|
||||
logError(error)
|
||||
setError(error.message)
|
||||
setProgressMessage('')
|
||||
setLoading(false)
|
||||
|
||||
if (cliMode) {
|
||||
// In CLI mode, set result with error to trigger completion
|
||||
setResult(`Error: ${error.message}`);
|
||||
setResult(`Error: ${error.message}`)
|
||||
} else {
|
||||
setResult(null);
|
||||
setResult(null)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Auto-add if inputValue is provided
|
||||
useEffect(() => {
|
||||
if (inputValue && !hasAttemptedAutoAdd.current && !error && !result) {
|
||||
hasAttemptedAutoAdd.current = true;
|
||||
void handleAdd();
|
||||
hasAttemptedAutoAdd.current = true
|
||||
void handleAdd()
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: intentional
|
||||
}, []); // Only run once on mount
|
||||
}, []) // Only run once on mount
|
||||
|
||||
return <Box flexDirection="column">
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Box flexDirection="column" paddingX={1} borderStyle="round">
|
||||
<Box marginBottom={1}>
|
||||
<Text bold>Add Marketplace</Text>
|
||||
@@ -133,29 +151,50 @@ export function AddMarketplace({
|
||||
<Text dimColor> · https://example.com/marketplace.json</Text>
|
||||
<Text dimColor> · ./path/to/marketplace</Text>
|
||||
<Box marginTop={1}>
|
||||
<TextInput value={inputValue} onChange={setInputValue} onSubmit={handleAdd} columns={80} cursorOffset={cursorOffset} onChangeCursorOffset={setCursorOffset} focus showCursor />
|
||||
<TextInput
|
||||
value={inputValue}
|
||||
onChange={setInputValue}
|
||||
onSubmit={handleAdd}
|
||||
columns={80}
|
||||
cursorOffset={cursorOffset}
|
||||
onChangeCursorOffset={setCursorOffset}
|
||||
focus
|
||||
showCursor
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
{isLoading && <Box marginTop={1}>
|
||||
{isLoading && (
|
||||
<Box marginTop={1}>
|
||||
<Spinner />
|
||||
<Text>
|
||||
{progressMessage || 'Adding marketplace to configuration…'}
|
||||
</Text>
|
||||
</Box>}
|
||||
{error && <Box marginTop={1}>
|
||||
</Box>
|
||||
)}
|
||||
{error && (
|
||||
<Box marginTop={1}>
|
||||
<Text color="error">{error}</Text>
|
||||
</Box>}
|
||||
{result && <Box marginTop={1}>
|
||||
</Box>
|
||||
)}
|
||||
{result && (
|
||||
<Box marginTop={1}>
|
||||
<Text>{result}</Text>
|
||||
</Box>}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<Box marginLeft={3}>
|
||||
<Text dimColor italic>
|
||||
<Byline>
|
||||
<KeyboardShortcutHint shortcut="Enter" action="add" />
|
||||
<ConfigurableShortcutHint action="confirm:no" context="Settings" fallback="Esc" description="cancel" />
|
||||
<ConfigurableShortcutHint
|
||||
action="confirm:no"
|
||||
context="Settings"
|
||||
fallback="Esc"
|
||||
description="cancel"
|
||||
/>
|
||||
</Byline>
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>;
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user