@rwoll/canvas-kit 0.0.0-stage → 0.1.1

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 (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +506 -2
  3. package/cli/canvas-kit.mjs +148 -0
  4. package/cli/lib.mjs +697 -0
  5. package/cli/release.json +4 -0
  6. package/dist/client.d.ts +72 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +156 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/define.d.ts +249 -0
  11. package/dist/define.d.ts.map +1 -0
  12. package/dist/define.js +197 -0
  13. package/dist/define.js.map +1 -0
  14. package/dist/errors.d.ts +12 -0
  15. package/dist/errors.d.ts.map +1 -0
  16. package/dist/errors.js +39 -0
  17. package/dist/errors.js.map +1 -0
  18. package/dist/extension.d.ts +25 -0
  19. package/dist/extension.d.ts.map +1 -0
  20. package/dist/extension.js +70 -0
  21. package/dist/extension.js.map +1 -0
  22. package/dist/index.d.ts +5 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +4 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/jobs.d.ts +56 -0
  27. package/dist/jobs.d.ts.map +1 -0
  28. package/dist/jobs.js +33 -0
  29. package/dist/jobs.js.map +1 -0
  30. package/dist/playwright.d.ts +79 -0
  31. package/dist/playwright.d.ts.map +1 -0
  32. package/dist/playwright.js +124 -0
  33. package/dist/playwright.js.map +1 -0
  34. package/dist/react.d.ts +55 -0
  35. package/dist/react.d.ts.map +1 -0
  36. package/dist/react.js +72 -0
  37. package/dist/react.js.map +1 -0
  38. package/dist/server/headless.d.ts +20 -0
  39. package/dist/server/headless.d.ts.map +1 -0
  40. package/dist/server/headless.js +35 -0
  41. package/dist/server/headless.js.map +1 -0
  42. package/dist/server/host.d.ts +146 -0
  43. package/dist/server/host.d.ts.map +1 -0
  44. package/dist/server/host.js +1078 -0
  45. package/dist/server/host.js.map +1 -0
  46. package/dist/server/index.d.ts +9 -0
  47. package/dist/server/index.d.ts.map +1 -0
  48. package/dist/server/index.js +5 -0
  49. package/dist/server/index.js.map +1 -0
  50. package/dist/server/release.d.ts +30 -0
  51. package/dist/server/release.d.ts.map +1 -0
  52. package/dist/server/release.js +71 -0
  53. package/dist/server/release.js.map +1 -0
  54. package/dist/server/storage.d.ts +63 -0
  55. package/dist/server/storage.d.ts.map +1 -0
  56. package/dist/server/storage.js +253 -0
  57. package/dist/server/storage.js.map +1 -0
  58. package/dist/testing.d.ts +49 -0
  59. package/dist/testing.d.ts.map +1 -0
  60. package/dist/testing.js +42 -0
  61. package/dist/testing.js.map +1 -0
  62. package/dist/vite.d.ts +15 -0
  63. package/dist/vite.d.ts.map +1 -0
  64. package/dist/vite.js +213 -0
  65. package/dist/vite.js.map +1 -0
  66. package/package.json +115 -3
  67. package/styles.css +122 -0
  68. package/templates/canvas/README.md +19 -0
  69. package/templates/canvas/e2e/canvas.spec.ts +15 -0
  70. package/templates/canvas/index.html +13 -0
  71. package/templates/canvas/package.json +29 -0
  72. package/templates/canvas/playwright.config.ts +5 -0
  73. package/templates/canvas/server/canvas.test.ts +22 -0
  74. package/templates/canvas/server/canvas.ts +27 -0
  75. package/templates/canvas/src/App.css +21 -0
  76. package/templates/canvas/src/App.tsx +31 -0
  77. package/templates/canvas/src/index.css +3 -0
  78. package/templates/canvas/src/main.tsx +11 -0
  79. package/templates/canvas/tsconfig.app.json +1 -0
  80. package/templates/canvas/tsconfig.json +7 -0
  81. package/templates/canvas/tsconfig.node.json +1 -0
  82. package/templates/canvas/vite.config.ts +7 -0
  83. package/templates/ui/README.md +18 -0
  84. package/templates/ui/package.json +22 -0
  85. package/templates/ui/src/Checklist.tsx +42 -0
  86. package/templates/ui/src/Header.tsx +17 -0
  87. package/templates/ui/src/Markdown.tsx +140 -0
  88. package/templates/ui/src/TextButton.tsx +6 -0
  89. package/templates/ui/src/index.ts +4 -0
  90. package/templates/ui/theme.css +143 -0
  91. package/templates/ui/tsconfig.json +18 -0
  92. package/tsconfig/canvas.json +27 -0
  93. package/tsconfig/node.json +24 -0
@@ -0,0 +1,49 @@
1
+ import type { ActionInput, ActionResult, ActionsOf, AgentMessage, AnyCanvas, JobName, JobStatusOf, StateOf } from './define.ts';
2
+ import type { JobAction } from './jobs.ts';
3
+ import { CanvasHost, type JobOutcome, type OpenResult, type RunJobOptions } from './server/host.ts';
4
+ import type { ReleaseInfo } from './server/release.ts';
5
+ import type { StateStoreOptions } from './server/storage.ts';
6
+ /** Actions a test can call: the canvas's own, `get_state`, and the built-in job actions. */
7
+ export type HarnessAction<C extends AnyCanvas> = Extract<keyof ActionsOf<C>, string> | 'get_state' | JobAction;
8
+ export type HarnessInput<C extends AnyCanvas, K> = K extends keyof ActionsOf<C> ? ActionInput<C, K> : K extends JobAction ? Record<string, unknown> : Record<string, never>;
9
+ export type HarnessResult<C extends AnyCanvas, K> = K extends keyof ActionsOf<C> ? ActionResult<C, K> : K extends JobAction ? unknown : StateOf<C>;
10
+ export interface TestCanvas<C extends AnyCanvas> {
11
+ readonly host: CanvasHost;
12
+ /** Temporary folder used instead of `<copilot-home>/extension-data`. */
13
+ readonly dataRoot: string;
14
+ /** Messages actions sent with `ctx.sendToAgent()`, oldest first. */
15
+ readonly sentToAgent: AgentMessage[];
16
+ open(instanceId: string, input?: unknown): Promise<OpenResult>;
17
+ invoke<K extends HarnessAction<C>>(instanceId: string, action: K, input?: HarnessInput<C, K>, source?: 'agent' | 'ui'): Promise<HarnessResult<C, K>>;
18
+ state(instanceId: string): StateOf<C> | undefined;
19
+ /** The instance's jobs, as `useJobs()` shows them. */
20
+ jobs(instanceId: string): JobStatusOf<C>[] | undefined;
21
+ /**
22
+ * Run a job now (even if not due or paused, unless `force: false`) for an instance
23
+ * or a saved key: a job's name, or the ID of a job added from a job with input.
24
+ */
25
+ runJob(id: JobName<C> | (string & {}), options?: RunJobOptions): Promise<JobOutcome>;
26
+ /** Run every due job once, as the host's timer does. */
27
+ tickJobs(): Promise<void>;
28
+ /** Close the host and delete the temporary data folder. */
29
+ close(): Promise<void>;
30
+ }
31
+ export interface TestCanvasOptions {
32
+ uiDir?: string;
33
+ dataRoot?: string;
34
+ release?: ReleaseInfo;
35
+ /** Replace the default recorder, for example to simulate a failed send. */
36
+ sendToAgent?: (message: AgentMessage) => Promise<void>;
37
+ /** The clock for `ctx.now()` and job schedules. */
38
+ now?: () => number;
39
+ /** Run due jobs on a timer (`auto`) or only through `runJob` and `tickJobs` (`manual`, the default). */
40
+ jobs?: 'auto' | 'manual';
41
+ /** Cross-process lock timings, for tests of contention. */
42
+ store?: StateStoreOptions;
43
+ }
44
+ /**
45
+ * Run a canvas definition with a real HTTP server and private storage in a
46
+ * temporary folder, without the Copilot SDK.
47
+ */
48
+ export declare function createTestCanvas<C extends AnyCanvas>(canvas: C, options?: TestCanvasOptions): Promise<TestCanvas<C>>;
49
+ //# sourceMappingURL=testing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { mkdtemp, rm } from 'node:fs/promises';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import { CanvasHost } from "./server/host.js";
5
+ /**
6
+ * Run a canvas definition with a real HTTP server and private storage in a
7
+ * temporary folder, without the Copilot SDK.
8
+ */
9
+ export async function createTestCanvas(canvas, options = {}) {
10
+ const ownsData = !options.dataRoot;
11
+ const dataRoot = options.dataRoot ?? (await mkdtemp(join(tmpdir(), 'canvas-kit-test-')));
12
+ const sentToAgent = [];
13
+ const host = new CanvasHost(canvas, {
14
+ uiDir: options.uiDir,
15
+ dataRoot,
16
+ release: options.release,
17
+ sendToAgent: options.sendToAgent ??
18
+ (async (message) => {
19
+ sentToAgent.push(message);
20
+ }),
21
+ now: options.now,
22
+ jobs: options.jobs ?? 'manual',
23
+ store: options.store,
24
+ });
25
+ return {
26
+ host,
27
+ dataRoot,
28
+ sentToAgent,
29
+ open: (instanceId, input) => host.open({ instanceId, input }),
30
+ invoke: (instanceId, action, input, source = 'agent') => host.invoke({ instanceId, actionName: action, input, source }),
31
+ state: instanceId => host.snapshot(instanceId)?.state,
32
+ jobs: instanceId => host.snapshot(instanceId)?.jobs,
33
+ runJob: (id, runOptions) => host.runJob(id, runOptions),
34
+ tickJobs: () => host.tickJobs(),
35
+ close: async () => {
36
+ await host.close();
37
+ if (ownsData)
38
+ await rm(dataRoot, { recursive: true, force: true });
39
+ },
40
+ };
41
+ }
42
+ //# sourceMappingURL=testing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,UAAU,EAAwD,MAAM,kBAAkB,CAAC;AAsDpG;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAsB,MAAS,EAAE,UAA6B,EAAE;IACpG,MAAM,QAAQ,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;IACnC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;IACzF,MAAM,WAAW,GAAmB,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,EAAE;QAClC,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,QAAQ;QACR,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,WAAW,EACT,OAAO,CAAC,WAAW;YACnB,CAAC,KAAK,EAAC,OAAO,EAAC,EAAE;gBACf,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC5B,CAAC,CAAC;QACJ,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,QAAQ;QAC9B,KAAK,EAAE,OAAO,CAAC,KAAK;KACrB,CAAC,CAAC;IACH,OAAO;QACL,IAAI;QACJ,QAAQ;QACR,WAAW;QACX,IAAI,EAAE,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;QAC7D,MAAM,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,EAAE,CACtD,IAAI,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAU;QACzE,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,KAA+B;QAC/E,IAAI,EAAE,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,IAAoC;QACnF,MAAM,EAAE,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC;QACvD,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE;QAC/B,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YACnB,IAAI,QAAQ;gBAAE,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACrE,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/vite.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import type { PluginOption } from 'vite';
2
+ export interface CanvasKitOptions {
3
+ /** Module whose default export is the `defineCanvas()` result, relative to the Vite root. */
4
+ entry?: string;
5
+ /** Plugin and extension folder name. Defaults to the canvas package folder name. */
6
+ name?: string;
7
+ /** `open_canvas` input for the dev server's preview instance. */
8
+ devInput?: unknown;
9
+ }
10
+ /**
11
+ * Vite plugins for a canvas package. `vite build` writes an installable plugin to
12
+ * `dist/plugin/`; `vite` serves the UI with the canvas definition running in-process.
13
+ */
14
+ export declare function canvasKit(options?: CanvasKitOptions): PluginOption[];
15
+ //# sourceMappingURL=vite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAU,YAAY,EAAiB,MAAM,MAAM,CAAC;AAMhE,MAAM,WAAW,gBAAgB;IAC/B,6FAA6F;IAC7F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAgBD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,YAAY,EAAE,CAIxE"}
package/dist/vite.js ADDED
@@ -0,0 +1,213 @@
1
+ import react from '@vitejs/plugin-react';
2
+ import { readFileSync } from 'node:fs';
3
+ import { mkdir, rm, writeFile } from 'node:fs/promises';
4
+ import { isBuiltin } from 'node:module';
5
+ import { basename, join, resolve, sep } from 'node:path';
6
+ import { CanvasKitError } from "./errors.js";
7
+ import { CanvasHost, injectBootstrap } from "./server/host.js";
8
+ import { injectReleaseFooter } from "./server/release.js";
9
+ const ENTRY_ID = 'virtual:canvas-kit/extension-entry';
10
+ const RESOLVED_ENTRY_ID = `\0${ENTRY_ID}`;
11
+ // canvas.mjs: the definition and a headless job runner, loadable without the Copilot SDK.
12
+ const CANVAS_ENTRY_ID = 'virtual:canvas-kit/canvas-entry';
13
+ const RESOLVED_CANVAS_ENTRY_ID = `\0${CANVAS_ENTRY_ID}`;
14
+ const NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
15
+ const DEV_INSTANCE = 'dev';
16
+ const VITEST_EXCLUDE = ['**/node_modules/**', '**/dist/**', 'e2e/**'];
17
+ /**
18
+ * Vite plugins for a canvas package. `vite build` writes an installable plugin to
19
+ * `dist/plugin/`; `vite` serves the UI with the canvas definition running in-process.
20
+ */
21
+ export function canvasKit(options = {}) {
22
+ // Under Vitest, skip the Playwright specs in e2e/; they run with `playwright test`.
23
+ if (process.env.VITEST)
24
+ return [react(), { name: 'canvas-kit:vitest', config: () => ({ test: { exclude: VITEST_EXCLUDE } }) }];
25
+ return [react(), canvasKitPlugin(options)];
26
+ }
27
+ function canvasKitPlugin(options) {
28
+ let root = process.cwd();
29
+ let name = '';
30
+ let pkg = { version: '', description: '' };
31
+ let entry = '';
32
+ let outRoot = '';
33
+ let devServer;
34
+ let devHost;
35
+ let devCanvas;
36
+ const devRelease = () => ({ name, version: pkg.version, channel: 'dev' });
37
+ const devHostFor = async (server) => {
38
+ const module = (await server.ssrLoadModule(entry));
39
+ const canvas = module.default;
40
+ if (canvas?.kind !== 'canvas-kit/canvas')
41
+ throw new Error(`${entry} must default-export defineCanvas(...)`);
42
+ if (!devHost || canvas !== devCanvas) {
43
+ await devHost?.close();
44
+ devCanvas = canvas;
45
+ devHost = new CanvasHost(canvas, {
46
+ dataRoot: join(root, 'node_modules', '.canvas-dev-data'),
47
+ release: devRelease(),
48
+ // There is no agent in the dev server; show what would have been sent.
49
+ sendToAgent: async (message) => {
50
+ server.config.logger.info(`[canvas] Message for the agent (${message.mode ?? 'enqueue'}):\n${message.prompt}`);
51
+ },
52
+ log: (message, level) => {
53
+ const logger = server.config.logger;
54
+ if (level === 'error')
55
+ logger.error(`[canvas] ${message}`);
56
+ else if (level === 'warning')
57
+ logger.warn(`[canvas] ${message}`);
58
+ else
59
+ logger.info(`[canvas] ${message}`);
60
+ },
61
+ });
62
+ // Opened once per definition, like an agent opening the canvas; page loads do not reopen it.
63
+ await devHost.openLocal({ instanceId: DEV_INSTANCE, input: options.devInput });
64
+ }
65
+ return devHost;
66
+ };
67
+ return {
68
+ name: 'canvas-kit',
69
+ config(config) {
70
+ root = resolve(config.root ?? process.cwd());
71
+ name = options.name ?? basename(root);
72
+ if (!NAME_PATTERN.test(name))
73
+ throw new Error(`Canvas plugin name must be kebab-case: ${name}`);
74
+ const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
75
+ if (!manifest.version || !manifest.description)
76
+ throw new Error(`${join(root, 'package.json')} needs a version and description`);
77
+ pkg = { version: manifest.version, description: manifest.description };
78
+ entry = resolve(root, options.entry ?? 'server/canvas.ts');
79
+ outRoot = join(root, 'dist', 'plugin');
80
+ const extensionDir = join(outRoot, 'extensions', name);
81
+ return {
82
+ base: './',
83
+ resolve: { dedupe: ['react', 'react-dom'] },
84
+ build: { outDir: join(extensionDir, 'ui'), emptyOutDir: true, chunkSizeWarningLimit: 1500 },
85
+ builder: {},
86
+ environments: {
87
+ extension: {
88
+ consumer: 'server',
89
+ resolve: { noExternal: true },
90
+ build: {
91
+ outDir: extensionDir,
92
+ emptyOutDir: false,
93
+ copyPublicDir: false,
94
+ target: 'node20',
95
+ minify: false,
96
+ rolldownOptions: {
97
+ input: { extension: ENTRY_ID, canvas: CANVAS_ENTRY_ID },
98
+ // The Copilot host injects its own SDK copy at runtime.
99
+ external: [/^@github\/copilot-sdk(?:\/|$)/],
100
+ output: {
101
+ format: 'es',
102
+ entryFileNames: '[name].mjs',
103
+ chunkFileNames: 'chunks/[name]-[hash].mjs',
104
+ },
105
+ },
106
+ },
107
+ },
108
+ },
109
+ };
110
+ },
111
+ resolveId: {
112
+ order: 'pre',
113
+ handler(id, importer) {
114
+ if (id === ENTRY_ID)
115
+ return RESOLVED_ENTRY_ID;
116
+ if (id === CANVAS_ENTRY_ID)
117
+ return RESOLVED_CANVAS_ENTRY_ID;
118
+ const fromSource = importer && !importer.includes(`${sep}node_modules${sep}`) && !importer.startsWith('\0');
119
+ if (this.environment.config.consumer === 'client' && fromSource && (id.startsWith('node:') || isBuiltin(id))) {
120
+ this.error(`${importer} imports the Node.js module "${id}". UI code runs in the browser; ` +
121
+ 'move Node.js work into the canvas actions and use `import type` for server modules.');
122
+ }
123
+ return undefined;
124
+ },
125
+ },
126
+ load(id) {
127
+ if (id === RESOLVED_CANVAS_ENTRY_ID) {
128
+ return [
129
+ "import { runCanvasJob } from '@rwoll/canvas-kit/server';",
130
+ `import canvas from ${JSON.stringify(entry)};`,
131
+ 'export default canvas;',
132
+ '/** Run a scheduled job for saved documents with no chat open; see `canvas-kit run`. */',
133
+ 'export function runJob(job, options) {',
134
+ ' return runCanvasJob(canvas, job, options);',
135
+ '}',
136
+ '',
137
+ ].join('\n');
138
+ }
139
+ if (id !== RESOLVED_ENTRY_ID)
140
+ return undefined;
141
+ return [
142
+ "import { runCanvasExtension } from '@rwoll/canvas-kit/extension';",
143
+ `import canvas from ${JSON.stringify(CANVAS_ENTRY_ID)};`,
144
+ 'await runCanvasExtension(canvas, {',
145
+ " uiDir: new URL('./ui/', import.meta.url),",
146
+ " releaseFile: new URL('../../release.json', import.meta.url),",
147
+ ` plugin: ${JSON.stringify({ name, version: pkg.version })},`,
148
+ '});',
149
+ '',
150
+ ].join('\n');
151
+ },
152
+ buildApp: {
153
+ order: 'pre',
154
+ async handler(builder) {
155
+ await rm(outRoot, { recursive: true, force: true });
156
+ await builder.build(builder.environments.client);
157
+ await builder.build(builder.environments.extension);
158
+ const manifest = { name, version: pkg.version, description: pkg.description, extensions: 'extensions/' };
159
+ await mkdir(join(outRoot, '.plugin'), { recursive: true });
160
+ await writeFile(join(outRoot, '.plugin', 'plugin.json'), `${JSON.stringify(manifest, null, 2)}\n`);
161
+ },
162
+ },
163
+ configureServer(server) {
164
+ devServer = server;
165
+ server.middlewares.use((request, response, next) => {
166
+ const path = new URL(request.url ?? '/', 'http://localhost').pathname;
167
+ if (!path.startsWith('/__canvas/')) {
168
+ next();
169
+ return;
170
+ }
171
+ void (async () => {
172
+ let host;
173
+ try {
174
+ host = await devHostFor(server);
175
+ if (request.method === 'POST' && request.headers.origin !== `http://${request.headers.host}`) {
176
+ throw new CanvasKitError('forbidden', 'Same-origin POST required');
177
+ }
178
+ // Dev only: act as the agent, for example to preview a tour or proposal the UI cannot create.
179
+ const agentAction = /^\/__canvas\/dev\/agent\/([a-z][a-z0-9_]*)$/.exec(path);
180
+ if (agentAction && request.method === 'POST') {
181
+ await host.runDevAgentAction(DEV_INSTANCE, agentAction[1], request, response);
182
+ return;
183
+ }
184
+ await host.handleApi(DEV_INSTANCE, path.slice(1), request, response);
185
+ }
186
+ catch (error) {
187
+ if (host)
188
+ host.sendError(response, error);
189
+ else
190
+ next(error);
191
+ }
192
+ })();
193
+ });
194
+ server.watcher.on('change', file => {
195
+ if (file.startsWith(join(root, 'server') + sep))
196
+ server.ws.send({ type: 'full-reload' });
197
+ });
198
+ server.httpServer?.once('close', () => void devHost?.close());
199
+ },
200
+ transformIndexHtml: {
201
+ order: 'pre',
202
+ async handler(html, ctx) {
203
+ if (!ctx.server || !devServer)
204
+ return html;
205
+ const host = await devHostFor(devServer);
206
+ const bootstrap = host.bootstrapFor(DEV_INSTANCE, '/');
207
+ const page = bootstrap ? injectBootstrap(html, bootstrap) : html;
208
+ return devCanvas?.versionFooter ? injectReleaseFooter(page, devRelease()) : page;
209
+ },
210
+ },
211
+ };
212
+ }
213
+ //# sourceMappingURL=vite.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.js","sourceRoot":"","sources":["../src/vite.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,118 @@
1
1
  {
2
2
  "name": "@rwoll/canvas-kit",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.1",
4
+ "description": "Build Copilot canvas extensions with TypeScript and React: typed state and actions, a secure local host, a Vite build, test helpers, and marketplace publishing.",
5
+ "keywords": [
6
+ "copilot",
7
+ "github-copilot",
8
+ "canvas",
9
+ "copilot-extension",
10
+ "react",
11
+ "vite"
12
+ ],
13
+ "license": "MIT",
14
+ "author": "Ross A. Wollman",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/rwoll/canvas-kit.git",
18
+ "directory": "packages/canvas-kit"
19
+ },
20
+ "homepage": "https://github.com/rwoll/canvas-kit/tree/main/packages/canvas-kit#readme",
21
+ "bugs": "https://github.com/rwoll/canvas-kit/issues",
22
+ "type": "module",
23
+ "engines": {
24
+ "node": ">=22.12.0"
25
+ },
26
+ "bin": {
27
+ "canvas-kit": "./cli/canvas-kit.mjs"
28
+ },
29
+ "exports": {
30
+ ".": {
31
+ "types": "./dist/index.d.ts",
32
+ "default": "./dist/index.js"
33
+ },
34
+ "./client": {
35
+ "types": "./dist/client.d.ts",
36
+ "default": "./dist/client.js"
37
+ },
38
+ "./react": {
39
+ "types": "./dist/react.d.ts",
40
+ "default": "./dist/react.js"
41
+ },
42
+ "./server": {
43
+ "types": "./dist/server/index.d.ts",
44
+ "default": "./dist/server/index.js"
45
+ },
46
+ "./extension": {
47
+ "types": "./dist/extension.d.ts",
48
+ "default": "./dist/extension.js"
49
+ },
50
+ "./testing": {
51
+ "types": "./dist/testing.d.ts",
52
+ "default": "./dist/testing.js"
53
+ },
54
+ "./playwright": {
55
+ "types": "./dist/playwright.d.ts",
56
+ "default": "./dist/playwright.js"
57
+ },
58
+ "./vite": {
59
+ "types": "./dist/vite.d.ts",
60
+ "default": "./dist/vite.js"
61
+ },
62
+ "./cli": "./cli/lib.mjs",
63
+ "./styles.css": "./styles.css",
64
+ "./tsconfig/*": "./tsconfig/*",
65
+ "./package.json": "./package.json"
66
+ },
67
+ "files": [
68
+ "dist",
69
+ "cli",
70
+ "!cli/*.test.mjs",
71
+ "templates",
72
+ "styles.css",
73
+ "tsconfig",
74
+ "README.md",
75
+ "LICENSE"
76
+ ],
77
+ "dependencies": {
78
+ "@vitejs/plugin-react": "^6.1.1",
79
+ "zod": "^4.6.7"
80
+ },
81
+ "peerDependencies": {
82
+ "@github/copilot-sdk": "^1.0.25",
83
+ "@playwright/test": "^1.60.0",
84
+ "react": "^19.0.0",
85
+ "vite": "^8.0.0"
86
+ },
87
+ "peerDependenciesMeta": {
88
+ "@github/copilot-sdk": {
89
+ "optional": true
90
+ },
91
+ "@playwright/test": {
92
+ "optional": true
93
+ },
94
+ "react": {
95
+ "optional": true
96
+ }
97
+ },
98
+ "devDependencies": {
99
+ "@github/copilot-sdk": "^1.0.25",
100
+ "@playwright/test": "^1.60.0",
101
+ "@types/node": "^24.13.3",
102
+ "@types/react": "^19.2.18",
103
+ "react": "^19.2.8",
104
+ "typescript": "~6.0.2",
105
+ "vite": "^8.3.0",
106
+ "vitest": "^5.0.5"
107
+ },
108
+ "publishConfig": {
109
+ "access": "public",
110
+ "registry": "https://registry.npmjs.org/",
111
+ "provenance": true
112
+ },
113
+ "scripts": {
114
+ "build": "tsc -p tsconfig.build.json",
115
+ "typecheck": "tsc -b",
116
+ "test": "vitest run"
117
+ }
6
118
  }
package/styles.css ADDED
@@ -0,0 +1,122 @@
1
+ /* Base canvas styles: theme variables, typography, and accessible form controls. */
2
+ :root {
3
+ --text: #4b4654;
4
+ --text-h: #08060d;
5
+ --muted: #6b6375;
6
+ --bg: #fff;
7
+ --surface: #f7f6f9;
8
+ --border: #e5e4e7;
9
+ --code-bg: #f4f3ec;
10
+ --accent: #8a2be2;
11
+ --accent-contrast: #fff;
12
+ --accent-bg: rgba(170, 59, 255, 0.1);
13
+ --accent-border: rgba(170, 59, 255, 0.5);
14
+ --danger: #b42318;
15
+ --success: #067647;
16
+
17
+ --sans: system-ui, 'Segoe UI', Roboto, sans-serif;
18
+ --mono: ui-monospace, Consolas, monospace;
19
+
20
+ font: 15px/1.5 var(--sans);
21
+ color-scheme: light dark;
22
+ color: var(--text);
23
+ background: var(--bg);
24
+ font-synthesis: none;
25
+ text-rendering: optimizeLegibility;
26
+ -webkit-font-smoothing: antialiased;
27
+ -moz-osx-font-smoothing: grayscale;
28
+ }
29
+
30
+ @media (prefers-color-scheme: dark) {
31
+ :root {
32
+ --text: #c4c8d0;
33
+ --text-h: #f3f4f6;
34
+ --muted: #9ca3af;
35
+ --bg: #16171d;
36
+ --surface: #1f2028;
37
+ --border: #2e303a;
38
+ --code-bg: #1f2028;
39
+ --accent: #c084fc;
40
+ --accent-contrast: #16171d;
41
+ --accent-bg: rgba(192, 132, 252, 0.15);
42
+ --accent-border: rgba(192, 132, 252, 0.5);
43
+ --danger: #fda29b;
44
+ --success: #75e0a7;
45
+ }
46
+ }
47
+
48
+ *,
49
+ *::before,
50
+ *::after {
51
+ box-sizing: border-box;
52
+ }
53
+
54
+ body {
55
+ margin: 0;
56
+ }
57
+
58
+ h1,
59
+ h2,
60
+ h3 {
61
+ color: var(--text-h);
62
+ font-weight: 600;
63
+ line-height: 1.2;
64
+ }
65
+
66
+ code {
67
+ font-family: var(--mono);
68
+ font-size: 0.9em;
69
+ padding: 2px 6px;
70
+ border-radius: 4px;
71
+ background: var(--code-bg);
72
+ color: var(--text-h);
73
+ }
74
+
75
+ button,
76
+ input,
77
+ select,
78
+ textarea {
79
+ font: inherit;
80
+ color: inherit;
81
+ }
82
+
83
+ input,
84
+ select,
85
+ textarea {
86
+ padding: 6px 10px;
87
+ border: 1px solid var(--border);
88
+ border-radius: 6px;
89
+ background: var(--bg);
90
+ }
91
+
92
+ button {
93
+ padding: 6px 14px;
94
+ border: 1px solid var(--accent);
95
+ border-radius: 6px;
96
+ background: var(--accent);
97
+ color: var(--accent-contrast);
98
+ cursor: pointer;
99
+ }
100
+
101
+ button:disabled {
102
+ opacity: 0.55;
103
+ cursor: not-allowed;
104
+ }
105
+
106
+ :focus-visible {
107
+ outline: 2px solid var(--accent);
108
+ outline-offset: 2px;
109
+ }
110
+
111
+ [role='alert'] {
112
+ color: var(--danger);
113
+ }
114
+
115
+ .visually-hidden {
116
+ position: absolute;
117
+ width: 1px;
118
+ height: 1px;
119
+ overflow: hidden;
120
+ clip-path: inset(50%);
121
+ white-space: nowrap;
122
+ }
@@ -0,0 +1,19 @@
1
+ # __TITLE__
2
+
3
+ __DESCRIPTION__
4
+
5
+ Canvas ID: `__CANVAS_ID__`. Plugin name: `__NAME__`.
6
+
7
+ - `server/canvas.ts`: state schema, open input, and agent and UI actions (Node.js).
8
+ - `src/`: the React UI. It uses `import type` only from `server/`.
9
+ - `server/*.test.ts`: unit tests for the canvas logic (Vitest).
10
+ - `e2e/*.spec.ts`: browser tests against the built canvas (Playwright).
11
+
12
+ ```sh
13
+ pnpm --filter __NAME__ dev # UI with live canvas logic in a browser
14
+ pnpm --filter __NAME__ test # unit tests
15
+ pnpm --filter __NAME__ build # installable plugin in dist/plugin
16
+ pnpm --filter __NAME__ e2e # browser tests; needs the build and `playwright install chromium`
17
+ ```
18
+
19
+ See the [canvas-kit guide](https://github.com/rwoll/canvas-kit/tree/main/packages/canvas-kit#readme) for the API.
@@ -0,0 +1,15 @@
1
+ import { canvasTest, expect } from '@rwoll/canvas-kit/playwright'
2
+ import canvas from '../server/canvas.ts'
3
+
4
+ const test = canvasTest(canvas)
5
+
6
+ test('the user and the agent share live state', async ({ openCanvas, agent }) => {
7
+ const { page, state } = await openCanvas()
8
+
9
+ await page.getByRole('button', { name: 'Count is 0' }).click()
10
+ await expect(page.getByRole('button', { name: 'Count is 1' })).toBeVisible()
11
+ expect(state()).toEqual({ count: 1 })
12
+
13
+ await agent.invoke('reset')
14
+ await expect(page.getByRole('button', { name: 'Count is 0' })).toBeVisible()
15
+ })
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link rel="icon" href="data:," />
7
+ <title>__TITLE__</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>