feat(quick-pane): add chat-style exchange
This commit is contained in:
+56
-25
@@ -9,9 +9,12 @@ test("Quick Pane polls snapshots, renders answers, and gates handoff", async ()
|
||||
);
|
||||
assert.match(source, /get_session_runtime_snapshot/);
|
||||
assert.match(source, /setInterval\(\(\) => void refresh\(\), 800\)/);
|
||||
assert.match(source, /\{displayedAnswer && <pre>\{displayedAnswer\}<\/pre>\}/);
|
||||
assert.match(source, /const canContinue = !!escalation \|\| \(!!runtime && !!error\)/);
|
||||
assert.match(source, /\{canContinue && \(/);
|
||||
assert.match(source, /<ReactMarkdown remarkPlugins=\{\[remarkGfm\]\}>/);
|
||||
assert.match(source, /className="quick-pane-notice escalation"/);
|
||||
assert.match(
|
||||
source,
|
||||
/<button type="button" onClick=\{continueFull\}>\s*Continue\s*<\/button>/,
|
||||
);
|
||||
});
|
||||
|
||||
test("main Settings uses shared catalog selectors with provider derived from models", async () => {
|
||||
@@ -27,7 +30,10 @@ test("main Settings uses shared catalog selectors with provider derived from mod
|
||||
"utf8",
|
||||
),
|
||||
]);
|
||||
assert.match(catalog, /invoke<\{ models\?: Model\[\] \}>\("get_model_catalog"\)/);
|
||||
assert.match(
|
||||
catalog,
|
||||
/invoke<\{ models\?: Model\[\] \}>\("get_model_catalog"\)/,
|
||||
);
|
||||
assert.match(app, /getModelCatalog\(\)/);
|
||||
assert.match(app, /Quick model[\s\S]*?<select/);
|
||||
assert.match(app, /Follow-up model[\s\S]*?<select/);
|
||||
@@ -42,6 +48,8 @@ test("main Settings uses shared catalog selectors with provider derived from mod
|
||||
assert.doesNotMatch(pane, /Save Quick Pane settings/);
|
||||
assert.match(pane, /isStreaming === false/);
|
||||
assert.match(pane, /current === submitted\.request \? "" : current/);
|
||||
assert.match(pane, /readOnly=\{runActive\}/);
|
||||
assert.match(pane, /window\.requestAnimationFrame\(focusInput\)/);
|
||||
assert.match(pane, /\.slice\(0, 5\)/);
|
||||
assert.match(pane, /aria-label="Answer history"/);
|
||||
assert.doesNotMatch(pane, /localStorage|sessionStorage|save_ui_state/);
|
||||
@@ -61,7 +69,10 @@ test("Quick Pane keeps slash-containing model IDs atomic and reloads catalog on
|
||||
assert.match(pane, /modelId: selectedModel\.modelId/);
|
||||
assert.doesNotMatch(pane, /selectedModel\.split/);
|
||||
assert.match(pane, /onFocusChanged[\s\S]*?void loadModelCatalog\(\)/);
|
||||
assert.match(catalog, /JSON\.stringify\(\[identity\.provider, identity\.modelId\]\)/);
|
||||
assert.match(
|
||||
catalog,
|
||||
/JSON\.stringify\(\[identity\.provider, identity\.modelId\]\)/,
|
||||
);
|
||||
assert.match(catalog, /JSON\.parse\(value\)/);
|
||||
});
|
||||
|
||||
@@ -79,22 +90,31 @@ test("Quick Pane routes extension responses through existing bridge command", as
|
||||
});
|
||||
|
||||
test("Quick Pane uses native dimensions and request-first compact layout", async () => {
|
||||
const [source, stylesheet, configSource, nativeSource, capabilitySource] = await Promise.all([
|
||||
readFile(
|
||||
new URL("../ui/src/quick-pane/QuickPane.tsx", import.meta.url),
|
||||
"utf8",
|
||||
),
|
||||
readFile(
|
||||
new URL("../ui/src/quick-pane/quick-pane.css", import.meta.url),
|
||||
"utf8",
|
||||
),
|
||||
readFile(new URL("../ui/src-tauri/tauri.conf.json", import.meta.url), "utf8"),
|
||||
readFile(new URL("../ui/src-tauri/src/lib.rs", import.meta.url), "utf8"),
|
||||
readFile(new URL("../ui/src-tauri/capabilities/default.json", import.meta.url), "utf8"),
|
||||
]);
|
||||
const [source, stylesheet, configSource, nativeSource, capabilitySource] =
|
||||
await Promise.all([
|
||||
readFile(
|
||||
new URL("../ui/src/quick-pane/QuickPane.tsx", import.meta.url),
|
||||
"utf8",
|
||||
),
|
||||
readFile(
|
||||
new URL("../ui/src/quick-pane/quick-pane.css", import.meta.url),
|
||||
"utf8",
|
||||
),
|
||||
readFile(
|
||||
new URL("../ui/src-tauri/tauri.conf.json", import.meta.url),
|
||||
"utf8",
|
||||
),
|
||||
readFile(new URL("../ui/src-tauri/src/lib.rs", import.meta.url), "utf8"),
|
||||
readFile(
|
||||
new URL("../ui/src-tauri/capabilities/default.json", import.meta.url),
|
||||
"utf8",
|
||||
),
|
||||
]);
|
||||
const config = JSON.parse(configSource);
|
||||
const capability = JSON.parse(capabilitySource);
|
||||
const quickPane = config.app.windows.find((window) => window.label === "quick-pane");
|
||||
const quickPane = config.app.windows.find(
|
||||
(window) => window.label === "quick-pane",
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
{
|
||||
@@ -107,12 +127,16 @@ test("Quick Pane uses native dimensions and request-first compact layout", async
|
||||
assert.ok(capability.windows.includes("quick-pane"));
|
||||
assert.match(nativeSource, /WindowEvent::CloseRequested/);
|
||||
assert.match(nativeSource, /api\.prevent_close\(\)/);
|
||||
assert.match(nativeSource, /WebviewWindowBuilder::from_config\(app, config\)/);
|
||||
assert.match(
|
||||
nativeSource,
|
||||
/WebviewWindowBuilder::from_config\(app, config\)/,
|
||||
);
|
||||
assert.match(nativeSource, /get_or_create_quick_pane/);
|
||||
assert.doesNotMatch(source, /onCloseRequested/);
|
||||
assert.match(source, /className="quick-pane-request"/);
|
||||
assert.match(source, /className="quick-pane-output"/);
|
||||
assert.match(source, /<footer className="quick-pane-controls">/);
|
||||
assert.match(source, /className="quick-pane-exchange"/);
|
||||
assert.match(source, /className="quick-pane-composer"/);
|
||||
assert.match(source, /className="quick-pane-send"/);
|
||||
assert.match(source, /ref=\{inputRef\}/);
|
||||
assert.match(source, /focusInput\(\)/);
|
||||
assert.doesNotMatch(source, /if \(!event\.payload\)[\s\S]*?hide\(/);
|
||||
@@ -121,9 +145,16 @@ test("Quick Pane uses native dimensions and request-first compact layout", async
|
||||
/event\.key === "Enter" &&\s*!event\.shiftKey &&\s*!event\.nativeEvent\.isComposing/,
|
||||
);
|
||||
assert.match(source, /event\.preventDefault\(\);\s*void run\(\);/);
|
||||
assert.match(stylesheet, /\.quick-pane-request[\s\S]*?flex: 1 1 auto/);
|
||||
assert.match(stylesheet, /\.quick-pane-output[\s\S]*?max-height: 108px[\s\S]*?overflow: auto/);
|
||||
assert.match(stylesheet, /\.quick-pane-controls[\s\S]*?display: flex/);
|
||||
assert.match(
|
||||
stylesheet,
|
||||
/\.quick-pane-exchange[\s\S]*?flex: 1 1 auto[\s\S]*?overflow-y: auto/,
|
||||
);
|
||||
assert.match(
|
||||
stylesheet,
|
||||
/\.quick-pane-composer[\s\S]*?height: 120px[\s\S]*?min-height: 110px[\s\S]*?max-height: 130px/,
|
||||
);
|
||||
assert.match(stylesheet, /\.quick-pane-send[\s\S]*?position: absolute/);
|
||||
assert.match(stylesheet, /@media \(max-width: 400px\)/);
|
||||
assert.match(stylesheet, /#f0a347/);
|
||||
assert.doesNotMatch(stylesheet, /#8aa9d6|#46494f|#23252a/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user