@ai-gui/vue 0.3.0 → 0.4.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.
package/dist/index.cjs CHANGED
@@ -73,19 +73,25 @@ function useActionState(runtime, key) {
73
73
  /** Host element for imperative `mount` outputs, wired to Vue's lifecycle. */
74
74
  const MountHost = (0, vue.defineComponent)({
75
75
  name: "MountHost",
76
- props: { mount: {
77
- type: Function,
78
- required: true
79
- } },
76
+ props: {
77
+ mount: {
78
+ type: Function,
79
+ required: true
80
+ },
81
+ context: {
82
+ type: Object,
83
+ required: true
84
+ }
85
+ },
80
86
  setup(props) {
81
87
  const elRef = (0, vue.ref)(null);
82
88
  let cleanup;
83
89
  (0, vue.onMounted)(() => {
84
- if (elRef.value) cleanup = props.mount(elRef.value);
90
+ if (elRef.value) cleanup = props.mount(elRef.value, props.context);
85
91
  });
86
92
  (0, vue.watch)(() => props.mount, (mount) => {
87
93
  if (typeof cleanup === "function") cleanup();
88
- cleanup = elRef.value ? mount(elRef.value) : void 0;
94
+ cleanup = elRef.value ? mount(elRef.value, props.context) : void 0;
89
95
  });
90
96
  (0, vue.onBeforeUnmount)(() => {
91
97
  if (typeof cleanup === "function") cleanup();
@@ -97,11 +103,14 @@ const MountHost = (0, vue.defineComponent)({
97
103
  }
98
104
  });
99
105
  /** Translate a framework-neutral RenderOutput into a Vue VNode. */
100
- function renderOutput(out, sanitize) {
106
+ function renderOutput(out, sanitize, context = {}) {
101
107
  switch (out.kind) {
102
108
  case "html": return (0, vue.h)("div", { innerHTML: sanitizeOutput(out.html, sanitize) });
103
- case "element": return (0, vue.h)(out.tag, out.props, (out.children ?? []).map((child) => renderOutput(child, sanitize)));
104
- case "mount": return (0, vue.h)(MountHost, { mount: out.mount });
109
+ case "element": return (0, vue.h)(out.tag, out.props, (out.children ?? []).map((child) => renderOutput(child, sanitize, context)));
110
+ case "mount": return (0, vue.h)(MountHost, {
111
+ mount: out.mount,
112
+ context
113
+ });
105
114
  case "card": return (0, vue.h)("pre", { "data-aigui-card-fallback": "" }, [(0, vue.h)("code", JSON.stringify(out.data, null, 2))]);
106
115
  }
107
116
  }
@@ -116,6 +125,10 @@ const AsyncOutput = (0, vue.defineComponent)({
116
125
  sanitize: {
117
126
  type: [Boolean, Object],
118
127
  default: void 0
128
+ },
129
+ context: {
130
+ type: Object,
131
+ default: () => ({})
119
132
  }
120
133
  },
121
134
  setup(props) {
@@ -142,13 +155,42 @@ const AsyncOutput = (0, vue.defineComponent)({
142
155
  if (failed.value) return (0, vue.h)("span", { "data-aigui-async-error": "" });
143
156
  if (!resolved.value) return (0, vue.h)("span", { "data-aigui-async-pending": "" });
144
157
  try {
145
- return renderOutput(resolved.value, props.sanitize);
158
+ return renderOutput(resolved.value, props.sanitize, props.context);
146
159
  } catch {
147
160
  return (0, vue.h)("span", { "data-aigui-async-error": "" });
148
161
  }
149
162
  };
150
163
  }
151
164
  });
165
+ function createRenderMountContext(registry, onCardAction) {
166
+ return { mountCard(host, request) {
167
+ const component = registry?.getRender(request.type);
168
+ if (!component) return void 0;
169
+ const card = (0, vue.markRaw)((0, vue.toRaw)(component));
170
+ let data = request.data;
171
+ let destroyed = false;
172
+ const renderCard$1 = () => (0, vue.render)((0, vue.h)(card, {
173
+ data,
174
+ onAction: (action) => onCardAction?.({
175
+ ...action,
176
+ cardType: request.type
177
+ })
178
+ }), host);
179
+ renderCard$1();
180
+ return {
181
+ update(nextData) {
182
+ if (destroyed) return;
183
+ data = nextData;
184
+ renderCard$1();
185
+ },
186
+ destroy() {
187
+ if (destroyed) return;
188
+ destroyed = true;
189
+ (0, vue.render)(null, host);
190
+ }
191
+ };
192
+ } };
193
+ }
152
194
  function sanitizeOutput(html, sanitize) {
153
195
  if (sanitize === false) return html;
154
196
  return (0, __ai_gui_core.sanitizeHtml)(html, typeof sanitize === "object" ? sanitize : void 0);
@@ -166,12 +208,14 @@ function renderNode(node, ctx) {
166
208
  });
167
209
  try {
168
210
  const out = r(node);
211
+ const mountContext = createRenderMountContext(ctx.registry, ctx.onCardAction);
169
212
  if (out && typeof out.then === "function") return (0, vue.h)(AsyncOutput, {
170
213
  key: node.key,
171
214
  promise: out,
172
- sanitize: ctx.sanitize
215
+ sanitize: ctx.sanitize,
216
+ context: mountContext
173
217
  });
174
- const vnode = renderOutput(out, ctx.sanitize);
218
+ const vnode = renderOutput(out, ctx.sanitize, mountContext);
175
219
  vnode.key = node.key;
176
220
  return vnode;
177
221
  } catch {
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ShallowRef, VNode } from "vue";
2
- import { AIGuiPlugin, ASTNode, ActionRuntime, ActionState, CardRegistry, CardStore, FeedOptions, FeedSource, NodeRenderer, RenderOutput, Renderer, RendererOptions } from "@ai-gui/core";
2
+ import { AIGuiPlugin, ASTNode, ActionRuntime, ActionState, CardRegistry, CardStore, FeedOptions, FeedSource, NodeRenderer, RenderMountContext, RenderOutput, Renderer, RendererOptions } from "@ai-gui/core";
3
3
 
4
4
  //#region src/use-ai-renderer.d.ts
5
5
  interface UseAIRendererResult {
@@ -41,7 +41,7 @@ declare function renderNode(node: ASTNode, ctx: RenderContext): VNode;
41
41
  //#endregion
42
42
  //#region src/render-output.d.ts
43
43
  /** Translate a framework-neutral RenderOutput into a Vue VNode. */
44
- declare function renderOutput(out: RenderOutput, sanitize?: RendererOptions["sanitize"]): VNode;
44
+ declare function renderOutput(out: RenderOutput, sanitize?: RendererOptions["sanitize"], context?: RenderMountContext): VNode;
45
45
 
46
46
  //#endregion
47
47
  /** Await an async RenderOutput, rendering a placeholder until it resolves. */
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ShallowRef, VNode } from "vue";
2
- import { AIGuiPlugin, ASTNode, ActionRuntime, ActionState, CardRegistry, CardStore, FeedOptions, FeedSource, NodeRenderer, RenderOutput, Renderer, RendererOptions } from "@ai-gui/core";
2
+ import { AIGuiPlugin, ASTNode, ActionRuntime, ActionState, CardRegistry, CardStore, FeedOptions, FeedSource, NodeRenderer, RenderMountContext, RenderOutput, Renderer, RendererOptions } from "@ai-gui/core";
3
3
 
4
4
  //#region src/use-ai-renderer.d.ts
5
5
  interface UseAIRendererResult {
@@ -41,7 +41,7 @@ declare function renderNode(node: ASTNode, ctx: RenderContext): VNode;
41
41
  //#endregion
42
42
  //#region src/render-output.d.ts
43
43
  /** Translate a framework-neutral RenderOutput into a Vue VNode. */
44
- declare function renderOutput(out: RenderOutput, sanitize?: RendererOptions["sanitize"]): VNode;
44
+ declare function renderOutput(out: RenderOutput, sanitize?: RendererOptions["sanitize"], context?: RenderMountContext): VNode;
45
45
 
46
46
  //#endregion
47
47
  /** Await an async RenderOutput, rendering a placeholder until it resolves. */
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { defineComponent, h, markRaw, onBeforeUnmount, onMounted, onScopeDispose, ref, shallowRef, toRaw, watch } from "vue";
1
+ import { defineComponent, h, markRaw, onBeforeUnmount, onMounted, onScopeDispose, ref, render, shallowRef, toRaw, watch } from "vue";
2
2
  import { Renderer, collectNodeRenderers, sanitizeHtml } from "@ai-gui/core";
3
3
 
4
4
  //#region src/use-ai-renderer.ts
@@ -49,19 +49,25 @@ function useActionState(runtime, key) {
49
49
  /** Host element for imperative `mount` outputs, wired to Vue's lifecycle. */
50
50
  const MountHost = defineComponent({
51
51
  name: "MountHost",
52
- props: { mount: {
53
- type: Function,
54
- required: true
55
- } },
52
+ props: {
53
+ mount: {
54
+ type: Function,
55
+ required: true
56
+ },
57
+ context: {
58
+ type: Object,
59
+ required: true
60
+ }
61
+ },
56
62
  setup(props) {
57
63
  const elRef = ref(null);
58
64
  let cleanup;
59
65
  onMounted(() => {
60
- if (elRef.value) cleanup = props.mount(elRef.value);
66
+ if (elRef.value) cleanup = props.mount(elRef.value, props.context);
61
67
  });
62
68
  watch(() => props.mount, (mount) => {
63
69
  if (typeof cleanup === "function") cleanup();
64
- cleanup = elRef.value ? mount(elRef.value) : void 0;
70
+ cleanup = elRef.value ? mount(elRef.value, props.context) : void 0;
65
71
  });
66
72
  onBeforeUnmount(() => {
67
73
  if (typeof cleanup === "function") cleanup();
@@ -73,11 +79,14 @@ const MountHost = defineComponent({
73
79
  }
74
80
  });
75
81
  /** Translate a framework-neutral RenderOutput into a Vue VNode. */
76
- function renderOutput(out, sanitize) {
82
+ function renderOutput(out, sanitize, context = {}) {
77
83
  switch (out.kind) {
78
84
  case "html": return h("div", { innerHTML: sanitizeOutput(out.html, sanitize) });
79
- case "element": return h(out.tag, out.props, (out.children ?? []).map((child) => renderOutput(child, sanitize)));
80
- case "mount": return h(MountHost, { mount: out.mount });
85
+ case "element": return h(out.tag, out.props, (out.children ?? []).map((child) => renderOutput(child, sanitize, context)));
86
+ case "mount": return h(MountHost, {
87
+ mount: out.mount,
88
+ context
89
+ });
81
90
  case "card": return h("pre", { "data-aigui-card-fallback": "" }, [h("code", JSON.stringify(out.data, null, 2))]);
82
91
  }
83
92
  }
@@ -92,6 +101,10 @@ const AsyncOutput = defineComponent({
92
101
  sanitize: {
93
102
  type: [Boolean, Object],
94
103
  default: void 0
104
+ },
105
+ context: {
106
+ type: Object,
107
+ default: () => ({})
95
108
  }
96
109
  },
97
110
  setup(props) {
@@ -118,13 +131,42 @@ const AsyncOutput = defineComponent({
118
131
  if (failed.value) return h("span", { "data-aigui-async-error": "" });
119
132
  if (!resolved.value) return h("span", { "data-aigui-async-pending": "" });
120
133
  try {
121
- return renderOutput(resolved.value, props.sanitize);
134
+ return renderOutput(resolved.value, props.sanitize, props.context);
122
135
  } catch {
123
136
  return h("span", { "data-aigui-async-error": "" });
124
137
  }
125
138
  };
126
139
  }
127
140
  });
141
+ function createRenderMountContext(registry, onCardAction) {
142
+ return { mountCard(host, request) {
143
+ const component = registry?.getRender(request.type);
144
+ if (!component) return void 0;
145
+ const card = markRaw(toRaw(component));
146
+ let data = request.data;
147
+ let destroyed = false;
148
+ const renderCard$1 = () => render(h(card, {
149
+ data,
150
+ onAction: (action) => onCardAction?.({
151
+ ...action,
152
+ cardType: request.type
153
+ })
154
+ }), host);
155
+ renderCard$1();
156
+ return {
157
+ update(nextData) {
158
+ if (destroyed) return;
159
+ data = nextData;
160
+ renderCard$1();
161
+ },
162
+ destroy() {
163
+ if (destroyed) return;
164
+ destroyed = true;
165
+ render(null, host);
166
+ }
167
+ };
168
+ } };
169
+ }
128
170
  function sanitizeOutput(html, sanitize) {
129
171
  if (sanitize === false) return html;
130
172
  return sanitizeHtml(html, typeof sanitize === "object" ? sanitize : void 0);
@@ -142,12 +184,14 @@ function renderNode(node, ctx) {
142
184
  });
143
185
  try {
144
186
  const out = r(node);
187
+ const mountContext = createRenderMountContext(ctx.registry, ctx.onCardAction);
145
188
  if (out && typeof out.then === "function") return h(AsyncOutput, {
146
189
  key: node.key,
147
190
  promise: out,
148
- sanitize: ctx.sanitize
191
+ sanitize: ctx.sanitize,
192
+ context: mountContext
149
193
  });
150
- const vnode = renderOutput(out, ctx.sanitize);
194
+ const vnode = renderOutput(out, ctx.sanitize, mountContext);
151
195
  vnode.key = node.key;
152
196
  return vnode;
153
197
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-gui/vue",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Vue 3 adapter for AIGUI — stream LLM output into live Vue components with cards and plugins.",
5
5
  "keywords": [
6
6
  "llm",
@@ -51,7 +51,7 @@
51
51
  "access": "public"
52
52
  },
53
53
  "dependencies": {
54
- "@ai-gui/core": "0.3.0"
54
+ "@ai-gui/core": "0.4.1"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "vue": ">=3.3"