@claude-canvas/vite-plugin 0.2.0

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.
@@ -0,0 +1,7 @@
1
+ import { Plugin } from 'vite';
2
+ import { ClaudeCanvasOptions } from '@claude-canvas/bridge';
3
+ export { ClaudeCanvasOptions } from '@claude-canvas/bridge';
4
+
5
+ declare function claudeCanvas(options?: ClaudeCanvasOptions): Plugin;
6
+
7
+ export { claudeCanvas, claudeCanvas as default };
package/dist/index.js ADDED
@@ -0,0 +1,191 @@
1
+ // src/server-hook.ts
2
+ import { WSProtocol } from "@claude-canvas/bridge";
3
+ import { ClaudeBridge } from "@claude-canvas/bridge";
4
+ import { GitManager } from "@claude-canvas/bridge";
5
+ import { QARunner } from "@claude-canvas/bridge";
6
+ import { PromptBuilder } from "@claude-canvas/bridge";
7
+ function createServerHook(options) {
8
+ return (server) => {
9
+ const bridge = new ClaudeBridge(options);
10
+ const gitManager = new GitManager();
11
+ const qaRunner = new QARunner(options.qa);
12
+ server.ws.on("canvas:message", (rawData) => {
13
+ try {
14
+ const msg = WSProtocol.parseClientMessage(rawData);
15
+ switch (msg.type) {
16
+ case "canvas:session-start":
17
+ handleSessionStart(server, gitManager, options);
18
+ break;
19
+ case "canvas:session-end":
20
+ handleSessionEnd(server, gitManager, qaRunner, msg.payload.action);
21
+ break;
22
+ case "canvas:annotate":
23
+ handleAnnotate(server, bridge, msg.payload);
24
+ break;
25
+ case "canvas:chat":
26
+ handleChat(server, bridge, msg.payload.message);
27
+ break;
28
+ case "canvas:qa-retry":
29
+ handleQARetry(server, qaRunner);
30
+ break;
31
+ }
32
+ } catch (err) {
33
+ const errMsg = WSProtocol.createErrorMessage(
34
+ err instanceof Error ? err.message : "Unknown error",
35
+ true
36
+ );
37
+ server.ws.send("canvas:message", WSProtocol.serializeServerMessage(errMsg));
38
+ }
39
+ });
40
+ server.httpServer?.on("close", async () => {
41
+ await bridge.shutdown();
42
+ });
43
+ };
44
+ }
45
+ async function handleSessionStart(server, git, options) {
46
+ const session = await git.startSession({ branchPrefix: options.git?.branchPrefix });
47
+ server.ws.send("canvas:message", JSON.stringify({
48
+ type: "canvas:session-status",
49
+ payload: session
50
+ }));
51
+ }
52
+ async function handleSessionEnd(server, git, qa, action) {
53
+ if (action === "merge") {
54
+ const steps = [];
55
+ for await (const step of qa.run()) {
56
+ steps.push(step);
57
+ server.ws.send("canvas:message", JSON.stringify({
58
+ type: "canvas:qa-progress",
59
+ payload: { step: step.name, status: step.pass ? "pass" : "fail" }
60
+ }));
61
+ }
62
+ const result = qa.getResult(steps);
63
+ server.ws.send("canvas:message", JSON.stringify({
64
+ type: "canvas:qa-result",
65
+ payload: result
66
+ }));
67
+ if (result.overallPass) {
68
+ const mergeResult = await git.endSession("merge");
69
+ server.ws.send("canvas:message", JSON.stringify({
70
+ type: "canvas:merge-result",
71
+ payload: mergeResult
72
+ }));
73
+ }
74
+ } else {
75
+ const mergeResult = await git.endSession("discard");
76
+ server.ws.send("canvas:message", JSON.stringify({
77
+ type: "canvas:merge-result",
78
+ payload: mergeResult
79
+ }));
80
+ }
81
+ }
82
+ async function handleAnnotate(server, bridge, payload) {
83
+ const prompt = PromptBuilder.buildPrompt(payload.annotations, payload.memo);
84
+ for await (const delta of bridge.sendPrompt(prompt)) {
85
+ server.ws.send("canvas:message", JSON.stringify({
86
+ type: "canvas:stream",
87
+ payload: { delta, done: false }
88
+ }));
89
+ }
90
+ server.ws.send("canvas:message", JSON.stringify({
91
+ type: "canvas:stream",
92
+ payload: { delta: "", done: true }
93
+ }));
94
+ }
95
+ async function handleChat(server, bridge, message) {
96
+ for await (const delta of bridge.sendPrompt(message)) {
97
+ server.ws.send("canvas:message", JSON.stringify({
98
+ type: "canvas:stream",
99
+ payload: { delta, done: false }
100
+ }));
101
+ }
102
+ server.ws.send("canvas:message", JSON.stringify({
103
+ type: "canvas:stream",
104
+ payload: { delta: "", done: true }
105
+ }));
106
+ }
107
+ async function handleQARetry(server, qa) {
108
+ const steps = [];
109
+ for await (const step of qa.run()) {
110
+ steps.push(step);
111
+ server.ws.send("canvas:message", JSON.stringify({
112
+ type: "canvas:qa-progress",
113
+ payload: { step: step.name, status: step.pass ? "pass" : "fail" }
114
+ }));
115
+ }
116
+ const result = qa.getResult(steps);
117
+ server.ws.send("canvas:message", JSON.stringify({
118
+ type: "canvas:qa-result",
119
+ payload: result
120
+ }));
121
+ }
122
+
123
+ // src/html-inject.ts
124
+ function createHtmlInject(options) {
125
+ return () => {
126
+ return {
127
+ html: "",
128
+ tags: [
129
+ {
130
+ tag: "script",
131
+ attrs: { type: "module" },
132
+ children: generateClientScript(options),
133
+ injectTo: "body"
134
+ }
135
+ ]
136
+ };
137
+ };
138
+ }
139
+ function generateClientScript(options) {
140
+ const shortcut = options.shortcut || "ctrl+shift+a";
141
+ return `
142
+ import { ShadowContainer, CanvasOverlayPanel, ToolbarPanel, InspectorPopupPanel, ChatPanel, SessionBarPanel, QAResultPanel, FabButtonPanel, KeyboardHandler } from '@claude-canvas/core';
143
+
144
+ const container = new ShadowContainer();
145
+ container.mount();
146
+ const shadow = container.getShadowRoot();
147
+
148
+ const overlay = new CanvasOverlayPanel();
149
+ overlay.mount();
150
+
151
+ const toolbar = new ToolbarPanel(shadow);
152
+ const inspector = new InspectorPopupPanel(shadow);
153
+ const chat = new ChatPanel(shadow);
154
+ const sessionBar = new SessionBarPanel(shadow);
155
+ const qaResult = new QAResultPanel(shadow);
156
+ const fab = new FabButtonPanel(shadow);
157
+
158
+ // Wire up WebSocket via Vite HMR
159
+ if (import.meta.hot) {
160
+ import.meta.hot.on('canvas:message', (data) => {
161
+ const msg = JSON.parse(data);
162
+ // Route messages to appropriate panels
163
+ });
164
+ }
165
+
166
+ // Keyboard handler (shortcut: ${shortcut})
167
+ const keyboard = new KeyboardHandler({
168
+ onToggleMode: () => { /* toggle annotation mode */ },
169
+ onEscape: () => { overlay.setMode('off'); },
170
+ onToolSwitch: (mode) => { overlay.setMode(mode); toolbar.setActiveTool(mode); },
171
+ onSend: () => { /* send via chat */ },
172
+ });
173
+ keyboard.mount();
174
+ `;
175
+ }
176
+
177
+ // src/index.ts
178
+ function claudeCanvas(options = {}) {
179
+ return {
180
+ name: "vite-plugin-claude-canvas",
181
+ apply: "serve",
182
+ configureServer: createServerHook(options),
183
+ transformIndexHtml: createHtmlInject(options)
184
+ };
185
+ }
186
+ var index_default = claudeCanvas;
187
+ export {
188
+ claudeCanvas,
189
+ index_default as default
190
+ };
191
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server-hook.ts","../src/html-inject.ts","../src/index.ts"],"sourcesContent":["import type { ViteDevServer } from 'vite'\nimport type { AnnotationSet } from '@claude-canvas/core'\nimport type { ClaudeCanvasOptions } from './types.js'\nimport { WSProtocol } from '@claude-canvas/bridge'\nimport { ClaudeBridge } from '@claude-canvas/bridge'\nimport { GitManager } from '@claude-canvas/bridge'\nimport { QARunner } from '@claude-canvas/bridge'\nimport { PromptBuilder } from '@claude-canvas/bridge'\n\nexport function createServerHook(options: ClaudeCanvasOptions) {\n return (server: ViteDevServer) => {\n const bridge = new ClaudeBridge(options)\n const gitManager = new GitManager()\n const qaRunner = new QARunner(options.qa)\n\n server.ws.on('canvas:message', (rawData: string) => {\n try {\n const msg = WSProtocol.parseClientMessage(rawData)\n\n switch (msg.type) {\n case 'canvas:session-start':\n handleSessionStart(server, gitManager, options)\n break\n case 'canvas:session-end':\n handleSessionEnd(server, gitManager, qaRunner, msg.payload.action)\n break\n case 'canvas:annotate':\n handleAnnotate(server, bridge, msg.payload)\n break\n case 'canvas:chat':\n handleChat(server, bridge, msg.payload.message)\n break\n case 'canvas:qa-retry':\n handleQARetry(server, qaRunner)\n break\n }\n } catch (err) {\n const errMsg = WSProtocol.createErrorMessage(\n err instanceof Error ? err.message : 'Unknown error',\n true\n )\n server.ws.send('canvas:message', WSProtocol.serializeServerMessage(errMsg))\n }\n })\n\n // Cleanup on server close\n server.httpServer?.on('close', async () => {\n await bridge.shutdown()\n })\n }\n}\n\nasync function handleSessionStart(\n server: ViteDevServer,\n git: GitManager,\n options: ClaudeCanvasOptions\n) {\n const session = await git.startSession({ branchPrefix: options.git?.branchPrefix })\n server.ws.send('canvas:message', JSON.stringify({\n type: 'canvas:session-status',\n payload: session,\n }))\n}\n\nasync function handleSessionEnd(\n server: ViteDevServer,\n git: GitManager,\n qa: QARunner,\n action: 'merge' | 'discard'\n) {\n if (action === 'merge') {\n const steps = []\n for await (const step of qa.run()) {\n steps.push(step)\n server.ws.send('canvas:message', JSON.stringify({\n type: 'canvas:qa-progress',\n payload: { step: step.name, status: step.pass ? 'pass' : 'fail' },\n }))\n }\n const result = qa.getResult(steps)\n server.ws.send('canvas:message', JSON.stringify({\n type: 'canvas:qa-result',\n payload: result,\n }))\n\n if (result.overallPass) {\n const mergeResult = await git.endSession('merge')\n server.ws.send('canvas:message', JSON.stringify({\n type: 'canvas:merge-result',\n payload: mergeResult,\n }))\n }\n } else {\n const mergeResult = await git.endSession('discard')\n server.ws.send('canvas:message', JSON.stringify({\n type: 'canvas:merge-result',\n payload: mergeResult,\n }))\n }\n}\n\nasync function handleAnnotate(\n server: ViteDevServer,\n bridge: ClaudeBridge,\n payload: { annotations: AnnotationSet; memo: string }\n) {\n const prompt = PromptBuilder.buildPrompt(payload.annotations, payload.memo)\n for await (const delta of bridge.sendPrompt(prompt)) {\n server.ws.send('canvas:message', JSON.stringify({\n type: 'canvas:stream',\n payload: { delta, done: false },\n }))\n }\n server.ws.send('canvas:message', JSON.stringify({\n type: 'canvas:stream',\n payload: { delta: '', done: true },\n }))\n}\n\nasync function handleChat(\n server: ViteDevServer,\n bridge: ClaudeBridge,\n message: string\n) {\n for await (const delta of bridge.sendPrompt(message)) {\n server.ws.send('canvas:message', JSON.stringify({\n type: 'canvas:stream',\n payload: { delta, done: false },\n }))\n }\n server.ws.send('canvas:message', JSON.stringify({\n type: 'canvas:stream',\n payload: { delta: '', done: true },\n }))\n}\n\nasync function handleQARetry(server: ViteDevServer, qa: QARunner) {\n const steps = []\n for await (const step of qa.run()) {\n steps.push(step)\n server.ws.send('canvas:message', JSON.stringify({\n type: 'canvas:qa-progress',\n payload: { step: step.name, status: step.pass ? 'pass' : 'fail' },\n }))\n }\n const result = qa.getResult(steps)\n server.ws.send('canvas:message', JSON.stringify({\n type: 'canvas:qa-result',\n payload: result,\n }))\n}\n","import type { IndexHtmlTransformResult } from 'vite'\nimport type { ClaudeCanvasOptions } from './types.js'\n\nexport function createHtmlInject(options: ClaudeCanvasOptions) {\n return (): IndexHtmlTransformResult => {\n return {\n html: '',\n tags: [\n {\n tag: 'script',\n attrs: { type: 'module' },\n children: generateClientScript(options),\n injectTo: 'body',\n },\n ],\n }\n }\n}\n\nfunction generateClientScript(options: ClaudeCanvasOptions): string {\n const shortcut = options.shortcut || 'ctrl+shift+a'\n return `\n import { ShadowContainer, CanvasOverlayPanel, ToolbarPanel, InspectorPopupPanel, ChatPanel, SessionBarPanel, QAResultPanel, FabButtonPanel, KeyboardHandler } from '@claude-canvas/core';\n\n const container = new ShadowContainer();\n container.mount();\n const shadow = container.getShadowRoot();\n\n const overlay = new CanvasOverlayPanel();\n overlay.mount();\n\n const toolbar = new ToolbarPanel(shadow);\n const inspector = new InspectorPopupPanel(shadow);\n const chat = new ChatPanel(shadow);\n const sessionBar = new SessionBarPanel(shadow);\n const qaResult = new QAResultPanel(shadow);\n const fab = new FabButtonPanel(shadow);\n\n // Wire up WebSocket via Vite HMR\n if (import.meta.hot) {\n import.meta.hot.on('canvas:message', (data) => {\n const msg = JSON.parse(data);\n // Route messages to appropriate panels\n });\n }\n\n // Keyboard handler (shortcut: ${shortcut})\n const keyboard = new KeyboardHandler({\n onToggleMode: () => { /* toggle annotation mode */ },\n onEscape: () => { overlay.setMode('off'); },\n onToolSwitch: (mode) => { overlay.setMode(mode); toolbar.setActiveTool(mode); },\n onSend: () => { /* send via chat */ },\n });\n keyboard.mount();\n `\n}\n","import type { Plugin } from 'vite'\r\nimport type { ClaudeCanvasOptions } from './types.js'\r\nimport { createServerHook } from './server-hook.js'\r\nimport { createHtmlInject } from './html-inject.js'\r\n\r\nexport function claudeCanvas(options: ClaudeCanvasOptions = {}): Plugin {\r\n return {\r\n name: 'vite-plugin-claude-canvas',\r\n apply: 'serve',\r\n configureServer: createServerHook(options),\r\n transformIndexHtml: createHtmlInject(options),\r\n }\r\n}\r\n\r\nexport default claudeCanvas\r\n\r\nexport type { ClaudeCanvasOptions }\r\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@claude-canvas/vite-plugin",
3
+ "version": "0.2.0",
4
+ "description": "Vite plugin for visual annotation → Claude code modification → HMR verification",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "publishConfig": {
18
+ "access": "public"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/claude-canvas/claude-canvas.git",
23
+ "directory": "packages/vite-plugin"
24
+ },
25
+ "dependencies": {
26
+ "@claude-canvas/core": "0.2.0",
27
+ "@claude-canvas/bridge": "0.2.0"
28
+ },
29
+ "devDependencies": {
30
+ "tsup": "^8.4.0",
31
+ "vitest": "^3.0.0",
32
+ "typescript": "^5.7.0",
33
+ "vite": "^6.1.0",
34
+ "@types/node": "^22.0.0"
35
+ },
36
+ "peerDependencies": {
37
+ "vite": ">=5.0.0"
38
+ },
39
+ "keywords": [
40
+ "vite",
41
+ "vite-plugin",
42
+ "claude",
43
+ "annotation",
44
+ "devtools"
45
+ ],
46
+ "scripts": {
47
+ "build": "tsup",
48
+ "test": "vitest run",
49
+ "test:watch": "vitest",
50
+ "lint": "eslint src/",
51
+ "typecheck": "tsc --noEmit",
52
+ "clean": "rm -rf dist"
53
+ }
54
+ }