@nyte-ai/plugin 0.0.25-beta.1 → 0.0.25-nightly.20261101.40

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 (88) hide show
  1. package/THIRD-PARTY-NOTICES.md +49 -32
  2. package/dist/chunks/bash-description-0ah30s12.js +33 -0
  3. package/dist/chunks/bash-description-4h0hnsv4.js +68 -0
  4. package/dist/chunks/{bash-description-dnvgk30y.js → bash-description-4rfavmha.js} +32 -1
  5. package/dist/chunks/bash-description-5dpf5hpt.js +724 -0
  6. package/dist/chunks/{bash-description-yyd9jznf.js → bash-description-94km1hm2.js} +1 -1
  7. package/dist/chunks/{bash-description-svrhh5a5.js → bash-description-99k8z2r7.js} +3 -2
  8. package/dist/chunks/bash-description-9gw9ets8.js +162 -0
  9. package/dist/chunks/{bash-description-h13r0byk.js → bash-description-axnga0jz.js} +3 -3
  10. package/dist/chunks/bash-description-b78pre8c.js +147 -0
  11. package/dist/chunks/{bash-description-ye3wk5r3.js → bash-description-bas41ptb.js} +6 -24
  12. package/dist/chunks/{bash-description-2v3g7rd9.js → bash-description-bj5yh7tr.js} +26 -64
  13. package/dist/chunks/{bash-description-6z2kgtyt.js → bash-description-bkhr9zrz.js} +4 -4
  14. package/dist/chunks/{bash-description-hg64tqf1.js → bash-description-f754ge33.js} +49 -3
  15. package/dist/chunks/{bash-description-zz15raxk.js → bash-description-ff18794t.js} +1 -1
  16. package/dist/chunks/{bash-description-wmcbg6fw.js → bash-description-g7gfy7nw.js} +1 -1
  17. package/dist/chunks/{bash-description-1neewp76.js → bash-description-hp4rb8k4.js} +4 -3
  18. package/dist/chunks/bash-description-myvnmtt2.js +125 -0
  19. package/dist/chunks/{bash-description-9nn3yp18.js → bash-description-q2v8wbn8.js} +9 -1
  20. package/dist/chunks/bash-description-qwyy182r.js +452 -0
  21. package/dist/chunks/bash-description-rxpx004v.js +295 -0
  22. package/dist/chunks/{bash-description-eqp7ap2w.js → bash-description-z1581a29.js} +23 -9
  23. package/dist/src/acp/connection.d.ts +3 -1
  24. package/dist/src/acp/connection.js +3 -3
  25. package/dist/src/acp/index.d.ts +7 -4
  26. package/dist/src/acp/index.js +41 -8
  27. package/dist/src/acp/registry.d.ts +9 -0
  28. package/dist/src/acp/registry.js +5 -3
  29. package/dist/src/acp/thread.js +2 -2
  30. package/dist/src/acp/transcript.js +2 -2
  31. package/dist/src/acp/translate.d.ts +10 -2
  32. package/dist/src/acp/translate.js +3 -1
  33. package/dist/src/approvals/approvals.d.ts +1 -1
  34. package/dist/src/approvals/approvals.js +2 -2
  35. package/dist/src/approvals/schema.d.ts +3 -3
  36. package/dist/src/approvals/schema.js +1 -1
  37. package/dist/src/browser-tools.js +8 -2
  38. package/dist/src/canvas/canvas-compile.js +2 -2
  39. package/dist/src/canvas/canvas-preview.js +2 -2
  40. package/dist/src/canvas/canvas-protocol.d.ts +46 -0
  41. package/dist/src/canvas/canvas-protocol.js +11 -1
  42. package/dist/src/canvas/canvas.d.ts +17 -3
  43. package/dist/src/canvas/canvas.js +75 -31
  44. package/dist/src/canvas/schema.d.ts +28 -7
  45. package/dist/src/canvas/schema.js +2 -2
  46. package/dist/src/claude-code-sdk/index.d.ts +0 -10
  47. package/dist/src/claude-code-sdk/index.js +19 -179
  48. package/dist/src/claude-code-sdk/session.d.ts +22 -23
  49. package/dist/src/claude-code-sdk/session.js +6 -3
  50. package/dist/src/claude-code-sdk/transcript.d.ts +0 -6
  51. package/dist/src/claude-code-sdk/transcript.js +2 -4
  52. package/dist/src/claude-code-sdk/translate.d.ts +1 -5
  53. package/dist/src/claude-code-sdk/translate.js +2 -8
  54. package/dist/src/client/mount.d.ts +4 -2
  55. package/dist/src/client/mount.js +3 -0
  56. package/dist/src/client/notifications.d.ts +12 -4
  57. package/dist/src/client/notifications.js +25 -10
  58. package/dist/src/client/presentation.d.ts +138 -8
  59. package/dist/src/client/presentation.js +86 -371
  60. package/dist/src/codemode.js +151 -46
  61. package/dist/src/core.d.ts +1 -1
  62. package/dist/src/question/client/questions-tui.js +3 -3
  63. package/dist/src/question/client/questions.js +3 -3
  64. package/dist/src/question/question.js +84 -5
  65. package/dist/src/question/schema.js +3 -3
  66. package/dist/src/rename.d.ts +7 -35
  67. package/dist/src/rename.js +115 -48
  68. package/dist/src/subagents.d.ts +30 -0
  69. package/dist/src/subagents.js +323 -0
  70. package/dist/src/tool-search.d.ts +49 -0
  71. package/dist/src/tool-search.js +14 -0
  72. package/dist/src/web/body.d.ts +3 -0
  73. package/dist/src/web/body.js +6 -0
  74. package/dist/src/web/fetch.d.ts +16 -0
  75. package/dist/src/web/fetch.js +8 -0
  76. package/dist/src/web/html-markdown.d.ts +9 -0
  77. package/dist/src/web/html-markdown.js +10 -0
  78. package/dist/src/web/index.d.ts +24 -0
  79. package/dist/src/web/index.js +93 -0
  80. package/dist/src/web/providers.d.ts +60 -0
  81. package/dist/src/web/providers.js +11 -0
  82. package/dist/src/web/search.d.ts +21 -0
  83. package/dist/src/web/search.js +6 -0
  84. package/package.json +16 -7
  85. package/dist/chunks/bash-description-3j77ss7y.js +0 -86
  86. package/dist/chunks/bash-description-wbe8w0te.js +0 -530
  87. package/dist/src/web-search.d.ts +0 -78
  88. package/dist/src/web-search.js +0 -219
@@ -37,6 +37,7 @@ var __callDispose = (stack, error, hasError) => {
37
37
  };
38
38
 
39
39
  // src/browser-tools.ts
40
+ import { attachFile } from "@nyte-ai/core";
40
41
  import { asId, standard } from "@nyte-ai/schema";
41
42
  import { Type } from "typebox";
42
43
  var page = Type.Optional(Type.String({ description: "The page id; omit for the page opened last." }));
@@ -127,8 +128,13 @@ var capture = {
127
128
  execute: (args, invocation) => withPage(invocation, args.page, async (held) => {
128
129
  const image = await held.capture();
129
130
  try {
130
- const blob = await invocation.env.files.upload(image.chunks());
131
- return { content: [{ kind: "file", blob, mime: image.mime ?? "image/png" }] };
131
+ return {
132
+ content: [
133
+ await attachFile(invocation.env.files, image.chunks(), {
134
+ mime: image.mime ?? "image/png"
135
+ })
136
+ ]
137
+ };
132
138
  } finally {
133
139
  await image.close();
134
140
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  compileCanvas2
3
- } from "../../chunks/bash-description-zz15raxk.js";
4
- import"../../chunks/bash-description-dnvgk30y.js";
3
+ } from "../../chunks/bash-description-ff18794t.js";
4
+ import"../../chunks/bash-description-4rfavmha.js";
5
5
  import"../../chunks/bash-description-zfpm2rt0.js";
6
6
  export {
7
7
  compileCanvas2 as compileCanvas
@@ -2,8 +2,8 @@ import {
2
2
  CANVAS_PREVIEW_WIDTHS2,
3
3
  runCanvasPreview2,
4
4
  describeCanvasPreview2
5
- } from "../../chunks/bash-description-yyd9jznf.js";
6
- import"../../chunks/bash-description-dnvgk30y.js";
5
+ } from "../../chunks/bash-description-94km1hm2.js";
6
+ import"../../chunks/bash-description-4rfavmha.js";
7
7
  import"../../chunks/bash-description-zfpm2rt0.js";
8
8
  export {
9
9
  CANVAS_PREVIEW_WIDTHS2 as CANVAS_PREVIEW_WIDTHS,
@@ -1,7 +1,19 @@
1
+ /**
2
+ * The inline canvas contract every side shares, with no dependencies: the
3
+ * runtime version, the import surfaces a canvas module may use, the size
4
+ * caps, where a compiled module's source files sit in it, and the JSON-RPC
5
+ * messages between a client and the runtime shell, in the MCP Apps shape
6
+ * (`ui/*` methods as upstream defines them, `nyte/*` for the one extension).
7
+ * Builders make a message; readers narrow `unknown` data from a `message`
8
+ * event into a typed one or `undefined`.
9
+ */
10
+ import { CANVAS_LIBRARIES } from "./canvas-libraries.ts";
1
11
  /** The shell surface a compiled module was built against. Bump on any change to `KIT`, a kit component's props, the libraries or the global; a shell renders a canvas whose runtime is at most its own. Runtime 2 added `react-dom` and the libraries; the compiler stamps a canvas with 2 only when it imports one of them, so a runtime 1 shell still renders the rest. */
2
12
  export declare const CANVAS_RUNTIME = 2;
3
13
  /** The global the shell installs before importing a module: `{ runtime, react, jsxRuntime, reactDom, kit, library }`, where `library(specifier)` loads one of `LIBRARY_EXPORTS`' modules. */
4
14
  export declare const CANVAS_GLOBAL = "__nyteCanvas";
15
+ /** The global a client may set before the shell's scripts run (iOS, through a WebView's document-start script) to a `hostContextChangedNotification` the shell applies before it first paints, so it starts in the client's scheme rather than waiting for `ui/initialize`. */
16
+ export declare const CANVAS_STARTUP_CONTEXT = "__nyteCanvasContext";
5
17
  /** The import specifier for the kit. */
6
18
  export declare const KIT_SPECIFIER = "nyte/canvas";
7
19
  /** The entry module's file name: the tool's `source`, which its other files are imported from. */
@@ -24,6 +36,10 @@ export declare const JSX_RUNTIME_EXPORTS: readonly ["Fragment", "jsx", "jsxs"];
24
36
  export declare const REACT_DOM_EXPORTS: readonly ["createPortal", "flushSync"];
25
37
  /** Every name each library exports, by its import specifier. */
26
38
  export declare const LIBRARY_EXPORTS: Readonly<Record<string, readonly string[]>>;
39
+ /** A library a canvas may import, by its import specifier. */
40
+ export type CanvasLibrary = keyof typeof CANVAS_LIBRARIES;
41
+ /** Returns the library a value names, or undefined when it names none. */
42
+ export declare function readCanvasLibrary(value: unknown): CanvasLibrary | undefined;
27
43
  /** Each library's pinned version, by its import specifier. */
28
44
  export declare const LIBRARY_VERSIONS: Readonly<Record<string, string>>;
29
45
  /**
@@ -131,6 +147,11 @@ export type ShellMessage = {
131
147
  readonly kind: "open-link";
132
148
  readonly id: JsonRpcId;
133
149
  readonly url: string;
150
+ }
151
+ /** Asked only by a shell with no base URL to load `libraries/<name>.js` from (the inline one in a WebView); the request's id is the name. */
152
+ | {
153
+ readonly kind: "library";
154
+ readonly name: CanvasLibrary;
134
155
  } | {
135
156
  readonly kind: "error";
136
157
  readonly phase: "load" | "render";
@@ -153,6 +174,12 @@ export type HostMessage = {
153
174
  readonly kind: "open-link-result";
154
175
  readonly id: JsonRpcId;
155
176
  readonly isError: boolean;
177
+ }
178
+ /** `source` is the library's self-contained ES module. */
179
+ | {
180
+ readonly kind: "library-result";
181
+ readonly name: CanvasLibrary;
182
+ readonly source: string;
156
183
  };
157
184
  type Json = null | boolean | number | string | readonly Json[] | {
158
185
  readonly [key: string]: Json;
@@ -173,12 +200,31 @@ export declare function initializeResult(id: JsonRpcId, hostInfo: CanvasHostInfo
173
200
  export declare function renderNotification(module: CanvasModule): Json;
174
201
  export declare function hostContextChangedNotification(context: Partial<CanvasHostContext>): Json;
175
202
  export declare function openLinkResult(id: JsonRpcId, isError?: boolean): Json;
203
+ export declare function libraryRequest(name: CanvasLibrary): Json;
204
+ export declare function libraryResult(name: CanvasLibrary, source: string): Json;
176
205
  /** Returns the message a shell posted, or undefined for anything that is not one. */
177
206
  export declare function readShellMessage(data: unknown): ShellMessage | undefined;
178
207
  /** Returns the message a client posted into the shell, or undefined for anything that is not one. */
179
208
  export declare function readHostMessage(data: unknown): HostMessage | undefined;
180
209
  /** Returns the height a frame shows a canvas at, within the range. */
181
210
  export declare function clampCanvasHeight(height: number): number;
211
+ /** A canvas's height in CSS pixels as a preview measured it at one frame width. */
212
+ export type CanvasMeasuredHeight = {
213
+ readonly width: number;
214
+ readonly height: number;
215
+ };
216
+ /**
217
+ * Returns the height a frame `width` px wide starts a canvas at, before its
218
+ * shell reports one: the taller of the measured heights at the nearest widths
219
+ * either side, since a frame a few pixels short scrolls inside itself and
220
+ * takes the reader's scroll; past either end, the nearest; without any, the
221
+ * agent's hint, then the default. With no width yet, it skips the measured
222
+ * heights.
223
+ */
224
+ export declare function canvasStartHeight(canvas: {
225
+ readonly height: number | null;
226
+ readonly heights?: readonly CanvasMeasuredHeight[];
227
+ }, width: number | undefined): number;
182
228
  /** Returns the variables the shell may apply: allowlisted names, values stripped of the characters that could end a declaration. */
183
229
  export declare function sanitizeCanvasVariables(variables: Readonly<Record<string, string>>): Record<string, string>;
184
230
  export {};
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  CANVAS_RUNTIME2,
3
3
  CANVAS_GLOBAL2,
4
+ CANVAS_STARTUP_CONTEXT2,
4
5
  KIT_SPECIFIER2,
5
6
  CANVAS_ENTRY2,
6
7
  CANVAS_SOURCE_LIMIT2,
@@ -13,6 +14,7 @@ import {
13
14
  JSX_RUNTIME_EXPORTS2,
14
15
  REACT_DOM_EXPORTS2,
15
16
  LIBRARY_EXPORTS2,
17
+ readCanvasLibrary2,
16
18
  LIBRARY_VERSIONS2,
17
19
  canvasFilesComment2,
18
20
  locateCanvasStack2,
@@ -30,11 +32,14 @@ import {
30
32
  renderNotification2,
31
33
  hostContextChangedNotification2,
32
34
  openLinkResult2,
35
+ libraryRequest2,
36
+ libraryResult2,
33
37
  readShellMessage2,
34
38
  readHostMessage2,
35
39
  clampCanvasHeight2,
40
+ canvasStartHeight2,
36
41
  sanitizeCanvasVariables2
37
- } from "../../chunks/bash-description-dnvgk30y.js";
42
+ } from "../../chunks/bash-description-4rfavmha.js";
38
43
  import"../../chunks/bash-description-zfpm2rt0.js";
39
44
  export {
40
45
  CANVAS_CODE_LIMIT2 as CANVAS_CODE_LIMIT,
@@ -47,6 +52,7 @@ export {
47
52
  CANVAS_PROTOCOL_VERSION2 as CANVAS_PROTOCOL_VERSION,
48
53
  CANVAS_RUNTIME2 as CANVAS_RUNTIME,
49
54
  CANVAS_SOURCE_LIMIT2 as CANVAS_SOURCE_LIMIT,
55
+ CANVAS_STARTUP_CONTEXT2 as CANVAS_STARTUP_CONTEXT,
50
56
  CANVAS_VARIABLES2 as CANVAS_VARIABLES,
51
57
  JSX_RUNTIME_EXPORTS2 as JSX_RUNTIME_EXPORTS,
52
58
  KIT2 as KIT,
@@ -58,15 +64,19 @@ export {
58
64
  REACT_EXPORTS2 as REACT_EXPORTS,
59
65
  TINTS2 as TINTS,
60
66
  canvasFilesComment2 as canvasFilesComment,
67
+ canvasStartHeight2 as canvasStartHeight,
61
68
  clampCanvasHeight2 as clampCanvasHeight,
62
69
  errorNotification2 as errorNotification,
63
70
  hostContextChangedNotification2 as hostContextChangedNotification,
64
71
  initializeRequest2 as initializeRequest,
65
72
  initializeResult2 as initializeResult,
66
73
  initializedNotification2 as initializedNotification,
74
+ libraryRequest2 as libraryRequest,
75
+ libraryResult2 as libraryResult,
67
76
  locateCanvasStack2 as locateCanvasStack,
68
77
  openLinkRequest2 as openLinkRequest,
69
78
  openLinkResult2 as openLinkResult,
79
+ readCanvasLibrary2 as readCanvasLibrary,
70
80
  readHostMessage2 as readHostMessage,
71
81
  readShellMessage2 as readShellMessage,
72
82
  renderNotification2 as renderNotification,
@@ -4,22 +4,34 @@ export declare const canvas: import("@nyte-ai/core").PartDefinition<{
4
4
  runtime: number;
5
5
  title: string;
6
6
  height: number | null;
7
+ heights?: {
8
+ width: number;
9
+ height: number;
10
+ }[] | undefined;
7
11
  code: string;
8
12
  error: string | null;
9
- revisions?: {
13
+ revisions: {
10
14
  runtime: number;
11
15
  title: string;
12
16
  height: number | null;
17
+ heights?: {
18
+ width: number;
19
+ height: number;
20
+ }[] | undefined;
13
21
  number: number;
14
22
  blob: import("@nyte-ai/schema").Id<"blob">;
15
23
  at: number;
16
- }[] | undefined;
24
+ }[];
17
25
  }, {
18
26
  replace: {
19
27
  input: import("@nyte-ai/schema").Schema<{
20
28
  runtime: number;
21
29
  title: string;
22
30
  height: number | null;
31
+ heights?: {
32
+ width: number;
33
+ height: number;
34
+ }[] | undefined;
23
35
  code: string;
24
36
  blob: import("@nyte-ai/schema").Id<"blob">;
25
37
  }>;
@@ -42,7 +54,9 @@ export declare const CANVAS_DESCRIPTION: string;
42
54
  * Returns the canvas plugin: the `canvas` part and `canvas_render`, which
43
55
  * compiles in-process on any host, plus `canvas_preview` when the host
44
56
  * passes a previewer, in which case `canvas_render` tells the model to
45
- * preview first.
57
+ * preview first and saves the module's heights at the preview widths: the
58
+ * session's last clean preview's when it compiled to the same module, or
59
+ * measured as it renders.
46
60
  *
47
61
  * @category plugins
48
62
  * @since 0.1.0
@@ -9,40 +9,42 @@ import {
9
9
  LIBRARY_VERSIONS2,
10
10
  TINTS2,
11
11
  KIT2
12
- } from "../../chunks/bash-description-dnvgk30y.js";
12
+ } from "../../chunks/bash-description-4rfavmha.js";
13
13
  import {
14
14
  compileCanvas2
15
- } from "../../chunks/bash-description-zz15raxk.js";
15
+ } from "../../chunks/bash-description-ff18794t.js";
16
16
  import {
17
17
  CANVAS_PREVIEW_WIDTHS2,
18
18
  describeCanvasPreview2
19
- } from "../../chunks/bash-description-yyd9jznf.js";
19
+ } from "../../chunks/bash-description-94km1hm2.js";
20
20
  import {
21
21
  CANVAS_RENDER_TOOL2,
22
22
  CANVAS_REVISIONS_KEPT2,
23
23
  canvas2
24
- } from "../../chunks/bash-description-1neewp76.js";
24
+ } from "../../chunks/bash-description-hp4rb8k4.js";
25
25
 
26
26
  // src/canvas/canvas.ts
27
- import { definePart, followedTrace, traced } from "@nyte-ai/core";
27
+ import { attachFile, definePart, followedTrace, traced } from "@nyte-ai/core";
28
28
  import { asId, standard } from "@nyte-ai/schema";
29
29
  import { Type } from "typebox";
30
30
  var handlers = {
31
31
  async replace(input, context) {
32
- const outcome = await context.part.update((current) => ({
32
+ const drawn = {
33
33
  runtime: input.runtime,
34
34
  title: input.title,
35
- code: input.code,
36
35
  height: input.height,
36
+ heights: input.heights ?? []
37
+ };
38
+ const outcome = await context.part.update((current) => ({
39
+ ...drawn,
40
+ code: input.code,
37
41
  error: null,
38
42
  revisions: [
39
- ...current.revisions ?? [],
43
+ ...current.revisions,
40
44
  {
41
- number: (current.revisions?.at(-1)?.number ?? 1) + 1,
45
+ number: (current.revisions.at(-1)?.number ?? 0) + 1,
42
46
  blob: input.blob,
43
- runtime: input.runtime,
44
- title: input.title,
45
- height: input.height,
47
+ ...drawn,
46
48
  at: Date.now()
47
49
  }
48
50
  ].slice(-CANVAS_REVISIONS_KEPT2)
@@ -85,7 +87,7 @@ var kitReference = Object.entries(KIT2).map(([name, signature]) => `- ${name} ${
85
87
  var CANVAS_DESCRIPTION = [
86
88
  `Render a React canvas inline in the chat. \`source\` is ${CANVAS_ENTRY2}, a TSX module whose default export is a component; split a large canvas into \`files\` it imports by relative path. Every file counts toward one ${Math.round(CANVAS_SOURCE_LIMIT2 / 1024)} KB budget.`,
87
89
  `Imports: \`react\`, \`react-dom\` (${REACT_DOM_EXPORTS2.map((name) => `\`${name}\``).join(" and ")} only), \`${KIT_SPECIFIER2}\`, the canvas's own files, and these libraries, each loaded only by a canvas that imports it: ${Object.entries(LIBRARY_VERSIONS2).map(([name, version]) => `\`${name}\` ${version}`).join(", ")}. \`three\` is the core module without its addons, so orbit a camera yourself. Nothing else resolves (no other npm packages, no URLs, no fetch). \`eval\` and \`new Function\` are unavailable at run time.`,
88
- `The canvas runs sandboxed with no network, sized to its content (up to ${CANVAS_MAX_HEIGHT2} px, then it scrolls), on the chat's background with the user's theme applied through the kit.`,
90
+ `The canvas runs sandboxed with no network, on the chat's background with the user's theme applied through the kit. It is as wide as the reply, ${CANVAS_PREVIEW_WIDTHS2.chat} px in the chat column and ${CANVAS_PREVIEW_WIDTHS2.phone} px on a phone, so lay it out to fit both, and as tall as its content up to ${CANVAS_MAX_HEIGHT2} px, then it scrolls. Give SVG and WebGL drawings a fixed pixel height; never use \`vh\` units or \`height: 100%\` on html or body, which follow the frame and make it stick, grow or collapse.`,
89
91
  "Use the kit for layout, text, data and charts; never hard-code colours, fonts or backgrounds. An `<a href>` to an http(s) URL opens in the user's browser, and one to a workspace path such as `src/app.ts:42` opens that file at that line; other schemes are refused. Pass `canvas` to replace an earlier canvas in place.",
90
92
  "",
91
93
  'Charts: `StackedBars` and `Sparkline` are compact and axis-free, for a figure that sits beside its own number (a Stat, a Table row); use them first. `LineChart`, `BarChart` and `PieChart` are full charts with axes, gridlines and a readout, for a series that needs reading on its own: a line for change over time, bars to compare categories (`layout="horizontal"` when the labels are long), a pie only for up to five parts of one whole. All of them share one look and fit the width they get; give each series a `tint` only when a hue carries meaning (green for good, red for bad), or leave the order to the kit, which keeps neighbouring series apart for colour-blind readers.',
@@ -115,13 +117,45 @@ async function compile(args, invocation) {
115
117
  ${describeErrors(compiled.errors)}`);
116
118
  return compiled;
117
119
  }
120
+ var PREVIEWS_KEPT = 64;
121
+ function rememberPreview(previews, session, preview) {
122
+ previews.delete(session);
123
+ previews.set(session, preview);
124
+ if (previews.size <= PREVIEWS_KEPT)
125
+ return;
126
+ const oldest = previews.keys().next().value;
127
+ if (oldest !== undefined)
128
+ previews.delete(oldest);
129
+ }
130
+ var MEASURE_TIMEOUT_MS = 1e4;
131
+ function previewHeights(report) {
132
+ if (report.errors.length > 0)
133
+ return [];
134
+ return ["chat", "phone"].flatMap((name) => {
135
+ const height = report.heights[name];
136
+ return height > 0 ? [{ width: CANVAS_PREVIEW_WIDTHS2[name], height }] : [];
137
+ });
138
+ }
139
+ async function measureCanvas(measuring, module, invocation) {
140
+ if (measuring === undefined)
141
+ return [];
142
+ const previewed = measuring.previews.get(invocation.session.id);
143
+ if (previewed !== undefined && previewed.digest === await digestCode(module.code))
144
+ return previewed.heights;
145
+ const outcome = await previewWithin(measuring.preview, { module, theme: "light" }, invocation.signal, MEASURE_TIMEOUT_MS);
146
+ return outcome.kind === "rendered" ? previewHeights(outcome.report) : [];
147
+ }
148
+ async function digestCode(code) {
149
+ const hash = await crypto.subtle.digest("SHA-256", encoder.encode(code));
150
+ return Array.from(new Uint8Array(hash), (byte) => byte.toString(16).padStart(2, "0")).join("");
151
+ }
118
152
  var PREVIEW_FIRST = "Before rendering, call `canvas_preview` with the same `source` and `files`: it shows you the canvas and its errors, console and height without the user seeing it. Fix what it shows, then render once.";
119
- function renderTool(previewing) {
153
+ function renderTool(measuring) {
120
154
  return {
121
155
  name: CANVAS_RENDER_TOOL2,
122
- description: previewing ? `${PREVIEW_FIRST}
156
+ description: measuring === undefined ? CANVAS_DESCRIPTION : `${PREVIEW_FIRST}
123
157
 
124
- ${CANVAS_DESCRIPTION}` : CANVAS_DESCRIPTION,
158
+ ${CANVAS_DESCRIPTION}`,
125
159
  parameters,
126
160
  class: (args) => ({
127
161
  kind: "custom",
@@ -132,7 +166,12 @@ ${CANVAS_DESCRIPTION}` : CANVAS_DESCRIPTION,
132
166
  replay: "safe",
133
167
  async execute(args, invocation) {
134
168
  const compiled = await compile(args, invocation);
135
- const drawn = { runtime: compiled.runtime, title: args.title, height: args.height ?? null };
169
+ const drawn = {
170
+ runtime: compiled.runtime,
171
+ title: args.title,
172
+ height: args.height ?? null,
173
+ heights: await measureCanvas(measuring, { runtime: compiled.runtime, code: compiled.code, title: args.title }, invocation)
174
+ };
136
175
  const blob = await invocation.env.files.upload(async function* () {
137
176
  yield encoder.encode(compiled.code);
138
177
  }());
@@ -169,10 +208,10 @@ var previewParameters = standard(Type.Object({
169
208
  }))
170
209
  }));
171
210
  var PREVIEW_TIMEOUT_MS = 45000;
172
- async function previewWithin(preview, request, signal) {
211
+ async function previewWithin(preview, request, signal, timeoutMs) {
173
212
  signal.throwIfAborted();
174
213
  const deadline = new AbortController;
175
- const timer = setTimeout(() => deadline.abort(), PREVIEW_TIMEOUT_MS);
214
+ const timer = setTimeout(() => deadline.abort(), timeoutMs);
176
215
  const stop = AbortSignal.any([signal, deadline.signal]);
177
216
  const stopped = new Promise((resolve) => stop.addEventListener("abort", () => resolve("stopped"), { once: true }));
178
217
  try {
@@ -185,10 +224,10 @@ async function previewWithin(preview, request, signal) {
185
224
  signal.throwIfAborted();
186
225
  return {
187
226
  kind: "unavailable",
188
- reason: `The preview took longer than ${PREVIEW_TIMEOUT_MS / 1000} seconds.`
227
+ reason: `The preview took longer than ${timeoutMs / 1000} seconds.`
189
228
  };
190
229
  }
191
- function previewTool(preview) {
230
+ function previewTool(measuring) {
192
231
  return {
193
232
  name: "canvas_preview",
194
233
  description: `Render a canvas off-screen in the real canvas runtime and see it before the user does: a PNG at the chat column's width (${CANVAS_PREVIEW_WIDTHS2.chat} px), its height there and at a phone's width (${CANVAS_PREVIEW_WIDTHS2.phone} px), every load or render error with its file and line, and the canvas's console output. Takes the same \`source\` and \`files\` as canvas_render and compiles them the same way; nothing is added to the chat.`,
@@ -199,10 +238,10 @@ function previewTool(preview) {
199
238
  replay: "safe",
200
239
  async execute(args, invocation) {
201
240
  const compiled = await compile(args, invocation);
202
- const outcome = await previewWithin(preview, {
241
+ const outcome = await previewWithin(measuring.preview, {
203
242
  module: { runtime: compiled.runtime, code: compiled.code, title: "Preview" },
204
243
  theme: args.theme ?? "light"
205
- }, invocation.signal);
244
+ }, invocation.signal, PREVIEW_TIMEOUT_MS);
206
245
  if (outcome.kind === "unavailable")
207
246
  return {
208
247
  content: [
@@ -213,25 +252,30 @@ function previewTool(preview) {
213
252
  ]
214
253
  };
215
254
  const { png } = outcome.report;
216
- const blob = await invocation.env.files.upload(async function* () {
217
- yield png;
218
- }());
255
+ const heights = previewHeights(outcome.report);
256
+ if (heights.length > 0)
257
+ rememberPreview(measuring.previews, invocation.session.id, {
258
+ digest: await digestCode(compiled.code),
259
+ heights
260
+ });
219
261
  return {
220
262
  content: [
221
263
  { kind: "text", text: describeCanvasPreview2(outcome.report) },
222
- { kind: "file", blob, mime: "image/png" }
264
+ await attachFile(invocation.env.files, async function* () {
265
+ yield png;
266
+ }(), { mime: "image/png" })
223
267
  ]
224
268
  };
225
269
  }
226
270
  };
227
271
  }
228
272
  function canvasPlugin(preview) {
273
+ if (preview === undefined)
274
+ return { id: "canvas", contribute: { parts: [canvas], tools: [renderTool(undefined)] } };
275
+ const measuring = { preview, previews: new Map };
229
276
  return {
230
277
  id: "canvas",
231
- contribute: {
232
- parts: [canvas],
233
- tools: preview === undefined ? [renderTool(false)] : [renderTool(true), previewTool(preview)]
234
- }
278
+ contribute: { parts: [canvas], tools: [renderTool(measuring), previewTool(measuring)] }
235
279
  };
236
280
  }
237
281
  var canvas_default = canvasPlugin();
@@ -17,21 +17,30 @@ declare const state: import("@nyte-ai/schema").Schema<{
17
17
  runtime: number;
18
18
  title: string;
19
19
  height: number | null;
20
+ heights?: {
21
+ width: number;
22
+ height: number;
23
+ }[] | undefined;
20
24
  code: string;
21
25
  error: string | null;
22
- revisions?: {
26
+ revisions: {
23
27
  runtime: number;
24
28
  title: string;
25
29
  height: number | null;
30
+ heights?: {
31
+ width: number;
32
+ height: number;
33
+ }[] | undefined;
26
34
  number: number;
27
35
  blob: import("@nyte-ai/schema").Id<"blob">;
28
36
  at: number;
29
- }[] | undefined;
37
+ }[];
30
38
  }>;
31
39
  /**
32
40
  * Returns a canvas part's state: the compiled module, the runtime it needs,
33
- * its title, the agent's height hint, the last error a client reported, and
34
- * its revisions, oldest first, the last one being the module itself.
41
+ * its title, the agent's height hint, the module's measured heights, the last
42
+ * error a client reported, and its revisions, oldest first, the last one
43
+ * being the module itself.
35
44
  *
36
45
  * @category plugins
37
46
  * @since 0.1.0
@@ -44,7 +53,7 @@ export type CanvasState = Infer<typeof state>;
44
53
  * @category plugins
45
54
  * @since 0.1.0
46
55
  */
47
- export type CanvasRevision = NonNullable<CanvasState["revisions"]>[number];
56
+ export type CanvasRevision = CanvasState["revisions"][number];
48
57
  /**
49
58
  * A canvas part: a React module the agent wrote, compiled on the host and
50
59
  * drawn by a client inside the sandboxed runtime shell. `replace` swaps the
@@ -58,22 +67,34 @@ export declare const canvas: import("@nyte-ai/core").PartDefinition<{
58
67
  runtime: number;
59
68
  title: string;
60
69
  height: number | null;
70
+ heights?: {
71
+ width: number;
72
+ height: number;
73
+ }[] | undefined;
61
74
  code: string;
62
75
  error: string | null;
63
- revisions?: {
76
+ revisions: {
64
77
  runtime: number;
65
78
  title: string;
66
79
  height: number | null;
80
+ heights?: {
81
+ width: number;
82
+ height: number;
83
+ }[] | undefined;
67
84
  number: number;
68
85
  blob: import("@nyte-ai/schema").Id<"blob">;
69
86
  at: number;
70
- }[] | undefined;
87
+ }[];
71
88
  }, {
72
89
  replace: {
73
90
  input: import("@nyte-ai/schema").Schema<{
74
91
  runtime: number;
75
92
  title: string;
76
93
  height: number | null;
94
+ heights?: {
95
+ width: number;
96
+ height: number;
97
+ }[] | undefined;
77
98
  code: string;
78
99
  blob: import("@nyte-ai/schema").Id<"blob">;
79
100
  }>;
@@ -2,8 +2,8 @@ import {
2
2
  CANVAS_RENDER_TOOL2,
3
3
  CANVAS_REVISIONS_KEPT2,
4
4
  canvas2
5
- } from "../../chunks/bash-description-1neewp76.js";
6
- import"../../chunks/bash-description-dnvgk30y.js";
5
+ } from "../../chunks/bash-description-hp4rb8k4.js";
6
+ import"../../chunks/bash-description-4rfavmha.js";
7
7
  import"../../chunks/bash-description-zfpm2rt0.js";
8
8
  export {
9
9
  CANVAS_RENDER_TOOL2 as CANVAS_RENDER_TOOL,
@@ -1,19 +1,9 @@
1
1
  import type { Api, Provider } from "@nyte-ai/ai";
2
- import type { SettingDefinition, ToolDefinition } from "@nyte-ai/core";
3
2
  import type { StartQuery } from "./session.ts";
4
- export declare const ultracodeSetting: SettingDefinition<boolean>;
5
3
  export declare function claudeCodeSdk(start?: StartQuery): {
6
4
  provider: Provider<Api>;
7
5
  plugin: {
8
6
  id: string;
9
- contribute: {
10
- tools: ToolDefinition<{
11
- id: string;
12
- name: string;
13
- input: Record<string, unknown>;
14
- }, unknown>[];
15
- settings: SettingDefinition<boolean>[];
16
- };
17
7
  activate(api: {
18
8
  readonly side: "core";
19
9
  readonly sdk: import("@nyte-ai/core").Connection;