agent-canvas 0.2.0 → 0.6.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.
- package/README.md +42 -17
- package/bin/agent-canvas.js +7 -7
- package/bin/agent-canvas.ts +48 -37
- package/bin/lib/commands/daemon.ts +46 -43
- package/bin/lib/commands/exec.ts +100 -100
- package/bin/lib/commands/fetch.ts +15 -15
- package/bin/lib/commands/install.ts +36 -36
- package/bin/lib/commands/instructions.ts +51 -51
- package/bin/lib/commands/push.ts +115 -97
- package/bin/lib/commands/review.ts +190 -0
- package/bin/lib/commands/watch.ts +24 -24
- package/bin/lib/config.ts +12 -12
- package/bin/lib/daemon-lifecycle.ts +47 -51
- package/bin/lib/helpers.ts +82 -76
- package/bin/lib/instructions/app-review.md +88 -0
- package/bin/lib/instructions/component-checklist.md +7 -5
- package/bin/lib/instructions/component-custom.md +20 -14
- package/bin/lib/instructions/component-diff.md +4 -3
- package/bin/lib/instructions/component-item.md +18 -8
- package/bin/lib/instructions/component-markdown.md +4 -2
- package/bin/lib/instructions/component-mermaid.md +12 -6
- package/bin/lib/instructions/component-multichoice.md +6 -2
- package/bin/lib/instructions/component-note.md +1 -1
- package/bin/lib/instructions/component-priority.md +1 -1
- package/bin/lib/instructions/component-rangeinput.md +9 -2
- package/bin/lib/instructions/component-secretinput.md +12 -11
- package/bin/lib/instructions/component-svg.md +62 -16
- package/bin/lib/instructions/component-table.md +6 -6
- package/bin/lib/instructions/component-usefeedback.md +8 -8
- package/bin/lib/instructions/component-userinput.md +6 -2
- package/bin/lib/instructions/flow-feature.md +22 -5
- package/bin/lib/instructions/flow-plan.md +5 -5
- package/bin/lib/instructions/flow-runbook.md +28 -25
- package/bin/lib/instructions/overview.md +27 -18
- package/bin/lib/instructions/theming.md +5 -0
- package/daemon/build.ts +171 -152
- package/daemon/client/App.tsx +1205 -1077
- package/daemon/client/CompareView.tsx +478 -458
- package/daemon/client/FileBrowser.tsx +241 -203
- package/daemon/client/FileViewer.tsx +220 -211
- package/daemon/client/OverviewView.tsx +283 -267
- package/daemon/client/ReviewerIdentityDialog.tsx +72 -71
- package/daemon/client/RevisionSelect.tsx +111 -95
- package/daemon/client/SessionSwitcher.tsx +81 -81
- package/daemon/client/ShareDialog.tsx +211 -212
- package/daemon/client/apiSchemas.ts +78 -0
- package/daemon/client/canvas-runtime.ts +1 -1
- package/daemon/client/clientApi.ts +194 -206
- package/daemon/client/components/SecretInput.tsx +138 -138
- package/daemon/client/components/index.ts +2 -2
- package/daemon/client/domDiff.ts +341 -333
- package/daemon/client/errorMessage.ts +3 -0
- package/daemon/client/exportMarkdown.ts +222 -201
- package/daemon/client/lcs.ts +19 -14
- package/daemon/client/shareCrypto.ts +57 -57
- package/daemon/client/unifiedDiff.ts +660 -649
- package/daemon/dist/annotations-runtime.js +1 -1
- package/daemon/dist/client.css +2 -2
- package/daemon/dist/client.js +77 -80
- package/daemon/dist/components.js +59 -59
- package/daemon/dist/preact-compat.js +1 -1
- package/daemon/dist/review.js +361 -0
- package/daemon/dist/runtime.js +1 -1
- package/daemon/langMap.ts +24 -6
- package/daemon/review-widget/anchor.ts +187 -0
- package/daemon/review-widget/client.ts +95 -0
- package/daemon/review-widget/index.tsx +36 -0
- package/daemon/review-widget/markup.ts +71 -0
- package/daemon/review-widget/screenshot.ts +91 -0
- package/daemon/review-widget/source.ts +103 -0
- package/daemon/review-widget/styles.css +359 -0
- package/daemon/review-widget/text-modules.d.ts +4 -0
- package/daemon/review-widget/tsconfig.json +16 -0
- package/daemon/review-widget/widget.tsx +436 -0
- package/daemon/src/components.ts +3 -3
- package/daemon/src/handlers/api.ts +330 -328
- package/daemon/src/handlers/files.ts +112 -105
- package/daemon/src/handlers/static.ts +47 -46
- package/daemon/src/handlers/uploads.ts +61 -56
- package/daemon/src/paths.ts +13 -10
- package/daemon/src/remote-feedback.ts +192 -192
- package/daemon/src/review/markdown.ts +52 -0
- package/daemon/src/review/model.ts +132 -0
- package/daemon/src/review/proxy.ts +177 -0
- package/daemon/src/review/server.ts +199 -0
- package/daemon/src/review/store.ts +151 -0
- package/daemon/src/server.ts +127 -86
- package/daemon/src/share.ts +163 -169
- package/daemon/src/stubFetch.ts +7 -0
- package/daemon/tsconfig.json +19 -19
- package/package.json +47 -47
- package/skills/canvas/SKILL.md +9 -1
- package/bin/lib/commands/exec.test.ts +0 -27
- package/bin/lib/helpers.test.ts +0 -79
- package/daemon/src/remote-feedback.test.ts +0 -165
- package/daemon/src/secrets-api.test.ts +0 -123
- package/daemon/src/share-e2e.test.ts +0 -277
- package/daemon/src/share.test.ts +0 -289
package/daemon/build.ts
CHANGED
|
@@ -1,114 +1,115 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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,
|
|
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(
|
|
10
|
-
const ANNOTATIONS_RUNTIME = fileURLToPath(import.meta.resolve(
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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
|
-
|
|
193
|
-
|
|
194
|
-
})
|
|
211
|
+
console.error('Build failed:', e)
|
|
212
|
+
process.exit(1)
|
|
213
|
+
})
|