Skip to content

feat(charts/vscode): Added charting capabilities to kilo-ui storybook and VS Code extension - #12525

Merged
cosi-conda merged 43 commits into
mainfrom
feature/charts
Aug 3, 2026
Merged

feat(charts/vscode): Added charting capabilities to kilo-ui storybook and VS Code extension#12525
cosi-conda merged 43 commits into
mainfrom
feature/charts

Conversation

@cosi-conda

@cosi-conda cosi-conda commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Context

  • Added charting capabilities to kilo session (VS code extension), which includes:
    • Additional model guidance for mermaid diagrams and new charts
    • Additional charting capabilities such as:
      • Bar chart
      • Line plot
      • Scatter plot
      • Temporal (time series)
      • Pie chart
      • Doughnut chart
      • Radar chart
      • Bubble chart
  • Storybook tool call section added to include new charting examples

Follow up features

  • TUI charting expansion
  • Zoom wheel feature for mermaid diagrams

Implementation

Various charting libraries were considered, but this was ultimately implemented with chart.js for the following reasons:

Option How it works Effort Notes
Chart.js Model outputs JSON config, render with chart.js Medium No CSP issues, vanilla canvas, PNG export, covers all required chart types, ~200kb bundle
Vega-Lite Model outputs JSON spec, render with vega-embed Medium Requires unsafe-eval CSP — not suitable for shipping. Most expressive but blocked by VS Code webview security.
uPlot Model outputs JSON data, render with uplot Low-Medium Extremely lightweight (~40kb) — best if only bar/line/time series needed
ECharts Model outputs JSON config, render with echarts Medium Good chart coverage, has SVG renderer mode, reasonable bundle

Screenshots / Video

Screenshot 2026-07-23 at 10 46 34 AM Screenshot 2026-07-23 at 10 46 40 AM Screenshot 2026-07-23 at 10 46 45 AM Screenshot 2026-07-23 at 10 47 14 AM Screenshot 2026-07-24 at 1 13 40 PM Screenshot 2026-07-24 at 4 25 04 PM Screenshot 2026-07-24 at 4 25 32 PM Screenshot 2026-07-24 at 4 25 47 PM image image image

How to Test

Manual/local verification

  1. bun run extension
  2. See the kilocode extension running a chat session.
  3. Prompt for various supported chart types and see them rendered in the message response.

Checklist

  • Issue linked above, or exception explained
  • Tests/verification described
  • Screenshots/video included for visual changes, or marked N/A
  • Changeset considered for user-facing changes
  • I personally reviewed the diff and can explain the changes, including any AI-assisted work.

@cosi-conda
cosi-conda marked this pull request as ready for review July 27, 2026 16:56
Comment thread packages/kilo-ui/src/components/chart.css
Comment thread packages/opencode/src/kilocode/tool/registry.ts Outdated
Comment thread packages/kilo-ui/src/components/chart.tsx Outdated
@kilo-code-bot

kilo-code-bot Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 2
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/kilo-ui/src/components/chart.tsx 3 Static chart.js import pulls the full library (~200KB) into the main webview chunk, since ChartTool is statically registered in message-part.tsx. Discussion open on the existing inline thread.
packages/kilo-ui/src/components/chart.tsx 63 The chart tool's own failure outputs are plain-text guidance strings, so they land in this catch and only reach the console — the user sees an empty chart container instead of a message. Consider setError(...) here.
Notes
  • Incremental scope: the only change since 4623b033 is commit 242b116b (8 lines in packages/kilo-ui/src/components/chart.tsx), which swaps the hardcoded series palette for --vscode-charts-{blue,green,purple,orange,red,yellow} with the previous hexes as fallbacks. Verified: the vars are read off document.documentElement, which is where the VS Code webview sets --vscode-*, and non-VS Code surfaces (kilo-ui Storybook, docs stories) fall back cleanly. No new issues in those lines.
  • Related to the open accessibility thread on line 14: getThemeColors() is only read inside the effect, and the effect tracks props.output/props.status. An already-rendered chart therefore keeps its old palette when the user switches VS Code theme until the component re-mounts. Worth confirming against the dynamic-update screenshots.
  • Still no changeset for a user-facing feature (new chart tool + webview rendering). Not anchorable to a diff line, so noted here.
Files Reviewed (incremental diff, 1 file)
  • packages/kilo-ui/src/components/chart.tsx - 2 carried-over issues (0 new)

Fix these issues in Kilo Cloud

Previous Review Summaries (6 snapshots, latest commit 4623b03)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 4623b03)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 2
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/kilo-ui/src/components/chart.tsx 3 Static chart.js import pulls the full library (~200KB) into the main webview chunk, since ChartTool is statically registered in message-part.tsx. Already discussed on the existing inline thread.
packages/kilo-ui/src/components/chart.tsx 58 The chart tool's own failure outputs are plain-text guidance strings, so they land in this catch and only reach the console — the user sees an empty chart container instead of a message. Consider setError(...) here.
Resolved since last review
  • WARNING chart.tsx:85 — cleanup destroying the chart on effect re-run while the rendered latch blocked recreation. 2d7b71f1 moves the onCleanup registration above the chart construction, resets rendered in cleanup, and only sets rendered = true after a successful new Chart(...). Re-verified: cleanup runs before each effect re-execution, so the chart is now rebuilt rather than left blank, and the instance is still destroyed on disposal (no leaked Chart/ResizeObserver).
Notes
  • Incremental scope: the only PR-authored change since c94d49ce is packages/kilo-ui/src/components/chart.tsx (commit 2d7b71f1); 4623b033 is a merge of main, whose changes are out of scope for this review. No new issues found in the changed lines.
  • rendered is now effectively a no-op guard: because the cleanup resets it before every re-run of the effect, it can never short-circuit line 46. Harmless, but the "render once" intent it expresses no longer holds — safe to drop if you want less state.
  • Still no changeset for a user-facing feature (new chart tool + webview rendering). Not anchorable to a diff line, so noted here.
Files Reviewed (incremental diff, 1 file)
  • packages/kilo-ui/src/components/chart.tsx - 2 carried-over issues (0 new)

Fix these issues in Kilo Cloud

Previous review (commit c94d49c)

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 2
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-ui/src/components/chart.tsx 85 onCleanup registered inside createEffect also fires when the effect re-runs, destroying the chart; the rendered latch (line 41) then blocks recreation, leaving a permanently blank canvas. The latch is also set before the !el.isConnected bail.

SUGGESTION

File Line Issue
packages/kilo-ui/src/components/chart.tsx 3 Static chart.js import pulls ~200KB into the main webview chunk (ChartTool is statically registered in message-part.tsx). A module-level memoized loader keeps both the split chunk and the single register call.
packages/kilo-ui/src/components/chart.tsx 58 The chart tool's failure outputs are plain text, so they land in this catch and only reach the console — the user sees an empty chart container. Consider setError(...) here.
Notes
  • The only change since the last review is the console.warn prefix on line 58 ("Chart:""[Kilo Chart]:"). No new issues introduced; the three findings above were re-verified against current HEAD and still apply.
  • Still no changeset for what is a user-facing feature (new chart tool + rendering in the VS Code webview). Not anchorable to a diff line, so noted here.
Files Reviewed (incremental diff, 1 file)
  • packages/kilo-ui/src/components/chart.tsx - 3 issues (0 new)

Fix these issues in Kilo Cloud

Previous review (commit 100f8c6)

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 2
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-ui/src/components/chart.tsx 85 onCleanup inside createEffect also runs on effect re-execution; the rendered latch then blocks recreation, leaving a permanently blank canvas. The latch is also set before the !el.isConnected bail.

SUGGESTION

File Line Issue
packages/kilo-ui/src/components/chart.tsx 3 Static chart.js import moves ~200KB into the main webview chunk (ChartTool is statically registered in message-part.tsx); a module-level memoized loader keeps both the split chunk and the single register call.
packages/kilo-ui/src/components/chart.tsx 58 The chart tool's error outputs are plain text, so they land in this branch and only reach the console — the user sees an empty chart container. Consider setError(...).
Notes
  • No changeset in the PR for what is a user-facing feature (new chart tool + rendering in the VS Code webview). Not anchorable to a diff line, so noting it here.
  • Previously flagged issues that are now resolved: chart.css import, vscode gating of the chart tool, per-slice borderColor, and the lost reactive owner for onCleanup (the cleanup is now registered synchronously — see the remaining caveat above).
Files Reviewed (incremental diff, 1 file)
  • packages/kilo-ui/src/components/chart.tsx - 3 issues

The rest of the diff since the last review is a main merge commit and contains no PR-authored changes.

Fix these issues in Kilo Cloud

Previous review (commit edc6976)

Status: No Issues Found | Recommendation: Merge

All previously flagged issues have been resolved in this update:

  • chart.css is now imported via packages/kilo-ui/src/styles/index.css
  • The chart tool is now gated to Flag.KILO_CLIENT === "vscode" in registry.ts, with a new test (packages/opencode/test/kilocode/chart-tool-gating.test.ts) covering vscode/cli/jetbrains cases
  • borderColor for pie/doughnut/polar datasets is now indexed per-slice, matching backgroundColor

The soul.txt chart guidance was also moved into system-prompt.ts as a vscode-gated block, consistent with the tool gating fix.

Files Reviewed (incremental diff, 10 files)
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/labs-tool-call-lab/search-previews-chromium-linux.png (generated baseline)
  • packages/kilo-ui/src/components/chart.tsx
  • packages/kilo-ui/src/styles/index.css
  • packages/opencode/src/kilocode/soul.txt (removed)
  • packages/opencode/src/kilocode/system-prompt.ts
  • packages/opencode/src/kilocode/tool/registry.ts
  • packages/opencode/test/fixtures/recordings/kilocode/session/native-anthropic-tool-loop.json
  • packages/opencode/test/fixtures/recordings/kilocode/session/native-openai-oauth-tool-loop.json
  • packages/opencode/test/fixtures/recordings/kilocode/session/native-zen-tool-loop.json
  • packages/opencode/test/kilocode/chart-tool-gating.test.ts

Previous review (commit 53179eb)

Status: No Issues Found | Recommendation: Merge

All previously flagged issues have been resolved in this update:

  • chart.css is now imported via packages/kilo-ui/src/styles/index.css
  • The chart tool is now gated to Flag.KILO_CLIENT === "vscode" in registry.ts, with a new test (packages/opencode/test/kilocode/chart-tool-gating.test.ts) covering vscode/cli/jetbrains cases
  • borderColor for pie/doughnut/polar datasets is now indexed per-slice, matching backgroundColor

The soul.txt chart guidance was also moved into system-prompt.ts as a vscode-gated block, consistent with the tool gating fix.

Files Reviewed (incremental diff, 10 files)
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/labs-tool-call-lab/search-previews-chromium-linux.png (generated baseline)
  • packages/kilo-ui/src/components/chart.tsx
  • packages/kilo-ui/src/styles/index.css
  • packages/opencode/src/kilocode/soul.txt (removed)
  • packages/opencode/src/kilocode/system-prompt.ts
  • packages/opencode/src/kilocode/tool/registry.ts
  • packages/opencode/test/fixtures/recordings/kilocode/session/native-anthropic-tool-loop.json
  • packages/opencode/test/fixtures/recordings/kilocode/session/native-openai-oauth-tool-loop.json
  • packages/opencode/test/fixtures/recordings/kilocode/session/native-zen-tool-loop.json
  • packages/opencode/test/kilocode/chart-tool-gating.test.ts

Previous review (commit 7f1d780)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-ui/src/components/chart.css 1 New stylesheet is never @imported into styles/index.css, so chart container/error/canvas styling won't apply
packages/opencode/src/kilocode/tool/registry.ts 217 chart tool is added for all clients (CLI/TUI included) instead of being gated to vscode, but only the vscode webview has a renderer

SUGGESTION

File Line Issue
packages/kilo-ui/src/components/chart.tsx 70 borderColor for pie/doughnut/polar datasets isn't indexed per-slice like backgroundColor, so slices beyond 6 get no themed border
Files Reviewed (16 files)
  • bun.lock
  • packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/labs-tool-call-lab/search-previews-chromium-linux.png (generated baseline)
  • packages/kilo-ui/package.json
  • packages/kilo-ui/src/components/chart.css
  • packages/kilo-ui/src/components/chart.tsx
  • packages/kilo-ui/src/components/message-part.tsx
  • packages/kilo-vscode/webview-ui/src/stories/tool-call-lab.stories.tsx
  • packages/opencode/src/kilocode/soul.txt
  • packages/opencode/src/kilocode/tool/chart.ts
  • packages/opencode/src/kilocode/tool/registry.ts
  • packages/opencode/test/fixtures/recordings/kilocode/session/native-anthropic-tool-loop.json
  • packages/opencode/test/fixtures/recordings/kilocode/session/native-openai-oauth-tool-loop.json
  • packages/opencode/test/fixtures/recordings/kilocode/session/native-zen-tool-loop.json
  • packages/opencode/test/kilocode/tool-registry-indexing-import-failure.test.ts
  • packages/opencode/test/kilocode/tool-registry-indexing.test.ts
  • packages/opencode/test/kilocode/tool-registry-semantic-import-failure.test.ts

Fix these issues in Kilo Cloud


Reviewed by claude-opus-5 · Input: 34 · Output: 8.7K · Cached: 822K

Review guidance: REVIEW.md from base branch main

Comment thread packages/kilo-ui/src/components/chart.tsx
Comment thread packages/kilo-ui/src/components/chart.tsx Outdated
Comment thread packages/opencode/src/kilocode/system-prompt.ts Outdated
@cosi-conda

Copy link
Copy Markdown
Contributor Author

Addressing comments and will be pushing updates soon.

Comment thread packages/kilo-ui/src/components/chart.tsx Outdated
@@ -0,0 +1,137 @@
/** @jsxImportSource solid-js */
import { createEffect, createSignal, onCleanup } from "solid-js"
import { Chart, registerables } from "chart.js"

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.

SUGGESTION: the static import puts all of chart.js in the main webview chunk

message-part.tsx registers ChartTool via a static import, so hoisting chart.js to a top-level import means the whole library (~200KB minified) is now loaded for every chat session, even when no chart is ever rendered. The previous dynamic import("chart.js") kept it in its own chunk.

If the eager cost is acceptable, this is fine as-is. If you'd rather keep the split chunk, a module-level memoized loader gives you both (no repeated register, no lost reactive owner):

const load = import("chart.js").then((m) => (m.Chart.register(...m.registerables), m.Chart))

and then register the cleanup synchronously in the effect while creating the instance in the .then().


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@marius-kilocode this is why I had it inline before, but I don't know if you have strong feelings about it. This could make it load faster initially but also means it could be loaded but never needed.

Comment thread packages/kilo-ui/src/components/chart.tsx Outdated
@cosi-conda

Copy link
Copy Markdown
Contributor Author

I profiled this in the real VS Code webview using the self-test CDP profiler, with production transcript virtualization and message update handlers. The implementation is performant enough for the expected use case of 2-3 charts per session.

  • A realistic 80-message fixture with 40 chart calls and 250 points per chart still mounted only 5 charts because the transcript is virtualized. Cold loading produced one roughly 76 ms main-thread pause when Chart.js initialized; subsequent loads were cheaper.
  • A 400-message stress fixture with 200 charts retained only 2-5 canvases in the DOM while scrolling. A full transcript traversal remained smooth, with no measured frame interval above 32 ms.
  • At an intentionally aggressive 60 updates/second, rendered chart updates averaged 1.69 ms (1.9 ms p95), with no interval above 32 ms. This should not materially affect normal model streaming.
  • For 2-3 charts with ordinary datasets, the observed memory overhead is small, roughly a few hundred KB in total. The earlier high memory figure required mounting hundreds of charts and retaining them for inspection, so it is not representative of normal usage.

There is one lifecycle issue worth fixing: onCleanup() is registered inside the asynchronous import("chart.js").then(...) callback. Detached canvases retained Chart.js state in the stress test, which indicates chart.destroy() is not running. This is unlikely to be noticeable with 2-3 charts, but cleanup should be registered synchronously to avoid accumulation during repeated session switching or chart-heavy histories.

Overall, the chart approach and current rendering performance are good enough for the intended usage; the cleanup issue is a contained correctness fix rather than a reason to redesign the feature.

Thank you. Would you please share your profiling steps? I have addressed the lifecycle code, so the only outstanding update would be addressing applying theme colors for accessibility.

@marius-kilocode

Copy link
Copy Markdown
Collaborator

@cosi-conda

Copy link
Copy Markdown
Contributor Author

@cosi-conda you can profile with https://github.com/Kilo-Org/vscode-extension-self-test if you like.

Thank you for that and also the review. I am just learning more about kilo and solidjs, although I have a lot of TS, React and Angular experience. Hopefully my next PR will be faster. :)

@cosi-conda
cosi-conda merged commit 742537a into main Aug 3, 2026
34 of 35 checks passed
@cosi-conda
cosi-conda deleted the feature/charts branch August 3, 2026 16:39
t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
feat(charts/vscode): Added charting capabilities to kilo-ui storybook and VS Code extension
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