agent-canvas 0.2.1 → 0.7.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.
Files changed (99) hide show
  1. package/README.md +42 -17
  2. package/bin/agent-canvas.js +7 -7
  3. package/bin/agent-canvas.ts +48 -37
  4. package/bin/lib/commands/daemon.ts +46 -43
  5. package/bin/lib/commands/exec.ts +100 -100
  6. package/bin/lib/commands/fetch.ts +15 -15
  7. package/bin/lib/commands/install.ts +36 -36
  8. package/bin/lib/commands/instructions.ts +51 -51
  9. package/bin/lib/commands/push.ts +115 -97
  10. package/bin/lib/commands/review.ts +190 -0
  11. package/bin/lib/commands/watch.ts +24 -24
  12. package/bin/lib/config.ts +12 -12
  13. package/bin/lib/daemon-lifecycle.ts +47 -51
  14. package/bin/lib/helpers.ts +82 -76
  15. package/bin/lib/instructions/app-review.md +88 -0
  16. package/bin/lib/instructions/component-checklist.md +7 -5
  17. package/bin/lib/instructions/component-custom.md +20 -14
  18. package/bin/lib/instructions/component-diff.md +4 -3
  19. package/bin/lib/instructions/component-item.md +18 -8
  20. package/bin/lib/instructions/component-markdown.md +4 -2
  21. package/bin/lib/instructions/component-mermaid.md +12 -6
  22. package/bin/lib/instructions/component-multichoice.md +6 -2
  23. package/bin/lib/instructions/component-note.md +1 -1
  24. package/bin/lib/instructions/component-priority.md +1 -1
  25. package/bin/lib/instructions/component-rangeinput.md +9 -2
  26. package/bin/lib/instructions/component-secretinput.md +12 -11
  27. package/bin/lib/instructions/component-svg.md +62 -16
  28. package/bin/lib/instructions/component-table.md +6 -6
  29. package/bin/lib/instructions/component-usefeedback.md +8 -8
  30. package/bin/lib/instructions/component-userinput.md +6 -2
  31. package/bin/lib/instructions/flow-feature.md +22 -5
  32. package/bin/lib/instructions/flow-plan.md +5 -5
  33. package/bin/lib/instructions/flow-runbook.md +28 -25
  34. package/bin/lib/instructions/overview.md +27 -18
  35. package/bin/lib/instructions/theming.md +5 -0
  36. package/daemon/build.ts +171 -152
  37. package/daemon/client/App.tsx +1205 -1077
  38. package/daemon/client/CompareView.tsx +478 -458
  39. package/daemon/client/FileBrowser.tsx +241 -203
  40. package/daemon/client/FileViewer.tsx +220 -211
  41. package/daemon/client/OverviewView.tsx +283 -267
  42. package/daemon/client/ReviewerIdentityDialog.tsx +72 -71
  43. package/daemon/client/RevisionSelect.tsx +111 -95
  44. package/daemon/client/SessionSwitcher.tsx +81 -81
  45. package/daemon/client/ShareDialog.tsx +211 -212
  46. package/daemon/client/apiSchemas.ts +78 -0
  47. package/daemon/client/canvas-runtime.ts +1 -1
  48. package/daemon/client/clientApi.ts +194 -206
  49. package/daemon/client/components/SecretInput.tsx +138 -138
  50. package/daemon/client/components/index.ts +2 -2
  51. package/daemon/client/domDiff.ts +341 -333
  52. package/daemon/client/errorMessage.ts +3 -0
  53. package/daemon/client/exportMarkdown.ts +222 -201
  54. package/daemon/client/lcs.ts +19 -14
  55. package/daemon/client/shareCrypto.ts +57 -57
  56. package/daemon/client/unifiedDiff.ts +660 -649
  57. package/daemon/dist/annotations-runtime.js +1 -1
  58. package/daemon/dist/client.css +2 -2
  59. package/daemon/dist/client.js +77 -80
  60. package/daemon/dist/components.js +59 -59
  61. package/daemon/dist/preact-compat.js +1 -1
  62. package/daemon/dist/review.js +361 -0
  63. package/daemon/dist/runtime.js +1 -1
  64. package/daemon/langMap.ts +24 -6
  65. package/daemon/review-widget/anchor.ts +187 -0
  66. package/daemon/review-widget/client.ts +95 -0
  67. package/daemon/review-widget/index.tsx +36 -0
  68. package/daemon/review-widget/markup.ts +71 -0
  69. package/daemon/review-widget/screenshot.ts +91 -0
  70. package/daemon/review-widget/source.ts +103 -0
  71. package/daemon/review-widget/styles.css +359 -0
  72. package/daemon/review-widget/text-modules.d.ts +4 -0
  73. package/daemon/review-widget/tsconfig.json +16 -0
  74. package/daemon/review-widget/widget.tsx +436 -0
  75. package/daemon/src/components.ts +3 -3
  76. package/daemon/src/handlers/api.ts +330 -328
  77. package/daemon/src/handlers/files.ts +112 -106
  78. package/daemon/src/handlers/static.ts +47 -46
  79. package/daemon/src/handlers/uploads.ts +61 -56
  80. package/daemon/src/paths.ts +13 -10
  81. package/daemon/src/remote-feedback.ts +192 -192
  82. package/daemon/src/review/markdown.ts +52 -0
  83. package/daemon/src/review/model.ts +132 -0
  84. package/daemon/src/review/proxy.ts +177 -0
  85. package/daemon/src/review/server.ts +199 -0
  86. package/daemon/src/review/store.ts +151 -0
  87. package/daemon/src/server.ts +127 -86
  88. package/daemon/src/share.ts +163 -169
  89. package/daemon/src/stubFetch.ts +7 -0
  90. package/daemon/tsconfig.json +19 -19
  91. package/package.json +47 -47
  92. package/skills/canvas/SKILL.md +5 -1
  93. package/bin/lib/commands/exec.test.ts +0 -27
  94. package/bin/lib/helpers.test.ts +0 -79
  95. package/daemon/src/files-api.test.ts +0 -78
  96. package/daemon/src/remote-feedback.test.ts +0 -165
  97. package/daemon/src/secrets-api.test.ts +0 -123
  98. package/daemon/src/share-e2e.test.ts +0 -277
  99. package/daemon/src/share.test.ts +0 -289
package/daemon/build.ts CHANGED
@@ -1,114 +1,115 @@
1
- import { mkdirSync, cpSync, writeFileSync, readFileSync, existsSync, watch as fsWatch } from "fs";
2
- import { join, dirname } from "path";
3
- import { fileURLToPath } from "url";
4
- import { $ } from "bun";
1
+ import { $ } from 'bun'
2
+ import { cpSync, existsSync, mkdirSync, readFileSync, watch as fsWatch, writeFileSync } from 'fs'
3
+ import { dirname, join } from 'path'
4
+ import { fileURLToPath } from 'url'
5
5
 
6
- const ROOT = dirname(import.meta.path);
7
- const DIST = join(ROOT, "dist");
6
+ const ROOT = dirname(import.meta.path)
7
+ const DIST = join(ROOT, 'dist')
8
8
  /** The kernel ships the runtime, the component library and the base stylesheet. */
9
- const KERNEL_CLIENT = dirname(fileURLToPath(import.meta.resolve("@fabrika/canvas-kernel/runtime")));
10
- const ANNOTATIONS_RUNTIME = fileURLToPath(import.meta.resolve("@fabrika/annotations/runtime"));
9
+ const KERNEL_CLIENT = dirname(fileURLToPath(import.meta.resolve('@fabrika/canvas-kernel/runtime')))
10
+ const ANNOTATIONS_RUNTIME = fileURLToPath(import.meta.resolve('@fabrika/annotations/runtime'))
11
11
 
12
12
  async function build() {
13
- console.log("Building canvas client...");
14
-
15
- mkdirSync(DIST, { recursive: true });
16
-
17
- const REACT_EXTERNALS = ["react", "react-dom", "react-dom/client", "react/jsx-runtime", "react/jsx-dev-runtime"];
18
- const ANNOTATION_EXTERNALS = [...REACT_EXTERNALS, "@fabrika/annotations/runtime"];
19
-
20
- const annotationResult = await Bun.build({
21
- entrypoints: [ANNOTATIONS_RUNTIME],
22
- outdir: DIST,
23
- format: "esm",
24
- external: REACT_EXTERNALS,
25
- naming: "annotations-runtime.js",
26
- minify: true,
27
- });
28
- if (!annotationResult.success) {
29
- console.error("Annotation runtime build failed:", annotationResult.logs);
30
- process.exit(1);
31
- }
32
-
33
- // 0. Build preact-compat bundle
34
- console.log(" Building preact-compat...");
35
- const preactResult = await Bun.build({
36
- entrypoints: [join(KERNEL_CLIENT, "preact-all.ts")],
37
- outdir: DIST,
38
- format: "esm",
39
- naming: "preact-compat.js",
40
- minify: true,
41
- });
42
-
43
- if (!preactResult.success) {
44
- console.error("Preact-compat build failed:", preactResult.logs);
45
- process.exit(1);
46
- }
47
-
48
- // Write jsx-runtime shim
49
- writeFileSync(join(DIST, "jsx-runtime.js"),
50
- `import { jsx, jsxs, Fragment } from "./preact-compat.js";\nexport { jsx, jsxs, Fragment };\nexport const jsxDEV = jsx;\n`
51
- );
52
-
53
- // 1. Build runtime (shared context between app and components)
54
- console.log(" Building #canvas/runtime...");
55
- const runtimeResult = await Bun.build({
56
- entrypoints: [join(KERNEL_CLIENT, "runtime.ts")],
57
- outdir: DIST,
58
- format: "esm",
59
- external: ANNOTATION_EXTERNALS,
60
- naming: "runtime.js",
61
- minify: true,
62
- });
63
-
64
- if (!runtimeResult.success) {
65
- console.error("Runtime build failed:", runtimeResult.logs);
66
- process.exit(1);
67
- }
68
-
69
- // 2. Build the components library (ESM, React + runtime external)
70
- console.log(" Building #canvas/components...");
71
- const componentsResult = await Bun.build({
72
- entrypoints: [join(ROOT, "client/components/index.ts")],
73
- outdir: DIST,
74
- format: "esm",
75
- external: [...ANNOTATION_EXTERNALS, "#canvas/runtime"],
76
- naming: "components.js",
77
- minify: true,
78
- });
79
-
80
- if (!componentsResult.success) {
81
- console.error("Components build failed:", componentsResult.logs);
82
- process.exit(1);
83
- }
84
-
85
- // 3. Build the main client app (ESM, React + components + runtime external)
86
- console.log(" Building client app...");
87
- const clientResult = await Bun.build({
88
- entrypoints: [join(ROOT, "client/App.tsx")],
89
- outdir: DIST,
90
- format: "esm",
91
- external: [...ANNOTATION_EXTERNALS, "#canvas/components", "#canvas/runtime"],
92
- naming: "client.js",
93
- minify: true,
94
- });
95
-
96
- if (!clientResult.success) {
97
- console.error("Client build failed:", clientResult.logs);
98
- process.exit(1);
99
- }
100
-
101
- // 4. Build Tailwind CSS
102
- console.log(" Building CSS...");
103
- await $`cd ${ROOT} && npx @tailwindcss/cli -i client/styles.css -o dist/client.css --minify`.quiet();
104
-
105
- // 5. Read theme.css to inline into HTML for browser Tailwind runtime
106
- const themeCss = readFileSync(join(KERNEL_CLIENT, "theme.css"), "utf-8");
107
-
108
- // 6. Create index.html
109
- console.log(" Creating index.html...");
110
-
111
- const indexHtml = `<!DOCTYPE html>
13
+ console.log('Building canvas client...')
14
+
15
+ mkdirSync(DIST, { recursive: true })
16
+
17
+ const REACT_EXTERNALS = ['react', 'react-dom', 'react-dom/client', 'react/jsx-runtime', 'react/jsx-dev-runtime']
18
+ const ANNOTATION_EXTERNALS = [...REACT_EXTERNALS, '@fabrika/annotations/runtime']
19
+
20
+ const annotationResult = await Bun.build({
21
+ entrypoints: [ANNOTATIONS_RUNTIME],
22
+ outdir: DIST,
23
+ format: 'esm',
24
+ external: REACT_EXTERNALS,
25
+ naming: 'annotations-runtime.js',
26
+ minify: true,
27
+ })
28
+ if (!annotationResult.success) {
29
+ console.error('Annotation runtime build failed:', annotationResult.logs)
30
+ process.exit(1)
31
+ }
32
+
33
+ // 0. Build preact-compat bundle
34
+ console.log(' Building preact-compat...')
35
+ const preactResult = await Bun.build({
36
+ entrypoints: [join(KERNEL_CLIENT, 'preact-all.ts')],
37
+ outdir: DIST,
38
+ format: 'esm',
39
+ naming: 'preact-compat.js',
40
+ minify: true,
41
+ })
42
+
43
+ if (!preactResult.success) {
44
+ console.error('Preact-compat build failed:', preactResult.logs)
45
+ process.exit(1)
46
+ }
47
+
48
+ // Write jsx-runtime shim
49
+ writeFileSync(
50
+ join(DIST, 'jsx-runtime.js'),
51
+ `import { jsx, jsxs, Fragment } from "./preact-compat.js";\nexport { jsx, jsxs, Fragment };\nexport const jsxDEV = jsx;\n`,
52
+ )
53
+
54
+ // 1. Build runtime (shared context between app and components)
55
+ console.log(' Building #canvas/runtime...')
56
+ const runtimeResult = await Bun.build({
57
+ entrypoints: [join(KERNEL_CLIENT, 'runtime.ts')],
58
+ outdir: DIST,
59
+ format: 'esm',
60
+ external: ANNOTATION_EXTERNALS,
61
+ naming: 'runtime.js',
62
+ minify: true,
63
+ })
64
+
65
+ if (!runtimeResult.success) {
66
+ console.error('Runtime build failed:', runtimeResult.logs)
67
+ process.exit(1)
68
+ }
69
+
70
+ // 2. Build the components library (ESM, React + runtime external)
71
+ console.log(' Building #canvas/components...')
72
+ const componentsResult = await Bun.build({
73
+ entrypoints: [join(ROOT, 'client/components/index.ts')],
74
+ outdir: DIST,
75
+ format: 'esm',
76
+ external: [...ANNOTATION_EXTERNALS, '#canvas/runtime'],
77
+ naming: 'components.js',
78
+ minify: true,
79
+ })
80
+
81
+ if (!componentsResult.success) {
82
+ console.error('Components build failed:', componentsResult.logs)
83
+ process.exit(1)
84
+ }
85
+
86
+ // 3. Build the main client app (ESM, React + components + runtime external)
87
+ console.log(' Building client app...')
88
+ const clientResult = await Bun.build({
89
+ entrypoints: [join(ROOT, 'client/App.tsx')],
90
+ outdir: DIST,
91
+ format: 'esm',
92
+ external: [...ANNOTATION_EXTERNALS, '#canvas/components', '#canvas/runtime'],
93
+ naming: 'client.js',
94
+ minify: true,
95
+ })
96
+
97
+ if (!clientResult.success) {
98
+ console.error('Client build failed:', clientResult.logs)
99
+ process.exit(1)
100
+ }
101
+
102
+ // 4. Build Tailwind CSS
103
+ console.log(' Building CSS...')
104
+ await $`cd ${ROOT} && bunx @tailwindcss/cli -i client/styles.css -o dist/client.css --minify`.quiet()
105
+
106
+ // 5. Read theme.css to inline into HTML for browser Tailwind runtime
107
+ const themeCss = readFileSync(join(KERNEL_CLIENT, 'theme.css'), 'utf-8')
108
+
109
+ // 6. Create index.html
110
+ console.log(' Creating index.html...')
111
+
112
+ const indexHtml = `<!DOCTYPE html>
112
113
  <html lang="en" data-theme="dark">
113
114
  <head>
114
115
  <meta charset="utf-8" />
@@ -143,52 +144,70 @@ ${themeCss}
143
144
  </script>
144
145
  <script type="module" src="/assets/client.js"></script>
145
146
  </body>
146
- </html>`;
147
-
148
- writeFileSync(join(DIST, "index.html"), indexHtml);
149
-
150
- // 7. Mirror runtime bundles into the canvas-share worker's static assets
151
- // dir so the worker serves the same version of the runtime as the daemon.
152
- // This is critical: a version drift between worker assets and the
153
- // compiled canvas JS in a share payload would silently break shared
154
- // canvases. Doing the copy as part of the daemon build keeps them in
155
- // lockstep automatically.
156
- const WORKER_PUBLIC = join(ROOT, "..", "workers", "canvas-share", "public", "assets");
157
- if (existsSync(join(ROOT, "..", "workers", "canvas-share"))) {
158
- console.log(" Copying runtime bundles to canvas-share worker...");
159
- mkdirSync(WORKER_PUBLIC, { recursive: true });
160
- for (const f of [
161
- "preact-compat.js",
162
- "jsx-runtime.js",
163
- "runtime.js",
164
- "annotations-runtime.js",
165
- "components.js",
166
- "client.js",
167
- "client.css",
168
- ]) {
169
- cpSync(join(DIST, f), join(WORKER_PUBLIC, f));
170
- }
171
- }
172
-
173
- console.log("Build complete! Output in dist/");
147
+ </html>`
148
+
149
+ writeFileSync(join(DIST, 'index.html'), indexHtml)
150
+
151
+ // The review widget runs inside someone else's page, so it carries its own Preact and needs no import map.
152
+ console.log(' Building review widget...')
153
+ const reviewResult = await Bun.build({
154
+ entrypoints: [join(ROOT, 'review-widget', 'index.tsx')],
155
+ outdir: DIST,
156
+ format: 'iife',
157
+ target: 'browser',
158
+ naming: 'review.js',
159
+ minify: true,
160
+ })
161
+ if (!reviewResult.success) {
162
+ console.error('Review widget build failed:', reviewResult.logs)
163
+ process.exit(1)
164
+ }
165
+
166
+ // 7. Mirror runtime bundles into the canvas-share worker's static assets
167
+ // dir so the worker serves the same version of the runtime as the daemon.
168
+ // This is critical: a version drift between worker assets and the
169
+ // compiled canvas JS in a share payload would silently break shared
170
+ // canvases. Doing the copy as part of the daemon build keeps them in
171
+ // lockstep automatically.
172
+ const WORKER = join(ROOT, '..', '..', 'canvas-share')
173
+ const WORKER_PUBLIC = join(WORKER, 'public', 'assets')
174
+ if (existsSync(WORKER)) {
175
+ console.log(' Copying runtime bundles to canvas-share worker...')
176
+ mkdirSync(WORKER_PUBLIC, { recursive: true })
177
+ for (
178
+ const f of [
179
+ 'preact-compat.js',
180
+ 'jsx-runtime.js',
181
+ 'runtime.js',
182
+ 'annotations-runtime.js',
183
+ 'components.js',
184
+ 'client.js',
185
+ 'client.css',
186
+ ]
187
+ ) {
188
+ cpSync(join(DIST, f), join(WORKER_PUBLIC, f))
189
+ }
190
+ }
191
+
192
+ console.log('Build complete! Output in dist/')
174
193
  }
175
194
 
176
195
  build().then(() => {
177
- if (process.argv.includes("--watch")) {
178
- let timeout: ReturnType<typeof setTimeout> | null = null;
179
- console.log("Watching for changes in client/ and the kernel client...");
180
- for (const dir of [join(ROOT, "client"), KERNEL_CLIENT, dirname(ANNOTATIONS_RUNTIME)]) {
181
- fsWatch(dir, { recursive: true }, (_event: string, filename: string | null) => {
182
- if (!filename || filename.endsWith("~")) return;
183
- if (timeout) clearTimeout(timeout);
184
- timeout = setTimeout(() => {
185
- console.log(`\n Changed: ${filename}`);
186
- build().catch((e) => console.error("Rebuild failed:", e));
187
- }, 200);
188
- });
189
- }
190
- }
196
+ if (process.argv.includes('--watch')) {
197
+ let timeout: ReturnType<typeof setTimeout> | null = null
198
+ console.log('Watching for changes in client/, review-widget/ and the kernel client...')
199
+ for (const dir of [join(ROOT, 'client'), join(ROOT, 'review-widget'), KERNEL_CLIENT, dirname(ANNOTATIONS_RUNTIME)]) {
200
+ fsWatch(dir, { recursive: true }, (_event: string, filename: string | null) => {
201
+ if (!filename || filename.endsWith('~')) return
202
+ if (timeout) clearTimeout(timeout)
203
+ timeout = setTimeout(() => {
204
+ console.log(`\n Changed: ${filename}`)
205
+ build().catch((e) => console.error('Rebuild failed:', e))
206
+ }, 200)
207
+ })
208
+ }
209
+ }
191
210
  }).catch((e) => {
192
- console.error("Build failed:", e);
193
- process.exit(1);
194
- });
211
+ console.error('Build failed:', e)
212
+ process.exit(1)
213
+ })