@spzxg/cli-ui 0.6.8 → 0.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/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-Be9_d9jB.js";
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-CtZDwP8y.js";
2
2
  export {
3
3
  a as CliBoard,
4
4
  i as CliBrowserView,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spzxg/cli-ui",
3
- "version": "0.6.8",
3
+ "version": "0.6.9",
4
4
  "type": "module",
5
5
  "description": "相互联动的 CliMsgList、CliChat、CliBoard,支持任务中枢和完整 Operator 工作区。",
6
6
  "main": "src/index.ts",
@@ -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);
@@ -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 || (options.queue && (!!message.trim() || sending || !onStop))) && <button type="button" className={`send cli-send${running ? " queue" : ""}`} disabled={disabled || !canSend} aria-busy={sending}
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>
@@ -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
- {(!running || !!payload || sending) && <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>}
307
- {running && <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>}
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>
@@ -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
- .send{width:44px;height:44px;min-width:44px;min-height:44px;flex:none;padding:0;border-radius:50%;background:var(--accent);color:var(--on-accent);display:grid;place-items:center;transition:filter .12s,opacity .12s,transform .12s;}
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:15px;height:15px;}
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
- /* mid-turn: queue button + stop button sit side by side */
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:17px;height:17px;}
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,7 +1415,7 @@ 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);}
@@ -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:11px;gap:0;padding-left:6px;padding-right:6px;}
1442
- .composer .comp-setting>svg{display:none;}
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 .comp-toolbar:not(:has(.send.stop)) .comp-setting{gap:4px;font-size:12px;}
1445
- .composer .comp-toolbar:not(:has(.send.stop)) .permission>svg:first-child{display:block;width:14px;height:14px;}
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
- .cli-ui .send{width:44px;height:44px;min-width:44px;min-height:44px;flex:none;padding:0;border-radius:50%;background:var(--accent);color:var(--on-accent);display:grid;place-items:center;transition:filter .12s,opacity .12s,transform .12s;}
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:15px;height:15px;}
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
- /* mid-turn: queue button + stop button sit side by side */
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:17px;height:17px;}
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,7 +1415,7 @@
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);}
@@ -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:11px;gap:0;padding-left:6px;padding-right:6px;}
1442
- .cli-ui .composer .comp-setting>svg{display:none;}
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 .comp-toolbar:not(:has(.send.stop)) .comp-setting{gap:4px;font-size:12px;}
1445
- .cli-ui .composer .comp-toolbar:not(:has(.send.stop)) .permission>svg:first-child{display:block;width:14px;height:14px;}
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
@@ -54,8 +54,9 @@
54
54
  .cli-ui .cli-export{white-space:nowrap;}
55
55
  .cli-ui .comp-area textarea{min-width:0;}
56
56
  .cli-ui .comp-foot{gap:8px;padding:8px 10px;background:transparent;border-top:0;flex-wrap:wrap;}
57
+ .cli-ui .comp-foot>.comp-control{flex:0 0 auto;}
57
58
  .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);}
59
+ @media(hover:hover) and (pointer:fine){.cli-ui .cli-attach:hover{background:var(--surface-2);color:var(--ink);}}
59
60
  .cli-ui .cli-attach svg{width:22px;height:22px;}
60
61
  .cli-ui .comp-foot:has(.comp-model)>.spacer{display:none;}
61
62
  .cli-ui .cli-export:focus-visible,.cli-ui .cli-attach:focus-visible{outline:2px solid var(--accent);outline-offset:3px;}
@@ -454,19 +455,20 @@ cli-split{display:block;}
454
455
  .cli-ui .cli-auto-background pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:220px;overflow:auto;}
455
456
 
456
457
  /* 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 12px -1px;padding:4px 8px 8px;border:1px solid var(--line-strong);border-radius:18px 18px 0 0;background:var(--raise);}
458
- .cli-ui .cli-queue-row{display:flex;align-items:center;gap:8px;min-width:0;min-height:46px;}
458
+ .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);}
459
+ .cli-ui .cli-queue-row{display:flex;align-items:center;gap:8px;min-width:0;min-height:44px;}
459
460
  .cli-ui .cli-queue-row+.cli-queue-row{border-top:1px solid var(--line-2);}
460
461
  .cli-ui .cli-queue-icon{display:grid;place-items:center;flex:none;width:20px;color:var(--ink-4);}
461
462
  .cli-ui .cli-queue-icon svg{width:16px;height:16px;}
462
463
  .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
464
  .cli-ui .cli-queue-thumb{flex:none;width:32px;height:32px;object-fit:cover;border:1px solid var(--line);border-radius:7px;}
464
465
  .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
466
  .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
467
  .cli-ui .cli-queue-remove svg,.cli-ui .cli-queue-more svg{width:17px;height:17px;}
468
- .cli-ui .cli-queue-remove:hover,.cli-ui .cli-queue-more:hover{background:var(--surface-2);color:var(--ink);}
469
- .cli-ui .cli-queue-remove:hover{color:var(--red);}
468
+ @media(hover:hover) and (pointer:fine){
469
+ .cli-ui .cli-queue-remove:hover,.cli-ui .cli-queue-more:hover{background:var(--surface-2);color:var(--ink);}
470
+ .cli-ui .cli-queue-remove:hover{color:var(--red);}
471
+ }
470
472
  .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
473
  .cli-ui .cli-queue-popover{width:420px;}
472
474
  .cli-ui .cli-queue-detail{max-height:min(44vh,320px);overflow:auto;overscroll-behavior:contain;overflow-wrap:anywhere;}
@@ -479,11 +481,10 @@ cli-split{display:block;}
479
481
  .cli-ui .cli-queue-feedback[role="alert"]{color:var(--red);}
480
482
  .cli-ui .session>.cli-queue{width:calc(100% - 48px);max-width:800px;align-self:center;margin:8px 24px 16px;border-radius:16px;}
481
483
  @container(max-width:420px){
482
- .cli-ui .cli-queue{margin:0 8px -1px;padding:4px 6px 7px;max-height:112px;}
484
+ .cli-ui .cli-queue{margin:0 10px -12px;padding:4px 6px 16px;max-height:112px;}
483
485
  .cli-ui .cli-queue-row{gap:5px;}
484
- .cli-ui .cli-queue-state{display:none;}
485
486
  }
486
- @media(pointer:coarse){.cli-ui .cli-queue-remove,.cli-ui .cli-queue-more{width:36px;height:40px;}}
487
+ @media(pointer:coarse){.cli-ui .cli-queue-remove,.cli-ui .cli-queue-more{width:44px;height:44px;}}
487
488
  @media(max-height:500px){.cli-ui .cli-queue{max-height:70px;}}
488
489
 
489
490
  /* 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)}>