@the-forge-flow/visual-explainer-pi 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +226 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +238 -0
- package/dist/templates/architecture.d.ts +33 -0
- package/dist/templates/architecture.d.ts.map +1 -0
- package/dist/templates/architecture.js +292 -0
- package/dist/templates/data-table.d.ts +25 -0
- package/dist/templates/data-table.d.ts.map +1 -0
- package/dist/templates/data-table.js +255 -0
- package/dist/templates/mermaid.d.ts +11 -0
- package/dist/templates/mermaid.d.ts.map +1 -0
- package/dist/templates/mermaid.js +149 -0
- package/dist/templates/shared.d.ts +17 -0
- package/dist/templates/shared.d.ts.map +1 -0
- package/dist/templates/shared.js +663 -0
- package/dist/types.d.ts +57 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/utils/browser-open.d.ts +6 -0
- package/dist/utils/browser-open.d.ts.map +1 -0
- package/dist/utils/browser-open.js +33 -0
- package/dist/utils/file-writer.d.ts +8 -0
- package/dist/utils/file-writer.d.ts.map +1 -0
- package/dist/utils/file-writer.js +40 -0
- package/dist/utils/validators.d.ts +11 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +93 -0
- package/package.json +73 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 MonsieurBarti
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/MonsieurBarti/The-Forge-Flow-CC/refs/heads/main/assets/forge-banner.png" alt="The Forge Flow - Visual Explainer PI" width="100%">
|
|
3
|
+
|
|
4
|
+
<h1>🎨 Visual Explainer PI</h1>
|
|
5
|
+
|
|
6
|
+
<p>
|
|
7
|
+
<strong>PI extension for generating beautiful HTML visualizations</strong>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
<p>
|
|
11
|
+
<a href="https://github.com/MonsieurBarti/visual-explainer-pi/actions/workflows/ci.yml">
|
|
12
|
+
<img src="https://img.shields.io/github/actions/workflow/status/MonsieurBarti/visual-explainer-pi/ci.yml?label=CI&style=flat-square" alt="CI Status">
|
|
13
|
+
</a>
|
|
14
|
+
<a href="https://www.npmjs.com/package/@the-forge-flow/visual-explainer-pi">
|
|
15
|
+
<img src="https://img.shields.io/npm/v/@the-forge-flow/visual-explainer-pi?style=flat-square" alt="npm version">
|
|
16
|
+
</a>
|
|
17
|
+
<a href="LICENSE">
|
|
18
|
+
<img src="https://img.shields.io/github/license/MonsieurBarti/visual-explainer-pi?style=flat-square" alt="License">
|
|
19
|
+
</a>
|
|
20
|
+
</p>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
Turns complex terminal output into styled, self-contained HTML pages for diagrams, architecture overviews, diff reviews, data tables, and project recaps. Built on top of the design system from [nicobailon/visual-explainer](https://github.com/nicobailon/visual-explainer).
|
|
26
|
+
|
|
27
|
+
## ✨ Features
|
|
28
|
+
|
|
29
|
+
- **🎨 11 Visual Types**: architecture, flowchart, sequence, ER, state, table, diff, plan, timeline, dashboard, slides
|
|
30
|
+
- **🖌️ 8 Aesthetic Palettes**: blueprint, editorial, paper, terminal, dracula, nord, solarized, gruvbox
|
|
31
|
+
- **📄 Self-Contained HTML**: single file with embedded CSS/JS, opens in any browser
|
|
32
|
+
- **🧜 Mermaid Integration**: automatic diagrams with zoom/pan controls
|
|
33
|
+
- **📊 Data Tables**: responsive tables with sticky headers and status indicators
|
|
34
|
+
- **🤖 PI-native**: seamless integration with PI's tool system, abort-signal aware, output truncated to PI's limits
|
|
35
|
+
|
|
36
|
+
## 📦 Installation
|
|
37
|
+
|
|
38
|
+
### 1. Install the extension with `pi install`
|
|
39
|
+
|
|
40
|
+
PI discovers the extension automatically once installed as a pi package. By default this installs globally into `~/.pi/agent/`; pass `-l` to install into the current project (`.pi/`) instead.
|
|
41
|
+
|
|
42
|
+
**From npm (recommended):**
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pi install npm:@the-forge-flow/visual-explainer-pi
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**From GitHub (tracks `main`):**
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
pi install git:github.com/MonsieurBarti/visual-explainer-pi
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Pin to a specific version:**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# npm — pin to a published version
|
|
58
|
+
pi install npm:@the-forge-flow/visual-explainer-pi@0.1.0
|
|
59
|
+
|
|
60
|
+
# git — pin to a release tag
|
|
61
|
+
pi install git:github.com/MonsieurBarti/visual-explainer-pi@visual-explainer-pi-v0.1.0
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then reload PI with `/reload` (or restart it). On the next session you should see a notification that `Visual explainer ready`.
|
|
65
|
+
|
|
66
|
+
**Manage installed packages:**
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
pi list # show installed packages
|
|
70
|
+
pi update # update non-pinned packages
|
|
71
|
+
pi remove npm:@the-forge-flow/visual-explainer-pi
|
|
72
|
+
pi config # enable/disable individual extensions, skills, prompts, themes
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> For project-scoped installs, package filtering, and more, see the [pi packages doc](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/packages.md).
|
|
76
|
+
|
|
77
|
+
## 🚀 Usage
|
|
78
|
+
|
|
79
|
+
The extension registers a single `generate_visual` tool that the LLM can call directly. It also exposes two slash commands to reopen recently generated files.
|
|
80
|
+
|
|
81
|
+
### `generate_visual`
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// Render a technical architecture diagram
|
|
85
|
+
generate_visual({
|
|
86
|
+
type: "architecture",
|
|
87
|
+
title: "Auth System Overview",
|
|
88
|
+
aesthetic: "blueprint",
|
|
89
|
+
content: {
|
|
90
|
+
sections: [
|
|
91
|
+
{ label: "Edge", content: "<div class=\"inner-card\">API Gateway</div>" },
|
|
92
|
+
{ label: "Core", content: "<div class=\"inner-card\">Auth Service</div>", isHero: true },
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Render a Mermaid flowchart
|
|
98
|
+
generate_visual({
|
|
99
|
+
type: "flowchart",
|
|
100
|
+
title: "Data Pipeline",
|
|
101
|
+
aesthetic: "editorial",
|
|
102
|
+
content: "graph LR; A[Ingest] --> B[Transform] --> C[Store]",
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Render a comparison table
|
|
106
|
+
generate_visual({
|
|
107
|
+
type: "table",
|
|
108
|
+
title: "API Endpoints",
|
|
109
|
+
aesthetic: "paper",
|
|
110
|
+
content: [
|
|
111
|
+
{ method: "GET", path: "/users", status: "stable" },
|
|
112
|
+
{ method: "POST", path: "/users", status: "beta" },
|
|
113
|
+
],
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Tool Parameters
|
|
118
|
+
|
|
119
|
+
| Parameter | Type | Description |
|
|
120
|
+
|-----------|------|-------------|
|
|
121
|
+
| `type` | enum | Visual type: `architecture`, `flowchart`, `sequence`, `er`, `state`, `table`, `diff`, `plan`, `timeline`, `dashboard`, `slides`, `mermaid_custom` |
|
|
122
|
+
| `content` | string \| array | Raw content (mermaid syntax, markdown) or structured data rows |
|
|
123
|
+
| `title` | string | Title for the visualization |
|
|
124
|
+
| `aesthetic` | enum | Palette: `blueprint`, `editorial`, `paper`, `terminal`, `dracula`, `nord`, `solarized`, `gruvbox` |
|
|
125
|
+
| `theme` | enum | `light`, `dark`, or `auto` |
|
|
126
|
+
| `filename` | string | Optional output filename (auto-generated if omitted) |
|
|
127
|
+
|
|
128
|
+
### Slash Commands
|
|
129
|
+
|
|
130
|
+
- `/visual-reopen <n>` — re-open a recently generated visual by index (1-10)
|
|
131
|
+
- `/visual-list` — list recently generated visuals
|
|
132
|
+
|
|
133
|
+
### Output Location
|
|
134
|
+
|
|
135
|
+
Generated HTML files are saved to `~/.agent/diagrams/` and automatically opened in your default browser.
|
|
136
|
+
|
|
137
|
+
## 🏗️ Architecture
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
┌─────────────┐ ┌──────────────────┐ ┌─────────────┐
|
|
141
|
+
│ LLM Request│────▶│ generate_visual │────▶│ Browser │
|
|
142
|
+
│ (via PI) │ │ (defineTool) │ │ (HTML) │
|
|
143
|
+
└─────────────┘ └────────┬─────────┘ └─────────────┘
|
|
144
|
+
│
|
|
145
|
+
┌────────▼─────────┐
|
|
146
|
+
│ Palette + Template│
|
|
147
|
+
│ HTML Generation │
|
|
148
|
+
│ File Written │
|
|
149
|
+
└───────────────────┘
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Every tool call:
|
|
153
|
+
|
|
154
|
+
1. Validates parameters (`type`, `content`, `aesthetic`, `theme`).
|
|
155
|
+
2. Picks a template (`architecture`, `mermaid`, `data-table`) and a palette.
|
|
156
|
+
3. Generates a self-contained HTML document with embedded CSS/JS.
|
|
157
|
+
4. Truncates output to PI's ~50KB/2000-line limit via `truncateHead`.
|
|
158
|
+
5. Writes the file to `~/.agent/diagrams/` and opens it in the default browser.
|
|
159
|
+
|
|
160
|
+
## 🎨 Design Principles
|
|
161
|
+
|
|
162
|
+
Inherited from [nicobailon/visual-explainer](https://github.com/nicobailon/visual-explainer):
|
|
163
|
+
|
|
164
|
+
- **Typography First** — distinctive font pairings (never Inter as primary)
|
|
165
|
+
- **Warm Palettes** — terracotta, sage, teal, rose (never indigo/violet/pink defaults)
|
|
166
|
+
- **Depth Hierarchy** — hero → elevated → default → recessed visual weight
|
|
167
|
+
- **No AI Slop** — forbidden: gradient text, emoji headers, neon glows, animated shadows
|
|
168
|
+
- **Accessibility** — respects `prefers-reduced-motion`, semantic HTML tables
|
|
169
|
+
|
|
170
|
+
## 🧪 Development
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
# Install dependencies (also wires lefthook git hooks)
|
|
174
|
+
bun install
|
|
175
|
+
|
|
176
|
+
# Run tests
|
|
177
|
+
bun test
|
|
178
|
+
|
|
179
|
+
# Lint & format
|
|
180
|
+
bun run check
|
|
181
|
+
|
|
182
|
+
# Typecheck
|
|
183
|
+
bun run typecheck
|
|
184
|
+
|
|
185
|
+
# Build for publish
|
|
186
|
+
bun run build
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## 📁 Project Structure
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
src/
|
|
193
|
+
├── index.ts # Extension entry, tool registration, state
|
|
194
|
+
├── types.ts # TypeScript type definitions
|
|
195
|
+
├── templates/
|
|
196
|
+
│ ├── architecture.ts # CSS Grid card layout
|
|
197
|
+
│ ├── data-table.ts # HTML table template
|
|
198
|
+
│ ├── mermaid.ts # Mermaid diagram wrapper
|
|
199
|
+
│ └── shared.ts # Palettes, fonts, CSS variables
|
|
200
|
+
└── utils/
|
|
201
|
+
├── browser-open.ts # Cross-platform browser launcher
|
|
202
|
+
├── file-writer.ts # Temp file + state management
|
|
203
|
+
└── validators.ts # Input validation
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## 🤝 Contributing
|
|
207
|
+
|
|
208
|
+
1. Fork the repository
|
|
209
|
+
2. Create your feature branch (`git checkout -b feat/amazing`)
|
|
210
|
+
3. Commit with conventional commits (`git commit -m "feat: add something"`)
|
|
211
|
+
4. Push to the branch (`git push origin feat/amazing`)
|
|
212
|
+
5. Open a Pull Request
|
|
213
|
+
|
|
214
|
+
## 🙏 Credits
|
|
215
|
+
|
|
216
|
+
This extension re-uses the visual design system (palettes, typography, layout primitives) from [**nicobailon/visual-explainer**](https://github.com/nicobailon/visual-explainer) by [Nico Bailon](https://github.com/nicobailon). The PI integration layer (tool API, validators, templates re-implementation, tests) is original work. Huge thanks to Nico for the beautiful aesthetic foundation.
|
|
217
|
+
|
|
218
|
+
## 📜 License
|
|
219
|
+
|
|
220
|
+
MIT © [MonsieurBarti](https://github.com/MonsieurBarti)
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
<div align="center">
|
|
225
|
+
<sub>Built with ⚡ by <a href="https://github.com/MonsieurBarti">MonsieurBarti</a></sub>
|
|
226
|
+
</div>
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual Explainer PI Extension
|
|
3
|
+
*
|
|
4
|
+
* Generates beautiful, self-contained HTML pages for diagrams, architecture,
|
|
5
|
+
* diff reviews, plan audits, data tables, and project recaps.
|
|
6
|
+
*
|
|
7
|
+
* Based on nicobailon/visual-explainer design principles.
|
|
8
|
+
*/
|
|
9
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
10
|
+
/**
|
|
11
|
+
* Main extension export
|
|
12
|
+
*/
|
|
13
|
+
export default function visualExplainerExtension(pi: ExtensionAPI): void;
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AA+JlE;;GAEG;AACH,MAAM,CAAC,OAAO,UAAU,wBAAwB,CAAC,EAAE,EAAE,YAAY,QA6IhE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Visual Explainer PI Extension
|
|
3
|
+
*
|
|
4
|
+
* Generates beautiful, self-contained HTML pages for diagrams, architecture,
|
|
5
|
+
* diff reviews, plan audits, data tables, and project recaps.
|
|
6
|
+
*
|
|
7
|
+
* Based on nicobailon/visual-explainer design principles.
|
|
8
|
+
*/
|
|
9
|
+
import { StringEnum } from "@mariozechner/pi-ai";
|
|
10
|
+
import { defineTool, truncateHead } from "@mariozechner/pi-coding-agent";
|
|
11
|
+
import { Type } from "@sinclair/typebox";
|
|
12
|
+
import { generateArchitectureTemplate } from "./templates/architecture.js";
|
|
13
|
+
import { generateTableTemplate } from "./templates/data-table.js";
|
|
14
|
+
import { generateMermaidTemplate } from "./templates/mermaid.js";
|
|
15
|
+
import { openInBrowser } from "./utils/browser-open.js";
|
|
16
|
+
import { createInitialState, writeHtmlFile } from "./utils/file-writer.js";
|
|
17
|
+
import { generateDefaultFilename, sanitizeFilename, validateParams } from "./utils/validators.js";
|
|
18
|
+
// Extension state
|
|
19
|
+
const state = createInitialState();
|
|
20
|
+
/**
|
|
21
|
+
* Generate visual HTML based on type and content
|
|
22
|
+
*/
|
|
23
|
+
async function generateVisual(params, pi) {
|
|
24
|
+
// Determine if dark mode
|
|
25
|
+
const isDark = params.theme === "dark" || (params.theme === "auto" && prefersDarkMode());
|
|
26
|
+
// Generate HTML based on type
|
|
27
|
+
let html;
|
|
28
|
+
switch (params.type) {
|
|
29
|
+
case "architecture":
|
|
30
|
+
html = generateArchitectureTemplate(params.title, params.content, params.aesthetic ?? "blueprint", isDark);
|
|
31
|
+
break;
|
|
32
|
+
case "flowchart":
|
|
33
|
+
case "sequence":
|
|
34
|
+
case "er":
|
|
35
|
+
case "state":
|
|
36
|
+
case "mermaid_custom":
|
|
37
|
+
html = generateMermaidTemplate(params.title, {
|
|
38
|
+
mermaidSyntax: params.content,
|
|
39
|
+
caption: `${params.type} diagram`,
|
|
40
|
+
}, params.aesthetic ?? "blueprint", isDark);
|
|
41
|
+
break;
|
|
42
|
+
case "table":
|
|
43
|
+
html = generateTableTemplate(params.title, params.content, params.aesthetic ?? "blueprint", isDark);
|
|
44
|
+
break;
|
|
45
|
+
case "diff":
|
|
46
|
+
// For now, treat diff as architecture with special handling
|
|
47
|
+
html = generateArchitectureTemplate(params.title, {
|
|
48
|
+
sections: [
|
|
49
|
+
{
|
|
50
|
+
label: "Changes Overview",
|
|
51
|
+
content: `<div class="inner-card"><div class="title">${escapeHtml(params.content).substring(0, 100)}...</div></div>`,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
}, params.aesthetic ?? "blueprint", isDark);
|
|
55
|
+
break;
|
|
56
|
+
case "plan":
|
|
57
|
+
html = generateArchitectureTemplate(params.title, {
|
|
58
|
+
sections: [
|
|
59
|
+
{
|
|
60
|
+
label: "Implementation Plan",
|
|
61
|
+
content: `<div class="callout">${escapeHtml(params.content).substring(0, 200)}...</div>`,
|
|
62
|
+
isHero: true,
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
}, params.aesthetic ?? "blueprint", isDark);
|
|
66
|
+
break;
|
|
67
|
+
case "timeline":
|
|
68
|
+
case "dashboard":
|
|
69
|
+
case "slides":
|
|
70
|
+
// Fallback to architecture template for now
|
|
71
|
+
console.warn(`Type ${params.type} not fully implemented, using architecture template`);
|
|
72
|
+
html = generateArchitectureTemplate(params.title, {
|
|
73
|
+
sections: [
|
|
74
|
+
{
|
|
75
|
+
label: params.type,
|
|
76
|
+
content: `<div class="inner-card"><div class="title">Content</div><div class="desc">${escapeHtml(String(params.content)).substring(0, 200)}...</div></div>`,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
}, params.aesthetic ?? "blueprint", isDark);
|
|
80
|
+
break;
|
|
81
|
+
default:
|
|
82
|
+
throw new Error(`Unsupported visual type: ${params.type}`);
|
|
83
|
+
}
|
|
84
|
+
// Safety check: truncate if too large
|
|
85
|
+
const truncated = truncateHead(html, { maxBytes: 50000, maxLines: 2000 });
|
|
86
|
+
// Generate filename
|
|
87
|
+
const filename = params.filename
|
|
88
|
+
? sanitizeFilename(params.filename)
|
|
89
|
+
: generateDefaultFilename(params.title);
|
|
90
|
+
// Write file
|
|
91
|
+
const filePath = await writeHtmlFile(filename, truncated.content, state);
|
|
92
|
+
// Open in browser
|
|
93
|
+
await openInBrowser(filePath, pi);
|
|
94
|
+
// Generate preview snippet (first 500 chars of content summary)
|
|
95
|
+
const previewSnippet = `Generated ${params.type} visualization: ${params.title}`;
|
|
96
|
+
return {
|
|
97
|
+
filePath,
|
|
98
|
+
previewSnippet,
|
|
99
|
+
url: `file://${filePath}`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function prefersDarkMode() {
|
|
103
|
+
// This runs on the server, so we default to light
|
|
104
|
+
// In a real implementation, this could check system preferences
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
function escapeHtml(str) {
|
|
108
|
+
return str
|
|
109
|
+
.replace(/&/g, "&")
|
|
110
|
+
.replace(/</g, "<")
|
|
111
|
+
.replace(/>/g, ">")
|
|
112
|
+
.replace(/"/g, """)
|
|
113
|
+
.replace(/'/g, "'");
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Main extension export
|
|
117
|
+
*/
|
|
118
|
+
export default function visualExplainerExtension(pi) {
|
|
119
|
+
// Initialize on session start
|
|
120
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
121
|
+
if (ctx.hasUI) {
|
|
122
|
+
ctx.ui.notify("Visual explainer ready", "info");
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
// Register generate_visual tool
|
|
126
|
+
const generateVisualTool = defineTool({
|
|
127
|
+
name: "generate_visual",
|
|
128
|
+
label: "Generate Visual",
|
|
129
|
+
description: "Generate beautiful, self-contained HTML pages for diagrams, architecture overviews, diff reviews, data tables, and visual explanations. Opens result in browser. Based on nicobailon/visual-explainer design principles.",
|
|
130
|
+
promptSnippet: "Create a visual diagram/architecture/table",
|
|
131
|
+
promptGuidelines: [
|
|
132
|
+
"Use this tool when the user asks for diagrams, architecture views, or data tables",
|
|
133
|
+
"Proactively use for complex tables (4+ rows, 3+ columns) instead of ASCII",
|
|
134
|
+
"Choose aesthetic based on context: blueprint (technical), editorial (formal), paper (warm), terminal (retro), dracula/nord/solarized/gruvbox (IDE themes)",
|
|
135
|
+
"Content can be structured data (for tables) or mermaid syntax (for diagrams)",
|
|
136
|
+
],
|
|
137
|
+
parameters: Type.Object({
|
|
138
|
+
type: StringEnum([
|
|
139
|
+
"architecture",
|
|
140
|
+
"flowchart",
|
|
141
|
+
"sequence",
|
|
142
|
+
"er",
|
|
143
|
+
"state",
|
|
144
|
+
"table",
|
|
145
|
+
"diff",
|
|
146
|
+
"plan",
|
|
147
|
+
"timeline",
|
|
148
|
+
"dashboard",
|
|
149
|
+
"slides",
|
|
150
|
+
"mermaid_custom",
|
|
151
|
+
], { description: "Type of visualization to generate" }),
|
|
152
|
+
content: Type.Union([
|
|
153
|
+
Type.String({ description: "Raw content (mermaid syntax, markdown)" }),
|
|
154
|
+
Type.Array(Type.Record(Type.String(), Type.Unknown()), {
|
|
155
|
+
description: "Structured data rows for tables",
|
|
156
|
+
}),
|
|
157
|
+
]),
|
|
158
|
+
title: Type.String({ description: "Title for the visualization" }),
|
|
159
|
+
aesthetic: Type.Optional(StringEnum([
|
|
160
|
+
"blueprint",
|
|
161
|
+
"editorial",
|
|
162
|
+
"paper",
|
|
163
|
+
"terminal",
|
|
164
|
+
"dracula",
|
|
165
|
+
"nord",
|
|
166
|
+
"solarized",
|
|
167
|
+
"gruvbox",
|
|
168
|
+
], { description: "Visual aesthetic/theme palette" })),
|
|
169
|
+
theme: Type.Optional(StringEnum(["light", "dark", "auto"], {
|
|
170
|
+
description: "Color theme mode",
|
|
171
|
+
})),
|
|
172
|
+
filename: Type.Optional(Type.String({ description: "Output filename (auto-generated if omitted)" })),
|
|
173
|
+
}),
|
|
174
|
+
async execute(_toolCallId, rawParams, _signal, _onUpdate, _ctx) {
|
|
175
|
+
// Validate parameters
|
|
176
|
+
const params = validateParams(rawParams);
|
|
177
|
+
// Generate visual
|
|
178
|
+
const result = await generateVisual(params, pi);
|
|
179
|
+
return {
|
|
180
|
+
content: [
|
|
181
|
+
{
|
|
182
|
+
type: "text",
|
|
183
|
+
text: `${result.previewSnippet}\n\nOpened in browser: ${result.url}\nFile: ${result.filePath}`,
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
details: {
|
|
187
|
+
type: params.type,
|
|
188
|
+
title: params.title,
|
|
189
|
+
aesthetic: params.aesthetic,
|
|
190
|
+
theme: params.theme,
|
|
191
|
+
filePath: result.filePath,
|
|
192
|
+
url: result.url,
|
|
193
|
+
},
|
|
194
|
+
};
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
pi.registerTool(generateVisualTool);
|
|
198
|
+
// Register reopen command for recent files
|
|
199
|
+
pi.registerCommand("visual-reopen", {
|
|
200
|
+
description: "Re-open a recently generated visual by index (1-10)",
|
|
201
|
+
handler: async (args, ctx) => {
|
|
202
|
+
const index = Number.parseInt(args, 10) - 1;
|
|
203
|
+
if (index < 0 || index >= state.recentFiles.length) {
|
|
204
|
+
if (ctx.hasUI) {
|
|
205
|
+
ctx.ui.notify(`Invalid index. Use 1-${state.recentFiles.length}`, "error");
|
|
206
|
+
}
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const filePath = state.recentFiles[index];
|
|
210
|
+
await openInBrowser(filePath, pi);
|
|
211
|
+
if (ctx.hasUI) {
|
|
212
|
+
ctx.ui.notify(`Re-opened: ${filePath}`, "info");
|
|
213
|
+
}
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
// Register list command
|
|
217
|
+
pi.registerCommand("visual-list", {
|
|
218
|
+
description: "List recently generated visuals",
|
|
219
|
+
handler: async (_args, ctx) => {
|
|
220
|
+
if (state.recentFiles.length === 0) {
|
|
221
|
+
if (ctx.hasUI) {
|
|
222
|
+
ctx.ui.notify("No recent visuals", "warning");
|
|
223
|
+
}
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
const list = state.recentFiles.map((f, i) => `${i + 1}. ${f}`).join("\n");
|
|
227
|
+
if (ctx.hasUI) {
|
|
228
|
+
ctx.ui.notify(`Recent visuals:\n${list}`, "info");
|
|
229
|
+
}
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
// Cleanup on shutdown
|
|
233
|
+
pi.on("session_shutdown", async () => {
|
|
234
|
+
// Note: We don't delete the HTML files - they persist for user reference
|
|
235
|
+
// Only cleanup would be if we created any temp directories
|
|
236
|
+
state.tempDirs = [];
|
|
237
|
+
});
|
|
238
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Architecture template - CSS Grid card layout for text-heavy system overviews
|
|
3
|
+
* Based on nicobailon/visual-explainer architecture.html
|
|
4
|
+
*/
|
|
5
|
+
import type { Aesthetic } from "../types.js";
|
|
6
|
+
export interface ArchitectureSection {
|
|
7
|
+
label: string;
|
|
8
|
+
labelColor?: "accent" | "green" | "orange" | "teal" | "plum";
|
|
9
|
+
content: string;
|
|
10
|
+
isHero?: boolean;
|
|
11
|
+
isRecessed?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface ArchitectureContent {
|
|
14
|
+
sections: ArchitectureSection[];
|
|
15
|
+
flowArrows?: {
|
|
16
|
+
label: string;
|
|
17
|
+
}[];
|
|
18
|
+
threeColumn?: ArchitectureSection[];
|
|
19
|
+
pipeline?: {
|
|
20
|
+
steps: {
|
|
21
|
+
num: string;
|
|
22
|
+
name: string;
|
|
23
|
+
detail: string;
|
|
24
|
+
color: string;
|
|
25
|
+
}[];
|
|
26
|
+
legend?: {
|
|
27
|
+
color: string;
|
|
28
|
+
label: string;
|
|
29
|
+
}[];
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export declare function generateArchitectureTemplate(title: string, content: ArchitectureContent, aesthetic: Aesthetic, isDark: boolean): string;
|
|
33
|
+
//# sourceMappingURL=architecture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"architecture.d.ts","sourceRoot":"","sources":["../../src/templates/architecture.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAW,MAAM,aAAa,CAAC;AAUtD,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;IAC7D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IACnC,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,UAAU,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACpC,QAAQ,CAAC,EAAE;QACV,KAAK,EAAE;YAAE,GAAG,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACtE,MAAM,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KAC5C,CAAC;CACF;AAED,wBAAgB,4BAA4B,CAC3C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,mBAAmB,EAC5B,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE,OAAO,GACb,MAAM,CAQR"}
|