(opts: {
blurb: string;
seedPlan?: string;
getAppState: () => AppState;
setAppState: (f: (prev: AppState) => AppState) => void;
signal: AbortSignal;
/** True if the caller disconnected Remote Control before launching. */
disconnectedBridge?: boolean;
/**
* Called once teleportToRemote resolves with a session URL. Callers that
* have setMessages (REPL) append this as a second transcript message so the
* URL is visible without opening the ↓ detail view. Callers without
* transcript access (ExitPlanModePermissionRequest) omit this — the pill
* still shows live status.
*/
onSessionReady?: (msg: string) => void;
})
| 232 | * enqueuePendingNotification. |
| 233 | */ |
| 234 | export async function launchUltraplan(opts: { |
| 235 | blurb: string; |
| 236 | seedPlan?: string; |
| 237 | getAppState: () => AppState; |
| 238 | setAppState: (f: (prev: AppState) => AppState) => void; |
| 239 | signal: AbortSignal; |
| 240 | /** True if the caller disconnected Remote Control before launching. */ |
| 241 | disconnectedBridge?: boolean; |
| 242 | /** |
| 243 | * Called once teleportToRemote resolves with a session URL. Callers that |
| 244 | * have setMessages (REPL) append this as a second transcript message so the |
| 245 | * URL is visible without opening the ↓ detail view. Callers without |
| 246 | * transcript access (ExitPlanModePermissionRequest) omit this — the pill |
| 247 | * still shows live status. |
| 248 | */ |
| 249 | onSessionReady?: (msg: string) => void; |
| 250 | }): Promise<string> { |
| 251 | const { |
| 252 | blurb, |
| 253 | seedPlan, |
| 254 | getAppState, |
| 255 | setAppState, |
| 256 | signal, |
| 257 | disconnectedBridge, |
| 258 | onSessionReady |
| 259 | } = opts; |
| 260 | const { |
| 261 | ultraplanSessionUrl: active, |
| 262 | ultraplanLaunching |
| 263 | } = getAppState(); |
| 264 | if (active || ultraplanLaunching) { |
| 265 | logEvent('tengu_ultraplan_create_failed', { |
| 266 | reason: (active ? 'already_polling' : 'already_launching') as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS |
| 267 | }); |
| 268 | return buildAlreadyActiveMessage(active); |
| 269 | } |
| 270 | if (!blurb && !seedPlan) { |
| 271 | // No event — bare /ultraplan is a usage query, not an attempt. |
| 272 | return [ |
| 273 | // Rendered via <Markdown>; raw <message> is tokenized as HTML |
| 274 | // and dropped. Backslash-escape the brackets. |
| 275 | 'Usage: /ultraplan \\<prompt\\>, or include "ultraplan" anywhere', 'in your prompt', '', 'Advanced multi-agent plan mode with our most powerful model', '(Opus). Runs in Claude Code on the web. When the plan is ready,', 'you can execute it in the web session or send it back here.', 'Terminal stays free while the remote plans.', 'Requires /login.', '', `Terms: ${CCR_TERMS_URL}`].join('\n'); |
| 276 | } |
| 277 | |
| 278 | // Set synchronously before the detached flow to prevent duplicate launches |
| 279 | // during the teleportToRemote window. |
| 280 | setAppState(prev => prev.ultraplanLaunching ? prev : { |
| 281 | ...prev, |
| 282 | ultraplanLaunching: true |
| 283 | }); |
| 284 | void launchDetached({ |
| 285 | blurb, |
| 286 | seedPlan, |
| 287 | getAppState, |
| 288 | setAppState, |
| 289 | signal, |
| 290 | onSessionReady |
| 291 | }); |
no test coverage detected