agent-canvas 0.1.10 → 0.1.12

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.
@@ -4,7 +4,7 @@
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1" />
6
6
  <title>Agent Canvas</title>
7
- <script>document.documentElement.dataset.theme = localStorage.getItem('canvas-theme') || 'dark';</script>
7
+ <script>!function(){var p=localStorage.getItem('canvas-theme')||'auto';document.documentElement.dataset.theme=p==='auto'?(matchMedia('(prefers-color-scheme:dark)').matches?'dark':'light'):p}()</script>
8
8
  <link rel="stylesheet" href="/assets/client.css" />
9
9
  <link rel="stylesheet" href="https://unpkg.com/@highlightjs/cdn-assets@11.11.1/styles/github-dark-dimmed.min.css" />
10
10
  <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
@@ -33,22 +33,28 @@ export async function compilePlan(jsx: string, projectRoot?: string): Promise<Co
33
33
  try {
34
34
  writeFileSync(tmpFile, source);
35
35
 
36
- const result = await Bun.build({
37
- entrypoints: [tmpFile],
38
- format: "esm",
39
- external: ["react", "react-dom", "#canvas/components", "#canvas/runtime"],
40
- });
41
-
42
- if (!result.success) {
43
- const errors = result.logs
44
- .filter((l) => l.level === "error")
45
- .map((l) => l.message)
46
- .join("\n");
47
- return { ok: false, error: errors || "Compilation failed" };
48
- }
36
+ try {
37
+ const result = await Bun.build({
38
+ entrypoints: [tmpFile],
39
+ format: "esm",
40
+ external: ["react", "react-dom", "#canvas/components", "#canvas/runtime"],
41
+ });
42
+
43
+ if (!result.success) {
44
+ const errors = result.logs
45
+ .filter((l) => l.level === "error")
46
+ .map((l) => l.message)
47
+ .join("\n");
48
+ return { ok: false, error: errors || "Compilation failed" };
49
+ }
49
50
 
50
- const js = await result.outputs[0].text();
51
- return { ok: true, js };
51
+ const js = await result.outputs[0].text();
52
+ return { ok: true, js };
53
+ } catch {
54
+ // Bun.build() can throw "Unknown Error, TODO" in long-running processes
55
+ // when its internal bundler state gets corrupted. Fall back to subprocess.
56
+ return await compilePlanSubprocess(tmpFile);
57
+ }
52
58
  } catch (e: any) {
53
59
  return { ok: false, error: e.message };
54
60
  } finally {
@@ -56,6 +62,28 @@ export async function compilePlan(jsx: string, projectRoot?: string): Promise<Co
56
62
  }
57
63
  }
58
64
 
65
+ async function compilePlanSubprocess(tmpFile: string): Promise<CompileResult> {
66
+ const outFile = `${tmpFile}.out.js`;
67
+ const proc = Bun.spawn(
68
+ ["bun", "build", tmpFile, "--format=esm",
69
+ "--external=react", "--external=react-dom",
70
+ "--external=#canvas/components", "--external=#canvas/runtime",
71
+ "--outfile", outFile],
72
+ { stdout: "pipe", stderr: "pipe" },
73
+ );
74
+ const exitCode = await proc.exited;
75
+ if (exitCode !== 0) {
76
+ const stderr = await new Response(proc.stderr).text();
77
+ return { ok: false, error: stderr || "Compilation failed" };
78
+ }
79
+ try {
80
+ const js = readFileSync(outFile, "utf-8");
81
+ return { ok: true, js };
82
+ } finally {
83
+ try { unlinkSync(outFile); } catch {}
84
+ }
85
+ }
86
+
59
87
  /**
60
88
  * Find <Markdown file="..." /> tags and inject __content with the file contents
61
89
  * resolved at compile time.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-canvas",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Interactive visual canvas for Claude Code — rich annotatable documents in the browser",
5
5
  "bin": {
6
6
  "agent-canvas": "bin/agent-canvas.js"
@@ -57,32 +57,37 @@ This opens the canvas in the user's browser (first time) and exits immediately.
57
57
 
58
58
  ### Waiting for feedback
59
59
 
60
- After pushing, wait for the user to review and submit:
60
+ After pushing, start the watch command **in the background** using the Bash tool's `run_in_background` parameter:
61
61
 
62
62
  ```bash
63
+ # Use Bash tool with run_in_background: true
63
64
  bunx agent-canvas watch --session ${CLAUDE_SESSION_ID}
64
65
  ```
65
66
 
66
- This **blocks until the user submits feedback**, then prints feedback markdown to stdout. If feedback was already submitted but not yet consumed, it returns immediately with the existing feedback.
67
+ This runs the watch process in the background. You will be **automatically notified** when the user submits feedback — the output will contain the feedback markdown. Do NOT poll, sleep, or proactively check on it. Just stop and wait for the notification.
67
68
 
68
- **Timeout handling**: The watch command may time out if the user takes a while to review. If it times out, don't retry automatically — wait for the user to tell you they've submitted feedback, then run the watch command again (or use `fetch`) to retrieve it.
69
+ If feedback was already submitted but not yet consumed, the command returns immediately with the existing feedback.
70
+
71
+ **Important**: After starting the background watch, do not continue with other work unless instructed. Wait for the notification that feedback has arrived before proceeding.
69
72
 
70
73
  ### Checking for feedback without blocking
71
74
 
72
- Use `fetch` to check for feedback without waiting:
75
+ Use `fetch` to retrieve feedback if the user tells you they've already submitted:
73
76
 
74
77
  ```bash
75
78
  bunx agent-canvas fetch --session ${CLAUDE_SESSION_ID}
76
79
  ```
77
80
 
78
- Returns immediately — prints feedback to stdout if available, otherwise produces no output. Use this to retry after a timeout or when the user tells you they've submitted.
81
+ Returns immediately — prints feedback to stdout if available, otherwise produces no output. Use this when the user tells you they've submitted feedback (e.g. after a reconnect or if the background watch was lost).
79
82
 
80
83
  ### Iterating
81
84
 
82
- Use the **Edit** tool to modify the existing JSX based on feedback — targeted edits, not full rewrites. Then push and wait again:
85
+ Use the **Edit** tool to modify the existing JSX based on feedback — targeted edits, not full rewrites. Then push and watch again:
83
86
 
84
87
  ```bash
85
88
  bunx agent-canvas push .claude/agent-canvas/${CLAUDE_SESSION_ID}/plan.jsx --session ${CLAUDE_SESSION_ID} --label "Implementation Plan (revised)"
89
+
90
+ # Use Bash tool with run_in_background: true
86
91
  bunx agent-canvas watch --session ${CLAUDE_SESSION_ID}
87
92
  ```
88
93
 
@@ -109,12 +114,15 @@ Maintain separate files for different phases:
109
114
 
110
115
  ```bash
111
116
  bunx agent-canvas push .claude/agent-canvas/${CLAUDE_SESSION_ID}/discovery.jsx --session ${CLAUDE_SESSION_ID} --label "Discovery"
117
+ # watch with run_in_background: true, wait for notification
112
118
  bunx agent-canvas watch --session ${CLAUDE_SESSION_ID}
113
119
  # ... process feedback ...
114
120
  bunx agent-canvas push .claude/agent-canvas/${CLAUDE_SESSION_ID}/requirements.jsx --session ${CLAUDE_SESSION_ID} --label "Requirements"
121
+ # watch with run_in_background: true, wait for notification
115
122
  bunx agent-canvas watch --session ${CLAUDE_SESSION_ID}
116
123
  # ... process feedback ...
117
124
  bunx agent-canvas push .claude/agent-canvas/${CLAUDE_SESSION_ID}/plan.jsx --session ${CLAUDE_SESSION_ID} --label "Implementation Plan"
125
+ # watch with run_in_background: true, wait for notification
118
126
  bunx agent-canvas watch --session ${CLAUDE_SESSION_ID}
119
127
  ```
120
128
 
@@ -156,7 +164,7 @@ User wants to make a decision?
156
164
  2. **Announce** briefly: "I'll start with discovery, then create a detailed plan."
157
165
  3. **Write canvas JSX** with the Write tool to `.claude/agent-canvas/${CLAUDE_SESSION_ID}/<name>.jsx`
158
166
  4. **Push + tell the user**: Push the canvas and show the `browserUrl` from the output so the user can open it
159
- 5. **IMMEDIATELY watch** — run `bunx agent-canvas watch --session ${CLAUDE_SESSION_ID}` right after push, in the same response. Never stop after pushing. The push→watch sequence is atomic: no push without a watch. The watch blocks until the user submits feedback.
167
+ 5. **IMMEDIATELY watch in background** — run `bunx agent-canvas watch --session ${CLAUDE_SESSION_ID}` with `run_in_background: true` right after push. Never stop after pushing. The push→watch sequence is atomic: no push without a watch. You will be notified when feedback arrives — do not poll or sleep.
160
168
  6. **Read feedback** — check for annotations, answers, added context files, approval
161
169
  7. **Edit with the Edit tool and re-push + watch**, or advance to next phase
162
170
  8. **After implementation**, push a summary canvas
@@ -2,7 +2,7 @@
2
2
 
3
3
  Each flow is a sequence of canvas rounds. Phases can be skipped or combined based on context.
4
4
 
5
- **Tooling reminder**: Write all `.jsx` files using the **Write** tool to `.claude/agent-canvas/${CLAUDE_SESSION_ID}/`. Edit them with the **Edit** tool. Push with `bunx agent-canvas push .claude/agent-canvas/${CLAUDE_SESSION_ID}/<file>.jsx --session ${CLAUDE_SESSION_ID} --label "<Label>"`, then `bunx agent-canvas watch --session ${CLAUDE_SESSION_ID}` to block for feedback. The JSX blocks below show what to write — they are the file content, not bash commands.
5
+ **Tooling reminder**: Write all `.jsx` files using the **Write** tool to `.claude/agent-canvas/${CLAUDE_SESSION_ID}/`. Edit them with the **Edit** tool. Push with `bunx agent-canvas push .claude/agent-canvas/${CLAUDE_SESSION_ID}/<file>.jsx --session ${CLAUDE_SESSION_ID} --label "<Label>"`, then run `bunx agent-canvas watch --session ${CLAUDE_SESSION_ID}` with `run_in_background: true` — you'll be notified when the user submits feedback. The JSX blocks below show what to write — they are the file content, not bash commands.
6
6
 
7
7
  ---
8
8