mirror of
http://10.0.2.1:3031/sauer/claude-code.git
synced 2026-06-30 12:56:58 +10:00
133 lines
22 KiB
TypeScript
133 lines
22 KiB
TypeScript
|
|
/**
|
||
|
|
* 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 './ink.js';
|
||
|
|
import { renderAndRun, showSetupDialog } from './interactiveHelpers.js';
|
||
|
|
import { KeybindingSetup } from './keybindings/KeybindingProviderSetup.js';
|
||
|
|
import type { AppState } from './state/AppStateStore.js';
|
||
|
|
import type { AgentMemoryScope } from './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')} />);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 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 => 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).
|
||
|
|
* Uses renderAndRun, NOT showSetupDialog. Wraps in <App><KeybindingSetup>.
|
||
|
|
* 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>);
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkFzc2lzdGFudFNlc3Npb24iLCJTdGF0c1N0b3JlIiwiUm9vdCIsInJlbmRlckFuZFJ1biIsInNob3dTZXR1cERpYWxvZyIsIktleWJpbmRpbmdTZXR1cCIsIkFwcFN0YXRlIiwiQWdlbnRNZW1vcnlTY29wZSIsIlRlbGVwb3J0UmVtb3RlUmVzcG9uc2UiLCJGcHNNZXRyaWNzIiwiVmFsaWRhdGlvbkVycm9yIiwiUmVzdW1lQ29udmVyc2F0aW9uUHJvcHMiLCJDb21wb25lbnRQcm9wcyIsIlJlc3VtZUNvbnZlcnNhdGlvbiIsImxhdW5jaFNuYXBzaG90VXBkYXRlRGlhbG9nIiwicm9vdCIsInByb3BzIiwiYWdlbnRUeXBlIiwic2NvcGUiLCJzbmFwc2hvdFRpbWVzdGFtcCIsIlByb21pc2UiLCJTbmFwc2hvdFVwZGF0ZURpYWxvZyIsImRvbmUiLCJsYXVuY2hJbnZhbGlkU2V0dGluZ3NEaWFsb2ciLCJzZXR0aW5nc0Vycm9ycyIsIm9uRXhpdCIsIkludmFsaWRTZXR0aW5nc0RpYWxvZyIsImxhdW5jaEFzc2lzdGFudFNlc3Npb25DaG9vc2VyIiwic2Vzc2lvbnMiLCJBc3Npc3RhbnRTZXNzaW9uQ2hvb3NlciIsImlkIiwibGF1bmNoQXNzaXN0YW50SW5zdGFsbFdpemFyZCIsIk5ld0luc3RhbGxXaXphcmQiLCJjb21wdXRlRGVmYXVsdEluc3RhbGxEaXIiLCJkZWZhdWx0RGlyIiwicmVqZWN0V2l0aEVycm9yIiwicmVhc29uIiwiRXJyb3IiLCJlcnJvclByb21pc2UiLCJfIiwicmVqZWN0IiwicmVzdWx0UHJvbWlzZSIsImRpciIsIm1lc3NhZ2UiLCJyYWNlIiwibGF1bmNoVGVsZXBvcnRSZXN1bWVXcmFwcGVyIiwiVGVsZXBvcnRSZXN1bWVXcmFwcGVyIiwibGF1bmNoVGVsZXBvcnRSZXBvTWlzbWF0Y2hEaWFsb2ciLCJ0YXJnZXRSZXBvIiwiaW5pdGlhbFBhdGhzIiwiVGVsZXBvcnRSZXBvTWlzbWF0Y2hEaWFsb2ciLCJsYXVuY2hSZXN1bWVDaG9vc2VyIiwiYXBwUHJvcHMiLCJnZXRGcHNNZXRyaWNzIiwic3RhdHMiLCJpbml0aWFsU3RhdGUiLCJ3b3JrdHJlZVBhdGhzUHJvbWlzZSIsInJlc3VtZVByb3BzIiwiT21pdCIsIndvcmt0cmVlUGF0aHMiLCJBcHAiLCJhbGwiXSwic291cmNlcyI6WyJkaWFsb2dMYXVuY2hlcnMudHN4Il0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogVGhpbiBsYXVuY2hlcnMgZm9yIG9uZS1vZmYgZGlhbG9nIEpTWCBzaXRlcyBpbiBtYWluLnRzeC5cbiAqIEVhY2ggbGF1bmNoZXIgZHluYW1pY2FsbHkgaW1wb3J0cyBpdHMgY29tcG9uZW50IGFuZCB3aXJlcyB0aGUgYGRvbmVgIGNhbGxiYWNrXG4gKiBpZGVudGljYWxseSB0byB0aGUgb3JpZ2luYWwgaW5saW5lIGNhbGwgc2l0ZS4gWmVybyBiZWhhdmlvciBjaGFuZ2UuXG4gKlxuICogUGFydCBvZiB0aGUgbWFpbi50c3ggUmVhY3QvSlNYIGV4dHJhY3Rpb24gZWZmb3J0LiBTZWUgc2libGluZyBQUnNcbiAqIHBlcmYvZXh0cmFjdC1pbnRlcmFjdGl2ZS1oZWxwZXJzIGFuZCBwZXJmL2xhdW5jaC1yZXBsLlxuICovXG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgdHlwZSB7IEFzc2lzdGFudFNlc3Npb24gfSBmcm9tICcuL2Fzc2lzdGFudC9zZXNzaW9uRGlzY292ZXJ5LmpzJ1xuaW1wb3J0IHR5cGUgeyBTdGF0c1N0b3JlIH0gZnJvbSAnLi9jb250ZXh0L3N0YXRzLmpzJ1xuaW1wb3J0IHR5cGUgeyBSb290IH0gZnJvbSAnLi9pbmsuanMnXG5pbXBvcnQgeyByZW5kZXJBbmRSdW4sIHNob3dTZXR1cERpYWxvZyB9IGZyb20gJy4vaW50ZXJhY3RpdmVIZWxwZXJzLmpzJ1xuaW1wb3J0IHsgS2V5YmluZGluZ1NldHVwIH0gZnJvbSAnLi9rZXliaW5kaW5ncy9LZXliaW5kaW5nUHJvdmlkZXJTZXR1cC5qcydcbmltcG9ydCB0eXBlIHsgQXBwU3RhdGUgfSBmcm9tICcuL3N0YXRlL0FwcFN0YXRlU3RvcmUuanMnXG5pbXBvcnQgdHlwZSB7IEFnZW50TWVtb3J5U2NvcGUgfSBmcm9tICcuL3Rvb2xzL0FnZW50VG9vbC9hZ2VudE1lbW9yeS5qcydcbmltcG9ydCB0eXBlIHsgVGVsZXBvcnRSZW1vdGVSZXNwb25zZSB9IGZyb20gJy4vdXRpbHMvY29udmVyc2F0aW9uUmVjb3ZlcnkuanMnXG5pbXBvcnQgdHlwZSB7IEZwc01ldHJpY3MgfSBmcm9tICcuL3V0aWxzL2Zwc1RyYWNrZXIuanMnXG5pbXBvcnQgdHlwZSB7IFZhbGlkYXRpb25FcnJvciB9IGZyb20gJy4vdXRpbHMvc2V0dGluZ3MvdmFsaWRhdGlvbi5qcydcblxuLy8gVHlwZS1vbmx5IGFjY2VzcyB0byBSZXN1bWVDb252ZXJzYXRpb24ncyBQcm9wcyB2aWEgdGhlIG1vZHVsZSB0eXBlLlxuLy8gTm8gcnVudGltZSBjb3N0IC0gZXJhc2VkIGF0IGNvbXBpbGUgdGltZS5cbnR5cGUgUmVzdW1lQ29udmVyc2F0aW9uUHJvcHMgPSBSZWFjdC5Db21wb25lbnRQcm9wczxcbiAgdHlwZW9mIGltcG9ydCgnLi9zY3JlZW5zL1Jlc3VtZUNvbnZlcnNhdGlvbi5qcycpLlJlc3VtZUNvbnZlcnNhdGlvblxuPlxuXG4vKipcbiAqIFNpdGUgfjMxNzM6IFNuYXBzaG90VXBkYXRlRGlhbG9nIChhZ2VudCBtZW1vcnkgc25hcHNob3QgdXBkYXRlIHByb21wdCkuXG4gKiBPcmlnaW5hbCBjYWxsYmFjayB3aXJpbmc6IG9uQ29tcGxldGU9e2RvbmV9LCBvbkNhbmNlbD17KCkgPT4gZG9uZSgna2VlcCcpfS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxhdW5jaFNuYXBzaG90VXBkYXRlRGlhbG9nKFxuICByb290OiBSb290LFxuICBwcm9wczoge1xuICAgIGFnZW50VHlwZTogc3RyaW5nXG4gICAgc2NvcGU6IEFnZW50TWVtb3J5U2NvcGVcbiAgICBzbmFwc2hvdFRpbWVzdGFtcDogc3RyaW5nXG4gIH0sXG4pOiBQcm9taXNlPCdtZXJnZScgfCAna2VlcCcgfCAncmVwbGFjZSc+IHtcbiAgY29uc3QgeyBTbmFwc2hvdFVwZGF0ZURpYWxvZyB9ID0gYXdhaXQgaW1wb3J0KFxuICAgICcuL2NvbXBvbmVudHMvYWdlbnRzL1NuYXBzaG90VXBkYXRlRGlhbG9nLmpzJ1xuICApXG4gIHJldHVybiBzaG93U2V0dXBEaWFsb2c8J21lcmdlJyB8ICdrZWVwJyB8ICdyZXBsYWNlJz4ocm9vdCwgZG9uZSA9PiAoXG4gICAgPFNuYXBzaG90VXBkYXRlRGlhbG9nXG4gICAgICBhZ2VudFR5cGU9e3Byb3BzLmFnZW50VHlwZX1cbiAgICAgIHNjb3BlPXtwcm9wcy5zY29wZX1cbiAgICAgIHN
|