@spzxg/cli-ui 0.6.8 → 0.6.10
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/CHANGELOG.md +14 -1
- package/README.md +3 -3
- package/dist/{cli-ui-embed-Be9_d9jB.js → cli-ui-embed-CbxWozLO.js} +9599 -9604
- package/dist/{cli-ui-index-CzNfiynu.js → cli-ui-index-ImgEunSf.js} +2 -2
- package/dist/{cli-ui-jszip.min-BL0mSekN.js → cli-ui-jszip.min-DGdGLbxr.js} +2 -2
- package/dist/{cli-ui-jszip.min-DjCIAfse.js → cli-ui-jszip.min-DWmufeZi.js} +1 -1
- package/dist/{cli-ui-xlsx-CscI4xk0.js → cli-ui-xlsx-s2TcknA1.js} +1 -1
- package/dist/cli-ui.css +1 -1
- package/dist/cli-ui.js +1 -1
- package/package.json +1 -1
- package/src/chat/CliChat.tsx +5 -3
- package/src/chat/Composer.tsx +5 -5
- package/src/chat/useExecutionConfig.ts +4 -4
- package/src/operator/node/Composer.tsx +5 -4
- package/src/operator.base.css +15 -17
- package/src/operator.css +15 -17
- package/src/styles.css +12 -10
- package/src/ui/QueuedMessages.tsx +0 -1
package/dist/cli-ui.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as a, b as i, d as r, e as t, f as o, h as C, i as l, j as n, k as m, m as d, l as u, n as w, o as B, p as f } from "./cli-ui-embed-
|
|
1
|
+
import { C as a, b as i, d as r, e as t, f as o, h as C, i as l, j as n, k as m, m as d, l as u, n as w, o as B, p as f } from "./cli-ui-embed-CbxWozLO.js";
|
|
2
2
|
export {
|
|
3
3
|
a as CliBoard,
|
|
4
4
|
i as CliBrowserView,
|
package/package.json
CHANGED
package/src/chat/CliChat.tsx
CHANGED
|
@@ -234,9 +234,11 @@ function ChatInner({ slots, passiveContext = true, configurationBusy, onClear, j
|
|
|
234
234
|
const agent = task?.agent ?? conv?.turns[conv.turns.length - 1]?.agent ?? null;
|
|
235
235
|
const draftScope = store.draftScope ? `${store.draftScope}:${key ?? `new:${instanceId}`}` : key ?? `new:${instanceId}`;
|
|
236
236
|
const initialOptions = newConversation ?? store.getNewConversationOptions();
|
|
237
|
+
const executionReady = !batch && (!key || !!job);
|
|
238
|
+
const executionEnabled = showComposer && executionReady && (cfg.composer.agentSelector || cfg.composer.executionMode);
|
|
237
239
|
const execution = useExecutionConfig({ client: store.client, scope: draftScope,
|
|
238
240
|
target: key && !isNew ? key : null, running: running || batchPending,
|
|
239
|
-
enabled:
|
|
241
|
+
enabled: executionEnabled, ready: executionReady,
|
|
240
242
|
initial: { ...(initialOptions?.agent ? { agent: initialOptions.agent } : {}), ...initialOptions?.executionConfig },
|
|
241
243
|
});
|
|
242
244
|
const agentText = labelOf(execution.config?.agent ?? agent);
|
|
@@ -852,8 +854,8 @@ function ChatInner({ slots, passiveContext = true, configurationBusy, onClear, j
|
|
|
852
854
|
model: execution.config?.model, reasoning: execution.config?.reasoning, permission_mode: execution.config?.permission_mode }}
|
|
853
855
|
agents={execution.config?.agents} caps={executionAgent?.capabilities} defaults={executionAgent?.defaults}
|
|
854
856
|
showAgent={cfg.composer.agentSelector} showPermission={cfg.composer.executionMode}
|
|
855
|
-
unavailableReason={executionReadOnly ? "当前接入仅支持读取执行设置。" : execution.error ?? (execution.loading ? "正在读取执行设置…" : undefined)}
|
|
856
|
-
disabled={composerDisabled || running || batchPending || !!configurationBusy || execution.loading || executionReadOnly}
|
|
857
|
+
unavailableReason={batch ? "一次性任务沿用任务执行设置,不支持在对话中修改。" : executionReadOnly ? "当前接入仅支持读取执行设置。" : execution.error ?? (!executionEnabled || execution.loading ? "正在读取执行设置…" : undefined)}
|
|
858
|
+
disabled={!executionEnabled || composerDisabled || running || batchPending || !!configurationBusy || execution.loading || executionReadOnly}
|
|
857
859
|
onSetAgent={agent => execution.save({ agent, model: null, reasoning: null, permission_mode: null })}
|
|
858
860
|
onSetModel={model => execution.save({ model })} onSetReasoning={reasoning => execution.save({ reasoning })}
|
|
859
861
|
onSetPermission={permission_mode => execution.save({ permission_mode })} />
|
package/src/chat/Composer.tsx
CHANGED
|
@@ -109,10 +109,11 @@ export function Composer({ draft, placeholder, disabled, disabledHint, running,
|
|
|
109
109
|
const tooLong = total > MAX_MESSAGE_CHARS;
|
|
110
110
|
const reading = pending.some((p) => p.status === "reading");
|
|
111
111
|
// 运行中不允许排队时,等这一轮结束再发。
|
|
112
|
-
const canSend = !!message.trim() && !pending.length && !reading && !tooLong && !sending && (!running || options.queue);
|
|
112
|
+
const canSend = !!message.trim() && !pending.length && !reading && !tooLong && !sending && !stopping && (!running || options.queue);
|
|
113
|
+
const showStop = running && !!onStop && !sending && (stopping || disabled || !options.queue || !message.trim());
|
|
113
114
|
|
|
114
115
|
const submit = async () => {
|
|
115
|
-
if (!canSend || disabled || readComposerDraft(draft).sending) return;
|
|
116
|
+
if (!canSend || disabled || stopLock.current || readComposerDraft(draft).sending) return;
|
|
116
117
|
const submitted = JSON.stringify([val, blocks]);
|
|
117
118
|
setSending(true);
|
|
118
119
|
setError(null);
|
|
@@ -210,7 +211,7 @@ export function Composer({ draft, placeholder, disabled, disabledHint, running,
|
|
|
210
211
|
{options.fileUpload && !disabled && <>
|
|
211
212
|
<input ref={fileRef} type="file" accept={uploadDocument ? FILE_UPLOAD_ACCEPT : ACCEPT_ATTR} multiple hidden onChange={(e) => { addFiles(Array.from(e.target.files ?? [])); e.target.value = ""; }} />
|
|
212
213
|
<button type="button" className="cli-attach" disabled={sending} aria-label={uploadDocument ? "添加文件" : "添加文档"} title={uploadDocument ? "添加文件(也可拖拽进来);HTML、Markdown 最大 100 MiB,其他支持类型最大 10 MiB" : `添加文档:${ACCEPTED_LABEL}(也可拖拽进来)`}
|
|
213
|
-
onClick={() => fileRef.current?.click()}>{Icon.plus()} <span>{options.fileButtonText}</span
|
|
214
|
+
onClick={() => fileRef.current?.click()}>{Icon.plus()}{options.fileButtonText && <span>{options.fileButtonText}</span>}</button>
|
|
214
215
|
</>}
|
|
215
216
|
{toolbar}
|
|
216
217
|
{options.hints && !disabled && <span className="hint comp-hint-extra">Shift + Enter 换行</span>}
|
|
@@ -224,12 +225,11 @@ export function Composer({ draft, placeholder, disabled, disabledHint, running,
|
|
|
224
225
|
onClick={async () => { if (controlLock.current) return; controlLock.current = true; setControlling(true); try { await taskControl.onToggle(); } catch (error) { setError(error instanceof Error ? error.message : "执行控制失败,请重试"); } finally { controlLock.current = false; setControlling(false); } }}>
|
|
225
226
|
{taskControl.paused ? Icon.play() : Icon.pause()}<span>{controlling ? "处理中…" : taskControl.paused ? "继续" : "暂停"}</span>
|
|
226
227
|
</button>}
|
|
227
|
-
{(!running ||
|
|
228
|
+
{showStop ? stopButton : (!running || options.queue) && <button type="button" className={`send cli-send${running ? " queue" : ""}`} disabled={disabled || !canSend} aria-busy={sending}
|
|
228
229
|
onClick={() => void submit()} aria-label={sending ? "正在发送" : running ? "排队发送" : "发送消息"}
|
|
229
230
|
title={sending ? "发送中…" : taskControl?.paused ? "排队发送,继续任务后依次执行" : running ? "排队发送,当前轮次结束后执行" : "发送消息(Enter)"}>
|
|
230
231
|
{sending ? <span className="spinner" /> : Icon.send()}
|
|
231
232
|
</button>}
|
|
232
|
-
{stopButton}
|
|
233
233
|
</div>
|
|
234
234
|
</div>
|
|
235
235
|
</div>
|
|
@@ -18,9 +18,9 @@ function validate(result: ExecutionConfiguration) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/** 按对话隔离读取与保存,不轮询;换对话后的迟到响应不覆盖当前选择。 */
|
|
21
|
-
export function useExecutionConfig({ client, scope, target, enabled, initial, running }: {
|
|
21
|
+
export function useExecutionConfig({ client, scope, target, enabled, ready = true, initial, running }: {
|
|
22
22
|
client: ConversationBackend; scope: string; target: string | null; enabled: boolean;
|
|
23
|
-
initial?: ExecutionOptions; running: boolean;
|
|
23
|
+
initial?: ExecutionOptions; running: boolean; ready?: boolean;
|
|
24
24
|
}) {
|
|
25
25
|
const [view, setView] = useState<{ scope: string; config?: ExecutionConfiguration; error?: string; loading: boolean; saveFailed?: boolean }>({ scope, loading: false });
|
|
26
26
|
const current = useRef(scope);
|
|
@@ -34,7 +34,7 @@ export function useExecutionConfig({ client, scope, target, enabled, initial, ru
|
|
|
34
34
|
const reload = useCallback(async () => {
|
|
35
35
|
const serial = ++request.current;
|
|
36
36
|
const active = () => mounted.current && current.current === scope && request.current === serial;
|
|
37
|
-
if (!enabled && !readComposerDraft(scope).executionUncertain) return;
|
|
37
|
+
if (!ready || (!enabled && !readComposerDraft(scope).executionUncertain)) return;
|
|
38
38
|
if (!client.getExecutionConfig) {
|
|
39
39
|
setView({ scope, loading: false, error: "当前接入尚未提供执行设置。" });
|
|
40
40
|
return;
|
|
@@ -50,7 +50,7 @@ export function useExecutionConfig({ client, scope, target, enabled, initial, ru
|
|
|
50
50
|
} catch (error) {
|
|
51
51
|
if (active()) setView(value => ({ ...(value.scope === scope ? value : {}), scope, error: errorText(error), loading: false }));
|
|
52
52
|
}
|
|
53
|
-
}, [client, scope, target, enabled]);
|
|
53
|
+
}, [client, scope, target, enabled, ready]);
|
|
54
54
|
useEffect(() => { void reload(); return () => { request.current++; }; }, [reload]);
|
|
55
55
|
const wasRunning = useRef(running);
|
|
56
56
|
useEffect(() => {
|
|
@@ -196,14 +196,15 @@ export function Composer({ task, agentLabel, disabled, running, onSend, onStop,
|
|
|
196
196
|
const pendingFork=sources.length&&draft.forkRequest?.signature===currentSignature?draft.forkRequest:null;
|
|
197
197
|
const payload=pendingFork?pendingFork.payload??ownPayload:ownPayload&&!isClear?appendBoardContext(ownPayload,boardView,task.id):ownPayload;
|
|
198
198
|
const tooLong = payload.length > MAX_MESSAGE_CHARS;
|
|
199
|
-
const canSend = !!payload && !uploading && !failed && !tooLong && !locked;
|
|
199
|
+
const canSend = !!payload && !uploading && !failed && !tooLong && !locked && !stopping;
|
|
200
|
+
const showStop = running && !sending && (stopping || locked || !payload);
|
|
200
201
|
const clear = () => {
|
|
201
202
|
if (running || locked || task.started !== 1) return;
|
|
202
203
|
onClear(); setSlash(false);
|
|
203
204
|
if (draft.text.trim() === "/clear") update((d) => ({ ...d, text: "" }));
|
|
204
205
|
};
|
|
205
206
|
const submit = async () => {
|
|
206
|
-
if (!canSend || sendingRef.current || isTaskSending(task.id) || isConfigurationBusy(task.id)) return;
|
|
207
|
+
if (!canSend || stoppingRef.current || sendingRef.current || isTaskSending(task.id) || isConfigurationBusy(task.id)) return;
|
|
207
208
|
if (draft.text.trim() === "/clear" && !draft.attachments.length && !draft.quote) { clear(); return; }
|
|
208
209
|
let submittedDraft = draftRef.current;
|
|
209
210
|
let requestId = "";
|
|
@@ -303,8 +304,8 @@ export function Composer({ task, agentLabel, disabled, running, onSend, onStop,
|
|
|
303
304
|
</div>
|
|
304
305
|
<RunControls {...controls} disabled={controls.disabled || sending} />
|
|
305
306
|
<div className="send-group">
|
|
306
|
-
{
|
|
307
|
-
|
|
307
|
+
{showStop ? <button type="button" className="send stop" disabled={stopping} aria-busy={stopping} aria-label={stopping ? "正在停止" : "停止当前轮次"} title={stopping ? "正在停止…" : "停止当前轮次"} onClick={() => void stop()}>{stopping ? <span className="spinner" /> : Icon.stop()}</button>
|
|
308
|
+
: <button type="button" className={`send${running ? " queue" : ""}`} disabled={!canSend} aria-busy={sending} aria-label={sending ? "正在发送" : sources.length ? `派生 ${sources.length} 个分支` : running ? "排队发送" : "发送消息"} title={sending ? "发送中…" : running ? "本轮结束后发送" : "发送消息(Enter)"} onClick={() => void submit()}>{sending ? <span className="spinner" /> : Icon.send()}</button>}
|
|
308
309
|
</div>
|
|
309
310
|
</div>
|
|
310
311
|
</div>
|
package/src/operator.base.css
CHANGED
|
@@ -1021,7 +1021,7 @@ button.tpeek-more:hover{color:var(--accent-ink);}
|
|
|
1021
1021
|
.comp-toolbar{display:flex;align-items:center;gap:7px;padding:4px 12px 12px;min-width:0;}
|
|
1022
1022
|
.comp-add{width:36px;height:36px;display:grid;place-items:center;border-radius:50%;flex:none;color:var(--ink-2);background:transparent;}
|
|
1023
1023
|
.comp-add svg{width:22px;height:22px;}
|
|
1024
|
-
.comp-add:hover,.comp-setting:hover{background:var(--surface-2);}
|
|
1024
|
+
@media(hover:hover) and (pointer:fine){.comp-add:hover,.comp-setting:hover{background:var(--surface-2);}}
|
|
1025
1025
|
.comp-control{position:relative;min-width:0;}
|
|
1026
1026
|
.comp-model{margin-left:auto;}
|
|
1027
1027
|
.comp-setting{display:flex;align-items:center;gap:6px;min-height:36px;max-width:100%;padding:6px 8px;border-radius:10px;color:var(--ink-2);background:transparent;font-size:12px;white-space:nowrap;}
|
|
@@ -1029,18 +1029,19 @@ button.tpeek-more:hover{color:var(--accent-ink);}
|
|
|
1029
1029
|
.comp-setting.elevated{color:var(--amber);}
|
|
1030
1030
|
.comp-model-name{min-width:0;max-width:220px;overflow:hidden;text-overflow:ellipsis;}
|
|
1031
1031
|
.comp-setting:disabled,.comp-add:disabled{opacity:.5;cursor:default;}
|
|
1032
|
-
|
|
1032
|
+
/* A 32px visual circle inside a 44px touch target. */
|
|
1033
|
+
.send{width:44px;height:44px;min-width:44px;min-height:44px;flex:none;padding:6px;border-radius:50%;background:var(--accent);background-clip:content-box;color:var(--on-accent);display:grid;place-items:center;transition:filter .12s,opacity .12s,transform .12s;}
|
|
1033
1034
|
.send:hover:not(:disabled){filter:brightness(1.08);}
|
|
1034
1035
|
.send:active:not(:disabled){transform:scale(.96);filter:brightness(.94);}
|
|
1035
1036
|
.send:disabled{opacity:.35;cursor:not-allowed;filter:none;}
|
|
1036
1037
|
.send[aria-busy="true"]{opacity:.7;cursor:progress;}
|
|
1037
|
-
.send.stop{background:var(--blue);color:var(--on-accent);}
|
|
1038
|
-
.send.stop svg{fill:currentColor;width:
|
|
1038
|
+
.send.stop{background-color:var(--blue);color:var(--on-accent);}
|
|
1039
|
+
.send.stop svg{fill:currentColor;width:20px;height:20px;}
|
|
1039
1040
|
.send .spinner{width:18px;height:18px;border-color:color-mix(in srgb,currentColor 30%,transparent);border-top-color:currentColor;}
|
|
1040
1041
|
@media(prefers-reduced-motion:reduce){.send{transition:none;}.send .spinner{animation:none;}}
|
|
1041
|
-
/*
|
|
1042
|
+
/* Send, queue and stop share one primary action slot. */
|
|
1042
1043
|
.send-group{display:flex;align-items:flex-end;gap:8px;flex:0 0 auto;}
|
|
1043
|
-
.send svg{width:
|
|
1044
|
+
.send svg{width:22px;height:22px;}
|
|
1044
1045
|
.comp-foot{display:flex;align-items:center;gap:10px;padding:9px 14px;border-top:1px solid var(--line-2);background:var(--surface-2);}
|
|
1045
1046
|
.comp-foot .hint{font-family:var(--mono);font-size:10px;color:var(--ink-3);display:flex;align-items:center;gap:5px;}
|
|
1046
1047
|
.comp-foot .hint svg{width:13px;height:13px;}
|
|
@@ -1057,7 +1058,6 @@ button.tpeek-more:hover{color:var(--accent-ink);}
|
|
|
1057
1058
|
@container (max-width:420px){.comp-foot .hint .kbd{display:none;}.run-sw{max-width:130px;}}
|
|
1058
1059
|
|
|
1059
1060
|
.send-group{display:flex;align-items:center;gap:6px;flex:none;}
|
|
1060
|
-
.send svg{width:19px;height:19px;}
|
|
1061
1061
|
.comp-error,.control-error{padding:8px 10px;font-size:12px;line-height:1.5;color:var(--red);overflow-wrap:anywhere;}
|
|
1062
1062
|
.comp-upload-status{padding:6px 10px;font-size:11px;color:var(--ink-3);}
|
|
1063
1063
|
.comp-quote{margin:12px 14px 0;}
|
|
@@ -1415,12 +1415,12 @@ button.pop-item:hover{background:var(--surface-2);}
|
|
|
1415
1415
|
.comp-add.on svg{transform:rotate(45deg);}
|
|
1416
1416
|
.composer .comp-setting{min-height:38px;border-radius:6px;padding:7px 10px;background:transparent;}
|
|
1417
1417
|
.composer .comp-add{width:38px;height:38px;border-radius:6px;background:transparent;}
|
|
1418
|
-
.composer .comp-setting:hover:not(:disabled),.composer .comp-add:hover:not(:disabled){background:var(--surface-2);}
|
|
1418
|
+
@media(hover:hover) and (pointer:fine){.composer .comp-setting:hover:not(:disabled),.composer .comp-add:hover:not(:disabled){background:var(--surface-2);}}
|
|
1419
1419
|
.composer .send{width:44px;height:44px;}
|
|
1420
1420
|
.composer .comp-box{border-radius:26px;border-color:var(--line);box-shadow:0 4px 20px rgba(0,0,0,.035);}
|
|
1421
1421
|
.composer .comp-box:focus-within{border-color:var(--line-strong);box-shadow:0 6px 24px rgba(0,0,0,.055);}
|
|
1422
1422
|
.composer .comp-toolbar{gap:6px;padding:6px 12px 12px;}
|
|
1423
|
-
.composer .comp-area{padding:
|
|
1423
|
+
.composer .comp-area{padding:12px 20px 4px;}
|
|
1424
1424
|
.composer .attach-chip.image{width:108px;height:88px;border-radius:12px;}
|
|
1425
1425
|
.composer .attach-chip.image>img{height:100%;object-fit:cover;}
|
|
1426
1426
|
.composer .attach-chip .attach-x{width:26px;height:26px;top:4px;right:4px;font-size:16px;}
|
|
@@ -1429,7 +1429,7 @@ button.pop-item:hover{background:var(--surface-2);}
|
|
|
1429
1429
|
.composer .attach-row .attach-chip{flex:none;}
|
|
1430
1430
|
.composer .cli-blocks{max-height:min(30vh,180px);}
|
|
1431
1431
|
@container(max-width:420px){
|
|
1432
|
-
.composer .comp-area{padding:
|
|
1432
|
+
.composer .comp-area{padding:12px 16px 4px;}
|
|
1433
1433
|
.composer .comp-toolbar{gap:4px;padding:6px 10px 10px;}
|
|
1434
1434
|
.composer .comp-setting{padding:6px 9px;}
|
|
1435
1435
|
.composer .attach-chip.image{width:86px;height:76px;}
|
|
@@ -1438,12 +1438,11 @@ button.pop-item:hover{background:var(--surface-2);}
|
|
|
1438
1438
|
.composer .comp-toolbar{flex-wrap:nowrap;padding-left:8px;padding-right:8px;}
|
|
1439
1439
|
.composer .comp-toolbar>.comp-control{flex:0 0 auto;}
|
|
1440
1440
|
.composer .comp-toolbar>.comp-model{flex:0 1 auto;min-width:44px;margin-left:auto;}
|
|
1441
|
-
.composer .comp-setting{font-size:
|
|
1442
|
-
.composer .comp-setting>svg{
|
|
1441
|
+
.composer .comp-setting{font-size:12px;gap:4px;padding-left:4px;padding-right:4px;}
|
|
1442
|
+
.composer .comp-setting>svg{flex:none;}
|
|
1443
1443
|
.composer .comp-model-name{max-width:42px;}
|
|
1444
|
-
.composer .
|
|
1445
|
-
.composer .comp-
|
|
1446
|
-
.composer .comp-toolbar:not(:has(.send.stop)) .comp-model .comp-setting>svg{display:block;width:12px;height:12px;}
|
|
1444
|
+
.composer .permission>svg:first-child{width:14px;height:14px;}
|
|
1445
|
+
.composer .comp-model .comp-setting>svg{width:12px;height:12px;}
|
|
1447
1446
|
.composer .comp-foot{flex-wrap:wrap;gap:6px;}
|
|
1448
1447
|
.composer .comp-foot>.send-group{margin-left:auto;}
|
|
1449
1448
|
}
|
|
@@ -1482,7 +1481,6 @@ button.pop-item:hover{background:var(--surface-2);}
|
|
|
1482
1481
|
/* generic separators / utility */
|
|
1483
1482
|
.divider{height:1px;background:var(--line);margin:6px 0;}
|
|
1484
1483
|
|
|
1485
|
-
.send svg{width:17px;height:17px;}
|
|
1486
1484
|
.sug-btn svg,.btn-sm svg{width:13px;height:13px;}
|
|
1487
1485
|
|
|
1488
1486
|
/* status label (opt-in via .slabel consumers; hidden by default) */
|
|
@@ -1842,7 +1840,7 @@ button.pop-item:hover{background:var(--surface-2);}
|
|
|
1842
1840
|
[data-chat-layout]>.composer>.composer-inner{width:100%;max-width:var(--cli-chat-content-max);margin-inline:auto;}
|
|
1843
1841
|
[data-chat-layout]>.cli-refs,[data-chat-layout]>.cli-queue{width:calc(100% - 2 * var(--cli-chat-gutter) - var(--cli-chat-scrollbar,0px));max-width:var(--cli-chat-content-max);margin-inline:auto;margin-inline-start:max(var(--cli-chat-gutter),calc((100% - var(--cli-chat-scrollbar,0px) - var(--cli-chat-content-max)) / 2));flex-shrink:0;}
|
|
1844
1842
|
@container chat-column (max-width:900px){[data-chat-layout]>*{--cli-chat-content-max:100%;}}
|
|
1845
|
-
@container chat-column (max-width:640px){[data-chat-layout]>*{--cli-chat-gutter:12px;}}
|
|
1843
|
+
@container chat-column (max-width:640px){[data-chat-layout]>*{--cli-chat-gutter:12px;}.session [data-chat-layout]>.composer{padding-inline-end:var(--cli-chat-gutter);}}
|
|
1846
1844
|
.task-origin{display:flex;align-items:center;gap:5px;font-size:10px;color:var(--ink-3);padding-top:7px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
1847
1845
|
.fork-sources{display:flex;flex-wrap:wrap;gap:6px;padding:12px 14px 0;}
|
|
1848
1846
|
.fork-sources>span{max-width:100%;display:flex;align-items:center;gap:6px;padding:6px 8px;border:1px solid var(--line);background:var(--surface-2);border-radius:8px;font-size:11px;color:var(--ink-2);overflow-wrap:anywhere;}
|
package/src/operator.css
CHANGED
|
@@ -1021,7 +1021,7 @@
|
|
|
1021
1021
|
.cli-ui .comp-toolbar{display:flex;align-items:center;gap:7px;padding:4px 12px 12px;min-width:0;}
|
|
1022
1022
|
.cli-ui .comp-add{width:36px;height:36px;display:grid;place-items:center;border-radius:50%;flex:none;color:var(--ink-2);background:transparent;}
|
|
1023
1023
|
.cli-ui .comp-add svg{width:22px;height:22px;}
|
|
1024
|
-
.cli-ui .comp-add:hover,.cli-ui .comp-setting:hover{background:var(--surface-2);}
|
|
1024
|
+
@media(hover:hover) and (pointer:fine){.cli-ui .comp-add:hover,.cli-ui .comp-setting:hover{background:var(--surface-2);}}
|
|
1025
1025
|
.cli-ui .comp-control{position:relative;min-width:0;}
|
|
1026
1026
|
.cli-ui .comp-model{margin-left:auto;}
|
|
1027
1027
|
.cli-ui .comp-setting{display:flex;align-items:center;gap:6px;min-height:36px;max-width:100%;padding:6px 8px;border-radius:10px;color:var(--ink-2);background:transparent;font-size:12px;white-space:nowrap;}
|
|
@@ -1029,18 +1029,19 @@
|
|
|
1029
1029
|
.cli-ui .comp-setting.elevated{color:var(--amber);}
|
|
1030
1030
|
.cli-ui .comp-model-name{min-width:0;max-width:220px;overflow:hidden;text-overflow:ellipsis;}
|
|
1031
1031
|
.cli-ui .comp-setting:disabled,.cli-ui .comp-add:disabled{opacity:.5;cursor:default;}
|
|
1032
|
-
|
|
1032
|
+
/* A 32px visual circle inside a 44px touch target. */
|
|
1033
|
+
.cli-ui .send{width:44px;height:44px;min-width:44px;min-height:44px;flex:none;padding:6px;border-radius:50%;background:var(--accent);background-clip:content-box;color:var(--on-accent);display:grid;place-items:center;transition:filter .12s,opacity .12s,transform .12s;}
|
|
1033
1034
|
.cli-ui .send:hover:not(:disabled){filter:brightness(1.08);}
|
|
1034
1035
|
.cli-ui .send:active:not(:disabled){transform:scale(.96);filter:brightness(.94);}
|
|
1035
1036
|
.cli-ui .send:disabled{opacity:.35;cursor:not-allowed;filter:none;}
|
|
1036
1037
|
.cli-ui .send[aria-busy="true"]{opacity:.7;cursor:progress;}
|
|
1037
|
-
.cli-ui .send.stop{background:var(--blue);color:var(--on-accent);}
|
|
1038
|
-
.cli-ui .send.stop svg{fill:currentColor;width:
|
|
1038
|
+
.cli-ui .send.stop{background-color:var(--blue);color:var(--on-accent);}
|
|
1039
|
+
.cli-ui .send.stop svg{fill:currentColor;width:20px;height:20px;}
|
|
1039
1040
|
.cli-ui .send .spinner{width:18px;height:18px;border-color:color-mix(in srgb,currentColor 30%,transparent);border-top-color:currentColor;}
|
|
1040
1041
|
@media(prefers-reduced-motion:reduce){.cli-ui .send{transition:none;}.cli-ui .send .spinner{animation:none;}}
|
|
1041
|
-
/*
|
|
1042
|
+
/* Send, queue and stop share one primary action slot. */
|
|
1042
1043
|
.cli-ui .send-group{display:flex;align-items:flex-end;gap:8px;flex:0 0 auto;}
|
|
1043
|
-
.cli-ui .send svg{width:
|
|
1044
|
+
.cli-ui .send svg{width:22px;height:22px;}
|
|
1044
1045
|
.cli-ui .comp-foot{display:flex;align-items:center;gap:10px;padding:9px 14px;border-top:1px solid var(--line-2);background:var(--surface-2);}
|
|
1045
1046
|
.cli-ui .comp-foot .hint{font-family:var(--mono);font-size:10px;color:var(--ink-3);display:flex;align-items:center;gap:5px;}
|
|
1046
1047
|
.cli-ui .comp-foot .hint svg{width:13px;height:13px;}
|
|
@@ -1057,7 +1058,6 @@
|
|
|
1057
1058
|
@container (max-width:420px){.cli-ui .comp-foot .hint .kbd{display:none;}.cli-ui .run-sw{max-width:130px;}}
|
|
1058
1059
|
|
|
1059
1060
|
.cli-ui .send-group{display:flex;align-items:center;gap:6px;flex:none;}
|
|
1060
|
-
.cli-ui .send svg{width:19px;height:19px;}
|
|
1061
1061
|
.cli-ui .comp-error,.cli-ui .control-error{padding:8px 10px;font-size:12px;line-height:1.5;color:var(--red);overflow-wrap:anywhere;}
|
|
1062
1062
|
.cli-ui .comp-upload-status{padding:6px 10px;font-size:11px;color:var(--ink-3);}
|
|
1063
1063
|
.cli-ui .comp-quote{margin:12px 14px 0;}
|
|
@@ -1415,12 +1415,12 @@
|
|
|
1415
1415
|
.cli-ui .comp-add.on svg{transform:rotate(45deg);}
|
|
1416
1416
|
.cli-ui .composer .comp-setting{min-height:38px;border-radius:6px;padding:7px 10px;background:transparent;}
|
|
1417
1417
|
.cli-ui .composer .comp-add{width:38px;height:38px;border-radius:6px;background:transparent;}
|
|
1418
|
-
.cli-ui .composer .comp-setting:hover:not(:disabled),.cli-ui .composer .comp-add:hover:not(:disabled){background:var(--surface-2);}
|
|
1418
|
+
@media(hover:hover) and (pointer:fine){.cli-ui .composer .comp-setting:hover:not(:disabled),.cli-ui .composer .comp-add:hover:not(:disabled){background:var(--surface-2);}}
|
|
1419
1419
|
.cli-ui .composer .send{width:44px;height:44px;}
|
|
1420
1420
|
.cli-ui .composer .comp-box{border-radius:26px;border-color:var(--line);box-shadow:0 4px 20px rgba(0,0,0,.035);}
|
|
1421
1421
|
.cli-ui .composer .comp-box:focus-within{border-color:var(--line-strong);box-shadow:0 6px 24px rgba(0,0,0,.055);}
|
|
1422
1422
|
.cli-ui .composer .comp-toolbar{gap:6px;padding:6px 12px 12px;}
|
|
1423
|
-
.cli-ui .composer .comp-area{padding:
|
|
1423
|
+
.cli-ui .composer .comp-area{padding:12px 20px 4px;}
|
|
1424
1424
|
.cli-ui .composer .attach-chip.image{width:108px;height:88px;border-radius:12px;}
|
|
1425
1425
|
.cli-ui .composer .attach-chip.image>img{height:100%;object-fit:cover;}
|
|
1426
1426
|
.cli-ui .composer .attach-chip .attach-x{width:26px;height:26px;top:4px;right:4px;font-size:16px;}
|
|
@@ -1429,7 +1429,7 @@
|
|
|
1429
1429
|
.cli-ui .composer .attach-row .attach-chip{flex:none;}
|
|
1430
1430
|
.cli-ui .composer .cli-blocks{max-height:min(30vh,180px);}
|
|
1431
1431
|
@container(max-width:420px){
|
|
1432
|
-
.cli-ui .composer .comp-area{padding:
|
|
1432
|
+
.cli-ui .composer .comp-area{padding:12px 16px 4px;}
|
|
1433
1433
|
.cli-ui .composer .comp-toolbar{gap:4px;padding:6px 10px 10px;}
|
|
1434
1434
|
.cli-ui .composer .comp-setting{padding:6px 9px;}
|
|
1435
1435
|
.cli-ui .composer .attach-chip.image{width:86px;height:76px;}
|
|
@@ -1438,12 +1438,11 @@
|
|
|
1438
1438
|
.cli-ui .composer .comp-toolbar{flex-wrap:nowrap;padding-left:8px;padding-right:8px;}
|
|
1439
1439
|
.cli-ui .composer .comp-toolbar>.comp-control{flex:0 0 auto;}
|
|
1440
1440
|
.cli-ui .composer .comp-toolbar>.comp-model{flex:0 1 auto;min-width:44px;margin-left:auto;}
|
|
1441
|
-
.cli-ui .composer .comp-setting{font-size:
|
|
1442
|
-
.cli-ui .composer .comp-setting>svg{
|
|
1441
|
+
.cli-ui .composer .comp-setting{font-size:12px;gap:4px;padding-left:4px;padding-right:4px;}
|
|
1442
|
+
.cli-ui .composer .comp-setting>svg{flex:none;}
|
|
1443
1443
|
.cli-ui .composer .comp-model-name{max-width:42px;}
|
|
1444
|
-
.cli-ui .composer .
|
|
1445
|
-
.cli-ui .composer .comp-
|
|
1446
|
-
.cli-ui .composer .comp-toolbar:not(:has(.send.stop)) .comp-model .comp-setting>svg{display:block;width:12px;height:12px;}
|
|
1444
|
+
.cli-ui .composer .permission>svg:first-child{width:14px;height:14px;}
|
|
1445
|
+
.cli-ui .composer .comp-model .comp-setting>svg{width:12px;height:12px;}
|
|
1447
1446
|
.cli-ui .composer .comp-foot{flex-wrap:wrap;gap:6px;}
|
|
1448
1447
|
.cli-ui .composer .comp-foot>.send-group{margin-left:auto;}
|
|
1449
1448
|
}
|
|
@@ -1482,7 +1481,6 @@
|
|
|
1482
1481
|
/* generic separators / utility */
|
|
1483
1482
|
.cli-ui .divider{height:1px;background:var(--line);margin:6px 0;}
|
|
1484
1483
|
|
|
1485
|
-
.cli-ui .send svg{width:17px;height:17px;}
|
|
1486
1484
|
.cli-ui .sug-btn svg,.cli-ui .btn-sm svg{width:13px;height:13px;}
|
|
1487
1485
|
|
|
1488
1486
|
/* status label (opt-in via .slabel consumers; hidden by default) */
|
|
@@ -1842,7 +1840,7 @@
|
|
|
1842
1840
|
.cli-ui [data-chat-layout]>.composer>.composer-inner{width:100%;max-width:var(--cli-chat-content-max);margin-inline:auto;}
|
|
1843
1841
|
.cli-ui [data-chat-layout]>.cli-refs,.cli-ui [data-chat-layout]>.cli-queue{width:calc(100% - 2 * var(--cli-chat-gutter) - var(--cli-chat-scrollbar,0px));max-width:var(--cli-chat-content-max);margin-inline:auto;margin-inline-start:max(var(--cli-chat-gutter),calc((100% - var(--cli-chat-scrollbar,0px) - var(--cli-chat-content-max)) / 2));flex-shrink:0;}
|
|
1844
1842
|
@container chat-column (max-width:900px){.cli-ui [data-chat-layout]>*{--cli-chat-content-max:100%;}}
|
|
1845
|
-
@container chat-column (max-width:640px){.cli-ui [data-chat-layout]>*{--cli-chat-gutter:12px;}}
|
|
1843
|
+
@container chat-column (max-width:640px){.cli-ui [data-chat-layout]>*{--cli-chat-gutter:12px;}.cli-ui .session [data-chat-layout]>.composer{padding-inline-end:var(--cli-chat-gutter);}}
|
|
1846
1844
|
.cli-ui .task-origin{display:flex;align-items:center;gap:5px;font-size:10px;color:var(--ink-3);padding-top:7px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
|
|
1847
1845
|
.cli-ui .fork-sources{display:flex;flex-wrap:wrap;gap:6px;padding:12px 14px 0;}
|
|
1848
1846
|
.cli-ui .fork-sources>span{max-width:100%;display:flex;align-items:center;gap:6px;padding:6px 8px;border:1px solid var(--line);background:var(--surface-2);border-radius:8px;font-size:11px;color:var(--ink-2);overflow-wrap:anywhere;}
|
package/src/styles.css
CHANGED
|
@@ -53,9 +53,11 @@
|
|
|
53
53
|
.cli-ui .sess-head .crumb{overflow-wrap:anywhere;}
|
|
54
54
|
.cli-ui .cli-export{white-space:nowrap;}
|
|
55
55
|
.cli-ui .comp-area textarea{min-width:0;}
|
|
56
|
-
.cli-ui .comp-foot{gap:
|
|
56
|
+
.cli-ui .composer .comp-foot{gap:4px;padding:4px 10px;background:transparent;border-top:0;flex-wrap:wrap;}
|
|
57
|
+
.cli-ui .comp-foot>.comp-control{flex:0 0 auto;}
|
|
58
|
+
.cli-ui .comp-foot .permission{padding-inline:6px;}
|
|
57
59
|
.cli-ui .cli-attach{display:inline-flex;justify-content:center;align-items:center;gap:5px;min-width:44px;min-height:44px;padding:0 8px;border-radius:7px;color:var(--ink-3);font-size:12px;}
|
|
58
|
-
.cli-ui .cli-attach:hover{background:var(--surface-2);color:var(--ink);}
|
|
60
|
+
@media(hover:hover) and (pointer:fine){.cli-ui .cli-attach:hover{background:var(--surface-2);color:var(--ink);}}
|
|
59
61
|
.cli-ui .cli-attach svg{width:22px;height:22px;}
|
|
60
62
|
.cli-ui .comp-foot:has(.comp-model)>.spacer{display:none;}
|
|
61
63
|
.cli-ui .cli-export:focus-visible,.cli-ui .cli-attach:focus-visible{outline:2px solid var(--accent);outline-offset:3px;}
|
|
@@ -454,19 +456,20 @@ cli-split{display:block;}
|
|
|
454
456
|
.cli-ui .cli-auto-background pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:220px;overflow:auto;}
|
|
455
457
|
|
|
456
458
|
/* The live queue sits just above the composer; expanded content stays in a viewport-bound card. */
|
|
457
|
-
.cli-ui .cli-queue{flex:none;min-width:0;max-height:154px;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;margin:0
|
|
458
|
-
.cli-ui .cli-queue-row{display:flex;align-items:center;gap:8px;min-width:0;min-height:
|
|
459
|
+
.cli-ui .cli-queue{flex:none;min-width:0;max-height:154px;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;margin:0 16px -12px;padding:4px 10px 16px;border:1px solid var(--line);border-radius:18px 18px 0 0;background:var(--raise);}
|
|
460
|
+
.cli-ui .cli-queue-row{display:flex;align-items:center;gap:8px;min-width:0;min-height:44px;}
|
|
459
461
|
.cli-ui .cli-queue-row+.cli-queue-row{border-top:1px solid var(--line-2);}
|
|
460
462
|
.cli-ui .cli-queue-icon{display:grid;place-items:center;flex:none;width:20px;color:var(--ink-4);}
|
|
461
463
|
.cli-ui .cli-queue-icon svg{width:16px;height:16px;}
|
|
462
464
|
.cli-ui .cli-queue-summary{display:flex;align-items:center;gap:8px;flex:1;min-width:0;min-height:40px;padding:4px 0;text-align:left;color:var(--ink-2);}
|
|
463
465
|
.cli-ui .cli-queue-thumb{flex:none;width:32px;height:32px;object-fit:cover;border:1px solid var(--line);border-radius:7px;}
|
|
464
466
|
.cli-ui .cli-queue-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px;line-height:1.5;}
|
|
465
|
-
.cli-ui .cli-queue-state{flex:none;color:var(--ink-4);font-size:10px;white-space:nowrap;}
|
|
466
467
|
.cli-ui .cli-queue-remove,.cli-ui .cli-queue-more{display:grid;place-items:center;flex:none;width:30px;height:34px;border-radius:9px;color:var(--ink-3);}
|
|
467
468
|
.cli-ui .cli-queue-remove svg,.cli-ui .cli-queue-more svg{width:17px;height:17px;}
|
|
468
|
-
|
|
469
|
-
.cli-ui .cli-queue-remove:hover{color:var(--
|
|
469
|
+
@media(hover:hover) and (pointer:fine){
|
|
470
|
+
.cli-ui .cli-queue-remove:hover,.cli-ui .cli-queue-more:hover{background:var(--surface-2);color:var(--ink);}
|
|
471
|
+
.cli-ui .cli-queue-remove:hover{color:var(--red);}
|
|
472
|
+
}
|
|
470
473
|
.cli-ui .cli-queue-summary:focus-visible,.cli-ui .cli-queue-remove:focus-visible,.cli-ui .cli-queue-more:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-radius:8px;}
|
|
471
474
|
.cli-ui .cli-queue-popover{width:420px;}
|
|
472
475
|
.cli-ui .cli-queue-detail{max-height:min(44vh,320px);overflow:auto;overscroll-behavior:contain;overflow-wrap:anywhere;}
|
|
@@ -479,11 +482,10 @@ cli-split{display:block;}
|
|
|
479
482
|
.cli-ui .cli-queue-feedback[role="alert"]{color:var(--red);}
|
|
480
483
|
.cli-ui .session>.cli-queue{width:calc(100% - 48px);max-width:800px;align-self:center;margin:8px 24px 16px;border-radius:16px;}
|
|
481
484
|
@container(max-width:420px){
|
|
482
|
-
.cli-ui .cli-queue{margin:0
|
|
485
|
+
.cli-ui .cli-queue{margin:0 10px -12px;padding:4px 6px 16px;max-height:112px;}
|
|
483
486
|
.cli-ui .cli-queue-row{gap:5px;}
|
|
484
|
-
.cli-ui .cli-queue-state{display:none;}
|
|
485
487
|
}
|
|
486
|
-
@media(pointer:coarse){.cli-ui .cli-queue-remove,.cli-ui .cli-queue-more{width:
|
|
488
|
+
@media(pointer:coarse){.cli-ui .cli-queue-remove,.cli-ui .cli-queue-more{width:44px;height:44px;}}
|
|
487
489
|
@media(max-height:500px){.cli-ui .cli-queue{max-height:70px;}}
|
|
488
490
|
|
|
489
491
|
/* Keep controls reachable when a keyboard, split host or landscape view leaves little height. */
|
|
@@ -55,7 +55,6 @@ function QueuedMessage({ message, index, onCancel, attachmentUrl, renderMessage
|
|
|
55
55
|
{thumbnail?.url && <img className="cli-queue-thumb" src={thumbnail.url} alt={thumbnail.attachment.name} loading="lazy" onError={event => { event.currentTarget.hidden = true; }} />}
|
|
56
56
|
<span className="cli-queue-text">{preview.summary}</span>
|
|
57
57
|
</button>
|
|
58
|
-
<span className="cli-queue-state">排队中</span>
|
|
59
58
|
{onCancel && <button className="cli-queue-remove" title="从队列中移除" aria-label={`移除第 ${index + 1} 条排队消息`} onClick={() => onCancel(message)}>{Icon.x()}</button>}
|
|
60
59
|
<button className="cli-queue-more" title="更多排队消息操作" aria-label={`第 ${index + 1} 条排队消息的更多操作`} aria-expanded={open} aria-haspopup="dialog" onClick={toggle}>{Icon.dots()}</button>
|
|
61
60
|
{open && <Popover className="composer-popover cli-queue-popover" ariaLabel="排队消息内容" placement="top" align="start" returnFocusRef={returnFocusRef} onClose={() => setOpen(false)}>
|