mirror of
https://github.com/paoloanzn/free-code.git
synced 2026-10-22 02:53:27 -05:00
feat: add UltraplanLaunchDialog and UltraplanChoiceDialog components
These components were referenced in REPL.tsx but never defined, causing
a runtime crash when ultraplan tried to launch. Added:
- UltraplanLaunchDialog: pre-launch confirmation with terms/cancel
- UltraplanChoiceDialog: post-plan approval with execute-here/dismiss
- Conditional requires in REPL.tsx gated on feature('ULTRAPLAN')
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
61a23c19bf
commit
fcf5ab7dbb
3 files changed
+162
No files matched your search
@@ -0,0 +1,114 @@
|
||||
import React, { useCallback } from 'react'
|
||||
import { Box, Text } from '../ink.js'
|
||||
import { Select } from './CustomSelect/index.js'
|
||||
import { Dialog } from './design-system/Dialog.js'
|
||||
import type { AppState } from '../state/AppStateStore.js'
|
||||
import { useSetAppState } from '../state/AppState.js'
|
||||
import type { Message } from '../types/message.js'
|
||||
import type { RemoteAgentTaskState } from '../tasks/RemoteAgentTask/RemoteAgentTask.js'
|
||||
import type { FileStateCache } from '../utils/fileStateCache.js'
|
||||
import {
|
||||
createUserMessage,
|
||||
createSystemMessage,
|
||||
prepareUserContent,
|
||||
} from '../utils/messages.js'
|
||||
import { updateTaskState } from '../utils/task/framework.js'
|
||||
import { archiveRemoteSession } from '../utils/teleport.js'
|
||||
import { logForDebugging } from '../utils/debug.js'
|
||||
|
||||
type UltraplanChoice = 'execute' | 'dismiss'
|
||||
|
||||
type Props = {
|
||||
plan: string
|
||||
sessionId: string
|
||||
taskId: string
|
||||
setMessages: React.Dispatch<React.SetStateAction<Message[]>>
|
||||
readFileState: FileStateCache
|
||||
getAppState: () => AppState
|
||||
setConversationId: (id: string) => void
|
||||
}
|
||||
|
||||
export function UltraplanChoiceDialog({
|
||||
plan,
|
||||
sessionId,
|
||||
taskId,
|
||||
setMessages,
|
||||
}: Props): React.ReactNode {
|
||||
const setAppState = useSetAppState()
|
||||
|
||||
const handleChoice = useCallback(
|
||||
(choice: UltraplanChoice) => {
|
||||
if (choice === 'execute') {
|
||||
setMessages(prev => [
|
||||
...prev,
|
||||
createSystemMessage(
|
||||
'Ultraplan approved. Executing the following plan:',
|
||||
'info',
|
||||
),
|
||||
createUserMessage({
|
||||
content: prepareUserContent({ inputString: plan }),
|
||||
}),
|
||||
])
|
||||
}
|
||||
|
||||
// Mark task completed
|
||||
updateTaskState<RemoteAgentTaskState>(taskId, setAppState, t =>
|
||||
t.status !== 'running'
|
||||
? t
|
||||
: { ...t, status: 'completed', endTime: Date.now() },
|
||||
)
|
||||
|
||||
// Clear ultraplan state
|
||||
setAppState(prev => ({
|
||||
...prev,
|
||||
ultraplanPendingChoice: undefined,
|
||||
ultraplanSessionUrl: undefined,
|
||||
}))
|
||||
|
||||
// Archive the remote session
|
||||
void archiveRemoteSession(sessionId).catch(e =>
|
||||
logForDebugging(`ultraplan choice archive failed: ${String(e)}`),
|
||||
)
|
||||
},
|
||||
[plan, sessionId, taskId, setMessages, setAppState],
|
||||
)
|
||||
|
||||
const displayPlan =
|
||||
plan.length > 2000 ? plan.slice(0, 2000) + '\n\n... (truncated)' : plan
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
title="Ultraplan ready"
|
||||
onCancel={() => handleChoice('dismiss')}
|
||||
>
|
||||
<Box flexDirection="column" gap={1}>
|
||||
<Box
|
||||
flexDirection="column"
|
||||
borderStyle="single"
|
||||
borderColor="gray"
|
||||
paddingX={1}
|
||||
height={Math.min(displayPlan.split('\n').length + 2, 20)}
|
||||
overflow="hidden"
|
||||
>
|
||||
<Text>{displayPlan}</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
<Select
|
||||
options={[
|
||||
{
|
||||
value: 'execute' as const,
|
||||
label: 'Execute plan here',
|
||||
description:
|
||||
'Send the plan to Claude for execution in this session',
|
||||
},
|
||||
{
|
||||
value: 'dismiss' as const,
|
||||
label: 'Dismiss',
|
||||
description: 'Discard the plan',
|
||||
},
|
||||
]}
|
||||
onChange={(value: UltraplanChoice) => handleChoice(value)}
|
||||
/>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
import React from 'react'
|
||||
import { Box, Text } from '../ink.js'
|
||||
import { Select } from './CustomSelect/index.js'
|
||||
import { Dialog } from './design-system/Dialog.js'
|
||||
import { CCR_TERMS_URL } from '../commands/ultraplan.js'
|
||||
|
||||
type UltraplanLaunchChoice = 'launch' | 'cancel'
|
||||
|
||||
type Props = {
|
||||
onChoice: (
|
||||
choice: UltraplanLaunchChoice,
|
||||
opts?: { disconnectedBridge?: boolean },
|
||||
) => void
|
||||
}
|
||||
|
||||
export function UltraplanLaunchDialog({ onChoice }: Props): React.ReactNode {
|
||||
return (
|
||||
<Dialog
|
||||
title="Launch ultraplan?"
|
||||
onCancel={() => onChoice('cancel')}
|
||||
>
|
||||
<Box flexDirection="column" gap={1}>
|
||||
<Text>
|
||||
This will start a remote Claude Code session on the web to draft an
|
||||
advanced plan using Opus. The plan typically takes 10–30 minutes.
|
||||
Your terminal stays free while it works.
|
||||
</Text>
|
||||
<Text dimColor>Terms: {CCR_TERMS_URL}</Text>
|
||||
</Box>
|
||||
<Select
|
||||
options={[
|
||||
{
|
||||
value: 'launch' as const,
|
||||
label: 'Launch ultraplan',
|
||||
},
|
||||
{
|
||||
value: 'cancel' as const,
|
||||
label: 'Cancel',
|
||||
},
|
||||
]}
|
||||
onChange={(value: UltraplanLaunchChoice) => onChoice(value)}
|
||||
/>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
@@ -270,6 +270,9 @@ import type { HookProgress } from '../types/hooks.js';
|
||||
import { TungstenLiveMonitor } from '../tools/TungstenTool/TungstenLiveMonitor.js';
|
||||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
const WebBrowserPanelModule = feature('WEB_BROWSER_TOOL') ? require('../tools/WebBrowserTool/WebBrowserPanel.js') as typeof import('../tools/WebBrowserTool/WebBrowserPanel.js') : null;
|
||||
const UltraplanLaunchDialog: typeof import('../components/UltraplanLaunchDialog.js').UltraplanLaunchDialog = feature('ULTRAPLAN') ? require('../components/UltraplanLaunchDialog.js').UltraplanLaunchDialog : () => null;
|
||||
const UltraplanChoiceDialog: typeof import('../components/UltraplanChoiceDialog.js').UltraplanChoiceDialog = feature('ULTRAPLAN') ? require('../components/UltraplanChoiceDialog.js').UltraplanChoiceDialog : () => null;
|
||||
const launchUltraplan: typeof import('../commands/ultraplan.js').launchUltraplan = feature('ULTRAPLAN') ? require('../commands/ultraplan.js').launchUltraplan : () => Promise.resolve('');
|
||||
/* eslint-enable @typescript-eslint/no-require-imports */
|
||||
import { IssueFlagBanner } from '../components/PromptInput/IssueFlagBanner.js';
|
||||
import { useIssueFlagBanner } from '../hooks/useIssueFlagBanner.js';
|
||||
|
||||
Reference in new issue
Block a user