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.
- package/bin/lib/commands/push.ts +8 -3
- package/daemon/src/compiler.ts +23 -2
- package/package.json +1 -1
package/bin/lib/commands/push.ts
CHANGED
|
@@ -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
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
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`, {
|
package/daemon/src/compiler.ts
CHANGED
|
@@ -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
|
-
|
|
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 || "
|
|
190
|
+
return { ok: false, error: errors || "Bundle failed" };
|
|
170
191
|
}
|
|
171
192
|
|
|
172
193
|
const js = await result.outputs[0].text();
|