pi-web-ui 0.29.0 → 0.29.2

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/themes/light.css CHANGED
@@ -1706,6 +1706,36 @@ body {
1706
1706
  border-left-color: var(--accent);
1707
1707
  }
1708
1708
 
1709
+ /* per-file stage / unstage actions (visible on hover) */
1710
+ .scm-file-actions {
1711
+ display: none;
1712
+ margin-left: auto;
1713
+ gap: 2px;
1714
+ }
1715
+ .scm-file:hover .scm-file-actions {
1716
+ display: inline-flex;
1717
+ }
1718
+ .scm-act {
1719
+ width: 18px;
1720
+ height: 18px;
1721
+ padding: 0;
1722
+ border: 1px solid var(--border);
1723
+ border-radius: 4px;
1724
+ background: var(--bg-elev2);
1725
+ color: var(--text-2);
1726
+ font-size: 13px;
1727
+ line-height: 1;
1728
+ display: inline-flex;
1729
+ align-items: center;
1730
+ justify-content: center;
1731
+ cursor: pointer;
1732
+ }
1733
+ .scm-act:hover {
1734
+ background: var(--accent-soft);
1735
+ color: var(--text);
1736
+ border-color: var(--accent);
1737
+ }
1738
+
1709
1739
  .scm-file-xy {
1710
1740
  display: inline-flex;
1711
1741
  align-items: center;
@@ -2233,6 +2263,38 @@ body {
2233
2263
  font-size: 11px;
2234
2264
  color: var(--text-dim);
2235
2265
  }
2266
+ /* 运行命令行:默认单行省略 + 悬浮 tooltip 显示完整命令,点击切换换行展开 */
2267
+ .bg-task-cmd {
2268
+ display: flex;
2269
+ align-items: flex-start;
2270
+ gap: 6px;
2271
+ width: 100%;
2272
+ margin-top: 4px;
2273
+ padding: 3px 7px;
2274
+ border: 1px solid var(--border);
2275
+ border-radius: 5px;
2276
+ background: var(--bg-elev3, rgba(255, 255, 255, 0.04));
2277
+ color: var(--text-dim);
2278
+ font-size: 11px;
2279
+ text-align: left;
2280
+ cursor: pointer;
2281
+ }
2282
+ .bg-task-cmd svg {
2283
+ flex: none;
2284
+ margin-top: 1px;
2285
+ }
2286
+ .bg-task-cmd code {
2287
+ min-width: 0;
2288
+ white-space: nowrap;
2289
+ overflow: hidden;
2290
+ text-overflow: ellipsis;
2291
+ font-family: var(--mono, ui-monospace, monospace);
2292
+ color: var(--text);
2293
+ }
2294
+ .bg-task-cmd.open code {
2295
+ white-space: pre-wrap;
2296
+ overflow-wrap: anywhere;
2297
+ }
2236
2298
  .bg-task-stop {
2237
2299
  flex: none;
2238
2300
  display: inline-flex;
@@ -2284,6 +2346,150 @@ body {
2284
2346
  cursor: not-allowed;
2285
2347
  }
2286
2348
 
2349
+ /* ---- 全局搜索弹窗 (GlobalSearchModal):搜对话 / 项目 / 文件 ---- */
2350
+ .gs-backdrop {
2351
+ align-items: flex-start;
2352
+ padding-top: 10vh;
2353
+ }
2354
+ .gs-modal {
2355
+ display: flex;
2356
+ flex-direction: column;
2357
+ width: min(640px, 92vw);
2358
+ max-height: 70vh;
2359
+ border: 1px solid var(--border);
2360
+ border-radius: 12px;
2361
+ background: var(--bg-elev2, var(--bg-elev));
2362
+ box-shadow: 0 18px 60px rgba(0, 0, 0, 0.45);
2363
+ overflow: hidden;
2364
+ }
2365
+ .gs-input-row {
2366
+ display: flex;
2367
+ align-items: center;
2368
+ gap: 10px;
2369
+ padding: 12px 14px;
2370
+ border-bottom: 1px solid var(--border);
2371
+ color: var(--text-faint);
2372
+ }
2373
+ .gs-input-row svg {
2374
+ flex: none;
2375
+ }
2376
+ .gs-input-row input {
2377
+ flex: 1;
2378
+ min-width: 0;
2379
+ border: none;
2380
+ outline: none;
2381
+ background: transparent;
2382
+ color: var(--text);
2383
+ font-size: 15px;
2384
+ }
2385
+ .gs-close {
2386
+ flex: none;
2387
+ display: inline-flex;
2388
+ padding: 4px;
2389
+ border: none;
2390
+ background: transparent;
2391
+ color: var(--text-faint);
2392
+ cursor: pointer;
2393
+ border-radius: 6px;
2394
+ }
2395
+ .gs-close:hover {
2396
+ color: var(--text);
2397
+ background: var(--bg-elev3, rgba(0, 0, 0, 0.03));
2398
+ }
2399
+ .gs-results {
2400
+ flex: 1;
2401
+ min-height: 0;
2402
+ overflow-y: auto;
2403
+ padding: 6px 8px 10px;
2404
+ }
2405
+ .gs-empty {
2406
+ padding: 26px 12px;
2407
+ font-size: 13px;
2408
+ color: var(--text-faint);
2409
+ text-align: center;
2410
+ }
2411
+ .gs-section + .gs-section {
2412
+ margin-top: 10px;
2413
+ }
2414
+ .gs-section-head {
2415
+ display: flex;
2416
+ align-items: center;
2417
+ gap: 6px;
2418
+ padding: 6px 8px 4px;
2419
+ font-size: 11px;
2420
+ font-weight: 700;
2421
+ letter-spacing: 0.6px;
2422
+ text-transform: uppercase;
2423
+ color: var(--text-faint);
2424
+ }
2425
+ .gs-section-head em {
2426
+ font-style: normal;
2427
+ font-weight: 600;
2428
+ color: var(--accent);
2429
+ }
2430
+ .gs-item {
2431
+ display: flex;
2432
+ flex-direction: column;
2433
+ gap: 2px;
2434
+ width: 100%;
2435
+ padding: 7px 10px;
2436
+ border: none;
2437
+ border-radius: 7px;
2438
+ background: transparent;
2439
+ color: var(--text-dim);
2440
+ font-size: 13px;
2441
+ text-align: left;
2442
+ cursor: pointer;
2443
+ }
2444
+ .gs-item:hover:not(:disabled),
2445
+ .gs-item.active:not(:disabled) {
2446
+ background: var(--bg-elev3, rgba(0, 0, 0, 0.03));
2447
+ }
2448
+ .gs-item:disabled {
2449
+ cursor: default;
2450
+ opacity: 0.55;
2451
+ }
2452
+ .gs-item-title {
2453
+ display: flex;
2454
+ align-items: baseline;
2455
+ gap: 8px;
2456
+ font-size: 13px;
2457
+ font-weight: 600;
2458
+ color: var(--text);
2459
+ overflow: hidden;
2460
+ white-space: nowrap;
2461
+ text-overflow: ellipsis;
2462
+ }
2463
+ .gs-item-meta {
2464
+ font-style: normal;
2465
+ font-size: 11px;
2466
+ font-weight: 500;
2467
+ color: var(--text-dim);
2468
+ background: var(--bg-elev3, rgba(0, 0, 0, 0.03));
2469
+ border-radius: 4px;
2470
+ padding: 1px 6px;
2471
+ }
2472
+ .gs-item-sub {
2473
+ font-size: 11.5px;
2474
+ color: var(--text-dim);
2475
+ overflow: hidden;
2476
+ white-space: nowrap;
2477
+ text-overflow: ellipsis;
2478
+ }
2479
+ .gs-truncated {
2480
+ padding: 5px 10px;
2481
+ font-size: 11.5px;
2482
+ color: var(--amber, #e6b450);
2483
+ }
2484
+ .gs-foot {
2485
+ display: flex;
2486
+ gap: 14px;
2487
+ padding: 8px 14px;
2488
+ border-top: 1px solid var(--border);
2489
+ font-size: 11px;
2490
+ color: var(--text-faint);
2491
+ }
2492
+
2287
2493
  /* Desktop-only toolbar block (model/thinking/sound/lang/update/github).
2288
2494
  On phones it is replaced by the single "⋯" button (.topbar-more). */
2289
2495
  .topbar-desktop {
@@ -2430,6 +2636,69 @@ body {
2430
2636
  text-align: center;
2431
2637
  }
2432
2638
 
2639
+ /* Scrollable middle band of the model dropdown — the model list; the
2640
+ dd-header / dd-search-row on top and the dd-footer below stay fixed. */
2641
+ .dd-model-scroll {
2642
+ max-height: min(300px, 42vh);
2643
+ overflow-y: auto;
2644
+ }
2645
+
2646
+ /* Fixed footer (refresh / manage models) — never scrolls away. */
2647
+ .dd-footer {
2648
+ border-top: 1px solid var(--border-soft);
2649
+ margin-top: 6px;
2650
+ padding-top: 3px;
2651
+ }
2652
+
2653
+ /* 模型下拉(dd-menu-model):外层菜单本身不滚动,只有中间的模型列表
2654
+ (.dd-model-scroll)滚动——顶部搜索行和底部「刷新 / 管理模型」始终可见。 */
2655
+ .dd-menu.dd-menu-model {
2656
+ display: flex;
2657
+ flex-direction: column;
2658
+ overflow-y: hidden;
2659
+ }
2660
+ .dd-menu.dd-menu-model .dd-model-scroll {
2661
+ flex: 1 1 auto;
2662
+ min-height: 0;
2663
+ max-height: none; /* 由外层 max-height 约束,列表吃掉剩余空间后内部滚动 */
2664
+ }
2665
+ .dd-menu.dd-menu-model .dd-footer {
2666
+ flex-shrink: 0;
2667
+ }
2668
+ .dd-footer .dd-refresh {
2669
+ border-top: none;
2670
+ margin-top: 0;
2671
+ }
2672
+
2673
+ /* 模型下拉的搜索过滤框(ModelThinking) */
2674
+ .dd-search-row {
2675
+ display: flex;
2676
+ align-items: center;
2677
+ gap: 7px;
2678
+ margin: 2px 8px 6px;
2679
+ padding: 0 8px;
2680
+ border: 1px solid var(--border);
2681
+ border-radius: 7px;
2682
+ background: var(--bg-elev);
2683
+ color: var(--text-faint);
2684
+ }
2685
+ .dd-search-row:focus-within {
2686
+ border-color: var(--accent);
2687
+ }
2688
+ .dd-search-row svg {
2689
+ flex: none;
2690
+ }
2691
+ .dd-search {
2692
+ flex: 1;
2693
+ min-width: 0;
2694
+ height: 28px;
2695
+ border: none;
2696
+ outline: none;
2697
+ background: transparent;
2698
+ color: var(--text);
2699
+ font-size: 12.5px;
2700
+ }
2701
+
2433
2702
  .dd-item {
2434
2703
  display: flex;
2435
2704
  align-items: center;
@@ -2607,6 +2876,22 @@ body {
2607
2876
 
2608
2877
  /* ----------------------------------------------------------------- notices */
2609
2878
 
2879
+ /* Protocol version mismatch (stale page after an in-place app update). */
2880
+ .protocol-banner {
2881
+ position: fixed;
2882
+ top: 52px;
2883
+ left: 50%;
2884
+ transform: translateX(-50%);
2885
+ z-index: 60;
2886
+ padding: 6px 14px;
2887
+ border-radius: 8px;
2888
+ background: rgba(245, 158, 11, 0.12);
2889
+ border: 1px solid var(--amber);
2890
+ color: var(--amber);
2891
+ font-size: 12px;
2892
+ white-space: nowrap;
2893
+ }
2894
+
2610
2895
  .notices {
2611
2896
  position: fixed;
2612
2897
  /* 顶部偏下:顶栏下方,不挡顶栏也不贴消息区 */
@@ -2725,6 +3010,15 @@ body {
2725
3010
  flex: 1;
2726
3011
  overflow-y: auto;
2727
3012
  padding: 20px 0 12px;
3013
+ /* 惰性窗口化自己做 scrollTop 补偿(LazyMount / MessageList sweep),
3014
+ * 浏览器原生滚动锚定会与之叠加导致双重跳动,关掉。 */
3015
+ overflow-anchor: none;
3016
+ }
3017
+
3018
+ /* 惰性窗口化的等高占位(视口外的重型消息收起后的替身) */
3019
+ .msg-lazy-ph {
3020
+ max-width: 860px;
3021
+ margin: 0 auto;
2728
3022
  }
2729
3023
 
2730
3024
  .msg {
@@ -2768,6 +3062,84 @@ body {
2768
3062
  margin-left: auto;
2769
3063
  }
2770
3064
 
3065
+ /* ------------------------------------------------ in-conversation search (Ctrl+F) */
3066
+
3067
+ .search-bar {
3068
+ position: absolute;
3069
+ top: 10px;
3070
+ left: 50%;
3071
+ transform: translateX(-50%);
3072
+ z-index: 30;
3073
+ display: flex;
3074
+ align-items: center;
3075
+ gap: 2px;
3076
+ max-width: min(480px, calc(100% - 32px));
3077
+ padding: 5px 6px 5px 12px;
3078
+ border-radius: 10px;
3079
+ border: 1px solid var(--border);
3080
+ background: var(--bg-elev2);
3081
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
3082
+ }
3083
+
3084
+ .search-input {
3085
+ background: transparent;
3086
+ border: none;
3087
+ outline: none;
3088
+ color: var(--text);
3089
+ font-size: 13px;
3090
+ width: 200px;
3091
+ padding: 4px 0;
3092
+ }
3093
+
3094
+ .search-input::placeholder {
3095
+ color: var(--text-faint);
3096
+ }
3097
+
3098
+ .search-count {
3099
+ font-size: 11px;
3100
+ color: var(--text-faint);
3101
+ white-space: nowrap;
3102
+ padding: 0 6px;
3103
+ font-variant-numeric: tabular-nums;
3104
+ }
3105
+
3106
+ .search-count.empty {
3107
+ color: var(--red);
3108
+ }
3109
+
3110
+ .search-btn {
3111
+ display: inline-flex;
3112
+ align-items: center;
3113
+ justify-content: center;
3114
+ width: 26px;
3115
+ height: 26px;
3116
+ border-radius: 7px;
3117
+ border: none;
3118
+ background: transparent;
3119
+ color: var(--text-dim);
3120
+ cursor: pointer;
3121
+ }
3122
+
3123
+ .search-btn:hover:not(:disabled) {
3124
+ background: var(--accent-soft);
3125
+ color: var(--text);
3126
+ }
3127
+
3128
+ .search-btn:disabled {
3129
+ opacity: 0.4;
3130
+ cursor: default;
3131
+ }
3132
+
3133
+ /* CSS Custom Highlight API —— 搜索命中内联高亮(不支持时自动无样式降级) */
3134
+ ::highlight(msg-search) {
3135
+ background-color: color-mix(in srgb, var(--amber) 28%, transparent);
3136
+ }
3137
+
3138
+ ::highlight(msg-search-active) {
3139
+ background-color: color-mix(in srgb, var(--amber) 80%, transparent);
3140
+ color: #1a1d26;
3141
+ }
3142
+
2771
3143
  /* ------------------------------------------------------- message edit/re-ask */
2772
3144
 
2773
3145
  .msg-actions {
@@ -4701,6 +5073,23 @@ body {
4701
5073
  /* ---- settings modal ---- */
4702
5074
  .settings-modal {
4703
5075
  max-width: 760px;
5076
+ /* 头部(modal-head/modal-desc)与底部(modal-actions)固定,仅内容区滚动 */
5077
+ overflow-y: hidden;
5078
+ }
5079
+ .settings-modal .modal-head,
5080
+ .settings-modal .modal-desc,
5081
+ .settings-modal .modal-actions,
5082
+ .settings-modal > .modal-close {
5083
+ flex-shrink: 0;
5084
+ }
5085
+ /* 滚动的内容区:承接原 modal 的 gap,各区块间距保持一致 */
5086
+ .settings-modal .modal-body {
5087
+ flex: 1 1 auto;
5088
+ min-height: 0;
5089
+ overflow-y: auto;
5090
+ display: flex;
5091
+ flex-direction: column;
5092
+ gap: 14px;
4704
5093
  }
4705
5094
 
4706
5095
  .set-section {
@@ -5091,6 +5480,38 @@ body {
5091
5480
  margin-top: 4px;
5092
5481
  }
5093
5482
 
5483
+ /* Model-config modal: fetch-models button row in the models section head. */
5484
+ .model-section-head {
5485
+ display: flex;
5486
+ align-items: center;
5487
+ justify-content: space-between;
5488
+ gap: 8px;
5489
+ flex-wrap: wrap;
5490
+ margin-top: 8px;
5491
+ }
5492
+ .model-section-head .form-section-title {
5493
+ margin: 0;
5494
+ }
5495
+ .model-section-actions {
5496
+ display: flex;
5497
+ align-items: center;
5498
+ gap: 8px;
5499
+ flex-wrap: wrap;
5500
+ }
5501
+ .fetch-msg {
5502
+ font-size: 12px;
5503
+ max-width: 260px;
5504
+ overflow: hidden;
5505
+ text-overflow: ellipsis;
5506
+ white-space: nowrap;
5507
+ }
5508
+ .fetch-msg.ok {
5509
+ color: var(--green);
5510
+ }
5511
+ .fetch-msg.err {
5512
+ color: var(--red);
5513
+ }
5514
+
5094
5515
  .section-hint {
5095
5516
  font-weight: 400;
5096
5517
  text-transform: none;
@@ -5193,6 +5614,16 @@ body {
5193
5614
  color: var(--text);
5194
5615
  background: var(--bg-elev);
5195
5616
  }
5617
+ /* 危险动作按钮(内置供应商「清空」等) */
5618
+ .btn.sm.danger {
5619
+ color: var(--red);
5620
+ border-color: var(--red);
5621
+ }
5622
+ .btn.sm.danger:hover {
5623
+ background: var(--red);
5624
+ color: #fff;
5625
+ }
5626
+
5196
5627
  .iconbtn.danger {
5197
5628
  color: #dc2626;
5198
5629
  }
@@ -1,2 +1,2 @@
1
- import{a as d,j as n}from"./markdown-DRBrS2Nf.js";import{b as $,T as R,u as O,F as P,a as K,c as q,d as L,e as B,f as J,g as X,h as G,r as Q}from"./index-BsrqFaSZ.js";import{D as U,o as V}from"./xterm-D1D2FVe3.js";import"./react-C9ovnpIm.js";function W({conversationId:s,terminalId:r,command:x,cwd:a,active:f,send:m,register:v}){const w=d.useRef(null),N=d.useRef(null),b=x?JSON.stringify(x):"";return d.useEffect(()=>{const p=w.current;if(!p)return;const t=new U({theme:$(),fontFamily:'"SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace',fontSize:13,cursorBlink:!0,scrollback:8e3}),c=new V;t.loadAddon(c),t.open(p),N.current={term:t,fit:c},f&&t.focus();const h=()=>{t.options.theme=$()};window.addEventListener(R,h),t.attachCustomKeyEventHandler(o=>{var F;if(o.type!=="keydown")return!0;const E=(F=o.key)==null?void 0:F.toLowerCase();if((o.ctrlKey||o.metaKey)&&E==="v")return!1;if(o.ctrlKey&&!o.shiftKey&&!o.altKey&&E==="c"&&t.hasSelection()){const T=t.textarea;return T&&(T.value=t.getSelection(),T.select()),!1}return!0});const g=v(s,r,{write:o=>t.write(o),dispose:()=>t.dispose()}),C=()=>{try{c.fit(),m({type:"terminal_resize",terminalId:r,conversationId:s,cols:t.cols,rows:t.rows})}catch{}},j=requestAnimationFrame(()=>{try{c.fit()}catch{}m(x?{type:"run_command",terminalId:r,conversationId:s,command:x,cols:t.cols,rows:t.rows}:{type:"terminal_create",terminalId:r,conversationId:s,cwd:a,cols:t.cols,rows:t.rows})}),k=t.onData(o=>{m({type:"terminal_input",terminalId:r,conversationId:s,data:o})});let y=null;return typeof ResizeObserver<"u"&&(y=new ResizeObserver(()=>{p.offsetWidth>0&&p.offsetHeight>0&&C()}),y.observe(p)),()=>{cancelAnimationFrame(j),k.dispose(),window.removeEventListener(R,h),y==null||y.disconnect(),g(),t.dispose(),N.current=null}},[s,r,b,m,v]),d.useEffect(()=>{if(!f)return;const p=requestAnimationFrame(()=>{const t=N.current;if(t){try{t.fit.fit(),m({type:"terminal_resize",terminalId:r,conversationId:s,cols:t.term.cols,rows:t.term.rows})}catch{}t.term.focus()}});return()=>cancelAnimationFrame(p)},[f]),n.jsx("div",{ref:w,className:`term-xterm ${f?"":"hidden"}`})}const A={name:"",command:"",cwd:"${pwd}"};function se({chat:s,send:r,terminal:x}){const a=O(),[f,m]=d.useState(null),[v,w]=d.useState(!1),[N,b]=d.useState(!1),[p,t]=d.useState(null),[c,h]=d.useState(A),[g,C]=d.useState(null),j=d.useRef(null);d.useEffect(()=>{s.terminals.length===0?m(null):s.terminals.some(e=>e.id===f)||m(s.terminals[s.terminals.length-1].id)},[s.terminals,f]),d.useEffect(()=>()=>{j.current&&clearTimeout(j.current)},[]);const k=e=>{var u;if(!s.ready)return;const i=Q(),l=s.activeConversationId||((u=s.state)==null?void 0:u.conversationId)||"";x.create({...e,id:i,conversationId:l,cols:e.cols??80,rows:e.rows??24,running:!0,exitCode:null}),m(i),w(!1)},y=()=>{var e;return k({title:a("terminalTitle",{n:s.terminals.length+1}),cwd:((e=s.state)==null?void 0:e.cwd)??""})},o=e=>{var u;const i=e.name||e.command,l=s.terminals.find(_=>_.title===i);if(l){x.restart(l.id),m(l.id),r({type:"run_command",terminalId:l.id,conversationId:l.conversationId,command:e,cols:80,rows:24});return}k({title:i,cwd:((u=s.state)==null?void 0:u.cwd)??"",command:e})},E=e=>{const i=s.terminals.find(l=>l.id===e);if(i&&r({type:"terminal_kill",terminalId:e,conversationId:i.conversationId}),x.close(e),f===e){const l=s.terminals.filter(u=>u.id!==e);m(l.length>0?l[l.length-1].id:null)}},F=()=>{b(!0),t(null),h(A)},T=e=>{const i=s.commands[e];i&&(b(!1),t(e),h({name:i.name,command:i.command,cwd:i.cwd??""}))},D=()=>{b(!1),t(null)},S=()=>{const e=c.name.trim(),i=c.command.trim();if(!e||!i)return;const l=c.cwd.trim(),u={name:e,command:i,cwd:l||void 0},_=N?[...s.commands,u]:p!==null?s.commands.map((z,H)=>H===p?u:z):s.commands;r({type:"save_commands",commands:_}),D()},I=e=>{if(g===e){const i=s.commands.filter((l,u)=>u!==e);r({type:"save_commands",commands:i}),C(null),j.current&&clearTimeout(j.current)}else C(e),j.current&&clearTimeout(j.current),j.current=setTimeout(()=>C(null),2500)},M=N||p!==null;return n.jsxs("div",{className:"terminal-view",children:[n.jsxs("aside",{className:`term-side term-commands ${v?"open":""}`,children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:a("commands")}),n.jsxs("div",{className:"panel-header-actions",children:[n.jsx("button",{type:"button",className:"panel-refresh",title:a("rerun"),onClick:()=>r({type:"list_commands"}),children:n.jsx(P,{})}),n.jsx("button",{type:"button",className:"panel-new",title:a("newCommand"),onClick:F,children:n.jsx(K,{})})]})]}),n.jsx("div",{className:"panel-body",children:M?n.jsxs("div",{className:"cmd-form",children:[n.jsx("label",{htmlFor:"cmd-name",children:a("name")}),n.jsx("input",{id:"cmd-name",className:"cmd-input",value:c.name,placeholder:a("exampleName"),autoFocus:!0,onChange:e=>h({...c,name:e.target.value})}),n.jsx("label",{htmlFor:"cmd-command",children:a("command")}),n.jsx("input",{id:"cmd-command",className:"cmd-input",value:c.command,placeholder:a("exampleCommand"),onChange:e=>h({...c,command:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("label",{htmlFor:"cmd-cwd",children:[a("directory")," ",n.jsx("span",{className:"cmd-hint",children:a("cwdHint")})]}),n.jsx("input",{id:"cmd-cwd",className:"cmd-input",value:c.cwd,placeholder:"${pwd}",onChange:e=>h({...c,cwd:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("div",{className:"cmd-form-actions",children:[n.jsx("button",{type:"button",className:"btn",onClick:D,children:a("cancel")}),n.jsx("button",{type:"button",className:"btn primary",disabled:!c.name.trim()||!c.command.trim(),onClick:S,children:a("save")})]})]}):n.jsxs(n.Fragment,{children:[s.commands.length===0&&n.jsx("div",{className:"panel-empty",children:a("noCommands")}),s.commands.map((e,i)=>n.jsxs("div",{className:"cmd-item",children:[n.jsx("button",{type:"button",className:"cmd-run",title:a("clickToRun"),onClick:()=>o(e),children:n.jsx(q,{})}),n.jsxs("button",{type:"button",className:"cmd-main",title:a("clickToRun"),onClick:()=>o(e),children:[n.jsx("span",{className:"cmd-name",children:e.name}),n.jsx("span",{className:"cmd-command",children:e.command}),e.cwd&&n.jsx("span",{className:"cmd-cwd",children:e.cwd})]}),n.jsx("button",{type:"button",className:"cmd-act",title:a("edit"),onClick:()=>T(i),children:n.jsx(L,{})}),n.jsx("button",{type:"button",className:`cmd-act del ${g===i?"confirm":""}`,title:a("delete"),onClick:()=>I(i),children:g===i?a("confirmQ"):n.jsx(B,{})})]},i))]})}),n.jsxs("div",{className:"term-tabs-block",children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:a("terminal")}),n.jsx("button",{type:"button",className:"panel-new",title:a("newTerminal"),onClick:y,children:n.jsx(K,{})})]}),n.jsxs("div",{className:"panel-body",children:[s.terminals.length===0&&n.jsx("div",{className:"panel-empty",children:a("noTerminal")}),s.terminals.map(e=>n.jsxs("div",{className:`term-tab ${e.id===f?"active":""}`,children:[n.jsxs("button",{type:"button",className:"term-tab-main",title:`${e.cwd}${e.command?`
1
+ import{a as d,j as n}from"./markdown-DRBrS2Nf.js";import{b as $,T as R,u as O,F as P,a as K,c as q,d as L,e as B,f as J,g as X,h as G,r as Q}from"./index-BiJTtKxQ.js";import{D as U,o as V}from"./xterm-D1D2FVe3.js";import"./react-C9ovnpIm.js";function W({conversationId:s,terminalId:r,command:x,cwd:a,active:f,send:m,register:v}){const w=d.useRef(null),N=d.useRef(null),b=x?JSON.stringify(x):"";return d.useEffect(()=>{const p=w.current;if(!p)return;const t=new U({theme:$(),fontFamily:'"SF Mono", "JetBrains Mono", ui-monospace, Menlo, Consolas, monospace',fontSize:13,cursorBlink:!0,scrollback:8e3}),c=new V;t.loadAddon(c),t.open(p),N.current={term:t,fit:c},f&&t.focus();const h=()=>{t.options.theme=$()};window.addEventListener(R,h),t.attachCustomKeyEventHandler(o=>{var F;if(o.type!=="keydown")return!0;const E=(F=o.key)==null?void 0:F.toLowerCase();if((o.ctrlKey||o.metaKey)&&E==="v")return!1;if(o.ctrlKey&&!o.shiftKey&&!o.altKey&&E==="c"&&t.hasSelection()){const T=t.textarea;return T&&(T.value=t.getSelection(),T.select()),!1}return!0});const g=v(s,r,{write:o=>t.write(o),dispose:()=>t.dispose()}),C=()=>{try{c.fit(),m({type:"terminal_resize",terminalId:r,conversationId:s,cols:t.cols,rows:t.rows})}catch{}},j=requestAnimationFrame(()=>{try{c.fit()}catch{}m(x?{type:"run_command",terminalId:r,conversationId:s,command:x,cols:t.cols,rows:t.rows}:{type:"terminal_create",terminalId:r,conversationId:s,cwd:a,cols:t.cols,rows:t.rows})}),k=t.onData(o=>{m({type:"terminal_input",terminalId:r,conversationId:s,data:o})});let y=null;return typeof ResizeObserver<"u"&&(y=new ResizeObserver(()=>{p.offsetWidth>0&&p.offsetHeight>0&&C()}),y.observe(p)),()=>{cancelAnimationFrame(j),k.dispose(),window.removeEventListener(R,h),y==null||y.disconnect(),g(),t.dispose(),N.current=null}},[s,r,b,m,v]),d.useEffect(()=>{if(!f)return;const p=requestAnimationFrame(()=>{const t=N.current;if(t){try{t.fit.fit(),m({type:"terminal_resize",terminalId:r,conversationId:s,cols:t.term.cols,rows:t.term.rows})}catch{}t.term.focus()}});return()=>cancelAnimationFrame(p)},[f]),n.jsx("div",{ref:w,className:`term-xterm ${f?"":"hidden"}`})}const A={name:"",command:"",cwd:"${pwd}"};function se({chat:s,send:r,terminal:x}){const a=O(),[f,m]=d.useState(null),[v,w]=d.useState(!1),[N,b]=d.useState(!1),[p,t]=d.useState(null),[c,h]=d.useState(A),[g,C]=d.useState(null),j=d.useRef(null);d.useEffect(()=>{s.terminals.length===0?m(null):s.terminals.some(e=>e.id===f)||m(s.terminals[s.terminals.length-1].id)},[s.terminals,f]),d.useEffect(()=>()=>{j.current&&clearTimeout(j.current)},[]);const k=e=>{var u;if(!s.ready)return;const i=Q(),l=s.activeConversationId||((u=s.state)==null?void 0:u.conversationId)||"";x.create({...e,id:i,conversationId:l,cols:e.cols??80,rows:e.rows??24,running:!0,exitCode:null}),m(i),w(!1)},y=()=>{var e;return k({title:a("terminalTitle",{n:s.terminals.length+1}),cwd:((e=s.state)==null?void 0:e.cwd)??""})},o=e=>{var u;const i=e.name||e.command,l=s.terminals.find(_=>_.title===i);if(l){x.restart(l.id),m(l.id),r({type:"run_command",terminalId:l.id,conversationId:l.conversationId,command:e,cols:80,rows:24});return}k({title:i,cwd:((u=s.state)==null?void 0:u.cwd)??"",command:e})},E=e=>{const i=s.terminals.find(l=>l.id===e);if(i&&r({type:"terminal_kill",terminalId:e,conversationId:i.conversationId}),x.close(e),f===e){const l=s.terminals.filter(u=>u.id!==e);m(l.length>0?l[l.length-1].id:null)}},F=()=>{b(!0),t(null),h(A)},T=e=>{const i=s.commands[e];i&&(b(!1),t(e),h({name:i.name,command:i.command,cwd:i.cwd??""}))},D=()=>{b(!1),t(null)},S=()=>{const e=c.name.trim(),i=c.command.trim();if(!e||!i)return;const l=c.cwd.trim(),u={name:e,command:i,cwd:l||void 0},_=N?[...s.commands,u]:p!==null?s.commands.map((z,H)=>H===p?u:z):s.commands;r({type:"save_commands",commands:_}),D()},I=e=>{if(g===e){const i=s.commands.filter((l,u)=>u!==e);r({type:"save_commands",commands:i}),C(null),j.current&&clearTimeout(j.current)}else C(e),j.current&&clearTimeout(j.current),j.current=setTimeout(()=>C(null),2500)},M=N||p!==null;return n.jsxs("div",{className:"terminal-view",children:[n.jsxs("aside",{className:`term-side term-commands ${v?"open":""}`,children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:a("commands")}),n.jsxs("div",{className:"panel-header-actions",children:[n.jsx("button",{type:"button",className:"panel-refresh",title:a("rerun"),onClick:()=>r({type:"list_commands"}),children:n.jsx(P,{})}),n.jsx("button",{type:"button",className:"panel-new",title:a("newCommand"),onClick:F,children:n.jsx(K,{})})]})]}),n.jsx("div",{className:"panel-body",children:M?n.jsxs("div",{className:"cmd-form",children:[n.jsx("label",{htmlFor:"cmd-name",children:a("name")}),n.jsx("input",{id:"cmd-name",className:"cmd-input",value:c.name,placeholder:a("exampleName"),autoFocus:!0,onChange:e=>h({...c,name:e.target.value})}),n.jsx("label",{htmlFor:"cmd-command",children:a("command")}),n.jsx("input",{id:"cmd-command",className:"cmd-input",value:c.command,placeholder:a("exampleCommand"),onChange:e=>h({...c,command:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("label",{htmlFor:"cmd-cwd",children:[a("directory")," ",n.jsx("span",{className:"cmd-hint",children:a("cwdHint")})]}),n.jsx("input",{id:"cmd-cwd",className:"cmd-input",value:c.cwd,placeholder:"${pwd}",onChange:e=>h({...c,cwd:e.target.value}),onKeyDown:e=>{e.key==="Enter"&&!e.nativeEvent.isComposing&&S()}}),n.jsxs("div",{className:"cmd-form-actions",children:[n.jsx("button",{type:"button",className:"btn",onClick:D,children:a("cancel")}),n.jsx("button",{type:"button",className:"btn primary",disabled:!c.name.trim()||!c.command.trim(),onClick:S,children:a("save")})]})]}):n.jsxs(n.Fragment,{children:[s.commands.length===0&&n.jsx("div",{className:"panel-empty",children:a("noCommands")}),s.commands.map((e,i)=>n.jsxs("div",{className:"cmd-item",children:[n.jsx("button",{type:"button",className:"cmd-run",title:a("clickToRun"),onClick:()=>o(e),children:n.jsx(q,{})}),n.jsxs("button",{type:"button",className:"cmd-main",title:a("clickToRun"),onClick:()=>o(e),children:[n.jsx("span",{className:"cmd-name",children:e.name}),n.jsx("span",{className:"cmd-command",children:e.command}),e.cwd&&n.jsx("span",{className:"cmd-cwd",children:e.cwd})]}),n.jsx("button",{type:"button",className:"cmd-act",title:a("edit"),onClick:()=>T(i),children:n.jsx(L,{})}),n.jsx("button",{type:"button",className:`cmd-act del ${g===i?"confirm":""}`,title:a("delete"),onClick:()=>I(i),children:g===i?a("confirmQ"):n.jsx(B,{})})]},i))]})}),n.jsxs("div",{className:"term-tabs-block",children:[n.jsxs("div",{className:"panel-header",children:[n.jsx("span",{className:"panel-title",children:a("terminal")}),n.jsx("button",{type:"button",className:"panel-new",title:a("newTerminal"),onClick:y,children:n.jsx(K,{})})]}),n.jsxs("div",{className:"panel-body",children:[s.terminals.length===0&&n.jsx("div",{className:"panel-empty",children:a("noTerminal")}),s.terminals.map(e=>n.jsxs("div",{className:`term-tab ${e.id===f?"active":""}`,children:[n.jsxs("button",{type:"button",className:"term-tab-main",title:`${e.cwd}${e.command?`
2
2
  > ${e.command.command}`:""}`,onClick:()=>{m(e.id),w(!1)},children:[n.jsx("span",{className:`term-tab-dot ${e.running?"run":"exit"}`}),n.jsxs("span",{className:"term-tab-title",children:[e.title,!e.running&&n.jsx("span",{className:"term-tab-exit",children:a("exited",{code:e.exitCode===null?"":` ${e.exitCode}`})})]})]}),n.jsx("button",{type:"button",className:"term-tab-close",title:a("closeTerminal"),onClick:()=>E(e.id),children:n.jsx(J,{})})]},e.id))]})]})]}),n.jsxs("div",{className:"term-main",children:[v&&n.jsx("div",{className:"drawer-backdrop",onClick:()=>w(!1)}),n.jsx("button",{type:"button",className:"term-side-toggle",title:a("commands"),onClick:()=>w(e=>!e),children:n.jsx(X,{})}),s.terminals.length===0?n.jsxs("div",{className:"term-empty",children:[n.jsx(G,{className:"term-empty-icon"}),n.jsx("div",{className:"term-empty-title",children:a("builtinTerminal")}),n.jsx("div",{className:"term-empty-sub",children:a("termEmptySub")})]}):s.terminals.map(e=>n.jsx(W,{conversationId:e.conversationId,terminalId:e.id,command:e.command,cwd:e.cwd,active:e.id===f,send:r,register:x.register},`${e.conversationId}:${e.id}`))]})]})}export{se as TerminalPanel};