@volter-ai-dev/supercode-ui 0.1.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.
- package/README.md +116 -0
- package/components.mjs +963 -0
- package/composer.mjs +168 -0
- package/controller.d.ts +53 -0
- package/controller.mjs +262 -0
- package/conversation.mjs +375 -0
- package/core.mjs +349 -0
- package/embed.mjs +972 -0
- package/index.d.ts +313 -0
- package/index.mjs +3 -0
- package/logo.mjs +114 -0
- package/messenger.mjs +947 -0
- package/package.json +106 -0
- package/sessions.mjs +196 -0
- package/styles.css +154 -0
package/package.json
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@volter-ai-dev/supercode-ui",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Composable default UI kit for Supercode-powered coding-agent experiences",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./index.d.ts",
|
|
9
|
+
"import": "./index.mjs"
|
|
10
|
+
},
|
|
11
|
+
"./core": {
|
|
12
|
+
"types": "./index.d.ts",
|
|
13
|
+
"import": "./core.mjs"
|
|
14
|
+
},
|
|
15
|
+
"./controller": {
|
|
16
|
+
"types": "./controller.d.ts",
|
|
17
|
+
"import": "./controller.mjs"
|
|
18
|
+
},
|
|
19
|
+
"./preact": {
|
|
20
|
+
"types": "./index.d.ts",
|
|
21
|
+
"import": "./components.mjs"
|
|
22
|
+
},
|
|
23
|
+
"./preact/logo": {
|
|
24
|
+
"types": "./index.d.ts",
|
|
25
|
+
"import": "./logo.mjs"
|
|
26
|
+
},
|
|
27
|
+
"./preact/conversation": {
|
|
28
|
+
"types": "./index.d.ts",
|
|
29
|
+
"import": "./conversation.mjs"
|
|
30
|
+
},
|
|
31
|
+
"./preact/sessions": {
|
|
32
|
+
"types": "./index.d.ts",
|
|
33
|
+
"import": "./sessions.mjs"
|
|
34
|
+
},
|
|
35
|
+
"./preact/composer": {
|
|
36
|
+
"types": "./index.d.ts",
|
|
37
|
+
"import": "./composer.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./preact/messenger": {
|
|
40
|
+
"types": "./index.d.ts",
|
|
41
|
+
"import": "./messenger.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./embed": {
|
|
44
|
+
"types": "./index.d.ts",
|
|
45
|
+
"import": "./embed.mjs"
|
|
46
|
+
},
|
|
47
|
+
"./styles.css": "./styles.css"
|
|
48
|
+
},
|
|
49
|
+
"types": "./index.d.ts",
|
|
50
|
+
"files": [
|
|
51
|
+
"core.mjs",
|
|
52
|
+
"controller.mjs",
|
|
53
|
+
"controller.d.ts",
|
|
54
|
+
"components.mjs",
|
|
55
|
+
"logo.mjs",
|
|
56
|
+
"conversation.mjs",
|
|
57
|
+
"sessions.mjs",
|
|
58
|
+
"composer.mjs",
|
|
59
|
+
"messenger.mjs",
|
|
60
|
+
"embed.mjs",
|
|
61
|
+
"index.mjs",
|
|
62
|
+
"index.d.ts",
|
|
63
|
+
"styles.css",
|
|
64
|
+
"README.md"
|
|
65
|
+
],
|
|
66
|
+
"scripts": {
|
|
67
|
+
"build": "esbuild src/components.jsx src/embed.jsx src/logo.jsx src/conversation.jsx src/sessions.jsx src/composer.jsx src/messenger.jsx --bundle --format=esm --platform=browser --jsx=automatic --jsx-import-source=preact --external:preact --external:preact/* --external:markdown-it --outdir=. --out-extension:.js=.mjs",
|
|
68
|
+
"build:fixture": "esbuild test/browser-entry.jsx --bundle --format=esm --platform=browser --jsx=automatic --jsx-import-source=preact --outfile=test/browser-bundle.mjs",
|
|
69
|
+
"storybook": "npm run build && storybook dev -p 6006",
|
|
70
|
+
"build:storybook": "npm run build && storybook build",
|
|
71
|
+
"test:storybook": "vitest --run",
|
|
72
|
+
"test": "node --test test/*.test.mjs"
|
|
73
|
+
},
|
|
74
|
+
"dependencies": {
|
|
75
|
+
"markdown-it": "^14.1.0"
|
|
76
|
+
},
|
|
77
|
+
"peerDependencies": {
|
|
78
|
+
"@volter-ai-dev/supercode-client": ">=0.3.7",
|
|
79
|
+
"preact": ">=10.19.0 <11"
|
|
80
|
+
},
|
|
81
|
+
"peerDependenciesMeta": {
|
|
82
|
+
"@volter-ai-dev/supercode-client": {
|
|
83
|
+
"optional": true
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"devDependencies": {
|
|
87
|
+
"@storybook/addon-a11y": "10.5.9",
|
|
88
|
+
"@storybook/addon-docs": "10.5.9",
|
|
89
|
+
"@storybook/addon-themes": "10.5.9",
|
|
90
|
+
"@storybook/addon-vitest": "10.5.9",
|
|
91
|
+
"@storybook/preact-vite": "10.5.9",
|
|
92
|
+
"@types/react": "19.2.18",
|
|
93
|
+
"@vitest/browser-playwright": "4.1.10",
|
|
94
|
+
"esbuild": "^0.25.0",
|
|
95
|
+
"playwright": "1.62.1",
|
|
96
|
+
"preact": "^10.19.0",
|
|
97
|
+
"preact-render-to-string": "^6.5.0",
|
|
98
|
+
"storybook": "10.5.9",
|
|
99
|
+
"vite": "7.3.6",
|
|
100
|
+
"vitest": "4.1.10"
|
|
101
|
+
},
|
|
102
|
+
"engines": {
|
|
103
|
+
"node": ">=20"
|
|
104
|
+
},
|
|
105
|
+
"license": "MIT OR Apache-2.0"
|
|
106
|
+
}
|
package/sessions.mjs
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
// src/components.jsx
|
|
2
|
+
import MarkdownIt from "markdown-it";
|
|
3
|
+
import { useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "preact/hooks";
|
|
4
|
+
|
|
5
|
+
// core.mjs
|
|
6
|
+
var HARNESS_NAMES = Object.freeze({
|
|
7
|
+
"claude-code": "Claude Code",
|
|
8
|
+
codex: "Codex",
|
|
9
|
+
opencode: "OpenCode",
|
|
10
|
+
pi: "Pi",
|
|
11
|
+
grok: "Grok"
|
|
12
|
+
});
|
|
13
|
+
var DEFAULT_LABELS = Object.freeze({
|
|
14
|
+
chats: "Chats",
|
|
15
|
+
newChat: "New chat",
|
|
16
|
+
searchChats: "Search chats",
|
|
17
|
+
askAgent: "Ask your agent\u2026",
|
|
18
|
+
continueHere: "Continue here",
|
|
19
|
+
joinLive: "Join live",
|
|
20
|
+
forkHere: "Fork here"
|
|
21
|
+
});
|
|
22
|
+
var EMPTY_UI_STATE = Object.freeze({
|
|
23
|
+
pill: Object.freeze({ tone: "off", label: "connecting\u2026" }),
|
|
24
|
+
startup: "connecting",
|
|
25
|
+
transcript: Object.freeze([]),
|
|
26
|
+
busy: false,
|
|
27
|
+
operation: null,
|
|
28
|
+
needsInput: false,
|
|
29
|
+
harness: "",
|
|
30
|
+
mode: "none",
|
|
31
|
+
strategy: null,
|
|
32
|
+
canSend: false,
|
|
33
|
+
canResume: false,
|
|
34
|
+
canBranch: false,
|
|
35
|
+
canAttach: false,
|
|
36
|
+
canDetach: false,
|
|
37
|
+
canOpenTerminal: false,
|
|
38
|
+
canExport: false,
|
|
39
|
+
canReduce: false,
|
|
40
|
+
canInterrupt: false,
|
|
41
|
+
canRespond: false,
|
|
42
|
+
messaging: null,
|
|
43
|
+
workspace: "",
|
|
44
|
+
taskPlan: Object.freeze({ source: "none", items: Object.freeze([]), residueCount: 0, observedAt: null }),
|
|
45
|
+
semantics: Object.freeze({ fidelity: null, residue: Object.freeze([]), residueCount: 0, parseErrors: 0, rawRecords: 0, subagents: Object.freeze([]) }),
|
|
46
|
+
terminalHandoff: null,
|
|
47
|
+
exportBackTarget: null,
|
|
48
|
+
exportReceipt: null,
|
|
49
|
+
reductionReceipt: null,
|
|
50
|
+
error: null,
|
|
51
|
+
recoverable: false,
|
|
52
|
+
harnesses: Object.freeze([]),
|
|
53
|
+
history: Object.freeze({ sessionLimit: 0, hasMoreSessions: false, transcriptLimit: 120, hasEarlier: false }),
|
|
54
|
+
savedDraft: "",
|
|
55
|
+
attention: Object.freeze([]),
|
|
56
|
+
sessions: Object.freeze([]),
|
|
57
|
+
attached: null,
|
|
58
|
+
owned: null,
|
|
59
|
+
attachError: null
|
|
60
|
+
});
|
|
61
|
+
function harnessDisplayName(id) {
|
|
62
|
+
return HARNESS_NAMES[id] ?? id;
|
|
63
|
+
}
|
|
64
|
+
function sessionDisplayName(session) {
|
|
65
|
+
const title = session.title?.trim();
|
|
66
|
+
return title && title !== session.name ? title : session.name || "Untitled chat";
|
|
67
|
+
}
|
|
68
|
+
function sessionActivity(state, row) {
|
|
69
|
+
if (state.needsInput && row.active) return "needs-input";
|
|
70
|
+
if (state.busy && row.active) return "working";
|
|
71
|
+
const attention = state.attention.find((item) => item.key === row.key)?.kind;
|
|
72
|
+
if (attention) return attention;
|
|
73
|
+
if (row.runtimeStatus === "busy") return "working";
|
|
74
|
+
if (row.live || row.runtimeStatus === "idle") return "recent";
|
|
75
|
+
return "idle";
|
|
76
|
+
}
|
|
77
|
+
function filterSessions(rows, query) {
|
|
78
|
+
const needle = query.trim().toLocaleLowerCase();
|
|
79
|
+
if (!needle) return [...rows];
|
|
80
|
+
return rows.filter((row) => [row.name, row.title, row.cwd, row.harness, harnessDisplayName(row.harness)].some((value) => value.toLocaleLowerCase().includes(needle)));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/components.jsx
|
|
84
|
+
import { jsx, jsxs } from "preact/jsx-runtime";
|
|
85
|
+
var markdown = new MarkdownIt({ html: false, linkify: true, breaks: false });
|
|
86
|
+
var defaultLinkOpen = markdown.renderer.rules.link_open;
|
|
87
|
+
markdown.renderer.rules.link_open = (tokens, index, options, env, self) => {
|
|
88
|
+
tokens[index]?.attrSet("target", "_blank");
|
|
89
|
+
tokens[index]?.attrSet("rel", "noreferrer noopener");
|
|
90
|
+
return defaultLinkOpen ? defaultLinkOpen(tokens, index, options, env, self) : self.renderToken(tokens, index, options);
|
|
91
|
+
};
|
|
92
|
+
var LOGOS = {
|
|
93
|
+
"claude-code": {
|
|
94
|
+
viewBox: "-1 3.5 26 18",
|
|
95
|
+
paths: [
|
|
96
|
+
["path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M20.998 10.949H24v3.102h-3v3.028h-1.487V20H18v-2.921h-1.487V20H15v-2.921H9V20H7.488v-2.921H6V20H4.487v-2.921H3V14.05H0V10.95h3V5h17.998v5.949zM6 10.949h1.488V8.102H6v2.847zm10.51 0H18V8.102h-1.49v2.847z" }]
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
codex: {
|
|
100
|
+
viewBox: "-1 -1 26 26",
|
|
101
|
+
paths: [
|
|
102
|
+
["path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M8.086.457a6.105 6.105 0 013.046-.415c1.333.153 2.521.72 3.564 1.7a.117.117 0 00.107.029c1.408-.346 2.762-.224 4.061.366l.063.03.154.076c1.357.703 2.33 1.77 2.918 3.198.278.679.418 1.388.421 2.126a5.655 5.655 0 01-.18 1.631.167.167 0 00.04.155 5.982 5.982 0 011.578 2.891c.385 1.901-.01 3.615-1.183 5.14l-.182.22a6.063 6.063 0 01-2.934 1.851.162.162 0 00-.108.102c-.255.736-.511 1.364-.987 1.992-1.199 1.582-2.962 2.462-4.948 2.451-1.583-.008-2.986-.587-4.21-1.736a.145.145 0 00-.14-.032c-.518.167-1.04.191-1.604.185a5.924 5.924 0 01-2.595-.622 6.058 6.058 0 01-2.146-1.781c-.203-.269-.404-.522-.551-.821a7.74 7.74 0 01-.495-1.283 6.11 6.11 0 01-.017-3.064.166.166 0 00.008-.074.115.115 0 00-.037-.064 5.958 5.958 0 01-1.38-2.202 5.196 5.196 0 01-.333-1.589 6.915 6.915 0 01.188-2.132c.45-1.484 1.309-2.648 2.577-3.493.282-.188.55-.334.802-.438.286-.12.573-.22.861-.304a.129.129 0 00.087-.087A6.016 6.016 0 015.635 2.31C6.315 1.464 7.132.846 8.086.457zm-.804 7.85a.848.848 0 00-1.473.842l1.694 2.965-1.688 2.848a.849.849 0 001.46.864l1.94-3.272a.849.849 0 00.007-.854l-1.94-3.393zm5.446 6.24a.849.849 0 000 1.695h4.848a.849.849 0 000-1.696h-4.848z" }]
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
grok: {
|
|
106
|
+
viewBox: "-1 -1 26 26",
|
|
107
|
+
paths: [["path", { d: "M9.27 15.29l7.978-5.897c.391-.29.95-.177 1.137.272.98 2.369.542 5.215-1.41 7.169-1.951 1.954-4.667 2.382-7.149 1.406l-2.711 1.257c3.889 2.661 8.611 2.003 11.562-.953 2.341-2.344 3.066-5.539 2.388-8.42l.006.007c-.983-4.232.242-5.924 2.75-9.383.06-.082.12-.164.179-.248l-3.301 3.305v-.01L9.267 15.292M7.623 16.723c-2.792-2.67-2.31-6.801.071-9.184 1.761-1.763 4.647-2.483 7.166-1.425l2.705-1.25a7.808 7.808 0 00-1.829-1A8.975 8.975 0 005.984 5.83c-2.533 2.536-3.33 6.436-1.962 9.764 1.022 2.487-.653 4.246-2.34 6.022-.599.63-1.199 1.259-1.682 1.925l7.62-6.815" }]]
|
|
108
|
+
},
|
|
109
|
+
opencode: { viewBox: "2.5 0 19 24", paths: [["path", { d: "M16 6H8v12h8V6zm4 16H4V2h16v20z" }]] },
|
|
110
|
+
pi: {
|
|
111
|
+
viewBox: "0 0 24 24",
|
|
112
|
+
paths: [
|
|
113
|
+
["path", { "fill-rule": "evenodd", "clip-rule": "evenodd", d: "M1 1h16.5v11H12v5.5H6.5V23H1V1zm5.5 5.5V12H12V6.5H6.5z" }],
|
|
114
|
+
["path", { d: "M17.5 12H23v11h-5.5V12z" }]
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
function HarnessLogo({ id, activity, size = 28, onMissingLogo }) {
|
|
119
|
+
const logo = LOGOS[id];
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
if (!logo) onMissingLogo?.(id);
|
|
122
|
+
}, [id, logo, onMissingLogo]);
|
|
123
|
+
if (!logo) return null;
|
|
124
|
+
return /* @__PURE__ */ jsxs("span", { class: "scui-logo", "data-harness": id, "data-activity": activity, style: `--scui-logo-size:${size}px`, "aria-hidden": "true", children: [
|
|
125
|
+
/* @__PURE__ */ jsx("svg", { viewBox: logo.viewBox, focusable: "false", children: logo.paths.map(([Tag, props], index) => /* @__PURE__ */ jsx(Tag, { ...props }, index)) }),
|
|
126
|
+
activity && activity !== "idle" ? /* @__PURE__ */ jsx("i", {}) : null
|
|
127
|
+
] });
|
|
128
|
+
}
|
|
129
|
+
function LoadingStatus({ state, compact = false }) {
|
|
130
|
+
const copy = {
|
|
131
|
+
connecting: ["Connecting to coding agents", "Checking installed harnesses and capabilities.", 0],
|
|
132
|
+
starting: [`Starting ${harnessDisplayName(state.harness) || "coding agent"}`, "Opening a controlled session in this workspace.", 1],
|
|
133
|
+
discovering: ["Loading recent sessions", "Scanning native session stores without loading full transcripts.", 2],
|
|
134
|
+
ready: ["Ready", "Coding sessions are up to date.", 3]
|
|
135
|
+
}[state.startup];
|
|
136
|
+
return /* @__PURE__ */ jsxs("div", { class: `scui-loading${compact ? " scui-loading-compact" : ""}`, role: "status", "aria-busy": state.startup !== "ready", children: [
|
|
137
|
+
/* @__PURE__ */ jsx("span", { class: "scui-orbit", "aria-hidden": "true", children: /* @__PURE__ */ jsx("i", {}) }),
|
|
138
|
+
/* @__PURE__ */ jsxs("span", { class: "scui-loading-copy", children: [
|
|
139
|
+
/* @__PURE__ */ jsx("strong", { children: copy[0] }),
|
|
140
|
+
/* @__PURE__ */ jsx("small", { children: copy[1] })
|
|
141
|
+
] }),
|
|
142
|
+
/* @__PURE__ */ jsx("span", { class: "scui-progress", "aria-hidden": "true", children: [1, 2, 3].map((step) => /* @__PURE__ */ jsx("i", { "data-progress": step <= copy[2] ? "done" : step === copy[2] + 1 ? "current" : "waiting" }, step)) })
|
|
143
|
+
] });
|
|
144
|
+
}
|
|
145
|
+
function SessionRow({ row, state, onOpen }) {
|
|
146
|
+
const activity = sessionActivity(state, row);
|
|
147
|
+
const preview = state.attention.find((item) => item.key === row.key)?.preview;
|
|
148
|
+
return /* @__PURE__ */ jsxs("button", { class: "scui-session", "data-active": row.active, "data-activity": activity, type: "button", onClick: () => onOpen(row), children: [
|
|
149
|
+
/* @__PURE__ */ jsx(HarnessLogo, { id: row.harness, activity, size: 34 }),
|
|
150
|
+
/* @__PURE__ */ jsxs("span", { class: "scui-session-copy", children: [
|
|
151
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
152
|
+
/* @__PURE__ */ jsx("strong", { children: sessionDisplayName(row) }),
|
|
153
|
+
/* @__PURE__ */ jsx("small", { children: row.age })
|
|
154
|
+
] }),
|
|
155
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
156
|
+
/* @__PURE__ */ jsx("b", { children: harnessDisplayName(row.harness) }),
|
|
157
|
+
/* @__PURE__ */ jsx("small", { children: preview || row.cwd || row.name })
|
|
158
|
+
] }),
|
|
159
|
+
state.attachError?.key === row.key ? /* @__PURE__ */ jsx("em", { children: state.attachError.message }) : null
|
|
160
|
+
] })
|
|
161
|
+
] });
|
|
162
|
+
}
|
|
163
|
+
function SessionList({ state, adapter, onOpen, onNew, onClose, components = {}, labels = DEFAULT_LABELS }) {
|
|
164
|
+
const [query, setQuery] = useState("");
|
|
165
|
+
const rows = filterSessions(state.sessions, query);
|
|
166
|
+
const Row = components.SessionRow ?? SessionRow;
|
|
167
|
+
return /* @__PURE__ */ jsxs("section", { class: "scui-list", children: [
|
|
168
|
+
/* @__PURE__ */ jsxs("header", { class: "scui-head", children: [
|
|
169
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
170
|
+
/* @__PURE__ */ jsx("strong", { children: labels.chats }),
|
|
171
|
+
/* @__PURE__ */ jsxs("small", { children: [
|
|
172
|
+
state.sessions.length,
|
|
173
|
+
" recent conversations"
|
|
174
|
+
] })
|
|
175
|
+
] }),
|
|
176
|
+
/* @__PURE__ */ jsx("button", { type: "button", "aria-label": labels.newChat, disabled: !state.harnesses.some((item) => item.startable), onClick: onNew, children: "\uFF0B" }),
|
|
177
|
+
onClose ? /* @__PURE__ */ jsx("button", { type: "button", "aria-label": "Close", onClick: onClose, children: "\xD7" }) : null
|
|
178
|
+
] }),
|
|
179
|
+
state.startup !== "ready" ? /* @__PURE__ */ jsx(LoadingStatus, { state, compact: rows.length > 0 }) : null,
|
|
180
|
+
state.sessions.length > 4 ? /* @__PURE__ */ jsxs("label", { class: "scui-search", children: [
|
|
181
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2315" }),
|
|
182
|
+
/* @__PURE__ */ jsx("input", { type: "search", "aria-label": labels.searchChats, placeholder: labels.searchChats, value: query, onInput: (event) => setQuery(event.currentTarget.value) }),
|
|
183
|
+
/* @__PURE__ */ jsx("small", { children: rows.length })
|
|
184
|
+
] }) : null,
|
|
185
|
+
/* @__PURE__ */ jsxs("div", { class: "scui-session-rows", children: [
|
|
186
|
+
!rows.length && state.startup === "ready" ? /* @__PURE__ */ jsx("div", { class: "scui-empty", children: query ? "No chats match your search." : state.error ?? "No coding chats found." }) : null,
|
|
187
|
+
rows.map((row) => /* @__PURE__ */ jsx(Row, { value: row, row, state, adapter, onOpen }, row.key)),
|
|
188
|
+
state.history.hasMoreSessions ? /* @__PURE__ */ jsx("button", { class: "scui-load", type: "button", onClick: () => adapter.onIntent({ action: "loadSessions" }), children: "Load older chats" }) : null
|
|
189
|
+
] })
|
|
190
|
+
] });
|
|
191
|
+
}
|
|
192
|
+
export {
|
|
193
|
+
LoadingStatus,
|
|
194
|
+
SessionList,
|
|
195
|
+
SessionRow
|
|
196
|
+
};
|
package/styles.css
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
:where(.scui-root) {
|
|
2
|
+
--scui-width: 420px;
|
|
3
|
+
--scui-height: 480px;
|
|
4
|
+
--scui-bg: #fff;
|
|
5
|
+
--scui-bg-raised: #f7f7f6;
|
|
6
|
+
--scui-fill: #f1f1ef;
|
|
7
|
+
--scui-fg: #191918;
|
|
8
|
+
--scui-muted: #5f5f5a;
|
|
9
|
+
--scui-border: #deded9;
|
|
10
|
+
--scui-border-strong: #c7c7c0;
|
|
11
|
+
--scui-accent: #2458b8;
|
|
12
|
+
--scui-positive: #22863a;
|
|
13
|
+
--scui-warning: #b26a00;
|
|
14
|
+
--scui-danger: #b4232e;
|
|
15
|
+
--scui-radius: 14px;
|
|
16
|
+
--scui-font: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
display: flex;
|
|
19
|
+
position: relative;
|
|
20
|
+
width: min(var(--scui-width), 100%);
|
|
21
|
+
height: min(var(--scui-height), 100%);
|
|
22
|
+
overflow: hidden;
|
|
23
|
+
border: 1px solid var(--scui-border);
|
|
24
|
+
border-radius: var(--scui-radius);
|
|
25
|
+
background: var(--scui-bg);
|
|
26
|
+
color: var(--scui-fg);
|
|
27
|
+
font: 13px/1.4 var(--scui-font);
|
|
28
|
+
color-scheme: light dark;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@media (prefers-color-scheme: dark) {
|
|
32
|
+
:where(.scui-root) {
|
|
33
|
+
--scui-bg: #151515;
|
|
34
|
+
--scui-bg-raised: #1c1c1b;
|
|
35
|
+
--scui-fill: #242422;
|
|
36
|
+
--scui-fg: #f3f3ef;
|
|
37
|
+
--scui-muted: #a3a39d;
|
|
38
|
+
--scui-border: #353532;
|
|
39
|
+
--scui-border-strong: #4a4a45;
|
|
40
|
+
--scui-accent: #72a7ff;
|
|
41
|
+
--scui-positive: #57c26e;
|
|
42
|
+
--scui-warning: #e8a23a;
|
|
43
|
+
--scui-danger: #ff747d;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
:where(.scui-root *), :where(.scui-root *::before), :where(.scui-root *::after) { box-sizing: border-box }
|
|
48
|
+
:where(.scui-root button, .scui-root input, .scui-root textarea, .scui-root select) { font: inherit }
|
|
49
|
+
:where(.scui-root button) { color: inherit }
|
|
50
|
+
:where(.scui-list button, .scui-chat button, .scui-request button, .scui-activity button, .scui-compose button, .scui-continuation button) { color: inherit }
|
|
51
|
+
:where(.scui-root button:focus-visible, .scui-root input:focus-visible, .scui-root textarea:focus-visible, .scui-root select:focus-visible, .scui-root [tabindex]:focus-visible) { outline: 2px solid var(--scui-accent); outline-offset: -2px }
|
|
52
|
+
|
|
53
|
+
.scui-list,.scui-chat { display:flex; flex:1; min-width:0; min-height:0; flex-direction:column }
|
|
54
|
+
.scui-head { display:flex; flex:none; align-items:center; gap:8px; min-height:49px; padding:7px 8px 7px 12px; border-bottom:1px solid var(--scui-border); background:var(--scui-bg-raised) }
|
|
55
|
+
.scui-head > span { display:grid; flex:1; min-width:0 }
|
|
56
|
+
.scui-head strong { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:13px }
|
|
57
|
+
.scui-head small { overflow:hidden; color:var(--scui-muted); font-size:10.5px; text-overflow:ellipsis; white-space:nowrap }
|
|
58
|
+
.scui-head > button,.scui-menu > summary { display:grid; place-items:center; width:30px; height:30px; padding:0; border:0; border-radius:8px; background:transparent; cursor:pointer; font-size:18px; list-style:none }
|
|
59
|
+
.scui-head > button:hover,.scui-menu > summary:hover { background:var(--scui-fill) }
|
|
60
|
+
.scui-menu { position:relative }
|
|
61
|
+
.scui-menu > summary::-webkit-details-marker { display:none }
|
|
62
|
+
.scui-menu > div { position:absolute; z-index:20; top:36px; right:0; display:grid; width:250px; max-height:300px; padding:5px; overflow:auto; border:1px solid var(--scui-border-strong); border-radius:10px; background:var(--scui-bg); box-shadow:0 10px 28px rgba(0,0,0,.22) }
|
|
63
|
+
.scui-menu button { padding:8px; border:0; border-radius:6px; background:transparent; text-align:left; cursor:pointer }
|
|
64
|
+
.scui-menu button:hover { background:var(--scui-fill) }
|
|
65
|
+
|
|
66
|
+
.scui-logo { position:relative; display:inline-grid; place-items:center; width:var(--scui-logo-size); height:var(--scui-logo-size); flex:none; border:1px solid var(--scui-border); border-radius:50%; background:#111; color:#f7f7f5 }
|
|
67
|
+
.scui-logo svg { width:70%; height:70%; fill:currentColor }
|
|
68
|
+
.scui-logo[data-harness="claude-code"] { color:#d97757 }
|
|
69
|
+
.scui-logo[data-harness="codex"] { color:#111; background:#f7f7f5 }
|
|
70
|
+
.scui-logo[data-harness="pi"] { color:#111; background:#efefeb }
|
|
71
|
+
.scui-logo > i { position:absolute; right:-5%; bottom:-5%; width:32%; height:32%; border:2px solid var(--scui-bg); border-radius:50%; background:var(--scui-muted) }
|
|
72
|
+
.scui-logo[data-activity="working"] > i { background:var(--scui-accent); animation:scui-breathe 1.4s ease-in-out infinite }
|
|
73
|
+
.scui-logo[data-activity="needs-input"] > i { background:var(--scui-warning) }
|
|
74
|
+
.scui-logo[data-activity="failed"] > i { background:var(--scui-danger) }
|
|
75
|
+
.scui-logo[data-activity="finished"] > i,.scui-logo[data-activity="unseen"] > i { background:var(--scui-positive) }
|
|
76
|
+
|
|
77
|
+
.scui-loading { display:grid; grid-template-columns:30px minmax(0,1fr); gap:4px 10px; align-items:center; margin:auto; padding:18px; color:var(--scui-muted) }
|
|
78
|
+
.scui-loading-compact { width:calc(100% - 16px); margin:8px; padding:8px; border:1px solid var(--scui-border); border-radius:9px; background:var(--scui-bg-raised) }
|
|
79
|
+
.scui-orbit { grid-row:1 / span 2; position:relative; width:27px; height:27px; border:1px solid var(--scui-border-strong); border-radius:50% }
|
|
80
|
+
.scui-orbit::before { content:""; position:absolute; inset:5px; border-radius:50%; background:var(--scui-fill); animation:scui-breathe 1.5s ease-in-out infinite }
|
|
81
|
+
.scui-orbit i { position:absolute; inset:-1px; border:2px solid transparent; border-top-color:var(--scui-accent); border-radius:50%; animation:scui-spin 1s linear infinite }
|
|
82
|
+
.scui-loading-copy { display:grid; gap:2px }.scui-loading-copy strong { color:var(--scui-fg); font-size:12px }.scui-loading-copy small { font-size:10.5px }
|
|
83
|
+
.scui-progress { grid-column:2; display:grid; grid-template-columns:repeat(3,minmax(18px,38px)); gap:4px }
|
|
84
|
+
.scui-progress i { height:2px; overflow:hidden; border-radius:2px; background:var(--scui-fill) }
|
|
85
|
+
.scui-progress i[data-progress="done"] { background:var(--scui-accent) }
|
|
86
|
+
.scui-progress i[data-progress="current"]::after { content:""; display:block; width:55%; height:100%; background:var(--scui-accent); animation:scui-progress 1s ease-in-out infinite alternate }
|
|
87
|
+
|
|
88
|
+
.scui-search { display:flex; flex:none; align-items:center; gap:7px; margin:8px; padding:6px 8px; border:1px solid var(--scui-border); border-radius:8px; background:var(--scui-bg-raised); color:var(--scui-muted) }
|
|
89
|
+
.scui-search input { flex:1; min-width:0; border:0; outline:0; background:transparent; color:var(--scui-fg) }
|
|
90
|
+
.scui-session-rows { flex:1; min-height:0; overflow:auto; padding:0 6px 8px }
|
|
91
|
+
.scui-session { display:flex; align-items:center; gap:9px; width:100%; padding:7px 8px; border:0; border-radius:9px; background:transparent; text-align:left; cursor:pointer }
|
|
92
|
+
.scui-session:hover,.scui-session[data-active="true"] { background:var(--scui-fill) }
|
|
93
|
+
.scui-session-copy { display:grid; flex:1; min-width:0; gap:2px }
|
|
94
|
+
.scui-session-copy > span { display:flex; align-items:baseline; gap:7px; min-width:0 }
|
|
95
|
+
.scui-session-copy strong,.scui-session-copy span > small { overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
|
|
96
|
+
.scui-session-copy strong { flex:1; font-size:12.5px }.scui-session-copy span:first-child > small { flex:none; color:var(--scui-muted); font-size:10px }
|
|
97
|
+
.scui-session-copy b { flex:none; padding:1px 5px; border-radius:4px; background:var(--scui-bg-raised); color:var(--scui-muted); font-size:9px; text-transform:uppercase }
|
|
98
|
+
.scui-session-copy span:last-child > small { color:var(--scui-muted); font-size:10.5px }
|
|
99
|
+
.scui-session-copy em { overflow:hidden; color:var(--scui-danger); font-size:10px; font-style:normal; text-overflow:ellipsis; white-space:nowrap }
|
|
100
|
+
.scui-load { display:block; margin:7px auto; padding:5px 10px; border:1px solid var(--scui-border); border-radius:8px; background:var(--scui-bg-raised); color:var(--scui-muted); cursor:pointer }
|
|
101
|
+
|
|
102
|
+
.scui-operation,.scui-error,.scui-receipt { display:flex; flex:none; align-items:center; gap:8px; min-height:32px; padding:6px 10px; border-bottom:1px solid var(--scui-border); background:var(--scui-bg-raised); font-size:10.5px }
|
|
103
|
+
.scui-operation i { width:11px; height:11px; border:2px solid var(--scui-border); border-top-color:var(--scui-accent); border-radius:50%; animation:scui-spin .8s linear infinite }
|
|
104
|
+
.scui-error { color:var(--scui-danger) }.scui-error span,.scui-receipt span { flex:1; min-width:0 }
|
|
105
|
+
.scui-error button,.scui-receipt button { border:0; background:transparent; color:var(--scui-accent); cursor:pointer }
|
|
106
|
+
.scui-receipt span { display:grid }.scui-receipt small { overflow:hidden; color:var(--scui-muted); text-overflow:ellipsis; white-space:nowrap }
|
|
107
|
+
|
|
108
|
+
.scui-conversation-wrap { position:relative; display:flex; flex:1; min-height:0 }
|
|
109
|
+
.scui-conversation { flex:1; min-width:0; overflow:auto; overscroll-behavior:contain; padding:12px 16px 18px }
|
|
110
|
+
.scui-conversation > div { display:flex; flex-direction:column; gap:10px }
|
|
111
|
+
.scui-empty { margin:auto; padding:20px; color:var(--scui-muted); text-align:center }
|
|
112
|
+
.scui-latest { position:absolute; z-index:5; right:12px; bottom:8px; padding:5px 9px; border:1px solid var(--scui-border-strong); border-radius:999px; background:var(--scui-bg-raised); box-shadow:0 2px 8px rgba(0,0,0,.2); cursor:pointer }
|
|
113
|
+
.scui-message { position:relative; overflow-wrap:anywhere }
|
|
114
|
+
.scui-message[data-role="user"] { align-self:flex-end; max-width:90%; padding:8px 9px; border:1px solid var(--scui-border); border-radius:10px; background:var(--scui-fill) }
|
|
115
|
+
.scui-pending { opacity:.7 }.scui-pending > small { display:block; margin-top:3px; color:var(--scui-muted); font-size:9.5px }
|
|
116
|
+
.scui-markdown { font-size:12.5px; line-height:1.55 }.scui-markdown > :first-child { margin-top:0 }.scui-markdown > :last-child { margin-bottom:0 }
|
|
117
|
+
.scui-markdown p { margin:0 0 8px }.scui-markdown h1,.scui-markdown h2,.scui-markdown h3 { margin:12px 0 5px; line-height:1.25 }.scui-markdown h1 { font-size:17px }.scui-markdown h2 { font-size:15px }.scui-markdown h3 { font-size:13px }
|
|
118
|
+
.scui-markdown ul,.scui-markdown ol { margin:5px 0 9px; padding-left:20px }.scui-markdown blockquote { margin:8px 0; padding-left:9px; border-left:2px solid var(--scui-border-strong); color:var(--scui-muted) }
|
|
119
|
+
.scui-markdown a { color:var(--scui-accent) }.scui-markdown code { padding:1px 4px; border-radius:4px; background:var(--scui-fill); font:.92em ui-monospace,SFMono-Regular,Menlo,monospace }
|
|
120
|
+
.scui-markdown pre { padding:8px; overflow:auto; border:1px solid var(--scui-border); border-radius:7px; background:var(--scui-bg-raised) }.scui-markdown pre code { padding:0; background:transparent }
|
|
121
|
+
.scui-markdown table { display:block; overflow:auto; border-collapse:collapse }.scui-markdown th,.scui-markdown td { padding:4px; border:1px solid var(--scui-border) }
|
|
122
|
+
.scui-context,.scui-reasoning,.scui-details,.scui-plan { color:var(--scui-muted); font-size:10.5px }
|
|
123
|
+
.scui-context summary,.scui-reasoning summary,.scui-details summary,.scui-plan summary { cursor:pointer }
|
|
124
|
+
.scui-context > div,.scui-details > div { display:grid; gap:5px; max-height:150px; margin-top:5px; padding:7px; overflow:auto; border:1px solid var(--scui-border); border-radius:7px; background:var(--scui-bg-raised) }
|
|
125
|
+
.scui-context p,.scui-details p { display:grid; margin:0 }.scui-context strong,.scui-details strong { color:var(--scui-fg) }
|
|
126
|
+
.scui-truncated { display:block; margin-top:5px; color:var(--scui-warning) }
|
|
127
|
+
.scui-notice { align-self:center; max-width:90%; padding:5px 8px; border-radius:7px; background:var(--scui-bg-raised); color:var(--scui-muted); font-size:10.5px; text-align:center }
|
|
128
|
+
|
|
129
|
+
.scui-activity { overflow:hidden; border:1px solid var(--scui-border); border-radius:9px; background:var(--scui-bg-raised) }
|
|
130
|
+
.scui-activity-head,.scui-tool-head { display:flex; align-items:center; gap:6px; width:100%; min-height:32px; padding:0 8px; border:0; background:transparent; text-align:left; cursor:pointer }
|
|
131
|
+
.scui-activity-head strong { font-size:11px }.scui-activity-head small { color:var(--scui-muted) }.scui-spacer { flex:1 }
|
|
132
|
+
.scui-fold { font-size:16px; transition:transform 120ms }.scui-fold[data-open="true"] { transform:rotate(90deg) }
|
|
133
|
+
.scui-tool { border-top:1px solid var(--scui-border) }.scui-tool-head:disabled { cursor:default }.scui-tool-glyph { width:18px; color:var(--scui-accent); text-align:center }.scui-tool-head strong { font-size:10.5px; text-transform:capitalize }
|
|
134
|
+
.scui-tool-target { min-width:0; overflow:hidden; color:var(--scui-muted); font:10px ui-monospace,SFMono-Regular,Menlo,monospace; text-overflow:ellipsis; white-space:nowrap }
|
|
135
|
+
.scui-tool-detail { padding:0 7px 7px }.scui-tool-detail pre { max-height:220px; margin:0 0 5px; padding:7px; overflow:auto; border-radius:6px; background:var(--scui-bg); font:10px/1.45 ui-monospace,SFMono-Regular,Menlo,monospace; white-space:pre-wrap }.scui-tool-detail pre[data-error="true"] { color:var(--scui-danger) }
|
|
136
|
+
.scui-request { padding:9px; border:1px solid var(--scui-warning); border-radius:9px; background:color-mix(in srgb,var(--scui-warning) 8%,var(--scui-bg)) }.scui-request-actions { display:flex; flex-wrap:wrap; gap:5px }.scui-request-actions button { padding:5px 8px; border:1px solid var(--scui-border-strong); border-radius:6px; background:var(--scui-bg); cursor:pointer }
|
|
137
|
+
.scui-request-done { color:var(--scui-muted); font-size:10.5px }
|
|
138
|
+
.scui-plan > summary { display:flex; justify-content:space-between; padding:6px 8px; border:1px solid var(--scui-border); border-radius:7px; background:var(--scui-bg-raised) }.scui-plan ol { display:grid; gap:4px; max-height:140px; margin:5px 0 0; padding:7px 8px 7px 25px; overflow:auto; border:1px solid var(--scui-border); border-radius:7px }.scui-plan li[data-status="completed"] { text-decoration:line-through; opacity:.65 }
|
|
139
|
+
.scui-working { display:flex; align-items:center; gap:4px; color:var(--scui-muted) }.scui-working > span { color:var(--scui-accent) }.scui-working > i { width:4px; height:4px; border-radius:50%; background:currentColor; animation:scui-dots 1.2s infinite }.scui-working > i:nth-of-type(2) { animation-delay:.15s }.scui-working > i:nth-of-type(3) { animation-delay:.3s }
|
|
140
|
+
|
|
141
|
+
.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 }
|
|
142
|
+
.scui-compose { flex:none; padding:8px; border-top:1px solid var(--scui-border); background:var(--scui-bg-raised) }
|
|
143
|
+
.scui-envelope { display:flex; align-items:flex-end; gap:7px; padding:7px; border:1px solid var(--scui-border-strong); border-radius:10px; background:var(--scui-bg) }.scui-envelope textarea { flex:1; min-width:0; min-height:34px; max-height:150px; resize:none; border:0; outline:0; background:transparent; color:var(--scui-fg) }.scui-envelope > span { display:flex; gap:4px }
|
|
144
|
+
.scui-send,.scui-stop { width:29px; height:29px; 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 }
|
|
145
|
+
.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 button { margin-left:auto; border:0; background:transparent }
|
|
146
|
+
.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) }
|
|
147
|
+
.scui-new { display:grid; justify-items:center; gap:5px; margin:auto; padding:20px; color:var(--scui-muted); text-align:center }.scui-new > span { color:var(--scui-accent); font-size:28px }.scui-new strong { color:var(--scui-fg) }
|
|
148
|
+
.scui-opening { position:absolute; z-index:30; inset:49px 0 0; display:flex; align-items:center; justify-content:center; gap:10px; padding:20px; background:var(--scui-bg) }.scui-opening > span { display:grid }.scui-opening small { color:var(--scui-muted) }.scui-opening > i { width:16px; height:16px; border:2px solid var(--scui-border); border-top-color:var(--scui-accent); border-radius:50%; animation:scui-spin .8s linear infinite }
|
|
149
|
+
|
|
150
|
+
@keyframes scui-spin { to { transform:rotate(360deg) } }
|
|
151
|
+
@keyframes scui-breathe { 50% { transform:scale(.72); opacity:.5 } }
|
|
152
|
+
@keyframes scui-progress { from { transform:translateX(-100%) } to { transform:translateX(180%) } }
|
|
153
|
+
@keyframes scui-dots { 50% { transform:translateY(-3px); opacity:.45 } }
|
|
154
|
+
@media (prefers-reduced-motion:reduce) { .scui-root * { animation-duration:.001ms !important; animation-iteration-count:1 !important; transition:none !important } }
|