更新大量 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,230 +1,152 @@
import { c as _c } from "react/compiler-runtime";
import React, { useCallback, useState } from 'react';
import TextInput from '../../components/TextInput.js';
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
import { Box, color, Text, useTheme } from '../../ink.js';
import { useKeybindings } from '../../keybindings/useKeybinding.js';
import React, { useCallback, useState } from 'react'
import TextInput from '../../components/TextInput.js'
import { useTerminalSize } from '../../hooks/useTerminalSize.js'
import { Box, color, Text, useTheme } from '../../ink.js'
import { useKeybindings } from '../../keybindings/useKeybinding.js'
interface ApiKeyStepProps {
existingApiKey: string | null;
useExistingKey: boolean;
apiKeyOrOAuthToken: string;
onApiKeyChange: (value: string) => void;
onToggleUseExistingKey: (useExisting: boolean) => void;
onSubmit: () => void;
onCreateOAuthToken?: () => void;
selectedOption?: 'existing' | 'new' | 'oauth';
onSelectOption?: (option: 'existing' | 'new' | 'oauth') => void;
existingApiKey: string | null
useExistingKey: boolean
apiKeyOrOAuthToken: string
onApiKeyChange: (value: string) => void
onToggleUseExistingKey: (useExisting: boolean) => void
onSubmit: () => void
onCreateOAuthToken?: () => void
selectedOption?: 'existing' | 'new' | 'oauth'
onSelectOption?: (option: 'existing' | 'new' | 'oauth') => void
}
export function ApiKeyStep(t0) {
const $ = _c(55);
const {
existingApiKey,
apiKeyOrOAuthToken,
onApiKeyChange,
onSubmit,
onToggleUseExistingKey,
export function ApiKeyStep({
existingApiKey,
apiKeyOrOAuthToken,
onApiKeyChange,
onSubmit,
onToggleUseExistingKey,
onCreateOAuthToken,
selectedOption = existingApiKey
? 'existing'
: onCreateOAuthToken
? 'oauth'
: 'new',
onSelectOption,
}: ApiKeyStepProps) {
const [cursorOffset, setCursorOffset] = useState(0)
const terminalSize = useTerminalSize()
const [theme] = useTheme()
const handlePrevious = useCallback(() => {
if (selectedOption === 'new' && onCreateOAuthToken) {
// From 'new' go up to 'oauth'
onSelectOption?.('oauth')
} else if (selectedOption === 'oauth' && existingApiKey) {
// From 'oauth' go up to 'existing' (only if it exists)
onSelectOption?.('existing')
onToggleUseExistingKey(true)
}
}, [
selectedOption,
onCreateOAuthToken,
selectedOption: t1,
onSelectOption
} = t0;
const selectedOption = t1 === undefined ? existingApiKey ? "existing" : onCreateOAuthToken ? "oauth" : "new" : t1;
const [cursorOffset, setCursorOffset] = useState(0);
const terminalSize = useTerminalSize();
const [theme] = useTheme();
let t2;
if ($[0] !== existingApiKey || $[1] !== onCreateOAuthToken || $[2] !== onSelectOption || $[3] !== onToggleUseExistingKey || $[4] !== selectedOption) {
t2 = () => {
if (selectedOption === "new" && onCreateOAuthToken) {
onSelectOption?.("oauth");
} else {
if (selectedOption === "oauth" && existingApiKey) {
onSelectOption?.("existing");
onToggleUseExistingKey(true);
}
}
};
$[0] = existingApiKey;
$[1] = onCreateOAuthToken;
$[2] = onSelectOption;
$[3] = onToggleUseExistingKey;
$[4] = selectedOption;
$[5] = t2;
} else {
t2 = $[5];
}
const handlePrevious = t2;
let t3;
if ($[6] !== onCreateOAuthToken || $[7] !== onSelectOption || $[8] !== onToggleUseExistingKey || $[9] !== selectedOption) {
t3 = () => {
if (selectedOption === "existing") {
onSelectOption?.(onCreateOAuthToken ? "oauth" : "new");
onToggleUseExistingKey(false);
} else {
if (selectedOption === "oauth") {
onSelectOption?.("new");
}
}
};
$[6] = onCreateOAuthToken;
$[7] = onSelectOption;
$[8] = onToggleUseExistingKey;
$[9] = selectedOption;
$[10] = t3;
} else {
t3 = $[10];
}
const handleNext = t3;
let t4;
if ($[11] !== onCreateOAuthToken || $[12] !== onSubmit || $[13] !== selectedOption) {
t4 = () => {
if (selectedOption === "oauth" && onCreateOAuthToken) {
onCreateOAuthToken();
} else {
onSubmit();
}
};
$[11] = onCreateOAuthToken;
$[12] = onSubmit;
$[13] = selectedOption;
$[14] = t4;
} else {
t4 = $[14];
}
const handleConfirm = t4;
const isTextInputVisible = selectedOption === "new";
let t5;
if ($[15] !== handleConfirm || $[16] !== handleNext || $[17] !== handlePrevious) {
t5 = {
"confirm:previous": handlePrevious,
"confirm:next": handleNext,
"confirm:yes": handleConfirm
};
$[15] = handleConfirm;
$[16] = handleNext;
$[17] = handlePrevious;
$[18] = t5;
} else {
t5 = $[18];
}
const t6 = !isTextInputVisible;
let t7;
if ($[19] !== t6) {
t7 = {
context: "Confirmation",
isActive: t6
};
$[19] = t6;
$[20] = t7;
} else {
t7 = $[20];
}
useKeybindings(t5, t7);
let t8;
if ($[21] !== handleNext || $[22] !== handlePrevious) {
t8 = {
"confirm:previous": handlePrevious,
"confirm:next": handleNext
};
$[21] = handleNext;
$[22] = handlePrevious;
$[23] = t8;
} else {
t8 = $[23];
}
let t9;
if ($[24] !== isTextInputVisible) {
t9 = {
context: "Confirmation",
isActive: isTextInputVisible
};
$[24] = isTextInputVisible;
$[25] = t9;
} else {
t9 = $[25];
}
useKeybindings(t8, t9);
let t10;
if ($[26] === Symbol.for("react.memo_cache_sentinel")) {
t10 = <Box flexDirection="column" marginBottom={1}><Text bold={true}>Install GitHub App</Text><Text dimColor={true}>Choose API key</Text></Box>;
$[26] = t10;
} else {
t10 = $[26];
}
let t11;
if ($[27] !== existingApiKey || $[28] !== selectedOption || $[29] !== theme) {
t11 = existingApiKey && <Box marginBottom={1}><Text>{selectedOption === "existing" ? color("success", theme)("> ") : " "}Use your existing Claude Code API key</Text></Box>;
$[27] = existingApiKey;
$[28] = selectedOption;
$[29] = theme;
$[30] = t11;
} else {
t11 = $[30];
}
let t12;
if ($[31] !== onCreateOAuthToken || $[32] !== selectedOption || $[33] !== theme) {
t12 = onCreateOAuthToken && <Box marginBottom={1}><Text>{selectedOption === "oauth" ? color("success", theme)("> ") : " "}Create a long-lived token with your Claude subscription</Text></Box>;
$[31] = onCreateOAuthToken;
$[32] = selectedOption;
$[33] = theme;
$[34] = t12;
} else {
t12 = $[34];
}
let t13;
if ($[35] !== selectedOption || $[36] !== theme) {
t13 = selectedOption === "new" ? color("success", theme)("> ") : " ";
$[35] = selectedOption;
$[36] = theme;
$[37] = t13;
} else {
t13 = $[37];
}
let t14;
if ($[38] !== t13) {
t14 = <Box marginBottom={1}><Text>{t13}Enter a new API key</Text></Box>;
$[38] = t13;
$[39] = t14;
} else {
t14 = $[39];
}
let t15;
if ($[40] !== apiKeyOrOAuthToken || $[41] !== cursorOffset || $[42] !== onApiKeyChange || $[43] !== onSubmit || $[44] !== selectedOption || $[45] !== terminalSize) {
t15 = selectedOption === "new" && <TextInput value={apiKeyOrOAuthToken} onChange={onApiKeyChange} onSubmit={onSubmit} onPaste={onApiKeyChange} focus={true} placeholder={"sk-ant\u2026 (Create a new key at https://platform.claude.com/settings/keys)"} mask="*" columns={terminalSize.columns} cursorOffset={cursorOffset} onChangeCursorOffset={setCursorOffset} showCursor={true} />;
$[40] = apiKeyOrOAuthToken;
$[41] = cursorOffset;
$[42] = onApiKeyChange;
$[43] = onSubmit;
$[44] = selectedOption;
$[45] = terminalSize;
$[46] = t15;
} else {
t15 = $[46];
}
let t16;
if ($[47] !== t11 || $[48] !== t12 || $[49] !== t14 || $[50] !== t15) {
t16 = <Box flexDirection="column" borderStyle="round" paddingX={1}>{t10}{t11}{t12}{t14}{t15}</Box>;
$[47] = t11;
$[48] = t12;
$[49] = t14;
$[50] = t15;
$[51] = t16;
} else {
t16 = $[51];
}
let t17;
if ($[52] === Symbol.for("react.memo_cache_sentinel")) {
t17 = <Box marginLeft={3}><Text dimColor={true}>/ to select · Enter to continue</Text></Box>;
$[52] = t17;
} else {
t17 = $[52];
}
let t18;
if ($[53] !== t16) {
t18 = <>{t16}{t17}</>;
$[53] = t16;
$[54] = t18;
} else {
t18 = $[54];
}
return t18;
existingApiKey,
onSelectOption,
onToggleUseExistingKey,
])
const handleNext = useCallback(() => {
if (selectedOption === 'existing') {
// From 'existing' go down to 'oauth' (if available) or 'new'
onSelectOption?.(onCreateOAuthToken ? 'oauth' : 'new')
onToggleUseExistingKey(false)
} else if (selectedOption === 'oauth') {
// From 'oauth' go down to 'new'
onSelectOption?.('new')
}
}, [
selectedOption,
onCreateOAuthToken,
onSelectOption,
onToggleUseExistingKey,
])
const handleConfirm = useCallback(() => {
if (selectedOption === 'oauth' && onCreateOAuthToken) {
onCreateOAuthToken()
} else {
onSubmit()
}
}, [selectedOption, onCreateOAuthToken, onSubmit])
// When the text input is visible, omit confirm:yes so bare 'y' passes
// through to the input instead of submitting. TextInput's onSubmit handles
// Enter. Keep the Confirmation context (not Settings) to avoid j/k bindings.
const isTextInputVisible = selectedOption === 'new'
useKeybindings(
{
'confirm:previous': handlePrevious,
'confirm:next': handleNext,
'confirm:yes': handleConfirm,
},
{ context: 'Confirmation', isActive: !isTextInputVisible },
)
useKeybindings(
{
'confirm:previous': handlePrevious,
'confirm:next': handleNext,
},
{ context: 'Confirmation', isActive: isTextInputVisible },
)
return (
<>
<Box flexDirection="column" borderStyle="round" paddingX={1}>
<Box flexDirection="column" marginBottom={1}>
<Text bold>Install GitHub App</Text>
<Text dimColor>Choose API key</Text>
</Box>
{existingApiKey && (
<Box marginBottom={1}>
<Text>
{selectedOption === 'existing'
? color('success', theme)('> ')
: ' '}
Use your existing Claude Code API key
</Text>
</Box>
)}
{onCreateOAuthToken && (
<Box marginBottom={1}>
<Text>
{selectedOption === 'oauth'
? color('success', theme)('> ')
: ' '}
Create a long-lived token with your Claude subscription
</Text>
</Box>
)}
<Box marginBottom={1}>
<Text>
{selectedOption === 'new' ? color('success', theme)('> ') : ' '}
Enter a new API key
</Text>
</Box>
{selectedOption === 'new' && (
<TextInput
value={apiKeyOrOAuthToken}
onChange={onApiKeyChange}
onSubmit={onSubmit}
onPaste={onApiKeyChange}
focus={true}
placeholder="sk-ant… (Create a new key at https://platform.claude.com/settings/keys)"
mask="*"
columns={terminalSize.columns}
cursorOffset={cursorOffset}
onChangeCursorOffset={setCursorOffset}
showCursor={true}
/>
)}
</Box>
<Box marginLeft={3}>
<Text dimColor>/ to select · Enter to continue</Text>
</Box>
</>
)
}

View File

@@ -1,189 +1,106 @@
import { c as _c } from "react/compiler-runtime";
import React, { useCallback, useState } from 'react';
import TextInput from '../../components/TextInput.js';
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
import { Box, color, Text, useTheme } from '../../ink.js';
import { useKeybindings } from '../../keybindings/useKeybinding.js';
import React, { useCallback, useState } from 'react'
import TextInput from '../../components/TextInput.js'
import { useTerminalSize } from '../../hooks/useTerminalSize.js'
import { Box, color, Text, useTheme } from '../../ink.js'
import { useKeybindings } from '../../keybindings/useKeybinding.js'
interface CheckExistingSecretStepProps {
useExistingSecret: boolean;
secretName: string;
onToggleUseExistingSecret: (useExisting: boolean) => void;
onSecretNameChange: (value: string) => void;
onSubmit: () => void;
useExistingSecret: boolean
secretName: string
onToggleUseExistingSecret: (useExisting: boolean) => void
onSecretNameChange: (value: string) => void
onSubmit: () => void
}
export function CheckExistingSecretStep(t0) {
const $ = _c(42);
const {
useExistingSecret,
secretName,
onToggleUseExistingSecret,
onSecretNameChange,
onSubmit
} = t0;
const [cursorOffset, setCursorOffset] = useState(0);
const terminalSize = useTerminalSize();
const [theme] = useTheme();
let t1;
if ($[0] !== onToggleUseExistingSecret) {
t1 = () => onToggleUseExistingSecret(true);
$[0] = onToggleUseExistingSecret;
$[1] = t1;
} else {
t1 = $[1];
}
const handlePrevious = t1;
let t2;
if ($[2] !== onToggleUseExistingSecret) {
t2 = () => onToggleUseExistingSecret(false);
$[2] = onToggleUseExistingSecret;
$[3] = t2;
} else {
t2 = $[3];
}
const handleNext = t2;
let t3;
if ($[4] !== handleNext || $[5] !== handlePrevious || $[6] !== onSubmit) {
t3 = {
"confirm:previous": handlePrevious,
"confirm:next": handleNext,
"confirm:yes": onSubmit
};
$[4] = handleNext;
$[5] = handlePrevious;
$[6] = onSubmit;
$[7] = t3;
} else {
t3 = $[7];
}
let t4;
if ($[8] !== useExistingSecret) {
t4 = {
context: "Confirmation",
isActive: useExistingSecret
};
$[8] = useExistingSecret;
$[9] = t4;
} else {
t4 = $[9];
}
useKeybindings(t3, t4);
let t5;
if ($[10] !== handleNext || $[11] !== handlePrevious) {
t5 = {
"confirm:previous": handlePrevious,
"confirm:next": handleNext
};
$[10] = handleNext;
$[11] = handlePrevious;
$[12] = t5;
} else {
t5 = $[12];
}
const t6 = !useExistingSecret;
let t7;
if ($[13] !== t6) {
t7 = {
context: "Confirmation",
isActive: t6
};
$[13] = t6;
$[14] = t7;
} else {
t7 = $[14];
}
useKeybindings(t5, t7);
let t8;
if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
t8 = <Box flexDirection="column" marginBottom={1}><Text bold={true}>Install GitHub App</Text><Text dimColor={true}>Setup API key secret</Text></Box>;
$[15] = t8;
} else {
t8 = $[15];
}
let t9;
if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
t9 = <Box marginBottom={1}><Text color="warning">ANTHROPIC_API_KEY already exists in repository secrets!</Text></Box>;
$[16] = t9;
} else {
t9 = $[16];
}
let t10;
if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
t10 = <Box marginBottom={1}><Text>Would you like to:</Text></Box>;
$[17] = t10;
} else {
t10 = $[17];
}
let t11;
if ($[18] !== theme || $[19] !== useExistingSecret) {
t11 = useExistingSecret ? color("success", theme)("> ") : " ";
$[18] = theme;
$[19] = useExistingSecret;
$[20] = t11;
} else {
t11 = $[20];
}
let t12;
if ($[21] !== t11) {
t12 = <Box marginBottom={1}><Text>{t11}Use the existing API key</Text></Box>;
$[21] = t11;
$[22] = t12;
} else {
t12 = $[22];
}
let t13;
if ($[23] !== theme || $[24] !== useExistingSecret) {
t13 = !useExistingSecret ? color("success", theme)("> ") : " ";
$[23] = theme;
$[24] = useExistingSecret;
$[25] = t13;
} else {
t13 = $[25];
}
let t14;
if ($[26] !== t13) {
t14 = <Box marginBottom={1}><Text>{t13}Create a new secret with a different name</Text></Box>;
$[26] = t13;
$[27] = t14;
} else {
t14 = $[27];
}
let t15;
if ($[28] !== cursorOffset || $[29] !== onSecretNameChange || $[30] !== onSubmit || $[31] !== secretName || $[32] !== terminalSize || $[33] !== useExistingSecret) {
t15 = !useExistingSecret && <><Box marginBottom={1}><Text>Enter new secret name (alphanumeric with underscores):</Text></Box><TextInput value={secretName} onChange={onSecretNameChange} onSubmit={onSubmit} focus={true} placeholder="e.g., CLAUDE_API_KEY" columns={terminalSize.columns} cursorOffset={cursorOffset} onChangeCursorOffset={setCursorOffset} showCursor={true} /></>;
$[28] = cursorOffset;
$[29] = onSecretNameChange;
$[30] = onSubmit;
$[31] = secretName;
$[32] = terminalSize;
$[33] = useExistingSecret;
$[34] = t15;
} else {
t15 = $[34];
}
let t16;
if ($[35] !== t12 || $[36] !== t14 || $[37] !== t15) {
t16 = <Box flexDirection="column" borderStyle="round" paddingX={1}>{t8}{t9}{t10}{t12}{t14}{t15}</Box>;
$[35] = t12;
$[36] = t14;
$[37] = t15;
$[38] = t16;
} else {
t16 = $[38];
}
let t17;
if ($[39] === Symbol.for("react.memo_cache_sentinel")) {
t17 = <Box marginLeft={3}><Text dimColor={true}>/ to select · Enter to continue</Text></Box>;
$[39] = t17;
} else {
t17 = $[39];
}
let t18;
if ($[40] !== t16) {
t18 = <>{t16}{t17}</>;
$[40] = t16;
$[41] = t18;
} else {
t18 = $[41];
}
return t18;
export function CheckExistingSecretStep({
useExistingSecret,
secretName,
onToggleUseExistingSecret,
onSecretNameChange,
onSubmit,
}: CheckExistingSecretStepProps) {
const [cursorOffset, setCursorOffset] = useState(0)
const terminalSize = useTerminalSize()
const [theme] = useTheme()
// When the text input is visible, omit confirm:yes so bare 'y' passes
// through to the input instead of submitting. TextInput's onSubmit handles
// Enter. Keep the Confirmation context (not Settings) to avoid j/k bindings.
const handlePrevious = useCallback(
() => onToggleUseExistingSecret(true),
[onToggleUseExistingSecret],
)
const handleNext = useCallback(
() => onToggleUseExistingSecret(false),
[onToggleUseExistingSecret],
)
useKeybindings(
{
'confirm:previous': handlePrevious,
'confirm:next': handleNext,
'confirm:yes': onSubmit,
},
{ context: 'Confirmation', isActive: useExistingSecret },
)
useKeybindings(
{
'confirm:previous': handlePrevious,
'confirm:next': handleNext,
},
{ context: 'Confirmation', isActive: !useExistingSecret },
)
return (
<>
<Box flexDirection="column" borderStyle="round" paddingX={1}>
<Box flexDirection="column" marginBottom={1}>
<Text bold>Install GitHub App</Text>
<Text dimColor>Setup API key secret</Text>
</Box>
<Box marginBottom={1}>
<Text color="warning">
ANTHROPIC_API_KEY already exists in repository secrets!
</Text>
</Box>
<Box marginBottom={1}>
<Text>Would you like to:</Text>
</Box>
<Box marginBottom={1}>
<Text>
{useExistingSecret ? color('success', theme)('> ') : ' '}
Use the existing API key
</Text>
</Box>
<Box marginBottom={1}>
<Text>
{!useExistingSecret ? color('success', theme)('> ') : ' '}
Create a new secret with a different name
</Text>
</Box>
{!useExistingSecret && (
<>
<Box marginBottom={1}>
<Text>
Enter new secret name (alphanumeric with underscores):
</Text>
</Box>
<TextInput
value={secretName}
onChange={onSecretNameChange}
onSubmit={onSubmit}
focus={true}
placeholder="e.g., CLAUDE_API_KEY"
columns={terminalSize.columns}
cursorOffset={cursorOffset}
onChangeCursorOffset={setCursorOffset}
showCursor={true}
/>
</>
)}
</Box>
<Box marginLeft={3}>
<Text dimColor>/ to select · Enter to continue</Text>
</Box>
</>
)
}

View File

@@ -1,14 +1,6 @@
import { c as _c } from "react/compiler-runtime";
import React from 'react';
import { Text } from '../../ink.js';
import React from 'react'
import { Text } from '../../ink.js'
export function CheckGitHubStep() {
const $ = _c(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = <Text>Checking GitHub CLI installation</Text>;
$[0] = t0;
} else {
t0 = $[0];
}
return t0;
return <Text>Checking GitHub CLI installation</Text>
}

View File

@@ -1,210 +1,125 @@
import { c as _c } from "react/compiler-runtime";
import React, { useCallback, useState } from 'react';
import TextInput from '../../components/TextInput.js';
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
import { Box, Text } from '../../ink.js';
import { useKeybindings } from '../../keybindings/useKeybinding.js';
import React, { useCallback, useState } from 'react'
import TextInput from '../../components/TextInput.js'
import { useTerminalSize } from '../../hooks/useTerminalSize.js'
import { Box, Text } from '../../ink.js'
import { useKeybindings } from '../../keybindings/useKeybinding.js'
interface ChooseRepoStepProps {
currentRepo: string | null;
useCurrentRepo: boolean;
repoUrl: string;
onRepoUrlChange: (value: string) => void;
onToggleUseCurrentRepo: (useCurrentRepo: boolean) => void;
onSubmit: () => void;
currentRepo: string | null
useCurrentRepo: boolean
repoUrl: string
onRepoUrlChange: (value: string) => void
onToggleUseCurrentRepo: (useCurrentRepo: boolean) => void
onSubmit: () => void
}
export function ChooseRepoStep(t0) {
const $ = _c(49);
const {
currentRepo,
useCurrentRepo,
repoUrl,
onRepoUrlChange,
onSubmit,
onToggleUseCurrentRepo
} = t0;
const [cursorOffset, setCursorOffset] = useState(0);
const [showEmptyError, setShowEmptyError] = useState(false);
const terminalSize = useTerminalSize();
const textInputColumns = terminalSize.columns;
let t1;
if ($[0] !== currentRepo || $[1] !== onSubmit || $[2] !== repoUrl || $[3] !== useCurrentRepo) {
t1 = () => {
const repoName = useCurrentRepo ? currentRepo : repoUrl;
if (!repoName?.trim()) {
setShowEmptyError(true);
return;
}
onSubmit();
};
$[0] = currentRepo;
$[1] = onSubmit;
$[2] = repoUrl;
$[3] = useCurrentRepo;
$[4] = t1;
} else {
t1 = $[4];
}
const handleSubmit = t1;
const isTextInputVisible = !useCurrentRepo || !currentRepo;
let t2;
if ($[5] !== onToggleUseCurrentRepo) {
t2 = () => {
onToggleUseCurrentRepo(true);
setShowEmptyError(false);
};
$[5] = onToggleUseCurrentRepo;
$[6] = t2;
} else {
t2 = $[6];
}
const handlePrevious = t2;
let t3;
if ($[7] !== onToggleUseCurrentRepo) {
t3 = () => {
onToggleUseCurrentRepo(false);
setShowEmptyError(false);
};
$[7] = onToggleUseCurrentRepo;
$[8] = t3;
} else {
t3 = $[8];
}
const handleNext = t3;
let t4;
if ($[9] !== handleNext || $[10] !== handlePrevious || $[11] !== handleSubmit) {
t4 = {
"confirm:previous": handlePrevious,
"confirm:next": handleNext,
"confirm:yes": handleSubmit
};
$[9] = handleNext;
$[10] = handlePrevious;
$[11] = handleSubmit;
$[12] = t4;
} else {
t4 = $[12];
}
const t5 = !isTextInputVisible;
let t6;
if ($[13] !== t5) {
t6 = {
context: "Confirmation",
isActive: t5
};
$[13] = t5;
$[14] = t6;
} else {
t6 = $[14];
}
useKeybindings(t4, t6);
let t7;
if ($[15] !== handleNext || $[16] !== handlePrevious) {
t7 = {
"confirm:previous": handlePrevious,
"confirm:next": handleNext
};
$[15] = handleNext;
$[16] = handlePrevious;
$[17] = t7;
} else {
t7 = $[17];
}
let t8;
if ($[18] !== isTextInputVisible) {
t8 = {
context: "Confirmation",
isActive: isTextInputVisible
};
$[18] = isTextInputVisible;
$[19] = t8;
} else {
t8 = $[19];
}
useKeybindings(t7, t8);
let t9;
if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
t9 = <Box flexDirection="column" marginBottom={1}><Text bold={true}>Install GitHub App</Text><Text dimColor={true}>Select GitHub repository</Text></Box>;
$[20] = t9;
} else {
t9 = $[20];
}
let t10;
if ($[21] !== currentRepo || $[22] !== useCurrentRepo) {
t10 = currentRepo && <Box marginBottom={1}><Text bold={useCurrentRepo} color={useCurrentRepo ? "permission" : undefined}>{useCurrentRepo ? "> " : " "}Use current repository: {currentRepo}</Text></Box>;
$[21] = currentRepo;
$[22] = useCurrentRepo;
$[23] = t10;
} else {
t10 = $[23];
}
const t11 = !useCurrentRepo || !currentRepo;
const t12 = !useCurrentRepo || !currentRepo ? "permission" : undefined;
const t13 = !useCurrentRepo || !currentRepo ? "> " : " ";
const t14 = currentRepo ? "Enter a different repository" : "Enter repository";
let t15;
if ($[24] !== t11 || $[25] !== t12 || $[26] !== t13 || $[27] !== t14) {
t15 = <Box marginBottom={1}><Text bold={t11} color={t12}>{t13}{t14}</Text></Box>;
$[24] = t11;
$[25] = t12;
$[26] = t13;
$[27] = t14;
$[28] = t15;
} else {
t15 = $[28];
}
let t16;
if ($[29] !== currentRepo || $[30] !== cursorOffset || $[31] !== handleSubmit || $[32] !== onRepoUrlChange || $[33] !== repoUrl || $[34] !== textInputColumns || $[35] !== useCurrentRepo) {
t16 = (!useCurrentRepo || !currentRepo) && <Box marginLeft={2} marginBottom={1}><TextInput value={repoUrl} onChange={value => {
onRepoUrlChange(value);
setShowEmptyError(false);
}} onSubmit={handleSubmit} focus={true} placeholder={"Enter a repo as owner/repo or https://github.com/owner/repo\u2026"} columns={textInputColumns} cursorOffset={cursorOffset} onChangeCursorOffset={setCursorOffset} showCursor={true} /></Box>;
$[29] = currentRepo;
$[30] = cursorOffset;
$[31] = handleSubmit;
$[32] = onRepoUrlChange;
$[33] = repoUrl;
$[34] = textInputColumns;
$[35] = useCurrentRepo;
$[36] = t16;
} else {
t16 = $[36];
}
let t17;
if ($[37] !== t10 || $[38] !== t15 || $[39] !== t16) {
t17 = <Box flexDirection="column" borderStyle="round" paddingX={1}>{t9}{t10}{t15}{t16}</Box>;
$[37] = t10;
$[38] = t15;
$[39] = t16;
$[40] = t17;
} else {
t17 = $[40];
}
let t18;
if ($[41] !== showEmptyError) {
t18 = showEmptyError && <Box marginLeft={3} marginBottom={1}><Text color="error">Please enter a repository name to continue</Text></Box>;
$[41] = showEmptyError;
$[42] = t18;
} else {
t18 = $[42];
}
const t19 = currentRepo ? "\u2191/\u2193 to select \xB7 " : "";
let t20;
if ($[43] !== t19) {
t20 = <Box marginLeft={3}><Text dimColor={true}>{t19}Enter to continue</Text></Box>;
$[43] = t19;
$[44] = t20;
} else {
t20 = $[44];
}
let t21;
if ($[45] !== t17 || $[46] !== t18 || $[47] !== t20) {
t21 = <>{t17}{t18}{t20}</>;
$[45] = t17;
$[46] = t18;
$[47] = t20;
$[48] = t21;
} else {
t21 = $[48];
}
return t21;
export function ChooseRepoStep({
currentRepo,
useCurrentRepo,
repoUrl,
onRepoUrlChange,
onSubmit,
onToggleUseCurrentRepo,
}: ChooseRepoStepProps) {
const [cursorOffset, setCursorOffset] = useState(0)
const [showEmptyError, setShowEmptyError] = useState(false)
const terminalSize = useTerminalSize()
const textInputColumns = terminalSize.columns
const handleSubmit = useCallback(() => {
const repoName = useCurrentRepo ? currentRepo : repoUrl
if (!repoName?.trim()) {
setShowEmptyError(true)
return
}
onSubmit()
}, [useCurrentRepo, currentRepo, repoUrl, onSubmit])
// When the text input is visible, omit confirm:yes so bare 'y' passes
// through to the input instead of submitting. TextInput's onSubmit handles
// Enter. Keep the Confirmation context (not Settings) to avoid j/k bindings.
const isTextInputVisible = !useCurrentRepo || !currentRepo
const handlePrevious = useCallback(() => {
onToggleUseCurrentRepo(true)
setShowEmptyError(false)
}, [onToggleUseCurrentRepo])
const handleNext = useCallback(() => {
onToggleUseCurrentRepo(false)
setShowEmptyError(false)
}, [onToggleUseCurrentRepo])
useKeybindings(
{
'confirm:previous': handlePrevious,
'confirm:next': handleNext,
'confirm:yes': handleSubmit,
},
{ context: 'Confirmation', isActive: !isTextInputVisible },
)
useKeybindings(
{
'confirm:previous': handlePrevious,
'confirm:next': handleNext,
},
{ context: 'Confirmation', isActive: isTextInputVisible },
)
return (
<>
<Box flexDirection="column" borderStyle="round" paddingX={1}>
<Box flexDirection="column" marginBottom={1}>
<Text bold>Install GitHub App</Text>
<Text dimColor>Select GitHub repository</Text>
</Box>
{currentRepo && (
<Box marginBottom={1}>
<Text
bold={useCurrentRepo}
color={useCurrentRepo ? 'permission' : undefined}
>
{useCurrentRepo ? '> ' : ' '}
Use current repository: {currentRepo}
</Text>
</Box>
)}
<Box marginBottom={1}>
<Text
bold={!useCurrentRepo || !currentRepo}
color={!useCurrentRepo || !currentRepo ? 'permission' : undefined}
>
{!useCurrentRepo || !currentRepo ? '> ' : ' '}
{currentRepo ? 'Enter a different repository' : 'Enter repository'}
</Text>
</Box>
{(!useCurrentRepo || !currentRepo) && (
<Box marginLeft={2} marginBottom={1}>
<TextInput
value={repoUrl}
onChange={value => {
onRepoUrlChange(value)
setShowEmptyError(false)
}}
onSubmit={handleSubmit}
focus={true}
placeholder="Enter a repo as owner/repo or https://github.com/owner/repo…"
columns={textInputColumns}
cursorOffset={cursorOffset}
onChangeCursorOffset={setCursorOffset}
showCursor={true}
/>
</Box>
)}
</Box>
{showEmptyError && (
<Box marginLeft={3} marginBottom={1}>
<Text color="error">Please enter a repository name to continue</Text>
</Box>
)}
<Box marginLeft={3}>
<Text dimColor>
{currentRepo ? '↑/↓ to select · ' : ''}Enter to continue
</Text>
</Box>
</>
)
}

View File

@@ -1,64 +1,78 @@
import { c as _c } from "react/compiler-runtime";
import React from 'react';
import { Box, Text } from '../../ink.js';
import type { Workflow } from './types.js';
import React from 'react'
import { Box, Text } from '../../ink.js'
import type { Workflow } from './types.js'
interface CreatingStepProps {
currentWorkflowInstallStep: number;
secretExists: boolean;
useExistingSecret: boolean;
secretName: string;
skipWorkflow?: boolean;
selectedWorkflows: Workflow[];
currentWorkflowInstallStep: number
secretExists: boolean
useExistingSecret: boolean
secretName: string
skipWorkflow?: boolean
selectedWorkflows: Workflow[]
}
export function CreatingStep(t0) {
const $ = _c(10);
const {
currentWorkflowInstallStep,
secretExists,
useExistingSecret,
secretName,
skipWorkflow: t1,
selectedWorkflows
} = t0;
const skipWorkflow = t1 === undefined ? false : t1;
let t2;
if ($[0] !== secretExists || $[1] !== secretName || $[2] !== selectedWorkflows || $[3] !== skipWorkflow || $[4] !== useExistingSecret) {
t2 = skipWorkflow ? ["Getting repository information", secretExists && useExistingSecret ? "Using existing API key secret" : `Setting up ${secretName} secret`] : ["Getting repository information", "Creating branch", selectedWorkflows.length > 1 ? "Creating workflow files" : "Creating workflow file", secretExists && useExistingSecret ? "Using existing API key secret" : `Setting up ${secretName} secret`, "Opening pull request page"];
$[0] = secretExists;
$[1] = secretName;
$[2] = selectedWorkflows;
$[3] = skipWorkflow;
$[4] = useExistingSecret;
$[5] = t2;
} else {
t2 = $[5];
}
const progressSteps = t2;
let t3;
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
t3 = <Box flexDirection="column" marginBottom={1}><Text bold={true}>Install GitHub App</Text><Text dimColor={true}>Create GitHub Actions workflow</Text></Box>;
$[6] = t3;
} else {
t3 = $[6];
}
let t4;
if ($[7] !== currentWorkflowInstallStep || $[8] !== progressSteps) {
t4 = <><Box flexDirection="column" borderStyle="round" paddingX={1}>{t3}{progressSteps.map((stepText, index) => {
let status = "pending";
export function CreatingStep({
currentWorkflowInstallStep,
secretExists,
useExistingSecret,
secretName,
skipWorkflow = false,
selectedWorkflows,
}: CreatingStepProps) {
const progressSteps = skipWorkflow
? [
'Getting repository information',
secretExists && useExistingSecret
? 'Using existing API key secret'
: `Setting up ${secretName} secret`,
]
: [
'Getting repository information',
'Creating branch',
selectedWorkflows.length > 1
? 'Creating workflow files'
: 'Creating workflow file',
secretExists && useExistingSecret
? 'Using existing API key secret'
: `Setting up ${secretName} secret`,
'Opening pull request page',
]
return (
<>
<Box flexDirection="column" borderStyle="round" paddingX={1}>
<Box flexDirection="column" marginBottom={1}>
<Text bold>Install GitHub App</Text>
<Text dimColor>Create GitHub Actions workflow</Text>
</Box>
{progressSteps.map((stepText, index) => {
let status: 'completed' | 'in-progress' | 'pending' = 'pending'
if (index < currentWorkflowInstallStep) {
status = "completed";
} else {
if (index === currentWorkflowInstallStep) {
status = "in-progress";
}
status = 'completed'
} else if (index === currentWorkflowInstallStep) {
status = 'in-progress'
}
return <Box key={index}><Text color={status === "completed" ? "success" : status === "in-progress" ? "warning" : undefined}>{status === "completed" ? "\u2713 " : ""}{stepText}{status === "in-progress" ? "\u2026" : ""}</Text></Box>;
})}</Box></>;
$[7] = currentWorkflowInstallStep;
$[8] = progressSteps;
$[9] = t4;
} else {
t4 = $[9];
}
return t4;
return (
<Box key={index}>
<Text
color={
status === 'completed'
? 'success'
: status === 'in-progress'
? 'warning'
: undefined
}
>
{status === 'completed' ? '✓ ' : ''}
{stepText}
{status === 'in-progress' ? '…' : ''}
</Text>
</Box>
)
})}
</Box>
</>
)
}

View File

@@ -1,84 +1,51 @@
import { c as _c } from "react/compiler-runtime";
import React from 'react';
import { GITHUB_ACTION_SETUP_DOCS_URL } from '../../constants/github-app.js';
import { Box, Text } from '../../ink.js';
import React from 'react'
import { GITHUB_ACTION_SETUP_DOCS_URL } from '../../constants/github-app.js'
import { Box, Text } from '../../ink.js'
interface ErrorStepProps {
error: string | undefined;
errorReason?: string;
errorInstructions?: string[];
error: string | undefined
errorReason?: string
errorInstructions?: string[]
}
export function ErrorStep(t0) {
const $ = _c(15);
const {
error,
errorReason,
errorInstructions
} = t0;
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t1 = <Box flexDirection="column" marginBottom={1}><Text bold={true}>Install GitHub App</Text></Box>;
$[0] = t1;
} else {
t1 = $[0];
}
let t2;
if ($[1] !== error) {
t2 = <Text color="error">Error: {error}</Text>;
$[1] = error;
$[2] = t2;
} else {
t2 = $[2];
}
let t3;
if ($[3] !== errorReason) {
t3 = errorReason && <Box marginTop={1}><Text dimColor={true}>Reason: {errorReason}</Text></Box>;
$[3] = errorReason;
$[4] = t3;
} else {
t3 = $[4];
}
let t4;
if ($[5] !== errorInstructions) {
t4 = errorInstructions && errorInstructions.length > 0 && <Box flexDirection="column" marginTop={1}><Text dimColor={true}>How to fix:</Text>{errorInstructions.map(_temp)}</Box>;
$[5] = errorInstructions;
$[6] = t4;
} else {
t4 = $[6];
}
let t5;
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
t5 = <Box marginTop={1}><Text dimColor={true}>For manual setup instructions, see:{" "}<Text color="claude">{GITHUB_ACTION_SETUP_DOCS_URL}</Text></Text></Box>;
$[7] = t5;
} else {
t5 = $[7];
}
let t6;
if ($[8] !== t2 || $[9] !== t3 || $[10] !== t4) {
t6 = <Box flexDirection="column" borderStyle="round" paddingX={1}>{t1}{t2}{t3}{t4}{t5}</Box>;
$[8] = t2;
$[9] = t3;
$[10] = t4;
$[11] = t6;
} else {
t6 = $[11];
}
let t7;
if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
t7 = <Box marginLeft={3}><Text dimColor={true}>Press any key to exit</Text></Box>;
$[12] = t7;
} else {
t7 = $[12];
}
let t8;
if ($[13] !== t6) {
t8 = <>{t6}{t7}</>;
$[13] = t6;
$[14] = t8;
} else {
t8 = $[14];
}
return t8;
}
function _temp(instruction, index) {
return <Box key={index} marginLeft={2}><Text dimColor={true}> </Text><Text>{instruction}</Text></Box>;
export function ErrorStep({
error,
errorReason,
errorInstructions,
}: ErrorStepProps) {
return (
<>
<Box flexDirection="column" borderStyle="round" paddingX={1}>
<Box flexDirection="column" marginBottom={1}>
<Text bold>Install GitHub App</Text>
</Box>
<Text color="error">Error: {error}</Text>
{errorReason && (
<Box marginTop={1}>
<Text dimColor>Reason: {errorReason}</Text>
</Box>
)}
{errorInstructions && errorInstructions.length > 0 && (
<Box flexDirection="column" marginTop={1}>
<Text dimColor>How to fix:</Text>
{errorInstructions.map((instruction, index) => (
<Box key={index} marginLeft={2}>
<Text dimColor> </Text>
<Text>{instruction}</Text>
</Box>
))}
</Box>
)}
<Box marginTop={1}>
<Text dimColor>
For manual setup instructions, see:{' '}
<Text color="claude">{GITHUB_ACTION_SETUP_DOCS_URL}</Text>
</Text>
</Box>
</Box>
<Box marginLeft={3}>
<Text dimColor>Press any key to exit</Text>
</Box>
</>
)
}

View File

@@ -1,102 +1,70 @@
import { c as _c } from "react/compiler-runtime";
import React from 'react';
import { Select } from 'src/components/CustomSelect/index.js';
import { Box, Text } from '../../ink.js';
import React from 'react'
import { Select } from 'src/components/CustomSelect/index.js'
import { Box, Text } from '../../ink.js'
interface ExistingWorkflowStepProps {
repoName: string;
onSelectAction: (action: 'update' | 'skip' | 'exit') => void;
repoName: string
onSelectAction: (action: 'update' | 'skip' | 'exit') => void
}
export function ExistingWorkflowStep(t0) {
const $ = _c(16);
const {
repoName,
onSelectAction
} = t0;
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t1 = [{
label: "Update workflow file with latest version",
value: "update"
}, {
label: "Skip workflow update (configure secrets only)",
value: "skip"
}, {
label: "Exit without making changes",
value: "exit"
}];
$[0] = t1;
} else {
t1 = $[0];
export function ExistingWorkflowStep({
repoName,
onSelectAction,
}: ExistingWorkflowStepProps) {
const options = [
{
label: 'Update workflow file with latest version',
value: 'update',
},
{
label: 'Skip workflow update (configure secrets only)',
value: 'skip',
},
{
label: 'Exit without making changes',
value: 'exit',
},
]
const handleSelect = (value: string) => {
onSelectAction(value as 'update' | 'skip' | 'exit')
}
const options = t1;
let t2;
if ($[1] !== onSelectAction) {
t2 = value => {
onSelectAction(value as 'update' | 'skip' | 'exit');
};
$[1] = onSelectAction;
$[2] = t2;
} else {
t2 = $[2];
const handleCancel = () => {
onSelectAction('exit')
}
const handleSelect = t2;
let t3;
if ($[3] !== onSelectAction) {
t3 = () => {
onSelectAction("exit");
};
$[3] = onSelectAction;
$[4] = t3;
} else {
t3 = $[4];
}
const handleCancel = t3;
let t4;
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
t4 = <Text bold={true}>Existing Workflow Found</Text>;
$[5] = t4;
} else {
t4 = $[5];
}
let t5;
if ($[6] !== repoName) {
t5 = <Box flexDirection="column" marginBottom={1}>{t4}<Text dimColor={true}>Repository: {repoName}</Text></Box>;
$[6] = repoName;
$[7] = t5;
} else {
t5 = $[7];
}
let t6;
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
t6 = <Box flexDirection="column" marginBottom={1}><Text>A Claude workflow file already exists at{" "}<Text color="claude">.github/workflows/claude.yml</Text></Text><Text dimColor={true}>What would you like to do?</Text></Box>;
$[8] = t6;
} else {
t6 = $[8];
}
let t7;
if ($[9] !== handleCancel || $[10] !== handleSelect) {
t7 = <Box flexDirection="column"><Select options={options} onChange={handleSelect} onCancel={handleCancel} /></Box>;
$[9] = handleCancel;
$[10] = handleSelect;
$[11] = t7;
} else {
t7 = $[11];
}
let t8;
if ($[12] === Symbol.for("react.memo_cache_sentinel")) {
t8 = <Box marginTop={1}><Text dimColor={true}>View the latest workflow template at:{" "}<Text color="claude">https://github.com/anthropics/claude-code-action/blob/main/examples/claude.yml</Text></Text></Box>;
$[12] = t8;
} else {
t8 = $[12];
}
let t9;
if ($[13] !== t5 || $[14] !== t7) {
t9 = <Box flexDirection="column" borderStyle="round" borderDimColor={true} paddingX={1}>{t5}{t6}{t7}{t8}</Box>;
$[13] = t5;
$[14] = t7;
$[15] = t9;
} else {
t9 = $[15];
}
return t9;
return (
<Box flexDirection="column" borderStyle="round" borderDimColor paddingX={1}>
<Box flexDirection="column" marginBottom={1}>
<Text bold>Existing Workflow Found</Text>
<Text dimColor>Repository: {repoName}</Text>
</Box>
<Box flexDirection="column" marginBottom={1}>
<Text>
A Claude workflow file already exists at{' '}
<Text color="claude">.github/workflows/claude.yml</Text>
</Text>
<Text dimColor>What would you like to do?</Text>
</Box>
<Box flexDirection="column">
<Select
options={options}
onChange={handleSelect}
onCancel={handleCancel}
/>
</Box>
<Box marginTop={1}>
<Text dimColor>
View the latest workflow template at:{' '}
<Text color="claude">
https://github.com/anthropics/claude-code-action/blob/main/examples/claude.yml
</Text>
</Text>
</Box>
</Box>
)
}

View File

@@ -1,93 +1,53 @@
import { c as _c } from "react/compiler-runtime";
import figures from 'figures';
import React from 'react';
import { GITHUB_ACTION_SETUP_DOCS_URL } from '../../constants/github-app.js';
import { Box, Text } from '../../ink.js';
import { useKeybinding } from '../../keybindings/useKeybinding.js';
import figures from 'figures'
import React from 'react'
import { GITHUB_ACTION_SETUP_DOCS_URL } from '../../constants/github-app.js'
import { Box, Text } from '../../ink.js'
import { useKeybinding } from '../../keybindings/useKeybinding.js'
interface InstallAppStepProps {
repoUrl: string;
onSubmit: () => void;
repoUrl: string
onSubmit: () => void
}
export function InstallAppStep(t0) {
const $ = _c(12);
const {
repoUrl,
onSubmit
} = t0;
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t1 = {
context: "Confirmation"
};
$[0] = t1;
} else {
t1 = $[0];
}
useKeybinding("confirm:yes", onSubmit, t1);
let t2;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t2 = <Box flexDirection="column" marginBottom={1}><Text bold={true}>Install the Claude GitHub App</Text></Box>;
$[1] = t2;
} else {
t2 = $[1];
}
let t3;
if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
t3 = <Box marginBottom={1}><Text>Opening browser to install the Claude GitHub App</Text></Box>;
$[2] = t3;
} else {
t3 = $[2];
}
let t4;
if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
t4 = <Box marginBottom={1}><Text>If your browser doesn't open automatically, visit:</Text></Box>;
$[3] = t4;
} else {
t4 = $[3];
}
let t5;
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
t5 = <Box marginBottom={1}><Text underline={true}>https://github.com/apps/claude</Text></Box>;
$[4] = t5;
} else {
t5 = $[4];
}
let t6;
if ($[5] !== repoUrl) {
t6 = <Box marginBottom={1}><Text>Please install the app for repository: <Text bold={true}>{repoUrl}</Text></Text></Box>;
$[5] = repoUrl;
$[6] = t6;
} else {
t6 = $[6];
}
let t7;
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
t7 = <Box marginBottom={1}><Text dimColor={true}>Important: Make sure to grant access to this specific repository</Text></Box>;
$[7] = t7;
} else {
t7 = $[7];
}
let t8;
if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
t8 = <Box><Text bold={true} color="permission">Press Enter once you've installed the app{figures.ellipsis}</Text></Box>;
$[8] = t8;
} else {
t8 = $[8];
}
let t9;
if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
t9 = <Box marginTop={1}><Text dimColor={true}>Having trouble? See manual setup instructions at:{" "}<Text color="claude">{GITHUB_ACTION_SETUP_DOCS_URL}</Text></Text></Box>;
$[9] = t9;
} else {
t9 = $[9];
}
let t10;
if ($[10] !== t6) {
t10 = <Box flexDirection="column" borderStyle="round" borderDimColor={true} paddingX={1}>{t2}{t3}{t4}{t5}{t6}{t7}{t8}{t9}</Box>;
$[10] = t6;
$[11] = t10;
} else {
t10 = $[11];
}
return t10;
export function InstallAppStep({ repoUrl, onSubmit }: InstallAppStepProps) {
// Enter to submit
useKeybinding('confirm:yes', onSubmit, { context: 'Confirmation' })
return (
<Box flexDirection="column" borderStyle="round" borderDimColor paddingX={1}>
<Box flexDirection="column" marginBottom={1}>
<Text bold>Install the Claude GitHub App</Text>
</Box>
<Box marginBottom={1}>
<Text>Opening browser to install the Claude GitHub App</Text>
</Box>
<Box marginBottom={1}>
<Text>If your browser doesn&apos;t open automatically, visit:</Text>
</Box>
<Box marginBottom={1}>
<Text underline>https://github.com/apps/claude</Text>
</Box>
<Box marginBottom={1}>
<Text>
Please install the app for repository: <Text bold>{repoUrl}</Text>
</Text>
</Box>
<Box marginBottom={1}>
<Text dimColor>
Important: Make sure to grant access to this specific repository
</Text>
</Box>
<Box>
<Text bold color="permission">
Press Enter once you&apos;ve installed the app{figures.ellipsis}
</Text>
</Box>
<Box marginTop={1}>
<Text dimColor>
Having trouble? See manual setup instructions at:{' '}
<Text color="claude">{GITHUB_ACTION_SETUP_DOCS_URL}</Text>
</Text>
</Box>
</Box>
)
}

View File

@@ -1,275 +1,343 @@
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, logEvent } from 'src/services/analytics/index.js';
import { KeyboardShortcutHint } from '../../components/design-system/KeyboardShortcutHint.js';
import { Spinner } from '../../components/Spinner.js';
import TextInput from '../../components/TextInput.js';
import { useTerminalSize } from '../../hooks/useTerminalSize.js';
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js';
import { setClipboard } from '../../ink/termio/osc.js';
import { Box, Link, Text } from '../../ink.js';
import { OAuthService } from '../../services/oauth/index.js';
import { saveOAuthTokensIfNeeded } from '../../utils/auth.js';
import { logError } from '../../utils/log.js';
import React, { useCallback, useEffect, useRef, useState } from 'react'
import {
type AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
logEvent,
} from 'src/services/analytics/index.js'
import { KeyboardShortcutHint } from '../../components/design-system/KeyboardShortcutHint.js'
import { Spinner } from '../../components/Spinner.js'
import TextInput from '../../components/TextInput.js'
import { useTerminalSize } from '../../hooks/useTerminalSize.js'
import type { KeyboardEvent } from '../../ink/events/keyboard-event.js'
import { setClipboard } from '../../ink/termio/osc.js'
import { Box, Link, Text } from '../../ink.js'
import { OAuthService } from '../../services/oauth/index.js'
import { saveOAuthTokensIfNeeded } from '../../utils/auth.js'
import { logError } from '../../utils/log.js'
interface OAuthFlowStepProps {
onSuccess: (token: string) => void;
onCancel: () => void;
onSuccess: (token: string) => void
onCancel: () => void
}
type OAuthStatus = {
state: 'starting';
} | {
state: 'waiting_for_login';
url: string;
} | {
state: 'processing';
} | {
state: 'success';
token: string;
} | {
state: 'error';
message: string;
toRetry?: OAuthStatus;
} | {
state: 'about_to_retry';
nextState: OAuthStatus;
};
const PASTE_HERE_MSG = 'Paste code here if prompted > ';
type OAuthStatus =
| { state: 'starting' }
| { state: 'waiting_for_login'; url: string }
| { state: 'processing' }
| { state: 'success'; token: string }
| { state: 'error'; message: string; toRetry?: OAuthStatus }
| { state: 'about_to_retry'; nextState: OAuthStatus }
const PASTE_HERE_MSG = 'Paste code here if prompted > '
export function OAuthFlowStep({
onSuccess,
onCancel
onCancel,
}: OAuthFlowStepProps): React.ReactNode {
const [oauthStatus, setOAuthStatus] = useState<OAuthStatus>({
state: 'starting'
});
const [oauthService] = useState(() => new OAuthService());
const [pastedCode, setPastedCode] = useState('');
const [cursorOffset, setCursorOffset] = useState(0);
const [showPastePrompt, setShowPastePrompt] = useState(false);
const [urlCopied, setUrlCopied] = useState(false);
const timersRef = useRef<Set<NodeJS.Timeout>>(new Set());
state: 'starting',
})
const [oauthService] = useState(() => new OAuthService())
const [pastedCode, setPastedCode] = useState('')
const [cursorOffset, setCursorOffset] = useState(0)
const [showPastePrompt, setShowPastePrompt] = useState(false)
const [urlCopied, setUrlCopied] = useState(false)
const timersRef = useRef<Set<NodeJS.Timeout>>(new Set())
// Separate ref so startOAuth's timer clear doesn't cancel the urlCopied reset
const urlCopiedTimerRef = useRef<NodeJS.Timeout | undefined>(undefined);
const terminalSize = useTerminalSize();
const textInputColumns = Math.max(50, terminalSize.columns - PASTE_HERE_MSG.length - 4);
const urlCopiedTimerRef = useRef<NodeJS.Timeout | undefined>(undefined)
const terminalSize = useTerminalSize()
const textInputColumns = Math.max(
50,
terminalSize.columns - PASTE_HERE_MSG.length - 4,
)
function handleKeyDown(e: KeyboardEvent): void {
if (oauthStatus.state !== 'error') return;
e.preventDefault();
if (oauthStatus.state !== 'error') return
e.preventDefault()
if (e.key === 'return' && oauthStatus.toRetry) {
setPastedCode('');
setCursorOffset(0);
setPastedCode('')
setCursorOffset(0)
setOAuthStatus({
state: 'about_to_retry',
nextState: oauthStatus.toRetry
});
nextState: oauthStatus.toRetry,
})
} else {
onCancel();
onCancel()
}
}
async function handleSubmitCode(value: string, url: string) {
try {
// Expecting format "authorizationCode#state" from the authorization callback URL
const [authorizationCode, state] = value.split('#');
const [authorizationCode, state] = value.split('#')
if (!authorizationCode || !state) {
setOAuthStatus({
state: 'error',
message: 'Invalid code. Please make sure the full code was copied',
toRetry: {
state: 'waiting_for_login',
url
}
});
return;
toRetry: { state: 'waiting_for_login', url },
})
return
}
// Track which path the user is taking (manual code entry)
logEvent('tengu_oauth_manual_entry', {});
logEvent('tengu_oauth_manual_entry', {})
oauthService.handleManualAuthCodeInput({
authorizationCode,
state
});
state,
})
} catch (err: unknown) {
logError(err);
logError(err)
setOAuthStatus({
state: 'error',
message: (err as Error).message,
toRetry: {
state: 'waiting_for_login',
url
}
});
toRetry: { state: 'waiting_for_login', url },
})
}
}
const startOAuth = useCallback(async () => {
// Clear any existing timers when starting new OAuth flow
timersRef.current.forEach(timer => clearTimeout(timer));
timersRef.current.clear();
timersRef.current.forEach(timer => clearTimeout(timer))
timersRef.current.clear()
try {
const result = await oauthService.startOAuthFlow(async url_0 => {
setOAuthStatus({
state: 'waiting_for_login',
url: url_0
});
const timer_0 = setTimeout(setShowPastePrompt, 3000, true);
timersRef.current.add(timer_0);
}, {
loginWithClaudeAi: true,
// Always use Claude AI for subscription tokens
inferenceOnly: true,
expiresIn: 365 * 24 * 60 * 60 // 1 year
});
const result = await oauthService.startOAuthFlow(
async url => {
setOAuthStatus({ state: 'waiting_for_login', url })
const timer = setTimeout(setShowPastePrompt, 3000, true)
timersRef.current.add(timer)
},
{
loginWithClaudeAi: true, // Always use Claude AI for subscription tokens
inferenceOnly: true,
expiresIn: 365 * 24 * 60 * 60, // 1 year
},
)
// Show processing state
setOAuthStatus({
state: 'processing'
});
setOAuthStatus({ state: 'processing' })
// OAuthFlowStep creates inference-only tokens for GitHub Actions, not a
// replacement login. Use saveOAuthTokensIfNeeded directly to avoid
// performLogout which would destroy the user's existing auth session.
saveOAuthTokensIfNeeded(result);
saveOAuthTokensIfNeeded(result)
// For OAuth flow, the access token can be used as an API key
const timer1 = setTimeout((setOAuthStatus_0, accessToken, onSuccess_0, timersRef_0) => {
setOAuthStatus_0({
state: 'success',
token: accessToken
});
// Auto-continue after brief delay to show success
const timer2 = setTimeout(onSuccess_0, 1000, accessToken);
timersRef_0.current.add(timer2 as ReturnType<typeof setTimeout>);
}, 100, setOAuthStatus, result.accessToken, onSuccess, timersRef);
timersRef.current.add(timer1);
} catch (err_0) {
const errorMessage = (err_0 as Error).message;
const timer1 = setTimeout(
(setOAuthStatus, accessToken, onSuccess, timersRef) => {
setOAuthStatus({ state: 'success', token: accessToken })
// Auto-continue after brief delay to show success
const timer2 = setTimeout(onSuccess, 1000, accessToken)
timersRef.current.add(timer2)
},
100,
setOAuthStatus,
result.accessToken,
onSuccess,
timersRef,
)
timersRef.current.add(timer1)
} catch (err) {
const errorMessage = (err as Error).message
setOAuthStatus({
state: 'error',
message: errorMessage,
toRetry: {
state: 'starting'
} // Allow retry by starting fresh OAuth flow
});
logError(err_0);
toRetry: { state: 'starting' }, // Allow retry by starting fresh OAuth flow
})
logError(err)
logEvent('tengu_oauth_error', {
error: errorMessage as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
});
error:
errorMessage as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
})
}
}, [oauthService, onSuccess]);
}, [oauthService, onSuccess])
useEffect(() => {
if (oauthStatus.state === 'starting') {
void startOAuth();
void startOAuth()
}
}, [oauthStatus.state, startOAuth]);
}, [oauthStatus.state, startOAuth])
// Retry logic
useEffect(() => {
if (oauthStatus.state === 'about_to_retry') {
const timer_1 = setTimeout((nextState, setShowPastePrompt_0, setOAuthStatus_1) => {
// Only show paste prompt when retrying to waiting_for_login
setShowPastePrompt_0(nextState.state === 'waiting_for_login');
setOAuthStatus_1(nextState);
}, 500, oauthStatus.nextState, setShowPastePrompt, setOAuthStatus);
timersRef.current.add(timer_1);
const timer = setTimeout(
(nextState, setShowPastePrompt, setOAuthStatus) => {
// Only show paste prompt when retrying to waiting_for_login
setShowPastePrompt(nextState.state === 'waiting_for_login')
setOAuthStatus(nextState)
},
500,
oauthStatus.nextState,
setShowPastePrompt,
setOAuthStatus,
)
timersRef.current.add(timer)
}
}, [oauthStatus]);
}, [oauthStatus])
useEffect(() => {
if (pastedCode === 'c' && oauthStatus.state === 'waiting_for_login' && showPastePrompt && !urlCopied) {
if (
pastedCode === 'c' &&
oauthStatus.state === 'waiting_for_login' &&
showPastePrompt &&
!urlCopied
) {
void setClipboard(oauthStatus.url).then(raw => {
if (raw) process.stdout.write(raw);
setUrlCopied(true);
clearTimeout(urlCopiedTimerRef.current);
urlCopiedTimerRef.current = setTimeout(setUrlCopied, 2000, false);
});
setPastedCode('');
if (raw) process.stdout.write(raw)
setUrlCopied(true)
clearTimeout(urlCopiedTimerRef.current)
urlCopiedTimerRef.current = setTimeout(setUrlCopied, 2000, false)
})
setPastedCode('')
}
}, [pastedCode, oauthStatus, showPastePrompt, urlCopied]);
}, [pastedCode, oauthStatus, showPastePrompt, urlCopied])
// Cleanup OAuth service and timers when component unmounts
useEffect(() => {
const timers = timersRef.current;
const timers = timersRef.current
return () => {
oauthService.cleanup();
oauthService.cleanup()
// Clear all timers
timers.forEach(timer_2 => clearTimeout(timer_2));
timers.clear();
clearTimeout(urlCopiedTimerRef.current);
};
}, [oauthService]);
timers.forEach(timer => clearTimeout(timer))
timers.clear()
clearTimeout(urlCopiedTimerRef.current)
}
}, [oauthService])
// Helper function to render the appropriate status message
function renderStatusMessage(): React.ReactNode {
switch (oauthStatus.state) {
case 'starting':
return <Box>
return (
<Box>
<Spinner />
<Text>Starting authentication</Text>
</Box>;
</Box>
)
case 'waiting_for_login':
return <Box flexDirection="column" gap={1}>
{!showPastePrompt && <Box>
return (
<Box flexDirection="column" gap={1}>
{!showPastePrompt && (
<Box>
<Spinner />
<Text>
Opening browser to sign in with your Claude account
</Text>
</Box>}
</Box>
)}
{showPastePrompt && <Box>
{showPastePrompt && (
<Box>
<Text>{PASTE_HERE_MSG}</Text>
<TextInput value={pastedCode} onChange={setPastedCode} onSubmit={(value_0: string) => handleSubmitCode(value_0, oauthStatus.url)} cursorOffset={cursorOffset} onChangeCursorOffset={setCursorOffset} columns={textInputColumns} />
</Box>}
</Box>;
<TextInput
value={pastedCode}
onChange={setPastedCode}
onSubmit={(value: string) =>
handleSubmitCode(value, oauthStatus.url)
}
cursorOffset={cursorOffset}
onChangeCursorOffset={setCursorOffset}
columns={textInputColumns}
/>
</Box>
)}
</Box>
)
case 'processing':
return <Box>
return (
<Box>
<Spinner />
<Text>Processing authentication</Text>
</Box>;
</Box>
)
case 'success':
return <Box flexDirection="column" gap={1}>
return (
<Box flexDirection="column" gap={1}>
<Text color="success">
Authentication token created successfully!
</Text>
<Text dimColor>Using token for GitHub Actions setup</Text>
</Box>;
</Box>
)
case 'error':
return <Box flexDirection="column" gap={1}>
return (
<Box flexDirection="column" gap={1}>
<Text color="error">OAuth error: {oauthStatus.message}</Text>
{oauthStatus.toRetry ? <Text dimColor>
{oauthStatus.toRetry ? (
<Text dimColor>
Press Enter to try again, or any other key to cancel
</Text> : <Text dimColor>Press any key to return to API key selection</Text>}
</Box>;
</Text>
) : (
<Text dimColor>Press any key to return to API key selection</Text>
)}
</Box>
)
case 'about_to_retry':
return <Box flexDirection="column" gap={1}>
return (
<Box flexDirection="column" gap={1}>
<Text color="permission">Retrying</Text>
</Box>;
</Box>
)
default:
return null;
return null
}
}
return <Box flexDirection="column" gap={1} tabIndex={0} autoFocus onKeyDown={handleKeyDown}>
return (
<Box
flexDirection="column"
gap={1}
tabIndex={0}
autoFocus
onKeyDown={handleKeyDown}
>
{/* Show header inline only for initial starting state */}
{oauthStatus.state === 'starting' && <Box flexDirection="column" gap={1} paddingBottom={1}>
{oauthStatus.state === 'starting' && (
<Box flexDirection="column" gap={1} paddingBottom={1}>
<Text bold>Create Authentication Token</Text>
<Text dimColor>Creating a long-lived token for GitHub Actions</Text>
</Box>}
</Box>
)}
{/* Show header for non-starting states (to avoid duplicate with inline header)*/}
{oauthStatus.state !== 'success' && oauthStatus.state !== 'starting' && oauthStatus.state !== 'processing' && <Box key="header" flexDirection="column" gap={1} paddingBottom={1}>
{oauthStatus.state !== 'success' &&
oauthStatus.state !== 'starting' &&
oauthStatus.state !== 'processing' && (
<Box key="header" flexDirection="column" gap={1} paddingBottom={1}>
<Text bold>Create Authentication Token</Text>
<Text dimColor>Creating a long-lived token for GitHub Actions</Text>
</Box>}
</Box>
)}
{/* Show URL when paste prompt is visible */}
{oauthStatus.state === 'waiting_for_login' && showPastePrompt && <Box flexDirection="column" key="urlToCopy" gap={1} paddingBottom={1}>
{oauthStatus.state === 'waiting_for_login' && showPastePrompt && (
<Box flexDirection="column" key="urlToCopy" gap={1} paddingBottom={1}>
<Box paddingX={1}>
<Text dimColor>
Browser didn&apos;t open? Use the url below to sign in{' '}
</Text>
{urlCopied ? <Text color="success">(Copied!)</Text> : <Text dimColor>
{urlCopied ? (
<Text color="success">(Copied!)</Text>
) : (
<Text dimColor>
<KeyboardShortcutHint shortcut="c" action="copy" parens />
</Text>}
</Text>
)}
</Box>
<Link url={oauthStatus.url}>
<Text dimColor>{oauthStatus.url}</Text>
</Link>
</Box>}
</Box>
)}
<Box paddingLeft={1} flexDirection="column" gap={1}>
{renderStatusMessage()}
</Box>
</Box>;
</Box>
)
}

View File

@@ -1,95 +1,65 @@
import { c as _c } from "react/compiler-runtime";
import React from 'react';
import { Box, Text } from '../../ink.js';
import React from 'react'
import { Box, Text } from '../../ink.js'
type SuccessStepProps = {
secretExists: boolean;
useExistingSecret: boolean;
secretName: string;
skipWorkflow?: boolean;
};
export function SuccessStep(t0) {
const $ = _c(21);
const {
secretExists,
useExistingSecret,
secretName,
skipWorkflow: t1
} = t0;
const skipWorkflow = t1 === undefined ? false : t1;
let t2;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t2 = <Box flexDirection="column" marginBottom={1}><Text bold={true}>Install GitHub App</Text><Text dimColor={true}>Success</Text></Box>;
$[0] = t2;
} else {
t2 = $[0];
}
let t3;
if ($[1] !== skipWorkflow) {
t3 = !skipWorkflow && <Text color="success"> GitHub Actions workflow created!</Text>;
$[1] = skipWorkflow;
$[2] = t3;
} else {
t3 = $[2];
}
let t4;
if ($[3] !== secretExists || $[4] !== useExistingSecret) {
t4 = secretExists && useExistingSecret && <Box marginTop={1}><Text color="success"> Using existing ANTHROPIC_API_KEY secret</Text></Box>;
$[3] = secretExists;
$[4] = useExistingSecret;
$[5] = t4;
} else {
t4 = $[5];
}
let t5;
if ($[6] !== secretExists || $[7] !== secretName || $[8] !== useExistingSecret) {
t5 = (!secretExists || !useExistingSecret) && <Box marginTop={1}><Text color="success"> API key saved as {secretName} secret</Text></Box>;
$[6] = secretExists;
$[7] = secretName;
$[8] = useExistingSecret;
$[9] = t5;
} else {
t5 = $[9];
}
let t6;
if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
t6 = <Box marginTop={1}><Text>Next steps:</Text></Box>;
$[10] = t6;
} else {
t6 = $[10];
}
let t7;
if ($[11] !== skipWorkflow) {
t7 = skipWorkflow ? <><Text>1. Install the Claude GitHub App if you haven't already</Text><Text>2. Your workflow file was kept unchanged</Text><Text>3. API key is configured and ready to use</Text></> : <><Text>1. A pre-filled PR page has been created</Text><Text>2. Install the Claude GitHub App if you haven't already</Text><Text>3. Merge the PR to enable Claude PR assistance</Text></>;
$[11] = skipWorkflow;
$[12] = t7;
} else {
t7 = $[12];
}
let t8;
if ($[13] !== t3 || $[14] !== t4 || $[15] !== t5 || $[16] !== t7) {
t8 = <Box flexDirection="column" borderStyle="round" paddingX={1}>{t2}{t3}{t4}{t5}{t6}{t7}</Box>;
$[13] = t3;
$[14] = t4;
$[15] = t5;
$[16] = t7;
$[17] = t8;
} else {
t8 = $[17];
}
let t9;
if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
t9 = <Box marginLeft={3}><Text dimColor={true}>Press any key to exit</Text></Box>;
$[18] = t9;
} else {
t9 = $[18];
}
let t10;
if ($[19] !== t8) {
t10 = <>{t8}{t9}</>;
$[19] = t8;
$[20] = t10;
} else {
t10 = $[20];
}
return t10;
secretExists: boolean
useExistingSecret: boolean
secretName: string
skipWorkflow?: boolean
}
export function SuccessStep({
secretExists,
useExistingSecret,
secretName,
skipWorkflow = false,
}: SuccessStepProps): React.ReactNode {
return (
<>
<Box flexDirection="column" borderStyle="round" paddingX={1}>
<Box flexDirection="column" marginBottom={1}>
<Text bold>Install GitHub App</Text>
<Text dimColor>Success</Text>
</Box>
{!skipWorkflow && (
<Text color="success"> GitHub Actions workflow created!</Text>
)}
{secretExists && useExistingSecret && (
<Box marginTop={1}>
<Text color="success">
Using existing ANTHROPIC_API_KEY secret
</Text>
</Box>
)}
{(!secretExists || !useExistingSecret) && (
<Box marginTop={1}>
<Text color="success"> API key saved as {secretName} secret</Text>
</Box>
)}
<Box marginTop={1}>
<Text>Next steps:</Text>
</Box>
{skipWorkflow ? (
<>
<Text>
1. Install the Claude GitHub App if you haven&apos;t already
</Text>
<Text>2. Your workflow file was kept unchanged</Text>
<Text>3. API key is configured and ready to use</Text>
</>
) : (
<>
<Text>1. A pre-filled PR page has been created</Text>
<Text>
2. Install the Claude GitHub App if you haven&apos;t already
</Text>
<Text>3. Merge the PR to enable Claude PR assistance</Text>
</>
)}
</Box>
<Box marginLeft={3}>
<Text dimColor>Press any key to exit</Text>
</Box>
</>
)
}

View File

@@ -1,72 +1,59 @@
import { c as _c } from "react/compiler-runtime";
import figures from 'figures';
import React from 'react';
import { GITHUB_ACTION_SETUP_DOCS_URL } from '../../constants/github-app.js';
import { Box, Text } from '../../ink.js';
import { useKeybinding } from '../../keybindings/useKeybinding.js';
import type { Warning } from './types.js';
import figures from 'figures'
import React from 'react'
import { GITHUB_ACTION_SETUP_DOCS_URL } from '../../constants/github-app.js'
import { Box, Text } from '../../ink.js'
import { useKeybinding } from '../../keybindings/useKeybinding.js'
import type { Warning } from './types.js'
interface WarningsStepProps {
warnings: Warning[];
onContinue: () => void;
warnings: Warning[]
onContinue: () => void
}
export function WarningsStep(t0) {
const $ = _c(8);
const {
warnings,
onContinue
} = t0;
let t1;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t1 = {
context: "Confirmation"
};
$[0] = t1;
} else {
t1 = $[0];
}
useKeybinding("confirm:yes", onContinue, t1);
let t2;
if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
t2 = <Box flexDirection="column" marginBottom={1}><Text bold={true}>{figures.warning} Setup Warnings</Text><Text dimColor={true}>We found some potential issues, but you can continue anyway</Text></Box>;
$[1] = t2;
} else {
t2 = $[1];
}
let t3;
if ($[2] !== warnings) {
t3 = warnings.map(_temp2);
$[2] = warnings;
$[3] = t3;
} else {
t3 = $[3];
}
let t4;
if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
t4 = <Box marginTop={1}><Text bold={true} color="permission">Press Enter to continue anyway, or Ctrl+C to exit and fix issues</Text></Box>;
$[4] = t4;
} else {
t4 = $[4];
}
let t5;
if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
t5 = <Box marginTop={1}><Text dimColor={true}>You can also try the manual setup steps if needed:{" "}<Text color="claude">{GITHUB_ACTION_SETUP_DOCS_URL}</Text></Text></Box>;
$[5] = t5;
} else {
t5 = $[5];
}
let t6;
if ($[6] !== t3) {
t6 = <><Box flexDirection="column" borderStyle="round" paddingX={1}>{t2}{t3}{t4}{t5}</Box></>;
$[6] = t3;
$[7] = t6;
} else {
t6 = $[7];
}
return t6;
}
function _temp2(warning, index) {
return <Box key={index} flexDirection="column" marginBottom={1}><Text color="warning" bold={true}>{warning.title}</Text><Text>{warning.message}</Text>{warning.instructions.length > 0 && <Box flexDirection="column" marginLeft={2} marginTop={1}>{warning.instructions.map(_temp)}</Box>}</Box>;
}
function _temp(instruction, i) {
return <Text key={i} dimColor={true}> {instruction}</Text>;
export function WarningsStep({ warnings, onContinue }: WarningsStepProps) {
// Enter to continue
useKeybinding('confirm:yes', onContinue, { context: 'Confirmation' })
return (
<>
<Box flexDirection="column" borderStyle="round" paddingX={1}>
<Box flexDirection="column" marginBottom={1}>
<Text bold>{figures.warning} Setup Warnings</Text>
<Text dimColor>
We found some potential issues, but you can continue anyway
</Text>
</Box>
{warnings.map((warning, index) => (
<Box key={index} flexDirection="column" marginBottom={1}>
<Text color="warning" bold>
{warning.title}
</Text>
<Text>{warning.message}</Text>
{warning.instructions.length > 0 && (
<Box flexDirection="column" marginLeft={2} marginTop={1}>
{warning.instructions.map((instruction, i) => (
<Text key={i} dimColor>
{instruction}
</Text>
))}
</Box>
)}
</Box>
))}
<Box marginTop={1}>
<Text bold color="permission">
Press Enter to continue anyway, or Ctrl+C to exit and fix issues
</Text>
</Box>
<Box marginTop={1}>
<Text dimColor>
You can also try the manual setup steps if needed:{' '}
<Text color="claude">{GITHUB_ACTION_SETUP_DOCS_URL}</Text>
</Text>
</Box>
</Box>
</>
)
}

File diff suppressed because it is too large Load Diff