From 32f1c6c26033dfb63fcc0a230e883fcd7e22089e Mon Sep 17 00:00:00 2001 From: abose Date: Sat, 10 Oct 2026 01:06:55 +0530 Subject: [PATCH 1/3] feat(ai): expose rich questions and interactive chat previews Add askRichQuestion to the shared panel and CLI tool catalog, with reusable HTML/CSS/JS files, answer handling and cancellation when its call ends. Guide standalone visual examples into interactive chat fences while keeping actual-page interactions in Live Preview. Add localized rich-UI labels and shared composer, question and source-view styles. Route Shadow DOM and middle-click links through Phoenix's existing URL opener. Extend the registered CLI tool contract checks. Validation: CLI Connector passes 57/57 on Linux and macOS. Paired Pro renderer, question, history and composer checks pass on Linux, macOS and Windows, including the final source-viewer regression on each platform. Changed-file ESLint, release Terser 3.17 parsing, LESS compilation and whitespace checks pass. Push and CI remain pending; the Pro pin is unchanged. --- src-node/ai-cli-connector.js | 5 +- src-node/ai-editor-tool-specs.js | 66 ++++++ src-node/ai-system-prompt.js | 34 ++- src-node/claude-code-agent.js | 1 + src-node/test/test-ai-cli-connector.js | 1 + src/brackets.js | 13 +- src/nls/root/strings.js | 14 ++ src/styles/Extn-AIChatPanel.less | 288 +++++++++++++++++++------ test/spec/AICliConnector-test.js | 10 +- 9 files changed, 361 insertions(+), 71 deletions(-) diff --git a/src-node/ai-cli-connector.js b/src-node/ai-cli-connector.js index 2576b33212..e247bf099f 100644 --- a/src-node/ai-cli-connector.js +++ b/src-node/ai-cli-connector.js @@ -249,7 +249,10 @@ class CliConnector { try { return await deadline(spec.handler(args), timeoutMs); } finally { - if (spec.name === "askInLivePreview") { this.cancelCall(session, frame.id); } + // A question still showing when its call ends, by error or budget, must not outlive it. + if (spec.name === "askInLivePreview" || spec.name === "askRichQuestion") { + this.cancelCall(session, frame.id); + } } } diff --git a/src-node/ai-editor-tool-specs.js b/src-node/ai-editor-tool-specs.js index a2eba6a729..6d1ac9948d 100644 --- a/src-node/ai-editor-tool-specs.js +++ b/src-node/ai-editor-tool-specs.js @@ -23,6 +23,7 @@ const path = require("path"); const fs = require("fs"); const { z } = require("zod"); +const {RICH_UI_STYLE_GUIDANCE} = require("./ai-system-prompt"); // Absolute path to the bundled API reference, mirrored from // docs/API-Reference/ at build time by build/api-docs-generator.js. @@ -52,6 +53,10 @@ const EXEC_PEER_TIMEOUT_MS = { useImage: 90000 }; +// A rich question waits until the user answers or its owner cancels it. The CLI transport needs a finite +// budget; this one is a day, and ending it cancels the question in the editor like any CLI cancellation. +const RICH_QUESTION_FAILSAFE_MS = 24 * 60 * 60 * 1000; + // Floor for caller-provided timeouts (e.g. execJsInLivePreview's // timeoutMs). 5s minimum stops the model from spamming impatient retries // on a preview that's just taking a beat to settle. No ceiling — the @@ -97,6 +102,9 @@ function getToolTimeout(name, args = {}) { if (name === "askInLivePreview") { return (args.timeoutS || 300) * 1000 + 15000; } + if (name === "askRichQuestion") { + return RICH_QUESTION_FAILSAFE_MS; + } if (name === "execJsInEditor" || name === "execJsInLivePreview") { return _resolveCallerTimeout(args.timeoutMs, 10000); } @@ -842,6 +850,64 @@ function getEditorToolSpecs(peerCall, options = {}) { } ); + addTool( + "askRichQuestion", + "Ask the user a question shown as rich interactive UI " + + (options.cli ? "in your session's pane in Phoenix" : "in the chat") + ", with no live preview needed, and " + + "wait for the answer: a visual choice, a short form, or something to look at and confirm. Prefer choices: " + + "each has id, label and optional description/color; Phoenix renders the cards and a pick returns " + + "{choice:id,label}. For custom content pass html or uiFile with its own