@ulearning/ai-generative-frame 0.0.0-stage → 1.0.0-next.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 (323) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +233 -2
  3. package/dist/assistant-ui/entry.d.ts +34 -0
  4. package/dist/assistant-ui/entry.d.ts.map +1 -0
  5. package/dist/assistant-ui/entry.js +50 -0
  6. package/dist/assistant-ui/entry.js.map +1 -0
  7. package/dist/assistant-ui/extension.d.ts +18 -0
  8. package/dist/assistant-ui/extension.d.ts.map +1 -0
  9. package/dist/assistant-ui/extension.js +0 -0
  10. package/dist/assistant-ui/history.d.ts +15 -0
  11. package/dist/assistant-ui/history.d.ts.map +1 -0
  12. package/dist/assistant-ui/history.js +39 -0
  13. package/dist/assistant-ui/history.js.map +1 -0
  14. package/dist/assistant-ui/modelContext.d.ts +45 -0
  15. package/dist/assistant-ui/modelContext.d.ts.map +1 -0
  16. package/dist/assistant-ui/modelContext.js +88 -0
  17. package/dist/assistant-ui/modelContext.js.map +1 -0
  18. package/dist/assistant-ui/snapshotSaver.d.ts +11 -0
  19. package/dist/assistant-ui/snapshotSaver.d.ts.map +1 -0
  20. package/dist/assistant-ui/snapshotSaver.js +83 -0
  21. package/dist/assistant-ui/snapshotSaver.js.map +1 -0
  22. package/dist/assistant-ui/tool-calls.d.ts +21 -0
  23. package/dist/assistant-ui/tool-calls.d.ts.map +1 -0
  24. package/dist/assistant-ui/tool-calls.js +65 -0
  25. package/dist/assistant-ui/tool-calls.js.map +1 -0
  26. package/dist/assistant-ui/toolkit.d.ts +96 -0
  27. package/dist/assistant-ui/toolkit.d.ts.map +1 -0
  28. package/dist/assistant-ui/toolkit.js +456 -0
  29. package/dist/assistant-ui/toolkit.js.map +1 -0
  30. package/dist/assistant-ui/useSharedContext.d.ts +14 -0
  31. package/dist/assistant-ui/useSharedContext.d.ts.map +1 -0
  32. package/dist/assistant-ui/useSharedContext.js +27 -0
  33. package/dist/assistant-ui/useSharedContext.js.map +1 -0
  34. package/dist/assistant-ui.d.ts +3 -0
  35. package/dist/assistant-ui.d.ts.map +1 -0
  36. package/dist/assistant-ui.js +1 -0
  37. package/dist/bootstrap.d.ts +23 -0
  38. package/dist/bootstrap.d.ts.map +1 -0
  39. package/dist/bootstrap.js +78 -0
  40. package/dist/bootstrap.js.map +1 -0
  41. package/dist/csp.d.ts +25 -0
  42. package/dist/csp.d.ts.map +1 -0
  43. package/dist/csp.js +78 -0
  44. package/dist/csp.js.map +1 -0
  45. package/dist/index.d.ts +6 -0
  46. package/dist/index.d.ts.map +1 -0
  47. package/dist/index.js +5 -0
  48. package/dist/json-schema.d.ts +70 -0
  49. package/dist/json-schema.d.ts.map +1 -0
  50. package/dist/json-schema.js +163 -0
  51. package/dist/json-schema.js.map +1 -0
  52. package/dist/preview.d.ts +30 -0
  53. package/dist/preview.d.ts.map +1 -0
  54. package/dist/preview.js +60 -0
  55. package/dist/preview.js.map +1 -0
  56. package/dist/prompts/guidance.d.ts +41 -0
  57. package/dist/prompts/guidance.d.ts.map +1 -0
  58. package/dist/prompts/guidance.js +268 -0
  59. package/dist/prompts/guidance.js.map +1 -0
  60. package/dist/prompts.d.ts +2 -0
  61. package/dist/prompts.d.ts.map +1 -0
  62. package/dist/prompts.js +1 -0
  63. package/dist/protocol.d.ts +114 -0
  64. package/dist/protocol.d.ts.map +1 -0
  65. package/dist/protocol.js +49 -0
  66. package/dist/protocol.js.map +1 -0
  67. package/dist/repair/repair.d.ts +72 -0
  68. package/dist/repair/repair.d.ts.map +1 -0
  69. package/dist/repair/repair.js +103 -0
  70. package/dist/repair/repair.js.map +1 -0
  71. package/dist/repair.d.ts +2 -0
  72. package/dist/repair.d.ts.map +1 -0
  73. package/dist/repair.js +1 -0
  74. package/dist/rpc.d.ts +60 -0
  75. package/dist/rpc.d.ts.map +1 -0
  76. package/dist/rpc.js +127 -0
  77. package/dist/rpc.js.map +1 -0
  78. package/dist/runtime/diagnostics.d.ts +17 -0
  79. package/dist/runtime/diagnostics.d.ts.map +1 -0
  80. package/dist/runtime/diagnostics.js +128 -0
  81. package/dist/runtime/diagnostics.js.map +1 -0
  82. package/dist/runtime/generated.d.ts +2 -0
  83. package/dist/runtime/generated.d.ts.map +1 -0
  84. package/dist/runtime/generated.js +5 -0
  85. package/dist/runtime/generated.js.map +1 -0
  86. package/dist/runtime/index.d.ts +7 -0
  87. package/dist/runtime/index.d.ts.map +1 -0
  88. package/dist/runtime/index.js +264 -0
  89. package/dist/runtime/index.js.map +1 -0
  90. package/dist/runtime/morph.d.ts +51 -0
  91. package/dist/runtime/morph.d.ts.map +1 -0
  92. package/dist/runtime/morph.js +251 -0
  93. package/dist/runtime/morph.js.map +1 -0
  94. package/dist/runtime/screenshot.d.ts +23 -0
  95. package/dist/runtime/screenshot.d.ts.map +1 -0
  96. package/dist/runtime/screenshot.js +188 -0
  97. package/dist/runtime/screenshot.js.map +1 -0
  98. package/dist/runtime/size.d.ts +10 -0
  99. package/dist/runtime/size.d.ts.map +1 -0
  100. package/dist/runtime/size.js +21 -0
  101. package/dist/runtime/size.js.map +1 -0
  102. package/dist/runtime/storage.d.ts +4 -0
  103. package/dist/runtime/storage.d.ts.map +1 -0
  104. package/dist/runtime/storage.js +38 -0
  105. package/dist/runtime/storage.js.map +1 -0
  106. package/dist/spec/actions.d.ts +40 -0
  107. package/dist/spec/actions.d.ts.map +1 -0
  108. package/dist/spec/actions.js +53 -0
  109. package/dist/spec/actions.js.map +1 -0
  110. package/dist/spec/assistant-ui/thread.d.ts +66 -0
  111. package/dist/spec/assistant-ui/thread.d.ts.map +1 -0
  112. package/dist/spec/assistant-ui/thread.js +252 -0
  113. package/dist/spec/assistant-ui/thread.js.map +1 -0
  114. package/dist/spec/assistant-ui/toolkit.d.ts +33 -0
  115. package/dist/spec/assistant-ui/toolkit.d.ts.map +1 -0
  116. package/dist/spec/assistant-ui/toolkit.js +142 -0
  117. package/dist/spec/assistant-ui/toolkit.js.map +1 -0
  118. package/dist/spec/assistant-ui/web.d.ts +6 -0
  119. package/dist/spec/assistant-ui/web.d.ts.map +1 -0
  120. package/dist/spec/assistant-ui/web.js +48 -0
  121. package/dist/spec/assistant-ui/web.js.map +1 -0
  122. package/dist/spec/assistant-ui.d.ts +3 -0
  123. package/dist/spec/assistant-ui.d.ts.map +1 -0
  124. package/dist/spec/assistant-ui.js +1 -0
  125. package/dist/spec/calc.d.ts +8 -0
  126. package/dist/spec/calc.d.ts.map +1 -0
  127. package/dist/spec/calc.js +498 -0
  128. package/dist/spec/calc.js.map +1 -0
  129. package/dist/spec/catalog.d.ts +52 -0
  130. package/dist/spec/catalog.d.ts.map +1 -0
  131. package/dist/spec/catalog.js +104 -0
  132. package/dist/spec/catalog.js.map +1 -0
  133. package/dist/spec/expressions.d.ts +45 -0
  134. package/dist/spec/expressions.d.ts.map +1 -0
  135. package/dist/spec/expressions.js +199 -0
  136. package/dist/spec/expressions.js.map +1 -0
  137. package/dist/spec/patch.d.ts +20 -0
  138. package/dist/spec/patch.d.ts.map +1 -0
  139. package/dist/spec/patch.js +77 -0
  140. package/dist/spec/patch.js.map +1 -0
  141. package/dist/spec/pending.d.ts +15 -0
  142. package/dist/spec/pending.d.ts.map +1 -0
  143. package/dist/spec/pending.js +33 -0
  144. package/dist/spec/pending.js.map +1 -0
  145. package/dist/spec/pointer.d.ts +17 -0
  146. package/dist/spec/pointer.d.ts.map +1 -0
  147. package/dist/spec/pointer.js +88 -0
  148. package/dist/spec/pointer.js.map +1 -0
  149. package/dist/spec/prompt.d.ts +29 -0
  150. package/dist/spec/prompt.d.ts.map +1 -0
  151. package/dist/spec/prompt.js +145 -0
  152. package/dist/spec/prompt.js.map +1 -0
  153. package/dist/spec/render-spec.d.ts +50 -0
  154. package/dist/spec/render-spec.d.ts.map +1 -0
  155. package/dist/spec/render-spec.js +104 -0
  156. package/dist/spec/render-spec.js.map +1 -0
  157. package/dist/spec/resolve.d.ts +39 -0
  158. package/dist/spec/resolve.d.ts.map +1 -0
  159. package/dist/spec/resolve.js +51 -0
  160. package/dist/spec/resolve.js.map +1 -0
  161. package/dist/spec/resolved.d.ts +3 -0
  162. package/dist/spec/resolved.d.ts.map +1 -0
  163. package/dist/spec/resolved.js +36 -0
  164. package/dist/spec/resolved.js.map +1 -0
  165. package/dist/spec/state.d.ts +34 -0
  166. package/dist/spec/state.d.ts.map +1 -0
  167. package/dist/spec/state.js +111 -0
  168. package/dist/spec/state.js.map +1 -0
  169. package/dist/spec/stream.d.ts +50 -0
  170. package/dist/spec/stream.d.ts.map +1 -0
  171. package/dist/spec/stream.js +168 -0
  172. package/dist/spec/stream.js.map +1 -0
  173. package/dist/spec/tools.d.ts +3 -0
  174. package/dist/spec/tools.d.ts.map +1 -0
  175. package/dist/spec/tools.js +3 -0
  176. package/dist/spec/tree.d.ts +21 -0
  177. package/dist/spec/tree.d.ts.map +1 -0
  178. package/dist/spec/tree.js +27 -0
  179. package/dist/spec/tree.js.map +1 -0
  180. package/dist/spec/types.d.ts +66 -0
  181. package/dist/spec/types.d.ts.map +1 -0
  182. package/dist/spec/types.js +9 -0
  183. package/dist/spec/types.js.map +1 -0
  184. package/dist/spec/validate.d.ts +32 -0
  185. package/dist/spec/validate.d.ts.map +1 -0
  186. package/dist/spec/validate.js +264 -0
  187. package/dist/spec/validate.js.map +1 -0
  188. package/dist/spec/vue/SpecRenderer.d.ts +43 -0
  189. package/dist/spec/vue/SpecRenderer.d.ts.map +1 -0
  190. package/dist/spec/vue/SpecRenderer.js +357 -0
  191. package/dist/spec/vue/SpecRenderer.js.map +1 -0
  192. package/dist/spec/vue/useSpecStream.d.ts +19 -0
  193. package/dist/spec/vue/useSpecStream.d.ts.map +1 -0
  194. package/dist/spec/vue/useSpecStream.js +115 -0
  195. package/dist/spec/vue/useSpecStream.js.map +1 -0
  196. package/dist/spec/vue.d.ts +3 -0
  197. package/dist/spec/vue.d.ts.map +1 -0
  198. package/dist/spec/vue.js +3 -0
  199. package/dist/spec.d.ts +12 -0
  200. package/dist/spec.d.ts.map +1 -0
  201. package/dist/spec.js +8 -0
  202. package/dist/theme.d.ts +38 -0
  203. package/dist/theme.d.ts.map +1 -0
  204. package/dist/theme.js +370 -0
  205. package/dist/theme.js.map +1 -0
  206. package/dist/tools/define.d.ts +43 -0
  207. package/dist/tools/define.d.ts.map +1 -0
  208. package/dist/tools/define.js +31 -0
  209. package/dist/tools/define.js.map +1 -0
  210. package/dist/tools/edits.d.ts +19 -0
  211. package/dist/tools/edits.d.ts.map +1 -0
  212. package/dist/tools/edits.js +55 -0
  213. package/dist/tools/edits.js.map +1 -0
  214. package/dist/tools/registry.d.ts +19 -0
  215. package/dist/tools/registry.d.ts.map +1 -0
  216. package/dist/tools/registry.js +33 -0
  217. package/dist/tools/registry.js.map +1 -0
  218. package/dist/tools/tools.d.ts +88 -0
  219. package/dist/tools/tools.d.ts.map +1 -0
  220. package/dist/tools/tools.js +235 -0
  221. package/dist/tools/tools.js.map +1 -0
  222. package/dist/tools.d.ts +5 -0
  223. package/dist/tools.d.ts.map +1 -0
  224. package/dist/tools.js +5 -0
  225. package/dist/version.d.ts +2 -0
  226. package/dist/version.d.ts.map +1 -0
  227. package/dist/version.js +5 -0
  228. package/dist/version.js.map +1 -0
  229. package/dist/vue/Widget.d.ts +16 -0
  230. package/dist/vue/Widget.d.ts.map +1 -0
  231. package/dist/vue/Widget.js +58 -0
  232. package/dist/vue/Widget.js.map +1 -0
  233. package/dist/vue/sync.d.ts +19 -0
  234. package/dist/vue/sync.d.ts.map +1 -0
  235. package/dist/vue/sync.js +31 -0
  236. package/dist/vue/sync.js.map +1 -0
  237. package/dist/vue/themeStore.d.ts +23 -0
  238. package/dist/vue/themeStore.d.ts.map +1 -0
  239. package/dist/vue/themeStore.js +115 -0
  240. package/dist/vue/themeStore.js.map +1 -0
  241. package/dist/vue/useThemeTokens.d.ts +6 -0
  242. package/dist/vue/useThemeTokens.d.ts.map +1 -0
  243. package/dist/vue/useThemeTokens.js +49 -0
  244. package/dist/vue/useThemeTokens.js.map +1 -0
  245. package/dist/vue/useWidget.d.ts +10 -0
  246. package/dist/vue/useWidget.d.ts.map +1 -0
  247. package/dist/vue/useWidget.js +81 -0
  248. package/dist/vue/useWidget.js.map +1 -0
  249. package/dist/vue.d.ts +5 -0
  250. package/dist/vue.d.ts.map +1 -0
  251. package/dist/vue.js +4 -0
  252. package/dist/widget.d.ts +129 -0
  253. package/dist/widget.d.ts.map +1 -0
  254. package/dist/widget.js +655 -0
  255. package/dist/widget.js.map +1 -0
  256. package/package.json +125 -3
  257. package/src/assistant-ui/entry.ts +124 -0
  258. package/src/assistant-ui/extension.ts +19 -0
  259. package/src/assistant-ui/history.ts +63 -0
  260. package/src/assistant-ui/modelContext.ts +162 -0
  261. package/src/assistant-ui/snapshotSaver.ts +116 -0
  262. package/src/assistant-ui/tool-calls.ts +115 -0
  263. package/src/assistant-ui/toolkit.tsx +747 -0
  264. package/src/assistant-ui/useSharedContext.ts +40 -0
  265. package/src/assistant-ui.ts +14 -0
  266. package/src/bootstrap.ts +112 -0
  267. package/src/csp.ts +96 -0
  268. package/src/index.ts +44 -0
  269. package/src/json-schema.ts +353 -0
  270. package/src/preview.ts +120 -0
  271. package/src/prompts/guidance.ts +369 -0
  272. package/src/prompts.ts +8 -0
  273. package/src/protocol.ts +141 -0
  274. package/src/repair/repair.ts +202 -0
  275. package/src/repair.ts +11 -0
  276. package/src/rpc.ts +228 -0
  277. package/src/runtime/diagnostics.ts +165 -0
  278. package/src/runtime/generated.ts +2 -0
  279. package/src/runtime/index.ts +343 -0
  280. package/src/runtime/morph.ts +352 -0
  281. package/src/runtime/screenshot.ts +288 -0
  282. package/src/runtime/size.ts +17 -0
  283. package/src/runtime/storage.ts +49 -0
  284. package/src/spec/actions.ts +111 -0
  285. package/src/spec/assistant-ui/thread.ts +381 -0
  286. package/src/spec/assistant-ui/toolkit.tsx +295 -0
  287. package/src/spec/assistant-ui/web.tsx +63 -0
  288. package/src/spec/assistant-ui.ts +2 -0
  289. package/src/spec/calc.ts +598 -0
  290. package/src/spec/catalog.ts +196 -0
  291. package/src/spec/expressions.ts +301 -0
  292. package/src/spec/patch.ts +112 -0
  293. package/src/spec/pending.ts +36 -0
  294. package/src/spec/pointer.ts +170 -0
  295. package/src/spec/prompt.ts +243 -0
  296. package/src/spec/render-spec.ts +144 -0
  297. package/src/spec/resolve.ts +123 -0
  298. package/src/spec/resolved.ts +53 -0
  299. package/src/spec/state.ts +193 -0
  300. package/src/spec/stream.ts +230 -0
  301. package/src/spec/tools.ts +17 -0
  302. package/src/spec/tree.ts +37 -0
  303. package/src/spec/types.ts +51 -0
  304. package/src/spec/validate.ts +429 -0
  305. package/src/spec/vue/SpecRenderer.tsx +544 -0
  306. package/src/spec/vue/__tests__/harness.ts +50 -0
  307. package/src/spec/vue/useSpecStream.ts +162 -0
  308. package/src/spec/vue.ts +13 -0
  309. package/src/spec.ts +55 -0
  310. package/src/theme.ts +423 -0
  311. package/src/tools/define.ts +65 -0
  312. package/src/tools/edits.ts +73 -0
  313. package/src/tools/registry.ts +44 -0
  314. package/src/tools/tools.ts +361 -0
  315. package/src/tools.ts +32 -0
  316. package/src/version.ts +4 -0
  317. package/src/vue/Widget.tsx +74 -0
  318. package/src/vue/sync.ts +36 -0
  319. package/src/vue/themeStore.ts +157 -0
  320. package/src/vue/useThemeTokens.ts +71 -0
  321. package/src/vue/useWidget.ts +117 -0
  322. package/src/vue.ts +8 -0
  323. package/src/widget.ts +1080 -0
@@ -0,0 +1,115 @@
1
+ import { DEFAULT_LIGHT_TOKENS, readThemeTokens } from "../theme.js";
2
+ // src/vue/themeStore.ts
3
+ const THEME_ATTRIBUTES = [
4
+ "class",
5
+ "data-theme",
6
+ "data-mode"
7
+ ];
8
+ const sameTokens = (a, b) => a.colorScheme === b.colorScheme && JSON.stringify(a.variables) === JSON.stringify(b.variables);
9
+ /** Runs `callback` on the next animation frame and returns a cancel function. */
10
+ const nextFrame = (callback) => {
11
+ if (typeof requestAnimationFrame === "function") {
12
+ const id = requestAnimationFrame(callback);
13
+ return () => cancelAnimationFrame(id);
14
+ }
15
+ const id = setTimeout(callback, 16);
16
+ return () => clearTimeout(id);
17
+ };
18
+ /**
19
+ * One reader per (element, sources, options): every subscriber shares one
20
+ * MutationObserver and one media listener, and a burst of mutations costs one
21
+ * `readThemeTokens` per animation frame.
22
+ */
23
+ function createThemeTokenStore(target, sources, options) {
24
+ const entry = {
25
+ tokens: void 0,
26
+ fresh: false,
27
+ listeners: /* @__PURE__ */ new Set(),
28
+ stop: void 0
29
+ };
30
+ const read = () => {
31
+ const next = readThemeTokens(target, sources);
32
+ if (entry.tokens && sameTokens(entry.tokens, next)) return false;
33
+ entry.tokens = next;
34
+ return true;
35
+ };
36
+ const start = () => {
37
+ let cancelFrame;
38
+ const update = () => {
39
+ cancelFrame = void 0;
40
+ if (read()) for (const listener of entry.listeners) listener();
41
+ };
42
+ const schedule = () => {
43
+ cancelFrame ??= nextFrame(update);
44
+ };
45
+ const doc = target.ownerDocument;
46
+ const observer = new MutationObserver(schedule);
47
+ observer.observe(doc.documentElement, {
48
+ attributes: true,
49
+ attributeFilter: [...THEME_ATTRIBUTES, "style"]
50
+ });
51
+ if (doc.body) observer.observe(doc.body, {
52
+ attributes: true,
53
+ attributeFilter: options.observeBodyStyle ? [...THEME_ATTRIBUTES, "style"] : THEME_ATTRIBUTES
54
+ });
55
+ if (target !== doc.documentElement && target !== doc.body) observer.observe(target, {
56
+ attributes: true,
57
+ attributeFilter: [...THEME_ATTRIBUTES, "style"]
58
+ });
59
+ const media = doc.defaultView?.matchMedia?.("(prefers-color-scheme: dark)");
60
+ media?.addEventListener("change", schedule);
61
+ schedule();
62
+ return () => {
63
+ observer.disconnect();
64
+ media?.removeEventListener("change", schedule);
65
+ cancelFrame?.();
66
+ };
67
+ };
68
+ return {
69
+ subscribe(listener) {
70
+ entry.listeners.add(listener);
71
+ entry.stop ??= start();
72
+ return () => {
73
+ entry.listeners.delete(listener);
74
+ if (entry.listeners.size === 0) {
75
+ entry.stop?.();
76
+ entry.stop = void 0;
77
+ entry.fresh = false;
78
+ }
79
+ };
80
+ },
81
+ getSnapshot() {
82
+ if (entry.stop && entry.tokens) return entry.tokens;
83
+ if (!entry.fresh) {
84
+ read();
85
+ entry.fresh = true;
86
+ queueMicrotask(() => {
87
+ entry.fresh = false;
88
+ });
89
+ }
90
+ return entry.tokens ?? DEFAULT_LIGHT_TOKENS;
91
+ },
92
+ get subscribers() {
93
+ return entry.listeners.size;
94
+ }
95
+ };
96
+ }
97
+ const stores = /* @__PURE__ */ new WeakMap();
98
+ /** The shared store for this element, sources, and options. */
99
+ function getThemeTokenStore(target, sources = {}, options = {}) {
100
+ const key = JSON.stringify([sources, options.observeBodyStyle ?? false]);
101
+ let byKey = stores.get(target);
102
+ if (!byKey) {
103
+ byKey = /* @__PURE__ */ new Map();
104
+ stores.set(target, byKey);
105
+ }
106
+ let store = byKey.get(key);
107
+ if (!store) {
108
+ store = createThemeTokenStore(target, sources, options);
109
+ byKey.set(key, store);
110
+ }
111
+ return store;
112
+ }
113
+ export { createThemeTokenStore, getThemeTokenStore };
114
+
115
+ //# sourceMappingURL=themeStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"themeStore.js","names":[],"sources":["../../src/vue/themeStore.ts"],"sourcesContent":["import {\n DEFAULT_LIGHT_TOKENS,\n readThemeTokens,\n type ThemeTokenSources,\n type ThemeTokens,\n} from \"../theme\";\n\nexport type ThemeObserveOptions = {\n /**\n * Also re-read when `<body>`'s `style` attribute changes. Off by default,\n * because scroll-lock and dialog libraries rewrite it constantly; turn it on\n * when the app sets theme variables through body styles.\n */\n observeBodyStyle?: boolean;\n};\n\nconst THEME_ATTRIBUTES = [\"class\", \"data-theme\", \"data-mode\"];\n\nconst sameTokens = (a: ThemeTokens, b: ThemeTokens) =>\n a.colorScheme === b.colorScheme &&\n JSON.stringify(a.variables) === JSON.stringify(b.variables);\n\n/** Runs `callback` on the next animation frame and returns a cancel function. */\nconst nextFrame = (callback: () => void): (() => void) => {\n if (typeof requestAnimationFrame === \"function\") {\n const id = requestAnimationFrame(callback);\n return () => cancelAnimationFrame(id);\n }\n const id = setTimeout(callback, 16);\n return () => clearTimeout(id);\n};\n\ntype Entry = {\n tokens: ThemeTokens | undefined;\n /** Snapshot read while nobody subscribes; valid for the current task. */\n fresh: boolean;\n listeners: Set<() => void>;\n stop: (() => void) | undefined;\n};\n\n/**\n * One reader per (element, sources, options): every subscriber shares one\n * MutationObserver and one media listener, and a burst of mutations costs one\n * `readThemeTokens` per animation frame.\n */\nexport function createThemeTokenStore(\n target: Element,\n sources: ThemeTokenSources,\n options: ThemeObserveOptions,\n) {\n const entry: Entry = {\n tokens: undefined,\n fresh: false,\n listeners: new Set(),\n stop: undefined,\n };\n\n const read = () => {\n const next = readThemeTokens(target, sources);\n if (entry.tokens && sameTokens(entry.tokens, next)) return false;\n entry.tokens = next;\n return true;\n };\n\n const start = () => {\n let cancelFrame: (() => void) | undefined;\n const update = () => {\n cancelFrame = undefined;\n if (read()) for (const listener of entry.listeners) listener();\n };\n const schedule = () => {\n cancelFrame ??= nextFrame(update);\n };\n const doc = target.ownerDocument;\n const observer = new MutationObserver(schedule);\n observer.observe(doc.documentElement, {\n attributes: true,\n attributeFilter: [...THEME_ATTRIBUTES, \"style\"],\n });\n if (doc.body) {\n observer.observe(doc.body, {\n attributes: true,\n attributeFilter: options.observeBodyStyle\n ? [...THEME_ATTRIBUTES, \"style\"]\n : THEME_ATTRIBUTES,\n });\n }\n if (target !== doc.documentElement && target !== doc.body) {\n observer.observe(target, {\n attributes: true,\n attributeFilter: [...THEME_ATTRIBUTES, \"style\"],\n });\n }\n const media = doc.defaultView?.matchMedia?.(\"(prefers-color-scheme: dark)\");\n media?.addEventListener(\"change\", schedule);\n // Anything that changed between the last read and now.\n schedule();\n return () => {\n observer.disconnect();\n media?.removeEventListener(\"change\", schedule);\n cancelFrame?.();\n };\n };\n\n return {\n subscribe(listener: () => void) {\n entry.listeners.add(listener);\n entry.stop ??= start();\n return () => {\n entry.listeners.delete(listener);\n if (entry.listeners.size === 0) {\n entry.stop?.();\n entry.stop = undefined;\n entry.fresh = false;\n }\n };\n },\n getSnapshot(): ThemeTokens {\n if (entry.stop && entry.tokens) return entry.tokens;\n if (!entry.fresh) {\n read();\n entry.fresh = true;\n queueMicrotask(() => {\n entry.fresh = false;\n });\n }\n return entry.tokens ?? DEFAULT_LIGHT_TOKENS;\n },\n get subscribers() {\n return entry.listeners.size;\n },\n };\n}\n\nexport type ThemeTokenStore = ReturnType<typeof createThemeTokenStore>;\n\nconst stores = new WeakMap<Element, Map<string, ThemeTokenStore>>();\n\n/** The shared store for this element, sources, and options. */\nexport function getThemeTokenStore(\n target: Element,\n sources: ThemeTokenSources = {},\n options: ThemeObserveOptions = {},\n): ThemeTokenStore {\n const key = JSON.stringify([sources, options.observeBodyStyle ?? false]);\n let byKey = stores.get(target);\n if (!byKey) {\n byKey = new Map();\n stores.set(target, byKey);\n }\n let store = byKey.get(key);\n if (!store) {\n store = createThemeTokenStore(target, sources, options);\n byKey.set(key, store);\n }\n return store;\n}\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { type MaybeRefOrGetter, type ShallowRef } from "vue";
2
+ import { type ThemeTokenSources, type ThemeTokens } from "../theme.js";
3
+ import { type ThemeObserveOptions } from "./themeStore.js";
4
+ /** One shared observer per element/source/options; subscriptions follow the component lifecycle. */
5
+ export declare function useThemeTokens(element?: MaybeRefOrGetter<Element | null | undefined>, sources?: ThemeTokenSources, options?: ThemeObserveOptions): Readonly<ShallowRef<ThemeTokens>>;
6
+ //# sourceMappingURL=useThemeTokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useThemeTokens.d.ts","mappings":"AAAA,OAAO,EAUL,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAChB,MAAM,KAAK;AACZ,OAAO,EAEL,KAAK,iBAAiB,EACtB,KAAK,WAAW,EACjB,MAAM,aAAU;AACjB,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,iBAAc;AAC3E;AACA,wBAAgB,cAAc,CAC5B,OAAO,CAAC,EAAE,gBAAgB,CAAC,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,EACtD,OAAO,CAAC,EAAE,iBAAiB,EAC3B,OAAO,GAAE,mBAAwB,GAChC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC","names":[],"ignoreList":[],"sources":["../../src/vue/useThemeTokens.ts"],"sourcesContent":[null]}
@@ -0,0 +1,49 @@
1
+ import { DEFAULT_LIGHT_TOKENS } from "../theme.js";
2
+ import { getThemeTokenStore } from "./themeStore.js";
3
+ import { onActivated, onBeforeUnmount, onDeactivated, onMounted, onServerPrefetch, readonly, shallowRef, toValue, watch } from "vue";
4
+ // src/vue/useThemeTokens.ts
5
+ /** One shared observer per element/source/options; subscriptions follow the component lifecycle. */
6
+ function useThemeTokens(element, sources, options = {}) {
7
+ const target = () => toValue(element) ?? (typeof document === "undefined" ? void 0 : document.documentElement);
8
+ const tokens = shallowRef(target() ? getThemeTokenStore(target(), sources, options).getSnapshot() : DEFAULT_LIGHT_TOKENS);
9
+ let stop;
10
+ let active = false;
11
+ const disconnect = () => {
12
+ stop?.();
13
+ stop = void 0;
14
+ };
15
+ const connect = () => {
16
+ disconnect();
17
+ const current = target();
18
+ if (!active || !current) return;
19
+ const store = getThemeTokenStore(current, sources, options);
20
+ tokens.value = store.getSnapshot();
21
+ stop = store.subscribe(() => {
22
+ tokens.value = store.getSnapshot();
23
+ });
24
+ };
25
+ onServerPrefetch(() => {
26
+ tokens.value = DEFAULT_LIGHT_TOKENS;
27
+ });
28
+ onMounted(() => {
29
+ active = true;
30
+ connect();
31
+ });
32
+ onActivated(() => {
33
+ active = true;
34
+ connect();
35
+ });
36
+ onDeactivated(() => {
37
+ active = false;
38
+ disconnect();
39
+ });
40
+ onBeforeUnmount(() => {
41
+ active = false;
42
+ disconnect();
43
+ });
44
+ watch(target, connect, { flush: "post" });
45
+ return readonly(tokens);
46
+ }
47
+ export { useThemeTokens };
48
+
49
+ //# sourceMappingURL=useThemeTokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useThemeTokens.js","names":[],"sources":["../../src/vue/useThemeTokens.ts"],"sourcesContent":["import {\n onActivated,\n onBeforeUnmount,\n onDeactivated,\n onMounted,\n onServerPrefetch,\n readonly,\n shallowRef,\n toValue,\n watch,\n type MaybeRefOrGetter,\n type ShallowRef,\n} from \"vue\";\nimport {\n DEFAULT_LIGHT_TOKENS,\n type ThemeTokenSources,\n type ThemeTokens,\n} from \"../theme\";\nimport { getThemeTokenStore, type ThemeObserveOptions } from \"./themeStore\";\n/** One shared observer per element/source/options; subscriptions follow the component lifecycle. */\nexport function useThemeTokens(\n element?: MaybeRefOrGetter<Element | null | undefined>,\n sources?: ThemeTokenSources,\n options: ThemeObserveOptions = {},\n): Readonly<ShallowRef<ThemeTokens>> {\n const target = () =>\n toValue(element) ??\n (typeof document === \"undefined\" ? undefined : document.documentElement);\n const tokens = shallowRef(\n target()\n ? getThemeTokenStore(target()!, sources, options).getSnapshot()\n : DEFAULT_LIGHT_TOKENS,\n );\n let stop: (() => void) | undefined;\n let active = false;\n const disconnect = () => {\n stop?.();\n stop = undefined;\n };\n const connect = () => {\n disconnect();\n const current = target();\n if (!active || !current) return;\n const store = getThemeTokenStore(current, sources, options);\n tokens.value = store.getSnapshot();\n stop = store.subscribe(() => {\n tokens.value = store.getSnapshot();\n });\n };\n onServerPrefetch(() => {\n tokens.value = DEFAULT_LIGHT_TOKENS;\n });\n onMounted(() => {\n active = true;\n connect();\n });\n onActivated(() => {\n active = true;\n connect();\n });\n onDeactivated(() => {\n active = false;\n disconnect();\n });\n onBeforeUnmount(() => {\n active = false;\n disconnect();\n });\n watch(target, connect, { flush: \"post\" });\n return readonly(tokens);\n}\n"],"mappings":";;;;;AAoBA,SAAgB,eACd,SACA,SACA,UAA+B,CAAC,GACG;CACnC,MAAM,eACJ,QAAQ,OAAO,MACd,OAAO,aAAa,cAAc,KAAA,IAAY,SAAS;CAC1D,MAAM,SAAS,WACb,OAAO,IACH,mBAAmB,OAAO,GAAI,SAAS,OAAO,CAAC,CAAC,YAAY,IAC5D,oBACN;CACA,IAAI;CACJ,IAAI,SAAS;CACb,MAAM,mBAAmB;EACvB,OAAO;EACP,OAAO,KAAA;CACT;CACA,MAAM,gBAAgB;EACpB,WAAW;EACX,MAAM,UAAU,OAAO;EACvB,IAAI,CAAC,UAAU,CAAC,SAAS;EACzB,MAAM,QAAQ,mBAAmB,SAAS,SAAS,OAAO;EAC1D,OAAO,QAAQ,MAAM,YAAY;EACjC,OAAO,MAAM,gBAAgB;GAC3B,OAAO,QAAQ,MAAM,YAAY;EACnC,CAAC;CACH;CACA,uBAAuB;EACrB,OAAO,QAAQ;CACjB,CAAC;CACD,gBAAgB;EACd,SAAS;EACT,QAAQ;CACV,CAAC;CACD,kBAAkB;EAChB,SAAS;EACT,QAAQ;CACV,CAAC;CACD,oBAAoB;EAClB,SAAS;EACT,WAAW;CACb,CAAC;CACD,sBAAsB;EACpB,SAAS;EACT,WAAW;CACb,CAAC;CACD,MAAM,QAAQ,SAAS,EAAE,OAAO,OAAO,CAAC;CACxC,OAAO,SAAS,MAAM;AACxB"}
@@ -0,0 +1,10 @@
1
+ import { type ComponentPublicInstance, type MaybeRefOrGetter, type ShallowRef } from "vue";
2
+ import { type CreateWidgetOptions, type WidgetHandle } from "../widget.js";
3
+ export type UseWidgetOptions = Omit<CreateWidgetOptions, "container" | "code">;
4
+ export type UseWidgetResult = {
5
+ ref: (element: Element | ComponentPublicInstance | null) => void;
6
+ widget: Readonly<ShallowRef<WidgetHandle | null>>;
7
+ };
8
+ /** Mount options are read per activation. Handlers and tokens follow the latest options. */
9
+ export declare function useWidget(options?: MaybeRefOrGetter<UseWidgetOptions>): UseWidgetResult;
10
+ //# sourceMappingURL=useWidget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWidget.d.ts","mappings":"AAAA,OAAO,EASL,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAChB,MAAM,KAAK;AAEZ,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,YAAY,EAElB,MAAM,cAAW;AAElB,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,EAAE,WAAW,GAAG,MAAM,CAAC;AAC9E,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,GAAG,uBAAuB,GAAG,IAAI,KAAK,IAAI;IAChE,MAAM,EAAE,QAAQ,CAAC,UAAU,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;CAClD;AAgBD;AACA,wBAAgB,SAAS,CACvB,OAAO,GAAE,gBAAgB,CAAC,gBAAgB,CAAM,GAC/C,eAAe","names":[],"ignoreList":[],"sources":["../../src/vue/useWidget.ts"],"sourcesContent":[null]}
@@ -0,0 +1,81 @@
1
+ import { RPC_ERROR, RpcError } from "../rpc.js";
2
+ import { createWidget } from "../widget.js";
3
+ import { onActivated, onBeforeUnmount, onDeactivated, onMounted, shallowReadonly, shallowRef, toValue, watch } from "vue";
4
+ // src/vue/useWidget.ts
5
+ const HANDLER_KEYS = Object.keys({
6
+ onPrompt: true,
7
+ onMessage: true,
8
+ onOpenLink: true,
9
+ onCallTool: true,
10
+ onInitialized: true,
11
+ onRequestDisplayMode: true,
12
+ onUpdateModelContext: true,
13
+ onCopyText: true,
14
+ onWidgetState: true,
15
+ onResize: true,
16
+ onError: true,
17
+ onLog: true
18
+ });
19
+ /** Mount options are read per activation. Handlers and tokens follow the latest options. */
20
+ function useWidget(options = {}) {
21
+ const element = shallowRef(null);
22
+ const active = shallowRef(false);
23
+ const widget = shallowRef(null);
24
+ let widgetState;
25
+ let sentTokens;
26
+ onMounted(() => {
27
+ active.value = true;
28
+ });
29
+ onActivated(() => {
30
+ active.value = true;
31
+ });
32
+ onDeactivated(() => {
33
+ active.value = false;
34
+ });
35
+ onBeforeUnmount(() => {
36
+ active.value = false;
37
+ });
38
+ watch([element, active], ([container, enabled], _previous, onCleanup) => {
39
+ if (!container || !enabled) return;
40
+ const initial = toValue(options);
41
+ const handlers = {};
42
+ for (const key of HANDLER_KEYS) {
43
+ if (!initial[key]) continue;
44
+ handlers[key] = (...args) => {
45
+ const handler = toValue(options)[key];
46
+ if (!handler) throw new RpcError(RPC_ERROR.methodNotFound, `${key} is no longer handled`);
47
+ return handler(...args);
48
+ };
49
+ }
50
+ const handle = createWidget({
51
+ ...initial,
52
+ ...handlers,
53
+ ...widgetState ? { initialState: widgetState.value } : {},
54
+ onWidgetState: (state) => {
55
+ widgetState = { value: state };
56
+ toValue(options).onWidgetState?.(state);
57
+ },
58
+ container
59
+ });
60
+ sentTokens = initial.tokens;
61
+ widget.value = handle;
62
+ onCleanup(() => {
63
+ widget.value = null;
64
+ handle.dispose();
65
+ });
66
+ }, { flush: "sync" });
67
+ watch(() => toValue(options).tokens, (tokens) => {
68
+ if (!widget.value || !tokens || sentTokens === tokens) return;
69
+ sentTokens = tokens;
70
+ widget.value.setTheme(tokens);
71
+ }, { flush: "post" });
72
+ return {
73
+ ref: (next) => {
74
+ element.value = next instanceof HTMLElement ? next : null;
75
+ },
76
+ widget: shallowReadonly(widget)
77
+ };
78
+ }
79
+ export { useWidget };
80
+
81
+ //# sourceMappingURL=useWidget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWidget.js","names":[],"sources":["../../src/vue/useWidget.ts"],"sourcesContent":["import {\n onActivated,\n onBeforeUnmount,\n onDeactivated,\n onMounted,\n shallowReadonly,\n shallowRef,\n toValue,\n watch,\n type ComponentPublicInstance,\n type MaybeRefOrGetter,\n type ShallowRef,\n} from \"vue\";\nimport { RPC_ERROR, RpcError } from \"../rpc\";\nimport {\n createWidget,\n type CreateWidgetOptions,\n type WidgetHandle,\n type WidgetHandlers,\n} from \"../widget\";\n\nexport type UseWidgetOptions = Omit<CreateWidgetOptions, \"container\" | \"code\">;\nexport type UseWidgetResult = {\n ref: (element: Element | ComponentPublicInstance | null) => void;\n widget: Readonly<ShallowRef<WidgetHandle | null>>;\n};\nconst HANDLER_KEYS = Object.keys({\n onPrompt: true,\n onMessage: true,\n onOpenLink: true,\n onCallTool: true,\n onInitialized: true,\n onRequestDisplayMode: true,\n onUpdateModelContext: true,\n onCopyText: true,\n onWidgetState: true,\n onResize: true,\n onError: true,\n onLog: true,\n} satisfies Record<keyof WidgetHandlers, true>) as (keyof WidgetHandlers)[];\n\n/** Mount options are read per activation. Handlers and tokens follow the latest options. */\nexport function useWidget(\n options: MaybeRefOrGetter<UseWidgetOptions> = {},\n): UseWidgetResult {\n const element = shallowRef<HTMLElement | null>(null);\n const active = shallowRef(false);\n const widget = shallowRef<WidgetHandle | null>(null);\n let widgetState: { value: unknown } | undefined;\n let sentTokens: UseWidgetOptions[\"tokens\"];\n onMounted(() => {\n active.value = true;\n });\n onActivated(() => {\n active.value = true;\n });\n onDeactivated(() => {\n active.value = false;\n });\n onBeforeUnmount(() => {\n active.value = false;\n });\n watch(\n [element, active],\n ([container, enabled], _previous, onCleanup) => {\n if (!container || !enabled) return;\n const initial = toValue(options);\n const handlers: Record<string, unknown> = {};\n for (const key of HANDLER_KEYS) {\n if (!initial[key]) continue;\n handlers[key] = (...args: unknown[]) => {\n const handler = toValue(options)[key] as\n | ((...args: unknown[]) => unknown)\n | undefined;\n if (!handler)\n throw new RpcError(\n RPC_ERROR.methodNotFound,\n `${key} is no longer handled`,\n );\n return handler(...args);\n };\n }\n const handle = createWidget({\n ...initial,\n ...(handlers as WidgetHandlers),\n ...(widgetState ? { initialState: widgetState.value } : {}),\n onWidgetState: (state) => {\n widgetState = { value: state };\n toValue(options).onWidgetState?.(state);\n },\n container,\n });\n sentTokens = initial.tokens;\n widget.value = handle;\n onCleanup(() => {\n widget.value = null;\n handle.dispose();\n });\n },\n { flush: \"sync\" },\n );\n watch(\n () => toValue(options).tokens,\n (tokens) => {\n if (!widget.value || !tokens || sentTokens === tokens) return;\n sentTokens = tokens;\n widget.value.setTheme(tokens);\n },\n { flush: \"post\" },\n );\n return {\n ref: (next) => {\n element.value = next instanceof HTMLElement ? next : null;\n },\n widget: shallowReadonly(widget),\n };\n}\n"],"mappings":";;;;AA0BA,MAAM,eAAe,OAAO,KAAK;CAC/B,UAAU;CACV,WAAW;CACX,YAAY;CACZ,YAAY;CACZ,eAAe;CACf,sBAAsB;CACtB,sBAAsB;CACtB,YAAY;CACZ,eAAe;CACf,UAAU;CACV,SAAS;CACT,OAAO;AACT,CAA8C;;AAG9C,SAAgB,UACd,UAA8C,CAAC,GAC9B;CACjB,MAAM,UAAU,WAA+B,IAAI;CACnD,MAAM,SAAS,WAAW,KAAK;CAC/B,MAAM,SAAS,WAAgC,IAAI;CACnD,IAAI;CACJ,IAAI;CACJ,gBAAgB;EACd,OAAO,QAAQ;CACjB,CAAC;CACD,kBAAkB;EAChB,OAAO,QAAQ;CACjB,CAAC;CACD,oBAAoB;EAClB,OAAO,QAAQ;CACjB,CAAC;CACD,sBAAsB;EACpB,OAAO,QAAQ;CACjB,CAAC;CACD,MACE,CAAC,SAAS,MAAM,IACf,CAAC,WAAW,UAAU,WAAW,cAAc;EAC9C,IAAI,CAAC,aAAa,CAAC,SAAS;EAC5B,MAAM,UAAU,QAAQ,OAAO;EAC/B,MAAM,WAAoC,CAAC;EAC3C,KAAK,MAAM,OAAO,cAAc;GAC9B,IAAI,CAAC,QAAQ,MAAM;GACnB,SAAS,QAAQ,GAAG,SAAoB;IACtC,MAAM,UAAU,QAAQ,OAAO,CAAC,CAAC;IAGjC,IAAI,CAAC,SACH,MAAM,IAAI,SACR,UAAU,gBACV,GAAG,IAAI,sBACT;IACF,OAAO,QAAQ,GAAG,IAAI;GACxB;EACF;EACA,MAAM,SAAS,aAAa;GAC1B,GAAG;GACH,GAAI;GACJ,GAAI,cAAc,EAAE,cAAc,YAAY,MAAM,IAAI,CAAC;GACzD,gBAAgB,UAAU;IACxB,cAAc,EAAE,OAAO,MAAM;IAC7B,QAAQ,OAAO,CAAC,CAAC,gBAAgB,KAAK;GACxC;GACA;EACF,CAAC;EACD,aAAa,QAAQ;EACrB,OAAO,QAAQ;EACf,gBAAgB;GACd,OAAO,QAAQ;GACf,OAAO,QAAQ;EACjB,CAAC;CACH,GACA,EAAE,OAAO,OAAO,CAClB;CACA,YACQ,QAAQ,OAAO,CAAC,CAAC,SACtB,WAAW;EACV,IAAI,CAAC,OAAO,SAAS,CAAC,UAAU,eAAe,QAAQ;EACvD,aAAa;EACb,OAAO,MAAM,SAAS,MAAM;CAC9B,GACA,EAAE,OAAO,OAAO,CAClB;CACA,OAAO;EACL,MAAM,SAAS;GACb,QAAQ,QAAQ,gBAAgB,cAAc,OAAO;EACvD;EACA,QAAQ,gBAAgB,MAAM;CAChC;AACF"}
package/dist/vue.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ export { Widget, type WidgetProps } from "./vue/Widget.js";
2
+ export { useWidget, type UseWidgetOptions, type UseWidgetResult, } from "./vue/useWidget.js";
3
+ export { useThemeTokens } from "./vue/useThemeTokens.js";
4
+ export type { ThemeObserveOptions } from "./vue/themeStore.js";
5
+ //# sourceMappingURL=vue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vue.d.ts","mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,iBAAc;AACvD,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,oBAAiB;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAsB;AACrD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAkB","names":[],"ignoreList":[],"sources":["../src/vue.ts"],"sourcesContent":[null]}
package/dist/vue.js ADDED
@@ -0,0 +1,4 @@
1
+ import { useThemeTokens } from "./vue/useThemeTokens.js";
2
+ import { useWidget } from "./vue/useWidget.js";
3
+ import { Widget } from "./vue/Widget.js";
4
+ export { Widget, useThemeTokens, useWidget };
@@ -0,0 +1,129 @@
1
+ import { SafeContentFrame } from "@ulearning/ai-safe-content-frame";
2
+ import type { CspOptions } from "./csp.js";
3
+ import { type ClearStorageResult, type ConsoleEntry, type DisplayMode, type EndResult, type FrameInspection, type HostContext, type McpAppInitializeParams, type ScreenshotOptions, type WidgetError, type WidgetSize } from "./protocol.js";
4
+ import { type ThemeTokens } from "./theme.js";
5
+ export type UiMessageParams = {
6
+ role?: string;
7
+ content?: {
8
+ type: string;
9
+ text?: string;
10
+ }[];
11
+ [key: string]: unknown;
12
+ };
13
+ export type ToolCallRequest = {
14
+ name: string;
15
+ arguments?: Record<string, unknown>;
16
+ };
17
+ export type WidgetHandlers = {
18
+ /** A widget called `sendPrompt(text)`, possibly without a user gesture; let the user review it before it is sent as their message. */
19
+ onPrompt?: (text: string) => unknown;
20
+ /** Raw MCP Apps `ui/message`. Takes precedence over `onPrompt`. */
21
+ onMessage?: (params: UiMessageParams) => unknown;
22
+ /** Defaults to opening an `http(s)` URL in a new tab with `noopener`. */
23
+ onOpenLink?: (url: string) => unknown;
24
+ onCallTool?: (call: ToolCallRequest) => unknown;
25
+ onInitialized?: (params: McpAppInitializeParams) => void;
26
+ onRequestDisplayMode?: (request: {
27
+ mode: DisplayMode;
28
+ }) => unknown;
29
+ onUpdateModelContext?: (params: unknown) => unknown;
30
+ /** A widget called `genframe.copyText(text)` or `navigator.clipboard.writeText(text)`. The request alone does not show the user asked for the copy, so confirm with them, such as through a Copy control the host renders, before writing the clipboard. Without it, copying fails in the widget. */
31
+ onCopyText?: (text: string) => unknown;
32
+ onWidgetState?: (state: unknown) => void;
33
+ onResize?: (size: WidgetSize) => void;
34
+ onError?: (error: WidgetError) => void;
35
+ onLog?: (entry: ConsoleEntry) => void;
36
+ };
37
+ export type CreateWidgetOptions = WidgetHandlers & {
38
+ container: HTMLElement;
39
+ /** Scopes the frame origin, see `SafeContentFrame`. Defaults to `"generative-frame"`. */
40
+ product?: string;
41
+ /** A preconfigured `SafeContentFrame`, for example with `useShadowDom`. */
42
+ frame?: SafeContentFrame;
43
+ /**
44
+ * Loads the Safe Content Frame shim from a domain you host instead of
45
+ * the default service. Widgets are isolated from your app and from each
46
+ * other only when the domain is a public suffix on the Public Suffix List.
47
+ */
48
+ unsafeShimDomain?: string;
49
+ /**
50
+ * Renders in a `sandbox="allow-scripts"` frame with an opaque (`null`)
51
+ * origin instead of Safe Content Frame: no shim domain, and no storage or
52
+ * cookies. Cannot be combined with `id`, `frame`, or `unsafeShimDomain`.
53
+ */
54
+ opaqueOrigin?: boolean;
55
+ /**
56
+ * Gives the widget a stable origin, so its localStorage, IndexedDB, and
57
+ * cookies persist across reloads for this id on this host origin. Choose
58
+ * it on the host (never from model output); widgets with the same id share
59
+ * storage. Without an id, every frame gets a fresh origin.
60
+ */
61
+ id?: string;
62
+ csp?: CspOptions | string;
63
+ tokens?: ThemeTokens;
64
+ /** Extra host context fields (locale, display mode, …) merged over the theme. */
65
+ context?: HostContext;
66
+ animate?: boolean;
67
+ css?: string;
68
+ /** The iframe never grows past this height; taller content scrolls inside it. */
69
+ maxHeight?: number;
70
+ minHeight?: number;
71
+ readyTimeoutMs?: number;
72
+ initialState?: unknown;
73
+ /** Complete code to render immediately, as `write(code)` then `end()`. */
74
+ code?: string;
75
+ };
76
+ export type WidgetInspection = FrameInspection & {
77
+ code: string;
78
+ };
79
+ export type Screenshot = {
80
+ dataUrl: string;
81
+ width: number;
82
+ height: number;
83
+ };
84
+ export type WidgetEventMap = {
85
+ ready: undefined;
86
+ resize: WidgetSize;
87
+ error: WidgetError;
88
+ log: ConsoleEntry;
89
+ end: EndResult;
90
+ };
91
+ export type WidgetHandle = {
92
+ /** Resolves once the frame runtime is connected; rejects if it never connects. */
93
+ readonly ready: Promise<void>;
94
+ /** All code written so far. */
95
+ readonly code: string;
96
+ readonly ended: boolean;
97
+ readonly iframe: HTMLIFrameElement | undefined;
98
+ /** Appends streamed code. Rendering is coalesced to animation frames. */
99
+ write(chunk: string): void;
100
+ /** Marks the code complete and runs held scripts in order. */
101
+ end(): Promise<EndResult>;
102
+ /** Renders new complete code, morphing in place or remounting when scripts already ran. A newer call removes a remount still in progress, whose promise rejects. */
103
+ replace(code: string): Promise<EndResult>;
104
+ setTheme(tokens: ThemeTokens): void;
105
+ setContext(context: HostContext): void;
106
+ notifyToolInput(args: Record<string, unknown>, options?: {
107
+ partial?: boolean;
108
+ }): void;
109
+ notifyToolResult(result: unknown): void;
110
+ screenshot(options?: ScreenshotOptions): Promise<Screenshot>;
111
+ inspect(): Promise<WidgetInspection>;
112
+ on<K extends keyof WidgetEventMap>(event: K, listener: (payload: WidgetEventMap[K]) => void): () => void;
113
+ dispose(): void;
114
+ };
115
+ /** The Safe Content Frame salt behind a widget id's stable origin. */
116
+ export declare const widgetStorageSalt: (id: string) => string;
117
+ /**
118
+ * Mounts a widget frame in `container`. The frame loads a bootstrap document
119
+ * once through Safe Content Frame; code then streams in over a private
120
+ * `MessagePort`, so every chunk renders without reloading the frame.
121
+ */
122
+ export declare function createWidget(options: CreateWidgetOptions): WidgetHandle;
123
+ /**
124
+ * Clears what widgets with this `id` stored (localStorage, sessionStorage,
125
+ * IndexedDB, Cache Storage, and cookies) by loading a hidden frame on the
126
+ * same origin. Resolves with the storage kinds that were cleared.
127
+ */
128
+ export declare function clearWidgetStorage(id: string, options?: Pick<CreateWidgetOptions, "product" | "unsafeShimDomain" | "readyTimeoutMs">): Promise<ClearStorageResult>;
129
+ //# sourceMappingURL=widget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget.d.ts","mappings":"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","names":[],"ignoreList":[],"sources":["../src/widget.ts"],"sourcesContent":[null]}