agent-canvas 0.1.22 → 0.1.24

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.
@@ -55,9 +55,14 @@ export async function handlePush(args: string[]) {
55
55
  let result = await response.json() as any;
56
56
 
57
57
  // Bun.build() can corrupt internal state in long-running daemons,
58
- // returning "Unknown Error, TODO". Restart daemon and retry once.
59
- if (!result.ok && typeof result.error === "string" && result.error.includes("Unknown Error")) {
60
- console.error("Daemon bundler crashed, restarting...");
58
+ // throwing opaque errors like "Bundle failed" or "Unknown Error".
59
+ // Restart and retry once — but not for clear syntax errors (which
60
+ // now have precise line/col info from the transpiler pre-check).
61
+ const isBundlerCrash = !result.ok && result.error === "Canvas compilation failed"
62
+ && result.errors && Object.values(result.errors).some((e: any) =>
63
+ typeof e === "string" && (e === "Bundle failed" || e.includes("Unknown Error")));
64
+ if (isBundlerCrash) {
65
+ console.error("Compilation failed, restarting daemon and retrying...");
61
66
  stopDaemon();
62
67
  await startDaemon();
63
68
  const retryResponse = await fetch(`${BASE_URL}/api/session/${sessionId}/plan`, {
@@ -20,6 +20,9 @@ const { Section, Item, Task, FilePreview, CodeBlock, Callout,
20
20
  Markdown, useFeedback, useAnnotations } = C;
21
21
  `;
22
22
 
23
+ /** Number of lines in COMPONENT_IMPORTS — used to adjust error line numbers */
24
+ const COMPONENT_IMPORTS_LINES = COMPONENT_IMPORTS.split("\n").length - 1;
25
+
23
26
  // --- Validation via Preact --------------------------------------------------
24
27
  // After Bun.build() succeeds we strip ESM syntax from the compiled output,
25
28
  // provide Preact as the React implementation with lightweight stub components,
@@ -121,7 +124,11 @@ async function validateCompiledPlan(js: string): Promise<{ ok: true } | { ok: fa
121
124
  try {
122
125
  await mermaid.parse(source);
123
126
  } catch (e: any) {
124
- return { ok: false, error: `Mermaid syntax error: ${e?.message || String(e)}` };
127
+ const msg = e?.message || String(e);
128
+ // DOMPurify doesn't work in Bun (no DOM) — mermaid.parse() triggers
129
+ // it for some diagram types even though it's just parsing. Skip these.
130
+ if (msg.includes("DOMPurify")) continue;
131
+ return { ok: false, error: `Mermaid syntax error: ${msg}` };
125
132
  }
126
133
  }
127
134
 
@@ -148,6 +155,20 @@ export async function compilePlan(jsx: string, projectRoot?: string): Promise<Co
148
155
  ? `${COMPONENT_IMPORTS}\n${jsx}`
149
156
  : `${COMPONENT_IMPORTS}\nexport default function Plan() {\n return (<>${jsx}</>);\n}\n`;
150
157
 
158
+ // Pre-validate syntax with Bun.Transpiler — gives precise error positions,
159
+ // unlike Bun.build() which throws opaque "Bundle failed" for syntax errors.
160
+ try {
161
+ const transpiler = new Bun.Transpiler({ loader: "jsx" });
162
+ transpiler.transformSync(source);
163
+ } catch (syntaxError: any) {
164
+ const pos = syntaxError?.position;
165
+ // Offset: COMPONENT_IMPORTS lines + wrapper lines (export default function Plan() + return)
166
+ const wrapperLines = hasDefaultExport ? 1 : 2;
167
+ const lineOffset = COMPONENT_IMPORTS_LINES + wrapperLines;
168
+ const loc = pos ? ` (line ${pos.line - lineOffset}, col ${pos.column})` : "";
169
+ return { ok: false, error: `${syntaxError?.message || "Syntax error"}${loc}` };
170
+ }
171
+
151
172
  const tmpFile = join(COMPILE_TEMP_DIR, `plan-${randomUUID()}.jsx`);
152
173
 
153
174
  try {
@@ -166,7 +187,7 @@ export async function compilePlan(jsx: string, projectRoot?: string): Promise<Co
166
187
  .filter((l) => l.level === "error")
167
188
  .map((l) => l.message)
168
189
  .join("\n");
169
- return { ok: false, error: errors || "Compilation failed" };
190
+ return { ok: false, error: errors || "Bundle failed" };
170
191
  }
171
192
 
172
193
  const js = await result.outputs[0].text();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-canvas",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
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"