@volter-ai-dev/supercode-ui 0.1.20 → 0.1.22

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/sessions.mjs CHANGED
@@ -162,6 +162,11 @@ var ICONS = {
162
162
  /* @__PURE__ */ jsx2("path", { d: "M9 3.5v10" }),
163
163
  /* @__PURE__ */ jsx2("path", { d: "m4.75 9.5 4.25 4 4.25-4" })
164
164
  ] }),
165
+ image: () => /* @__PURE__ */ jsxs(Fragment, { children: [
166
+ /* @__PURE__ */ jsx2("rect", { x: "3", y: "3.5", width: "12", height: "11", rx: "1.75" }),
167
+ /* @__PURE__ */ jsx2("circle", { cx: "6.5", cy: "7", r: "1.25" }),
168
+ /* @__PURE__ */ jsx2("path", { d: "m4.5 13 3.25-3 2.1 1.85 1.65-1.5L14 13" })
169
+ ] }),
165
170
  menu: () => /* @__PURE__ */ jsxs(Fragment, { children: [
166
171
  /* @__PURE__ */ jsx2("circle", { cx: "4", cy: "9", r: "1.25", fill: "currentColor", stroke: "none" }),
167
172
  /* @__PURE__ */ jsx2("circle", { cx: "9", cy: "9", r: "1.25", fill: "currentColor", stroke: "none" }),
@@ -187,8 +192,12 @@ function UiIcon({ name, size = 16, class: className = "" }) {
187
192
  return /* @__PURE__ */ jsx2("svg", { class: `scui-icon ${className}`, style: { "--scui-icon-size": `${size}px` }, viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", "stroke-width": "1.5", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(Glyph, {}) });
188
193
  }
189
194
 
195
+ // src/context.jsx
196
+ import { jsx as jsx3, jsxs as jsxs2 } from "preact/jsx-runtime";
197
+ var MAX_IMAGE_BYTES = 5 * 1024 * 1024;
198
+
190
199
  // src/conversation.jsx
191
- import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs2 } from "preact/jsx-runtime";
200
+ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs3 } from "preact/jsx-runtime";
192
201
  function LoadingStatus({ state, compact = false }) {
193
202
  const copy = {
194
203
  connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
@@ -196,19 +205,19 @@ function LoadingStatus({ state, compact = false }) {
196
205
  discovering: ["Loading recent sessions", "Scanning native session stores without loading full transcripts.", 2],
197
206
  ready: ["Ready", "Coding sessions are up to date.", 3]
198
207
  }[state.startup];
199
- return /* @__PURE__ */ jsxs2("div", { class: `scui-loading${compact ? " scui-loading-compact" : ""}`, role: "status", "aria-busy": state.startup !== "ready", children: [
200
- /* @__PURE__ */ jsx3("span", { class: "scui-orbit", "aria-hidden": "true", children: /* @__PURE__ */ jsx3("i", {}) }),
201
- /* @__PURE__ */ jsxs2("span", { class: "scui-loading-copy", children: [
202
- /* @__PURE__ */ jsx3("strong", { children: copy[0] }),
203
- /* @__PURE__ */ jsx3("small", { children: copy[1] })
208
+ return /* @__PURE__ */ jsxs3("div", { class: `scui-loading${compact ? " scui-loading-compact" : ""}`, role: "status", "aria-busy": state.startup !== "ready", children: [
209
+ /* @__PURE__ */ jsx4("span", { class: "scui-orbit", "aria-hidden": "true", children: /* @__PURE__ */ jsx4("i", {}) }),
210
+ /* @__PURE__ */ jsxs3("span", { class: "scui-loading-copy", children: [
211
+ /* @__PURE__ */ jsx4("strong", { children: copy[0] }),
212
+ /* @__PURE__ */ jsx4("small", { children: copy[1] })
204
213
  ] }),
205
- /* @__PURE__ */ jsx3("span", { class: "scui-progress", "aria-hidden": "true", children: [1, 2, 3].map((step) => /* @__PURE__ */ jsx3("i", { "data-progress": step <= copy[2] ? "done" : step === copy[2] + 1 ? "current" : "waiting" }, step)) })
214
+ /* @__PURE__ */ jsx4("span", { class: "scui-progress", "aria-hidden": "true", children: [1, 2, 3].map((step) => /* @__PURE__ */ jsx4("i", { "data-progress": step <= copy[2] ? "done" : step === copy[2] + 1 ? "current" : "waiting" }, step)) })
206
215
  ] });
207
216
  }
208
217
 
209
218
  // src/logo.jsx
210
219
  import { useEffect as useEffect3 } from "preact/hooks";
211
- import { jsx as jsx4, jsxs as jsxs3 } from "preact/jsx-runtime";
220
+ import { jsx as jsx5, jsxs as jsxs4 } from "preact/jsx-runtime";
212
221
  var LOGOS = {
213
222
  "claude-code": {
214
223
  viewBox: "-1 3.5 26 18",
@@ -259,29 +268,29 @@ function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
259
268
  if (!logo) onMissingLogo?.(id);
260
269
  }, [id, logo, onMissingLogo]);
261
270
  if (!logo) return null;
262
- return /* @__PURE__ */ jsxs3("span", { class: "scui-logo", "data-harness": id, "data-activity": activity, style: `--scui-logo-size:${size}px`, "aria-hidden": "true", children: [
263
- /* @__PURE__ */ jsx4("svg", { viewBox: logo.viewBox, preserveAspectRatio: "xMidYMid meet", focusable: "false", children: logo.paths.map(([Tag, props], index) => /* @__PURE__ */ jsx4(Tag, { ...props }, index)) }),
264
- activity && activity !== "idle" ? /* @__PURE__ */ jsx4("i", {}) : null
271
+ return /* @__PURE__ */ jsxs4("span", { class: "scui-logo", "data-harness": id, "data-activity": activity, style: `--scui-logo-size:${size}px`, "aria-hidden": "true", children: [
272
+ /* @__PURE__ */ jsx5("svg", { viewBox: logo.viewBox, preserveAspectRatio: "xMidYMid meet", focusable: "false", children: logo.paths.map(([Tag, props], index) => /* @__PURE__ */ jsx5(Tag, { ...props }, index)) }),
273
+ activity && activity !== "idle" ? /* @__PURE__ */ jsx5("i", {}) : null
265
274
  ] });
266
275
  }
267
276
 
268
277
  // src/sessions.jsx
269
- import { jsx as jsx5, jsxs as jsxs4 } from "preact/jsx-runtime";
278
+ import { jsx as jsx6, jsxs as jsxs5 } from "preact/jsx-runtime";
270
279
  var sessionListMemory = /* @__PURE__ */ new Map();
271
280
  function SessionRow({ row, state, onOpen }) {
272
281
  const activity = sessionActivity(state, row);
273
282
  const attentionPreview = state.attention.find((item) => item.key === row.key)?.preview;
274
283
  const title = sessionDisplayName(row);
275
284
  const detail = attentionPreview || row.preview || (row.name && row.name !== title ? row.name : row.cwd);
276
- return /* @__PURE__ */ jsxs4("button", { class: "scui-session", "data-active": row.active, "data-activity": activity, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${detail ? ` \xB7 ${detail}` : ""}${row.age ? ` \xB7 ${row.age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
277
- /* @__PURE__ */ jsx5(HarnessLogo, { id: row.harness, activity, size: 34 }),
278
- /* @__PURE__ */ jsxs4("span", { class: "scui-session-copy", children: [
279
- /* @__PURE__ */ jsxs4("span", { children: [
280
- /* @__PURE__ */ jsx5("strong", { children: title }),
281
- /* @__PURE__ */ jsx5("small", { children: row.age })
285
+ return /* @__PURE__ */ jsxs5("button", { class: "scui-session", "data-active": row.active, "data-activity": activity, "data-session-key": row.key, type: "button", "aria-label": `${title} \xB7 ${harnessDisplayName(row.harness)}${detail ? ` \xB7 ${detail}` : ""}${row.age ? ` \xB7 ${row.age}` : ""}`, "aria-current": row.active ? "true" : void 0, onClick: () => onOpen(row), children: [
286
+ /* @__PURE__ */ jsx6(HarnessLogo, { id: row.harness, activity, size: 34 }),
287
+ /* @__PURE__ */ jsxs5("span", { class: "scui-session-copy", children: [
288
+ /* @__PURE__ */ jsxs5("span", { children: [
289
+ /* @__PURE__ */ jsx6("strong", { children: title }),
290
+ /* @__PURE__ */ jsx6("small", { children: row.age })
282
291
  ] }),
283
- detail ? /* @__PURE__ */ jsx5("span", { children: /* @__PURE__ */ jsx5("small", { title: row.cwd, children: detail }) }) : null,
284
- state.attachError?.key === row.key ? /* @__PURE__ */ jsx5("em", { children: state.attachError.message }) : null
292
+ detail ? /* @__PURE__ */ jsx6("span", { children: /* @__PURE__ */ jsx6("small", { title: row.cwd, children: detail }) }) : null,
293
+ state.attachError?.key === row.key ? /* @__PURE__ */ jsx6("em", { children: state.attachError.message }) : null
285
294
  ] })
286
295
  ] });
287
296
  }
@@ -312,33 +321,33 @@ function SessionList({ state, adapter, onOpen, onNew, onClose, components = {},
312
321
  Promise.resolve(result).then(() => setLoadingMore(false), () => setLoadingMore(false));
313
322
  }
314
323
  };
315
- return /* @__PURE__ */ jsxs4("section", { class: "scui-list", ref: root, children: [
316
- /* @__PURE__ */ jsxs4("header", { class: "scui-head", children: [
317
- /* @__PURE__ */ jsxs4("span", { class: "scui-head-copy", children: [
318
- /* @__PURE__ */ jsx5("strong", { children: labels.chats }),
319
- /* @__PURE__ */ jsxs4("small", { children: [
324
+ return /* @__PURE__ */ jsxs5("section", { class: "scui-list", ref: root, children: [
325
+ /* @__PURE__ */ jsxs5("header", { class: "scui-head", children: [
326
+ /* @__PURE__ */ jsxs5("span", { class: "scui-head-copy", children: [
327
+ /* @__PURE__ */ jsx6("strong", { children: labels.chats }),
328
+ /* @__PURE__ */ jsxs5("small", { children: [
320
329
  state.sessions.length,
321
330
  " recent conversations"
322
331
  ] })
323
332
  ] }),
324
- /* @__PURE__ */ jsx5("button", { type: "button", "data-list-focus": "new", "aria-label": labels.newChat, disabled: !state.harnesses.some((item) => item.startable), onClick: onNew, children: /* @__PURE__ */ jsx5(UiIcon, { name: "plus", size: 18 }) }),
325
- onClose ? /* @__PURE__ */ jsx5("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx5(UiIcon, { name: "close", size: 18 }) }) : null
333
+ /* @__PURE__ */ jsx6("button", { type: "button", "data-list-focus": "new", "aria-label": labels.newChat, disabled: !state.harnesses.some((item) => item.startable), onClick: onNew, children: /* @__PURE__ */ jsx6(UiIcon, { name: "plus", size: 18 }) }),
334
+ onClose ? /* @__PURE__ */ jsx6("button", { type: "button", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx6(UiIcon, { name: "close", size: 18 }) }) : null
326
335
  ] }),
327
- state.startup !== "ready" ? /* @__PURE__ */ jsx5(LoadingStatus, { state, compact: rows.length > 0 }) : null,
328
- state.sessions.length > 4 ? /* @__PURE__ */ jsxs4("label", { class: "scui-search", children: [
329
- /* @__PURE__ */ jsx5(UiIcon, { name: "search", size: 15 }),
330
- /* @__PURE__ */ jsx5("input", { type: "search", "aria-label": labels.searchChats, placeholder: labels.searchChats, value: query, onInput: (event) => {
336
+ state.startup !== "ready" ? /* @__PURE__ */ jsx6(LoadingStatus, { state, compact: rows.length > 0 }) : null,
337
+ state.sessions.length > 4 ? /* @__PURE__ */ jsxs5("label", { class: "scui-search", children: [
338
+ /* @__PURE__ */ jsx6(UiIcon, { name: "search", size: 15 }),
339
+ /* @__PURE__ */ jsx6("input", { type: "search", "aria-label": labels.searchChats, placeholder: labels.searchChats, value: query, onInput: (event) => {
331
340
  const value = event.currentTarget.value;
332
341
  setQuery(value);
333
342
  boundedSet(sessionListMemory, memoryKey, { query: value, top: 0 });
334
343
  if (rowScroller.current) rowScroller.current.scrollTop = 0;
335
344
  } }),
336
- /* @__PURE__ */ jsx5("small", { children: rows.length })
345
+ /* @__PURE__ */ jsx6("small", { children: rows.length })
337
346
  ] }) : null,
338
- /* @__PURE__ */ jsxs4("div", { class: "scui-session-rows", ref: rowScroller, onScroll: (event) => boundedSet(sessionListMemory, memoryKey, { query, top: event.currentTarget.scrollTop }), children: [
339
- !rows.length && state.startup === "ready" ? /* @__PURE__ */ jsx5("div", { class: "scui-empty", children: query ? "No chats match your search." : state.error ?? "No coding chats found." }) : null,
340
- rows.map((row) => /* @__PURE__ */ jsx5(Row, { value: row, row, state, adapter, onOpen }, row.key)),
341
- state.history.hasMoreSessions ? /* @__PURE__ */ jsx5("button", { class: "scui-load", type: "button", disabled: loadingMore, onClick: loadMore, children: loadingMore ? "Loading older chats\u2026" : "Load older chats" }) : null
347
+ /* @__PURE__ */ jsxs5("div", { class: "scui-session-rows", ref: rowScroller, onScroll: (event) => boundedSet(sessionListMemory, memoryKey, { query, top: event.currentTarget.scrollTop }), children: [
348
+ !rows.length && state.startup === "ready" ? /* @__PURE__ */ jsx6("div", { class: "scui-empty", children: query ? "No chats match your search." : state.error ?? "No coding chats found." }) : null,
349
+ rows.map((row) => /* @__PURE__ */ jsx6(Row, { value: row, row, state, adapter, onOpen }, row.key)),
350
+ state.history.hasMoreSessions ? /* @__PURE__ */ jsx6("button", { class: "scui-load", type: "button", disabled: loadingMore, onClick: loadMore, children: loadingMore ? "Loading older chats\u2026" : "Load older chats" }) : null
342
351
  ] })
343
352
  ] });
344
353
  }
package/styles.css CHANGED
@@ -171,8 +171,11 @@
171
171
  .scui-continuation { display:flex; align-items:center; gap:8px; padding:7px 9px; border-top:1px solid var(--scui-border); background:var(--scui-bg-raised) }.scui-continuation > span { display:grid; flex:1 }.scui-continuation small { color:var(--scui-muted); font-size:10px }.scui-continuation button { padding:5px 8px; border:1px solid var(--scui-accent); border-radius:7px; background:transparent; color:var(--scui-accent); cursor:pointer }
172
172
  .scui-compose { flex:none; padding:8px; border-top:1px solid var(--scui-border); background:var(--scui-bg-raised) }
173
173
  .scui-envelope { display:flex; align-items:flex-end; gap:7px; padding:7px; border:1px solid var(--scui-border-strong); border-radius:16px; background:var(--scui-bg) }.scui-envelope textarea { flex:1; min-width:0; min-height:34px; max-height:150px; resize:none; overflow-y:hidden; border:0; outline:0; background:transparent; color:var(--scui-fg) }.scui-envelope > span { display:flex; gap:4px }
174
+ .scui-envelope.scui-drop-target { border-color:var(--scui-accent); background:color-mix(in srgb,var(--scui-accent) 7%,var(--scui-bg)); box-shadow:0 0 0 2px color-mix(in srgb,var(--scui-accent) 16%,transparent) }
174
175
  .scui-attach { display:grid; flex:0 0 34px; width:34px; height:34px; place-items:center; border:0; border-radius:50%; background:transparent; color:var(--scui-muted) }.scui-attach:hover:not(:disabled) { background:var(--scui-fill); color:var(--scui-fg) }
175
176
  .scui-compose-context { display:flex; gap:5px; margin-bottom:6px; overflow-x:auto; scrollbar-width:thin }.scui-compose-context > span { display:flex; flex:0 0 auto; max-width:210px; align-items:center; gap:5px; padding:4px 5px 4px 7px; border:1px solid var(--scui-border); border-radius:999px; background:var(--scui-fill); font-size:10px }.scui-compose-context strong { overflow:hidden; text-overflow:ellipsis; white-space:nowrap }.scui-compose-context button { display:grid; width:18px; height:18px; padding:0; place-items:center; border:0; border-radius:50%; background:transparent }.scui-compose-context button:hover { background:color-mix(in srgb,var(--scui-fg) 9%,transparent) }.scui-context-error { display:block; margin:0 2px 6px; color:var(--scui-danger) }
177
+ .scui-compose-images { display:flex; gap:6px; margin-bottom:6px; overflow-x:auto; scrollbar-width:thin }.scui-compose-images > span { position:relative; display:grid; flex:0 0 58px; width:58px; height:58px; overflow:hidden; border:1px solid var(--scui-border); border-radius:8px; background:var(--scui-fill); place-items:center }.scui-compose-images img { width:100%; height:100%; object-fit:cover }.scui-compose-images strong { position:absolute; right:2px; bottom:2px; left:2px; overflow:hidden; padding:2px 3px; border-radius:4px; background:rgba(0,0,0,.65); color:#fff; font-size:8px; font-weight:500; text-overflow:ellipsis; white-space:nowrap }.scui-compose-images button { position:absolute; z-index:1; top:2px; right:2px; display:grid; width:19px; height:19px; padding:0; border:1px solid rgba(255,255,255,.32); border-radius:50%; background:rgba(0,0,0,.68); color:#fff; place-items:center; cursor:pointer }
178
+ .scui-message-images { display:flex; max-width:280px; gap:5px; margin-bottom:6px; flex-wrap:wrap }.scui-message-images img { display:block; width:auto; min-width:72px; max-width:100%; height:auto; max-height:210px; border:1px solid var(--scui-border); border-radius:8px; object-fit:contain; background:var(--scui-fill) }.scui-message-images > span { display:flex; align-items:center; gap:5px; padding:5px 7px; border:1px solid var(--scui-border); border-radius:7px; color:var(--scui-muted); font-size:10px }
176
179
  .scui-send,.scui-stop { display:grid; width:29px; height:29px; padding:0; place-items:center; border:0; border-radius:8px; background:var(--scui-accent); color:#fff; cursor:pointer }.scui-stop { background:var(--scui-danger) }.scui-send:disabled,.scui-stop:disabled { opacity:.4; cursor:default }.scui-control-spinner { box-sizing:border-box; width:13px; height:13px; border:1.5px solid currentColor; border-right-color:transparent; border-radius:50%; animation:scui-spin .75s linear infinite }
177
180
  .scui-queue { display:grid; gap:4px; max-height:85px; margin-bottom:6px; overflow:auto; font-size:10.5px }.scui-queue > span { display:flex; gap:6px; padding:4px 6px; border-radius:5px; background:var(--scui-fill) }.scui-queue > span > span { display:grid; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }.scui-queue small { color:var(--scui-muted) }.scui-queue > span button { margin-left:auto; border:0; background:transparent }
178
181
  .scui-harness-picker { display:flex; align-items:center; gap:7px; margin-bottom:7px }.scui-harness-picker select { margin-left:auto; max-width:55%; padding:4px; border:1px solid var(--scui-border); border-radius:6px; background:var(--scui-bg); color:var(--scui-fg) }