feat(plugins): analyze plugin data in the built-in AI panel

This commit is contained in:
zipg authored and GitHub committed 2026-09-22 15:04:33 +08:00
1 parent 7653ebfda6
commit 1566bb8a9f
33 files changed
+716 -216

No files matched your search

+4 -4
View File
@@ -9,15 +9,15 @@ const zhCnLocalePath = fileURLToPath(new URL("../../apps/desktop/src/i18n/locale
const source = readFileSync(aiAssistantPath, "utf8");
const zhCnLocaleSource = readFileSync(zhCnLocalePath, "utf8");
test("AI composer keeps templates available without connections", () => {
test("AI composer keeps templates available without connections outside plugin conversations", () => {
const contextRowStart = source.indexOf("data-ai-composer-context-row");
const contextRowEnd = source.indexOf('v-if="mentionOpen"', contextRowStart);
const contextRow = source.slice(contextRowStart, contextRowEnd);
assert.notEqual(contextRowStart, -1, "the composer context row should exist");
assert.notEqual(contextRowEnd, -1, "the connection context row should end before mention suggestions");
assert.match(contextRow, /<template v-if="connectionStore\.connections\.length">/);
assert.match(contextRow, /<Popover v-model:open="showTemplateSelector">/);
assert.match(contextRow, /<details v-if="pluginContext"[\s\S]*?<template v-else-if="connectionStore\.connections\.length">/);
assert.match(contextRow, /<Popover v-if="!pluginContext" v-model:open="showTemplateSelector">/);
assert.match(contextRow, /max-w-\[40%\]/);
assert.match(contextRow, /<span class="ai-template-selector-label truncate">\{\{ templateSelectorTriggerLabel \}\}<\/span>/);
assert.match(contextRow, /:aria-label="templateSelectorTriggerLabel"/);
@@ -37,7 +37,7 @@ test("AI composer exposes mode and action as one compact selector", () => {
assert.notEqual(footerStart, -1, "the combined mode and action selector should exist");
assert.notEqual(footerEnd, -1, "the model selector should follow the combined selector");
assert.match(footer, /<Popover v-model:open="modeActionOpen">/);
assert.match(footer, /<span v-if="pluginContext"[\s\S]*?<Popover v-else v-model:open="modeActionOpen">/);
assert.match(footer, /:aria-label="modeActionTriggerLabel"/);
assert.match(footer, /switchModeActionTab\('ask'\)/);
assert.match(footer, /switchModeActionTab\('agent'\)/);
+1 -1
View File
@@ -108,5 +108,5 @@ test("send() snapshots custom prompts before deferred AI context loading", () =>
assert.ok(ensureLoadedAwait < snapshot, "the snapshot must be taken after templates finish loading");
assert.ok(snapshot < sqlFileLoad, "SQL file loading must not delay the custom prompt snapshot");
assert.ok(snapshot < aiContextLoad, "AI context loading must not delay the custom prompt snapshot");
assert.match(body.slice(snapshot, sqlFileLoad), /activeTemplates:\s*\[\.\.\.activeTemplates\.value\]/);
assert.match(body.slice(snapshot, sqlFileLoad), /activeTemplates:\s*runPluginContext \? \[\] : \[\.\.\.activeTemplates\.value\]/);
});
+2 -1
View File
@@ -74,7 +74,8 @@ test("AI request failures use localized backend diagnostics", () => {
test("AI analysis export keeps the connection that produced each assistant response", () => {
assert.match(source, /sourceConnectionName\?: string/);
assert.match(source, /runMessages\.push\(\{ role: "assistant", content: "", sourceConnectionName: connection\.name \}\)/);
assert.match(source, /const runSourceName = runPluginContext\?\.pluginName \?\? connection\?\.name \?\? ""/);
assert.match(source, /runMessages\.push\(\{ role: "assistant", content: "", sourceConnectionName: runSourceName \}\)/);
assert.match(source, /connectionName: msg\.sourceConnectionName \?\? props\.connection\?\.name/);
assert.match(source, /sourceConnectionName: m\.role === "assistant" \? conv\.connectionName : undefined/);
});