Skip to content

feat(sdk): Explorer query/ask/agent modes, saved queries + export, local-server LLM, and AI consent#706

Merged
ParidelPooya merged 14 commits into
mainfrom
feat/insight-vscode-query-modes
Jul 9, 2026
Merged

feat(sdk): Explorer query/ask/agent modes, saved queries + export, local-server LLM, and AI consent#706
ParidelPooya merged 14 commits into
mainfrom
feat/insight-vscode-query-modes

Conversation

@ParidelPooya

Copy link
Copy Markdown
Contributor

Enhancements to the Workflow Insight Explorer VS Code extension: three explicit
query modes, saved queries and result export, an OpenAI-compatible local-server
LLM provider, .vsix packaging for preview distribution, and an AI-usage
consent + data-handling disclosure across every surface.

What's included

Composer modes (Send is now a split dropdown; the choice is persisted in
workflowInsight.queryMode and restored on open):

  • Query — runs the text you type verbatim as a read-only query (no LLM, no
    drill-down injection); still read-only-enforced and row-capped. Prefills a
    destination-appropriate starter query and posts an explicit row-count summary.
  • Ask — one NL→query translation, run once (no agent loop).
  • Agent — the existing agentic explore→answer loop.
  • Distinct per-mode Send icon (query=script, ask=search, agent=gen-ai).

Saved queries & export — each result table has an Actions menu: Export as
CSV, Export as JSON (saved via the host), and Save query to favorites. Favorites
persist in globalState and can be re-run from an icon-only picker in the composer
(filtered to the current destination).

Local LLM support — new local-server provider that talks to an
OpenAI-compatible endpoint you run (Ollama, LM Studio, llama.cpp), configured via
workflowInsight.localServerUrl / localServerModel. No native module, so it
works from the packaged .vsix on every platform.

AI consent & data handling — before the first use of any AI feature
(Ask/Agent/Visualize), a disclosure modal explains that an LLM is used and that
the request text plus limited data (result column names + a small sample of rows)
are sent to the selected provider; Query mode sends nothing. Consent is stored in
workflowInsight.aiDisclosureAcceptedVersion and versioned so wording changes
re-prompt. The disclosure — including per-provider data-flow (Bedrock→AWS,
Copilot→GitHub, local-server→your endpoint, on-device→never leaves the machine) —
appears in the consent modal, the in-app settings panel, the native VS Code
settings descriptions, and the README.

Reliability fix — the Bedrock agent loop now shows the last row-bearing query
result when the model finishes with a prose-only answer, so a follow-up data
question still renders its table.

Packaging / distributionnpm run package builds a .vsix into vsix/
(git-ignored); preview builds are shared via GitHub Releases. README documents
install-from-VSIX and provider setup.

⚠️ Legal review required

The AI-usage disclosure wording (consent modal, settings descriptions, README)
is a placeholder pending Legal review — see AiConsentModal.tsx and
AI_DISCLOSURE_VERSION in webview-ui/src/types.ts. When approved copy lands,
update the text and bump AI_DISCLOSURE_VERSION to re-prompt consented users.

…in the Explorer

Composer modes: the Send button is now a split dropdown with three modes,
persisted as workflowInsight.queryMode and restored on open:
- query: run the typed text verbatim as a read-only query (no LLM, no
  drill-down injection); still read-only-enforced and row-capped. Posts an
  explicit row-count summary so a 0-row result (e.g. a query language that
  doesn't match the destination) isn't silent. The box prefills with a
  destination-appropriate starter query.
- ask: one NL->query translation, run once, present (no agent loop).
- agent: the existing agentic explore->answer loop.

Multi-result fix: the Bedrock tool loop now tracks the last successful,
row-bearing execution and presents it when the model finishes with a prose-only
answer, so a follow-up data question still shows its table instead of nothing.

Result actions: each result table has an Actions dropdown — Export as CSV,
Export as JSON (built in the webview, saved via the host's save dialog), and
Save query in favorites. Favorites persist in globalState (id/label/query/
destinationType); the composer has a Favorites picker, filtered to the current
destination, that runs a saved query in query mode.

Typecheck (ext + webview) + build clean, 123 tests pass.
- Add an `npm run package` script that builds the webview + extension bundle
  and writes a shareable `.vsix` into `vsix/` (via @vscode/vsce, packaged with
  --no-dependencies since esbuild already bundles runtime deps).
- Commit the packaged preview build so testers/customers can side-load it
  before the Marketplace launch; un-ignore `vsix/*.vsix` in .gitignore.
- Tighten .vscodeignore so the vsix only ships dist/ + media/ (excludes
  src, webview-ui, maps, configs) — 1.3 MB, 7 files.
- README: add an "Install (Preview Build)" section (download link + UI/CLI
  install steps + how to share it for preview access), a "Build from Source"
  section documenting `npm run package`, and clarify launch for installed
  vs. source users.

Note: the preview vsix targets the Bedrock/Copilot providers; the on-device
local-model option isn't bundled.
…e vsix via releases

Local model support that works from the packaged .vsix (Option B):
- New `local-server` provider talks to an OpenAI-compatible /chat/completions
  endpoint you run yourself (Ollama, LM Studio, llama.cpp) — no native module,
  so a single portable vsix works on every platform. Configured via
  workflowInsight.localServerUrl (default http://localhost:11434/v1) and
  workflowInsight.localServerModel (default llama3.1); wired through
  generateQuery, verifyResult, and completeText (analyze + chart spec) via a
  setLocalServer() module setting, mirroring setLocalModel.
- Settings UI: provider option + Server URL / Model fields with Ollama guidance.
- The embedded on-device `local` provider is unchanged (source-only; not in the
  vsix since node-llama-cpp is a native module).

Distribution:
- Stop committing the .vsix; ignore vsix/ again. Preview builds are shared via
  GitHub Releases instead. README updated: download from Releases, and a
  `gh release create ... vsix/*.vsix` note for publishing.
- README: generalized the provider setup step (Bedrock / Copilot / Local
  server / on-device) and added the new settings to the reference table.

Typecheck (ext + webview) + build + package clean, 123 tests pass.
The "Favorites" and "Send · <mode>" text buttons took too much width. Favorites
is now an icon-only star dropdown (variant="icon"); Send is an icon-only primary
button (send icon) with the mode in its aria-label. The active mode is marked
with a check in the mode dropdown, and the mode-aware placeholder still signals
which mode is active.
Adds an AI-usage disclosure + consent gate. Before the first use of any AI
feature — the Ask and Agent modes and the Visualize page — the user is shown a
notice explaining that an LLM is used and that their request text and, in some
cases, limited portions of their data (result column names and a small sample
of rows) are sent to the configured provider. The user must tick "I have read
and agree" and click "I agree" to proceed; the deferred action then runs.

- Consent is persisted in settings (workflowInsight.aiDisclosureAcceptedVersion)
  and versioned (AI_DISCLOSURE_VERSION) so a wording change re-prompts.
- Query mode is unaffected (it never calls an LLM) and stays usable without
  consent.
- Gating is enforced in the webview before any generate/visualize message is
  posted; the host persists the decision (onSetConsent).

LEGAL: the disclosure wording in AiConsentModal is a placeholder pending Legal
review; bump AI_DISCLOSURE_VERSION when the approved text lands to re-prompt.

Typecheck (ext + webview) + build clean, 123 tests pass.
…otice

Expands the disclosure to spell out where data goes per configured provider —
Amazon Bedrock (to AWS), GitHub Copilot (to GitHub/Microsoft), local server
(to a self-hosted endpoint you control), and on-device (never leaves the
machine) — so consent is informed for each option. Bumped AI_DISCLOSURE_VERSION
to 2 so previously-consented users re-accept the updated notice.
Expanded the settings.json descriptions so the disclosure is visible where
users configure the extension, not just in the modal:
- llmProvider: clarifies AI features (ask/agent/visualize) send request text and
  limited data (result column names + a small row sample) to the selected
  provider, that query mode uses no AI, and that data is subject to the
  provider's terms. Each enum option states where its data goes (Bedrock→AWS,
  Copilot→GitHub, local-server→your endpoint, local→on-device).
- bedrockModelId / localServerUrl / localServerModel / localModel: per-provider
  data-handling notes.
- queryMode: notes ask/agent use the LLM while query does not.
- aiDisclosureAcceptedVersion: documents that clearing it withdraws consent.

Wording remains pending Legal review.
…tting

- handleRunFavorite now runs saved queries verbatim in query mode without
  persisting query as the composer's default — re-running a favorite no longer
  silently changes the user's chosen default mode for future sessions.
- Reflow App.tsx/VisualizePage.tsx to satisfy Prettier (CI --check).
- Note why AI_DISCLOSURE_VERSION starts at "2".
Adds a host-side consent check (defense in depth) so a replayed or malformed
message can't reach the LLM without accepted consent. onGenerate (ask/agent)
and onVisualize now refuse when the stored aiDisclosureAcceptedVersion doesn't
match the current disclosure version; query mode stays exempt (no LLM).
- completeViaLocalServer now uses an AbortController timeout so a hung/slow
  local server can't hang the request forever, and requests response_format
  json_object so compatible servers constrain output to JSON.
- Replace the greedy /\{.*"query".*\}/ extraction with a balanced-brace parser
  that ignores braces inside string literals, so prose-wrapped or trailing
  braces don't capture the wrong span.
- Extract the parse logic into a dependency-free localServerParse module and
  add unit tests (valid, prose-wrapped, nested, string-brace, empty, invalid,
  missing/blank query).

@yaythomas yaythomas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@ParidelPooya
ParidelPooya marked this pull request as ready for review July 9, 2026 21:18
@ParidelPooya
ParidelPooya merged commit 737780e into main Jul 9, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants