@ycodium-ai/plugin-visualize 0.0.0-stage → 0.2.2942

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,3 +1,66 @@
1
- # Temporary Holding Version
1
+ # @ycodium-ai/plugin-visualize
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Puts an interactive HTML card in the conversation when an agent calls `visualize_visualize`.
4
+
5
+ ## What it does
6
+
7
+ The agent passes an inline HTML fragment. While the call is still streaming, Web and Desktop show a preview under the composer. When the call finishes, the same fragment is a sandboxed card under the answer, and a copy is written to `viz/<slug>-<hash>.html` in the session workspace. The agent only receives one confirmation line. Reopening the thread reads the stored card.
8
+
9
+ A later call can patch that file with one exact replacement instead of sending the whole fragment again. Buttons inside the card stay in the card. They do not send the next chat message.
10
+
11
+ ## Requirements
12
+
13
+ A Ycodium server that loads plugin API version 4, including tool presentation, the conversation dock, deliverable tool cards, workspace write, and skill companion files.
14
+
15
+ ## Install
16
+
17
+ From a checkout, build first, then install the directory:
18
+
19
+ ```
20
+ vp run --filter @ycodium-ai/plugin-visualize build
21
+ ycodium plugin add ./plugins/visualize
22
+ ```
23
+
24
+ From a published package:
25
+
26
+ ```
27
+ ycodium plugin add @ycodium-ai/plugin-visualize
28
+ ```
29
+
30
+ The plugin is not part of the default install. After it is enabled, new sessions see the tool `visualize_visualize`. Approve the declared permissions: read and write the session workspace, the composer dock, the turn tail, and a session projection named `cards`.
31
+
32
+ ## Read this before installing
33
+
34
+ The card runs third-party HTML in a sandboxed frame. Scripts are allowed. Network requests, nested frames, and form posts are not. A script or stylesheet loaded from a URL is rejected; inline it in the fragment. Images and fonts may still come from the CDN hosts named in the frame policy.
35
+
36
+ Disabling the plugin removes the tool and the card view. Confirmation lines already in the transcript stay. Files under `viz/` stay in the workspace. The plugin cache that replays cards can be deleted with the rest of that plugin's cache. Uninstalling does not delete workspace files.
37
+
38
+ ## Upgrading
39
+
40
+ ```
41
+ ycodium plugin add @ycodium-ai/plugin-visualize@<version>
42
+ ```
43
+
44
+ Installing a newer version replaces the running one. Cards written by the previous version still open when their presentation or cache entry is intact.
45
+
46
+ ## Limits
47
+
48
+ - The folded tool row keeps a one-line summary. The sandboxed card is the deliverable under the answer, not a second copy inside the folded group.
49
+ - Web and Desktop preview the call under the composer. The host only forwards the first 8000 characters of the arguments, and it refreshes that preview about four times a second. The phone does not receive the live argument text, so the dock stays empty there and the card appears after the call finishes, on the latest turn.
50
+ - The host stores each presentation in its database, so a card survives a server restart. This card is a deliverable, so the host's per-conversation size and age limits for presentations never evict or expire it. If the host has no presentation for a call, replay reads the plugin cache. If that cache is gone too, the confirmation line remains and the card body does not.
51
+ - A card button cannot send the next user message.
52
+ - The host recognizes this tool's activity row for every built-in agent: Codex, Claude, Grok, DSH, OpenCode, Kimi Code, and ACP. When that agent streams arguments, the composer preview fills. When an update has no arguments, the preview stays empty and the settled card still appears. The phone still does not receive the live argument text. Live model runs are not part of this package's checks.
53
+
54
+ ## Developing
55
+
56
+ ```
57
+ vp run --filter @ycodium-ai/plugin-visualize typecheck
58
+ vp run --filter @ycodium-ai/plugin-visualize test
59
+ vp run --filter @ycodium-ai/plugin-visualize build
60
+ ```
61
+
62
+ The server bundle externalizes `@ycodium-ai/plugin-api`. The UI bundle reads React from the host. `dist/` and `assets/ui.js` are build output.
63
+
64
+ ## License
65
+
66
+ UNLICENSED.
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
2
+ <rect x="3" y="4" width="26" height="24" rx="5" stroke="#3B82F6" stroke-width="2"/>
3
+ <path d="M9 21V15M16 21V11M23 21V17" stroke="#3B82F6" stroke-width="2.2" stroke-linecap="round"/>
4
+ </svg>
package/assets/ui.js ADDED
@@ -0,0 +1,326 @@
1
+ var W=window.__ycodiumPluginHost.react;var{Activity:he,Children:pe,Component:ye,Fragment:ve,Profiler:be,PureComponent:xe,StrictMode:ze,Suspense:we,__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE:ke,__COMPILER_RUNTIME:Se,act:Ie,cache:Ce,cacheSignal:Ee,captureOwnerStack:Te,cloneElement:Ae,createContext:Pe,createElement:m,createRef:Ne,forwardRef:Re,isValidElement:Ve,lazy:_e,memo:Fe,startTransition:Me,unstable_useCacheRefresh:Oe,use:De,useActionState:Le,useCallback:Be,useContext:$e,useDebugValue:He,useDeferredValue:Ue,useEffect:f,useEffectEvent:je,useId:Ge,useImperativeHandle:Ye,useInsertionEffect:We,useLayoutEffect:Je,useMemo:g,useOptimistic:Ze,useReducer:Qe,useRef:E,useState:y,useSyncExternalStore:qe,useTransition:Ke,version:Xe}=W;var J={'"':'"',"\\":"\\","/":"/",b:"\b",f:"\f",n:`
2
+ `,r:"\r",t:" "};function T(e){return Z(e,!1)}function Z(e,t){let n=/"fragment"\s*:\s*"/u.exec(e);if(!n)return;let r="";for(let i=n.index+n[0].length;i<e.length;i++){let o=e[i];if(o===void 0)break;if(o==='"')return r;if(o!=="\\"){r+=o;continue}let d=e[i+1];if(d===void 0)return t?void 0:r;if(d==="u"){let s=e.slice(i+2,i+6);if(s.length<4||!/^[0-9a-fA-F]{4}$/u.test(s))return t?void 0:r;r+=String.fromCharCode(Number.parseInt(s,16)),i+=5;continue}let l=J[d];if(l===void 0)return t?void 0:r;r+=l,i+=1}return t?void 0:r}var Q=/<script\b[^>]*>?(?![\s\S]*<script\b)/iu;function A(e){let t=Q.exec(e);if(!t)return e;let n=e.slice(t.index+t[0].length);return/<\/script\s*>/iu.test(n)?e:e.slice(0,t.index)}var q=/(?:workspace copy at|updated card at) (viz\/[a-z0-9][a-z0-9-]{0,80}-[0-9a-f]{8}\.html)/u;function v(e){return e==null?null:q.exec(e)?.[1]??null}function N(e){if(typeof e!="object"||e===null)return null;let t=e;if(t.kind!=="visualize")return null;let n=t.fragment,r=t.title,i=t.path,o=t.mode,d=t.invocationId,l=t.action,s=t.sizeBytes;return typeof n!="string"||n.trim().length===0||typeof r!="string"||r.trim().length===0||typeof i!="string"||o!=="inline"&&o!=="wide"||l!=="create"&&l!=="update"||typeof d!="string"||typeof s!="number"||!Number.isFinite(s)?null:{kind:"visualize",invocationId:d,fragment:n,title:r,mode:o,path:i,sizeBytes:s,action:l}}function P(e,t){return N(e)??z(t)}function R(e){let t=v(e.confirmation),n=P(e.presentation,e.commandData);if(n!==null&&K(n,e.invocationId,t))return n;if(t===null)return null;let r=P(void 0,e.pathCommandData);return r===null||r.path!==t?null:r}function K(e,t,n){return!(n!==null&&e.path!==n||t.length>0&&e.invocationId!==t&&n===null)}function z(e){return typeof e!="object"||e===null?null:N(e.card)}function V(e){if(typeof e!="object"||e===null)return[];let t=e.cards;if(!Array.isArray(t))return[];let n=[];for(let r of t){if(typeof r!="object"||r===null)continue;let i=r,o=i.mode,d=i.action;typeof i.invocationId!="string"||typeof i.title!="string"||typeof i.path=="string"&&(o!=="inline"&&o!=="wide"||d!=="create"&&d!=="update"||typeof i.sizeBytes=="number"&&n.push({invocationId:i.invocationId,title:i.title,mode:o,path:i.path,sizeBytes:i.sizeBytes,action:d}))}return n}function w(e){return e===void 0?{}:{background:e.surface,foreground:e.foreground,card:e.surface,"muted-foreground":e.muted,border:e.border,primary:e.accent,"primary-foreground":e.surface}}function _(e){return e.querySelector('meta[name="ycodium-plugin-surface"]')!==null}function h(e){return e.i18n.usePluginTranslation()}var F=`
3
+ .ycodium-visualize-ui {
4
+ box-sizing: border-box;
5
+ width: 100%;
6
+ min-width: 0;
7
+ color: var(--viz-fg, var(--foreground));
8
+ font: 13px/1.45 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
9
+ }
10
+ .ycodium-visualize-ui * { box-sizing: border-box; }
11
+ .ycodium-visualize-card {
12
+ display: flex;
13
+ flex-direction: column;
14
+ min-width: 0;
15
+ overflow: hidden;
16
+ border: 1px solid var(--viz-border, var(--border));
17
+ border-radius: var(--radius-lg, 12px);
18
+ background: var(--viz-surface, var(--card));
19
+ box-shadow: 0 1px 0 color-mix(in srgb, currentColor 6%, transparent);
20
+ }
21
+ .ycodium-visualize-card[data-status="streaming"] {
22
+ border-color: var(--viz-accent, var(--primary));
23
+ }
24
+ .ycodium-visualize-card[data-status="missing"] {
25
+ border-color: var(--destructive);
26
+ }
27
+ .ycodium-visualize-accent {
28
+ height: 3px;
29
+ background: var(--viz-accent, var(--primary));
30
+ }
31
+ .ycodium-visualize-header {
32
+ display: flex;
33
+ flex-wrap: wrap;
34
+ align-items: center;
35
+ gap: 8px 10px;
36
+ padding: 10px 12px 8px;
37
+ }
38
+ .ycodium-visualize-title {
39
+ flex: 1 1 10rem;
40
+ min-width: 0;
41
+ margin: 0;
42
+ overflow: hidden;
43
+ font-size: 14px;
44
+ font-weight: 600;
45
+ letter-spacing: -0.01em;
46
+ text-overflow: ellipsis;
47
+ white-space: nowrap;
48
+ }
49
+ .ycodium-visualize-chips {
50
+ display: flex;
51
+ flex-wrap: wrap;
52
+ gap: 6px;
53
+ }
54
+ .ycodium-visualize-chip {
55
+ display: inline-flex;
56
+ align-items: center;
57
+ gap: 6px;
58
+ max-width: 100%;
59
+ padding: 2px 8px;
60
+ border: 1px solid var(--viz-border, var(--border));
61
+ border-radius: 999px;
62
+ color: var(--viz-muted, var(--muted-foreground));
63
+ font-size: 11px;
64
+ letter-spacing: 0.02em;
65
+ }
66
+ .ycodium-visualize-dot {
67
+ width: 7px;
68
+ height: 7px;
69
+ border-radius: 999px;
70
+ background: var(--viz-accent, var(--primary));
71
+ }
72
+ .ycodium-visualize-copy {
73
+ margin-left: auto;
74
+ }
75
+ .ycodium-visualize-meta {
76
+ display: flex;
77
+ flex-wrap: wrap;
78
+ gap: 6px 14px;
79
+ padding: 0 12px 10px;
80
+ color: var(--viz-muted, var(--muted-foreground));
81
+ font-size: 12px;
82
+ }
83
+ .ycodium-visualize-path {
84
+ min-width: 0;
85
+ overflow: hidden;
86
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
87
+ text-overflow: ellipsis;
88
+ white-space: nowrap;
89
+ }
90
+ .ycodium-visualize-viewport {
91
+ min-width: 0;
92
+ border-top: 1px solid var(--viz-border, var(--border));
93
+ background: var(--viz-surface, var(--card));
94
+ }
95
+ .ycodium-visualize-viewport iframe {
96
+ display: block;
97
+ width: 100%;
98
+ min-height: 160px;
99
+ border: 0;
100
+ background: transparent;
101
+ }
102
+ .ycodium-visualize-card[data-mode="wide"] .ycodium-visualize-viewport iframe {
103
+ min-height: 220px;
104
+ }
105
+ .ycodium-visualize-note {
106
+ padding: 16px 14px 18px;
107
+ color: var(--viz-muted, var(--muted-foreground));
108
+ }
109
+ .ycodium-visualize-stack {
110
+ display: flex;
111
+ flex-direction: column;
112
+ gap: 12px;
113
+ width: 100%;
114
+ min-width: 0;
115
+ }
116
+ `;var{jsx:a,jsxs:c,Fragment:dt}=window.__ycodiumPluginHost.jsxRuntime;function p(e){let t=h(e.bridge),[n,r]=y(!1),i=e.bridge.ui;f(()=>{r(!1)},[e.path]);let o={...e.colors===void 0?{}:{"--viz-fg":e.colors.foreground,"--viz-surface":e.colors.surface,"--viz-muted":e.colors.muted,"--viz-border":e.colors.border,"--viz-accent":e.colors.accent},colorScheme:e.colorScheme};return c("div",{className:"ycodium-visualize-ui","data-mode":e.mode,"data-status":e.status,"data-visualize-card":"",style:o,children:[a("style",{children:F}),c("article",{className:"ycodium-visualize-card","data-mode":e.mode,"data-status":e.status,children:[a("div",{className:"ycodium-visualize-accent"}),c("header",{className:"ycodium-visualize-header",children:[a("h3",{className:"ycodium-visualize-title",children:e.title}),c("div",{className:"ycodium-visualize-chips",children:[c("span",{className:"ycodium-visualize-chip",children:[a("span",{className:"ycodium-visualize-dot"}),t(X(e.status))]}),a("span",{className:"ycodium-visualize-chip",children:e.mode==="wide"?t("card.modeWide"):t("card.modeInline")})]}),e.path.length>0?m(i.Button,{type:"button",size:"xs",variant:"outline",className:"ycodium-visualize-copy","aria-label":t(n?"card.copied":"card.copyPath"),onClick:()=>{e.bridge.writeClipboard(e.path).then(()=>{r(!0)})}},t(n?"card.copied":"card.copyPath")):null]}),e.sizeBytes!==null||e.path.length>0?c("div",{className:"ycodium-visualize-meta",children:[e.sizeBytes!==null?a("span",{children:t("card.bytes",{count:e.sizeBytes})}):null,e.path.length>0?a("span",{className:"ycodium-visualize-path",children:t("card.path",{path:e.path})}):null]}):null,e.children]})]})}function X(e){switch(e){case"streaming":return"status.streaming";case"ready":return"status.ready";case"loading":return"status.loading";case"missing":return"status.missing";default:return e}}function M(e){return e.className.split(/\s+/u).includes("dark")||e.prefersDark?"dark":"light"}var k="ycodium-visualize:height",b="ycodium-visualize:stream";function O(e,t){if(typeof e!="object"||e===null)return null;let n=e;if(n.type!==k||n.token!==t)return null;let r=n.height;return typeof r!="number"||!Number.isFinite(r)||r<0?null:r}function D(e){return Math.min(960,Math.max(96,Math.round(e)))}var L=`
117
+ :root {
118
+ color-scheme: light dark;
119
+ --background: var(--ycodium-viz-background, transparent);
120
+ --foreground: var(--ycodium-viz-foreground, light-dark(rgb(26 28 31), rgb(240 242 245)));
121
+ --card: var(--ycodium-viz-card, light-dark(rgb(0 0 0 / 4%), rgb(255 255 255 / 6%)));
122
+ --card-foreground: var(--ycodium-viz-foreground, light-dark(rgb(26 28 31), rgb(240 242 245)));
123
+ --muted-foreground: var(--ycodium-viz-muted-foreground, light-dark(rgb(26 28 31 / 55%), rgb(240 242 245 / 55%)));
124
+ --border: var(--ycodium-viz-border, light-dark(rgb(0 0 0 / 10%), rgb(255 255 255 / 12%)));
125
+ --primary: var(--ycodium-viz-primary, light-dark(rgb(65 118 230), rgb(110 150 240)));
126
+ --primary-foreground: var(--ycodium-viz-primary-foreground, light-dark(rgb(255 255 255), rgb(13 13 13)));
127
+ --viz-series-1: var(--ycodium-viz-primary, light-dark(rgb(65 118 230), rgb(110 150 240)));
128
+ --viz-series-2: light-dark(rgb(226 116 26), rgb(245 152 66));
129
+ --viz-series-3: light-dark(rgb(16 148 82), rgb(72 196 130));
130
+ --viz-series-4: light-dark(rgb(146 94 220), rgb(176 132 240));
131
+ --viz-series-5: light-dark(rgb(212 66 84), rgb(240 110 126));
132
+ --viz-series-6: light-dark(rgb(160 138 22), rgb(206 182 70));
133
+ --radius: 8px;
134
+ --font-size-base: 14px;
135
+ }
136
+
137
+ * { box-sizing: border-box; }
138
+ html, body { margin: 0; padding: 0; }
139
+ body {
140
+ background: var(--background);
141
+ color: var(--foreground);
142
+ font: 400 var(--font-size-base)/1.5 system-ui, -apple-system, 'Segoe UI', sans-serif;
143
+ }
144
+ h1, h2, h3 { margin: 0 0 0.5em; font-weight: 500; line-height: 1.3; }
145
+ h1 { font-size: 1.3em; }
146
+ h2 { font-size: 1.15em; }
147
+ h3 { font-size: 1em; }
148
+ p { margin: 0 0 0.75em; }
149
+ a { color: var(--primary); }
150
+ svg text { fill: var(--foreground); font-size: 12px; }
151
+ .text-small { font-size: 12px; color: var(--muted-foreground); }
152
+
153
+ .card {
154
+ background: var(--card);
155
+ color: var(--card-foreground);
156
+ border: 1px solid var(--border);
157
+ border-radius: var(--radius);
158
+ padding: 12px 14px;
159
+ }
160
+
161
+ .btn {
162
+ appearance: none;
163
+ display: inline-flex;
164
+ align-items: center;
165
+ gap: 6px;
166
+ padding: 5px 12px;
167
+ border: 1px solid var(--border);
168
+ border-radius: var(--radius);
169
+ background: transparent;
170
+ color: var(--foreground);
171
+ font: inherit;
172
+ cursor: pointer;
173
+ }
174
+ .btn:hover { background: color-mix(in oklab, var(--foreground) 6%, transparent); }
175
+ .btn-primary,
176
+ .btn[aria-pressed='true'],
177
+ .btn[aria-selected='true'],
178
+ .btn.is-selected {
179
+ background: var(--primary);
180
+ border-color: var(--primary);
181
+ color: var(--primary-foreground);
182
+ }
183
+ .btn-ghost { border-color: transparent; }
184
+ .btn:disabled { color: var(--muted-foreground); cursor: default; }
185
+
186
+ .viz-grid {
187
+ display: grid;
188
+ grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
189
+ gap: 10px;
190
+ }
191
+ .viz-row {
192
+ display: flex;
193
+ flex-wrap: wrap;
194
+ align-items: center;
195
+ gap: 10px;
196
+ }
197
+ .viz-controls {
198
+ display: flex;
199
+ flex-wrap: wrap;
200
+ align-items: end;
201
+ gap: 10px;
202
+ margin-bottom: 12px;
203
+ }
204
+ .viz-stat .viz-stat-label,
205
+ .viz-stat > :first-child { font-size: 12px; color: var(--muted-foreground); }
206
+ .viz-stat-value { font-size: 1.4em; font-weight: 500; line-height: 1.2; }
207
+ .viz-badge {
208
+ display: inline-block;
209
+ padding: 1px 8px;
210
+ border-radius: 999px;
211
+ background: color-mix(in oklab, var(--primary) 14%, transparent);
212
+ color: var(--primary);
213
+ font-size: 12px;
214
+ }
215
+
216
+ .form-label { display: block; font-size: 12px; color: var(--muted-foreground); margin-bottom: 4px; }
217
+ .form-control, .form-select {
218
+ width: 100%;
219
+ padding: 5px 10px;
220
+ border: 1px solid var(--border);
221
+ border-radius: var(--radius);
222
+ background: transparent;
223
+ color: var(--foreground);
224
+ font: inherit;
225
+ }
226
+ .form-check { display: flex; align-items: center; gap: 6px; }
227
+ .form-check input { accent-color: var(--primary); }
228
+ input[type='range'] { accent-color: var(--primary); }
229
+
230
+ table { border-collapse: collapse; width: 100%; }
231
+ th, td { text-align: left; padding: 5px 10px; border-bottom: 1px solid var(--border); }
232
+ th { font-weight: 500; color: var(--muted-foreground); font-size: 12px; }
233
+ .table-responsive { overflow-x: auto; }
234
+ `;var ee=["https://cdnjs.cloudflare.com","https://cdn.jsdelivr.net","https://esm.sh","https://fonts.bunny.net","https://fonts.googleapis.com","https://fonts.gstatic.com","https://unpkg.com"],S=["blob:","data:",...ee].join(" "),te="'unsafe-inline' 'unsafe-eval' 'wasm-unsafe-eval' blob: data:",ne="'unsafe-inline' blob: data:",re=["default-src 'none'",`script-src ${te}`,`style-src ${ne}`,`img-src ${S}`,`font-src ${S}`,`media-src ${S}`,"worker-src blob:","connect-src blob: data:","frame-src 'none'","object-src 'none'","base-uri 'none'","form-action 'none'"].join("; ");function ie(e){let t=e.trim();return/[;{}<>]/u.test(t)?"":t}function I(e){let t=Object.entries(e.themeVars).map(([n,r])=>[n,ie(r)]).filter(([,n])=>n.length>0).map(([n,r])=>`--ycodium-viz-${n}: ${r};`).join(" ");return`<!doctype html>
235
+ <html lang="en">
236
+ <head>
237
+ <meta charset="utf-8">
238
+ <meta name="viewport" content="width=device-width, initial-scale=1">
239
+ <meta name="referrer" content="no-referrer">
240
+ <meta http-equiv="Content-Security-Policy" content="${re}">
241
+ <title>${se(e.title)}</title>
242
+ <style>${L}
243
+ :root { ${t} color-scheme: ${e.colorScheme}; }
244
+ body { padding: 4px 2px; }</style>
245
+ </head>
246
+ <body>
247
+ ${e.fragment}
248
+ <script>${oe(e.reportToken)}<\/script>
249
+ </body>
250
+ </html>
251
+ `}function B(e){return I({...e,title:"preview",fragment:`<div id="ycodium-viz-stream-root"></div>
252
+ <style>
253
+ .ycodium-viz-enter { animation: ycodium-viz-enter 0.4s cubic-bezier(0.2, 0.7, 0.3, 1) both; }
254
+ @keyframes ycodium-viz-enter { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
255
+ @media (prefers-reduced-motion: reduce) { .ycodium-viz-enter { animation: none; } }
256
+ </style>
257
+ <script>${ae(e.reportToken)}<\/script>`})}function oe(e){let t=x(e);return`
258
+ (function () {
259
+ var post = function () {
260
+ parent.postMessage({
261
+ type: ${x(k)},
262
+ token: ${t},
263
+ height: document.documentElement.scrollHeight,
264
+ }, '*');
265
+ };
266
+ new ResizeObserver(post).observe(document.documentElement);
267
+ addEventListener('load', post);
268
+ post();
269
+ })();
270
+ `}function ae(e){return`
271
+ (function () {
272
+ var root = document.getElementById('ycodium-viz-stream-root');
273
+ var token = ${x(e)};
274
+ function syncAttrs(cur, next) {
275
+ var i, attrs = cur.attributes;
276
+ for (i = attrs.length - 1; i >= 0; i--) {
277
+ if (!next.hasAttribute(attrs[i].name)) cur.removeAttribute(attrs[i].name);
278
+ }
279
+ attrs = next.attributes;
280
+ for (i = 0; i < attrs.length; i++) {
281
+ if (cur.getAttribute(attrs[i].name) !== attrs[i].value) cur.setAttribute(attrs[i].name, attrs[i].value);
282
+ }
283
+ }
284
+ function executable(node) {
285
+ var script = document.createElement('script');
286
+ for (var i = 0; i < node.attributes.length; i++) {
287
+ script.setAttribute(node.attributes[i].name, node.attributes[i].value);
288
+ }
289
+ script.textContent = node.textContent;
290
+ return script;
291
+ }
292
+ function sync(cur, next) {
293
+ var want = next.childNodes, have = cur.childNodes, i;
294
+ for (i = 0; i < want.length; i++) {
295
+ var target = want[i], live = have[i];
296
+ if (live === undefined) {
297
+ var added = target.nodeName === 'SCRIPT' ? executable(target) : target.cloneNode(true);
298
+ if (added.nodeType === 1 && added.nodeName !== 'SCRIPT') added.classList.add('ycodium-viz-enter');
299
+ cur.appendChild(added);
300
+ continue;
301
+ }
302
+ if (live.nodeType !== target.nodeType || live.nodeName !== target.nodeName) {
303
+ cur.replaceChild(target.cloneNode(true), live);
304
+ continue;
305
+ }
306
+ if (live.nodeType === 3 || live.nodeType === 8) {
307
+ if (live.nodeValue !== target.nodeValue) live.nodeValue = target.nodeValue;
308
+ continue;
309
+ }
310
+ if (live.nodeType === 1) {
311
+ syncAttrs(live, target);
312
+ sync(live, target);
313
+ }
314
+ }
315
+ while (cur.childNodes.length > want.length) cur.removeChild(cur.lastChild);
316
+ }
317
+ addEventListener('message', function (event) {
318
+ var data = event.data;
319
+ if (!data || data.type !== ${x(b)} || data.token !== token) return;
320
+ if (typeof data.fragment !== 'string') return;
321
+ var next = document.createElement('div');
322
+ next.innerHTML = data.fragment;
323
+ sync(root, next);
324
+ });
325
+ })();
326
+ `}function x(e){return JSON.stringify(e).replaceAll("<","\\u003c")}function se(e){return e.replaceAll("&","&amp;").replaceAll("<","&lt;").replaceAll(">","&gt;")}function $(e){let t=e.colorScheme??j(),n=g(()=>I({fragment:e.fragment,title:e.title,themeVars:w(e.colors),colorScheme:t,reportToken:e.token}),[e.colors,e.fragment,e.title,e.token,t]);return a(U,{srcDoc:n,token:e.token,title:e.frameLabel,fragment:null})}function H(e){let t=j(),n=g(()=>B({themeVars:w(e.colors),colorScheme:t,reportToken:e.token}),[e.colors,e.token,t]);return a(U,{srcDoc:n,token:e.token,title:e.frameLabel,fragment:A(e.fragment)})}function U(e){let t=E(null),[n,r]=y(160);return f(()=>{let i=t.current;if(i===null)return;let o=d=>{if(d.source!==i.contentWindow)return;let l=O(d.data,e.token);l!==null&&r(D(l))};return window.addEventListener("message",o),()=>window.removeEventListener("message",o)},[e.token]),f(()=>{let i=t.current;if(i===null||e.fragment===null)return;let o=()=>{i.contentWindow?.postMessage({type:b,token:e.token,fragment:e.fragment},"*")};return i.addEventListener("load",o),o(),()=>i.removeEventListener("load",o)},[e.fragment,e.token]),a("div",{className:"ycodium-visualize-viewport",children:a("iframe",{ref:t,title:e.title,sandbox:"allow-scripts",srcDoc:e.srcDoc,style:{height:n}})})}function j(){let e=window.matchMedia?.("(prefers-color-scheme: dark)").matches??!1;return M({className:document.documentElement.className,prefersDark:e})}function C(e){let t=h(e.bridge),n=e.threadRef?.threadId??"",r=e.invocationId??"",i=ce(e.entry,e.details),o=v(i),d=e.bridge.commands.useQuery("card",{threadId:n,invocationId:r,path:""},{environmentId:e.environmentId}),l=e.bridge.commands.useQuery("card",{threadId:n,invocationId:o??"",path:o??""},{environmentId:e.environmentId}),s=R({invocationId:r,presentation:e.presentation,commandData:d.data,pathCommandData:l.data,confirmation:i}),u=e.colors;return s===null&&(d.isPending||o!==null&&l.isPending)?a(p,{bridge:e.bridge,title:t("status.loading"),mode:"inline",path:"",sizeBytes:null,status:"loading",...u===void 0?{}:{colors:u},...e.colorScheme===void 0?{}:{colorScheme:e.colorScheme},children:a("p",{className:"ycodium-visualize-note",children:t("card.loading")})}):s===null?a(p,{bridge:e.bridge,title:t("status.missing"),mode:"inline",path:"",sizeBytes:null,status:"missing",...u===void 0?{}:{colors:u},...e.colorScheme===void 0?{}:{colorScheme:e.colorScheme},children:a(ue,{bridge:e.bridge,title:t("status.missing"),description:t("card.missing")})}):a(p,{bridge:e.bridge,title:s.title,mode:s.mode,path:s.path,sizeBytes:s.sizeBytes,status:"ready",...u===void 0?{}:{colors:u},...e.colorScheme===void 0?{}:{colorScheme:e.colorScheme},children:a($,{fragment:s.fragment,title:s.title,token:s.invocationId.length>0?s.invocationId:r,frameLabel:t("card.frame",{title:s.title}),...u===void 0?{}:{colors:u},...e.colorScheme===void 0?{}:{colorScheme:e.colorScheme}})})}function G(e){return typeof e.argumentsText!="string"?null:a(de,{...e})}function de(e){let t=h(e.bridge),n=T(e.argumentsText),r=n===void 0?"":n.trim();return a(p,{bridge:e.bridge,title:t("status.streaming"),mode:"inline",path:"",sizeBytes:r.length===0?null:new TextEncoder().encode(r).length,status:"streaming",children:r.length===0?a("p",{className:"ycodium-visualize-note",children:t("dock.waiting")}):a(H,{fragment:r,token:e.threadId,frameLabel:t("card.frame",{title:t("status.streaming")})})})}function Y(e){return!_(document)||e.environmentId===void 0||e.threadId===void 0||e.threadId.length===0?null:a(le,{bridge:e.bridge,environmentId:e.environmentId,threadId:e.threadId})}function le(e){let t=e.bridge.commands.useSubscription("cards",{threadId:e.threadId},{environmentId:e.environmentId}),n=g(()=>V(t.data),[t.data]),r=g(()=>n.map(o=>({environmentId:e.environmentId,payload:{threadId:e.threadId,invocationId:o.invocationId}})),[n,e.environmentId,e.threadId]),i=e.bridge.commands.useQueryEach("card",r);return n.length===0?null:a("div",{className:"ycodium-visualize-stack",children:n.map((o,d)=>{let l=me(i.rows[d]?.data);return a(C,{bridge:e.bridge,environmentId:e.environmentId,invocationId:o.invocationId,entry:ge(o.invocationId),details:{files:[],inputFields:[]},...l===void 0?{}:{presentation:l},...e.threadId.length>0?{threadRef:{environmentId:e.environmentId,threadId:e.threadId}}:{}},o.invocationId)})})}function ue(e){let t=e.bridge.ui;return m(t.Alert,{variant:"error",layout:"inline"},m(t.AlertTitle,null,e.title),m(t.AlertDescription,null,e.description))}function ce(e,t){let n=e.toolIo?.output??t.output?.text??e.detail;return typeof n=="string"&&n.length>0?n:null}function me(e){return z(e)??void 0}function ge(e){return{id:e,label:"",displayFailed:!1}}function fe(e){return{views:{card(t){return a(C,{bridge:e,...t})}},slots:[{name:"conversation.input.dock",component(t){return a(G,{bridge:e,...t})}},{name:"conversation.chat.turnTail",component(t){return a(Y,{bridge:e,...t})}}]}}export{fe as default};