claude-code-best/src/dialogLaunchers.tsx
unraid 2247026bd5 chore: 添加脚本与构建配置更新
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-22 22:38:10 +08:00

202 lines
6.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Thin launchers for one-off dialog JSX sites in main.tsx.
* Each launcher dynamically imports its component and wires the `done` callback
* identically to the original inline call site. Zero behavior change.
*
* Part of the main.tsx React/JSX extraction effort. See sibling PRs
* perf/extract-interactive-helpers and perf/launch-repl.
*/
import React from 'react'
import type { AssistantSession } from './assistant/sessionDiscovery.js'
import type { StatsStore } from './context/stats.js'
import type { Root } from '@anthropic/ink'
import { renderAndRun, showSetupDialog } from './interactiveHelpers.js'
import { KeybindingSetup } from './keybindings/KeybindingProviderSetup.js'
import type { AppState } from './state/AppStateStore.js'
import type { AgentMemoryScope } from '@claude-code-best/builtin-tools/tools/AgentTool/agentMemory.js'
import type { TeleportRemoteResponse } from './utils/conversationRecovery.js'
import type { FpsMetrics } from './utils/fpsTracker.js'
import type { ValidationError } from './utils/settings/validation.js'
// Type-only access to ResumeConversation's Props via the module type.
// No runtime cost - erased at compile time.
type ResumeConversationProps = React.ComponentProps<
typeof import('./screens/ResumeConversation.js').ResumeConversation
>
/**
* Site ~3173: SnapshotUpdateDialog (agent memory snapshot update prompt).
* Original callback wiring: onComplete={done}, onCancel={() => done('keep')}.
*/
export async function launchSnapshotUpdateDialog(
root: Root,
props: {
agentType: string
scope: AgentMemoryScope
snapshotTimestamp: string
},
): Promise<'merge' | 'keep' | 'replace'> {
const { SnapshotUpdateDialog } = await import(
'./components/agents/SnapshotUpdateDialog.js'
)
return showSetupDialog<'merge' | 'keep' | 'replace'>(root, done => (
<SnapshotUpdateDialog
agentType={props.agentType}
scope={props.scope}
snapshotTimestamp={props.snapshotTimestamp}
onComplete={done}
onCancel={() => done('keep')} // Esc/cancel â safe default: keep current memory
/>
))
}
/**
* Site ~3250: InvalidSettingsDialog (settings validation errors).
* Original callback wiring: onContinue={done}, onExit passed through from caller.
*/
export async function launchInvalidSettingsDialog(
root: Root,
props: {
settingsErrors: ValidationError[]
onExit: () => void
},
): Promise<void> {
const { InvalidSettingsDialog } = await import(
'./components/InvalidSettingsDialog.js'
)
return showSetupDialog(root, done => (
<InvalidSettingsDialog
settingsErrors={props.settingsErrors}
onContinue={done}
onExit={props.onExit}
/>
))
}
/**
* Site ~4229: AssistantSessionChooser (pick a bridge session to attach to).
* Original callback wiring: onSelect={id => done(id)}, onCancel={() => done(null)}.
*/
export async function launchAssistantSessionChooser(
root: Root,
props: { sessions: AssistantSession[] },
): Promise<string | null> {
const { AssistantSessionChooser } = await import(
'./assistant/AssistantSessionChooser.js'
)
return showSetupDialog<string | null>(root, done => (
<AssistantSessionChooser
sessions={props.sessions}
onSelect={(id: string) => done(id)}
onCancel={() => done(null)}
/>
))
}
/**
* `claude assistant` found zero sessions — show the same install wizard
* as `/assistant` when daemon.json is empty. Resolves to the installed dir on
* success, null on cancel. Rejects on install failure so the caller can
* distinguish errors from user cancellation.
*/
export async function launchAssistantInstallWizard(
root: Root,
): Promise<string | null> {
const { NewInstallWizard, computeDefaultInstallDir } = await import(
'./commands/assistant/assistant.js'
)
const defaultDir = await computeDefaultInstallDir()
let rejectWithError: (reason: Error) => void
const errorPromise = new Promise<never>((_, reject) => {
rejectWithError = reject
})
const resultPromise = showSetupDialog<string | null>(root, done => (
<NewInstallWizard
defaultDir={defaultDir}
onInstalled={dir => done(dir)}
onCancel={() => done(null)}
onError={message =>
rejectWithError(new Error(`Installation failed: ${message}`))
}
/>
))
return Promise.race([resultPromise, errorPromise])
}
/**
* Site ~4549: TeleportResumeWrapper (interactive teleport session picker).
* Original callback wiring: onComplete={done}, onCancel={() => done(null)}, source="cliArg".
*/
export async function launchTeleportResumeWrapper(
root: Root,
): Promise<TeleportRemoteResponse | null> {
const { TeleportResumeWrapper } = await import(
'./components/TeleportResumeWrapper.js'
)
return showSetupDialog<TeleportRemoteResponse | null>(root, done => (
<TeleportResumeWrapper
onComplete={done}
onCancel={() => done(null)}
source="cliArg"
/>
))
}
/**
* Site ~4597: TeleportRepoMismatchDialog (pick a local checkout of the target repo).
* Original callback wiring: onSelectPath={done}, onCancel={() => done(null)}.
*/
export async function launchTeleportRepoMismatchDialog(
root: Root,
props: {
targetRepo: string
initialPaths: string[]
},
): Promise<string | null> {
const { TeleportRepoMismatchDialog } = await import(
'./components/TeleportRepoMismatchDialog.js'
)
return showSetupDialog<string | null>(root, done => (
<TeleportRepoMismatchDialog
targetRepo={props.targetRepo}
initialPaths={props.initialPaths}
onSelectPath={done}
onCancel={() => done(null)}
/>
))
}
/**
* Site ~4903: ResumeConversation mount (interactive session picker).
* Wraps in <App><KeybindingSetup> and uses renderAndRun.
* Preserves original Promise.all parallelism between getWorktreePaths and imports.
*/
export async function launchResumeChooser(
root: Root,
appProps: {
getFpsMetrics: () => FpsMetrics | undefined
stats: StatsStore
initialState: AppState
},
worktreePathsPromise: Promise<string[]>,
resumeProps: Omit<ResumeConversationProps, 'worktreePaths'>,
): Promise<void> {
const [worktreePaths, { ResumeConversation }, { App }] = await Promise.all([
worktreePathsPromise,
import('./screens/ResumeConversation.js'),
import('./components/App.js'),
])
await renderAndRun(
root,
<App
getFpsMetrics={appProps.getFpsMetrics}
stats={appProps.stats}
initialState={appProps.initialState}
>
<KeybindingSetup>
<ResumeConversation {...resumeProps} worktreePaths={worktreePaths} />
</KeybindingSetup>
</App>,
)
}