pi-web-ui 0.46.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/themes/white.css CHANGED
@@ -216,6 +216,19 @@ body.panel-resizing {
216
216
  overflow-y: auto;
217
217
  padding: 6px 6px 0;
218
218
  }
219
+ /* Cross-project running conversations: a group header names the workspace
220
+ when the group is NOT the current project (the current project stays bare
221
+ to preserve the old look). */
222
+ .panel-conv-group-title {
223
+ padding: 6px 8px 2px;
224
+ font-size: 10px;
225
+ font-weight: 600;
226
+ color: var(--text-dim);
227
+ letter-spacing: 0.02em;
228
+ white-space: nowrap;
229
+ overflow: hidden;
230
+ text-overflow: ellipsis;
231
+ }
219
232
  .panel-sessions {
220
233
  flex: 1;
221
234
  min-height: 0;
@@ -2871,6 +2884,67 @@ body.panel-resizing {
2871
2884
  overflow-y: auto;
2872
2885
  }
2873
2886
 
2887
+ /* Two-column middle band: provider filter sidebar (left) + model list
2888
+ (right). Only the list columns scroll independently. */
2889
+ .dd-model-body {
2890
+ display: flex;
2891
+ gap: 2px;
2892
+ min-height: 0;
2893
+ flex: 1 1 auto;
2894
+ }
2895
+ .dd-provider-col {
2896
+ .dd-provider-head {
2897
+ padding: 5px 8px 4px;
2898
+ font-size: 10px;
2899
+ font-weight: 700;
2900
+ letter-spacing: 0.6px;
2901
+ text-transform: uppercase;
2902
+ color: var(--text-faint);
2903
+ }
2904
+ flex: none;
2905
+ width: 112px;
2906
+ overflow-y: auto;
2907
+ border-right: 1px solid var(--border-soft);
2908
+ margin: 2px 4px 2px 0;
2909
+ padding-right: 4px;
2910
+ }
2911
+ .dd-provider-item {
2912
+ display: flex;
2913
+ align-items: center;
2914
+ justify-content: space-between;
2915
+ gap: 6px;
2916
+ width: 100%;
2917
+ padding: 6px 8px;
2918
+ border: none;
2919
+ border-radius: 6px;
2920
+ background: transparent;
2921
+ color: var(--text-dim);
2922
+ font-size: 12px;
2923
+ text-align: left;
2924
+ cursor: pointer;
2925
+ white-space: nowrap;
2926
+ }
2927
+ .dd-provider-item:hover {
2928
+ background: var(--bg-elev);
2929
+ color: var(--text);
2930
+ }
2931
+ .dd-provider-item.active {
2932
+ background: var(--accent-soft);
2933
+ color: var(--accent);
2934
+ font-weight: 600;
2935
+ }
2936
+ .dd-provider-name {
2937
+ overflow: hidden;
2938
+ text-overflow: ellipsis;
2939
+ min-width: 0;
2940
+ }
2941
+ .dd-provider-count {
2942
+ flex: none;
2943
+ font-size: 10.5px;
2944
+ color: var(--text-faint);
2945
+ font-family: var(--mono);
2946
+ }
2947
+
2874
2948
  /* Fixed footer (refresh / manage models) — never scrolls away. */
2875
2949
  .dd-footer {
2876
2950
  border-top: 1px solid var(--border-soft);
@@ -2878,12 +2952,15 @@ body.panel-resizing {
2878
2952
  padding-top: 3px;
2879
2953
  }
2880
2954
 
2881
- /* 模型下拉(dd-menu-model):外层菜单本身不滚动,只有中间的模型列表
2882
- (.dd-model-scroll)滚动——顶部搜索行和底部「刷新 / 管理模型」始终可见。 */
2955
+ /* 模型下拉(dd-menu-model):外层菜单本身不滚动,只有中间的两栏区域
2956
+ (.dd-model-body)滚动——顶部搜索行和底部「刷新 / 管理模型」始终可见。 */
2883
2957
  .dd-menu.dd-menu-model {
2884
2958
  display: flex;
2885
2959
  flex-direction: column;
2886
2960
  overflow-y: hidden;
2961
+ /* 加宽以容纳左侧服务商栏 + 右侧模型列表 */
2962
+ min-width: 330px;
2963
+ max-width: 460px;
2887
2964
  }
2888
2965
  .dd-menu.dd-menu-model .dd-model-scroll {
2889
2966
  flex: 1 1 auto;
@@ -4306,24 +4383,48 @@ span.msg-editor-hint svg {
4306
4383
  white-space: nowrap;
4307
4384
  }
4308
4385
 
4309
- .empty-examples {
4310
- margin-top: 34px;
4386
+ /* ---- 提示词模板(空态推荐卡片) ---- */
4387
+ .empty-templates {
4388
+ margin-top: 30px;
4389
+ width: min(720px, 92vw);
4390
+ }
4391
+
4392
+ .empty-templates-head {
4393
+ display: flex;
4394
+ align-items: baseline;
4395
+ justify-content: center;
4396
+ gap: 10px;
4397
+ flex-wrap: wrap;
4398
+ margin-bottom: 12px;
4399
+ }
4400
+
4401
+ .empty-templates-title {
4402
+ font-size: 14px;
4403
+ font-weight: 650;
4404
+ color: var(--text);
4405
+ }
4406
+
4407
+ .empty-templates-hint {
4408
+ font-size: 11.5px;
4409
+ color: var(--text-faint);
4410
+ }
4411
+
4412
+ .empty-templates-grid {
4311
4413
  display: grid;
4312
- grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
4414
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
4313
4415
  gap: 10px;
4314
- width: min(560px, 90vw);
4315
4416
  }
4316
4417
 
4317
- .empty-example {
4418
+ .empty-template {
4318
4419
  display: flex;
4319
- align-items: center;
4420
+ align-items: flex-start;
4320
4421
  gap: 10px;
4321
- padding: 11px 14px;
4422
+ padding: 11px 13px;
4423
+ position: relative; /* 右上角 ✏️ 编辑按钮的定位基准 */
4322
4424
  border: 1px solid var(--border);
4323
4425
  border-radius: 12px;
4324
4426
  background: var(--bg-elev);
4325
4427
  color: var(--text-dim);
4326
- font-size: 13px;
4327
4428
  text-align: left;
4328
4429
  cursor: pointer;
4329
4430
  transition:
@@ -4332,23 +4433,313 @@ span.msg-editor-hint svg {
4332
4433
  transform 0.12s,
4333
4434
  box-shadow 0.15s;
4334
4435
  }
4335
- .empty-example:hover {
4436
+
4437
+ /* 卡片右上角的编辑(✏️)按钮:点卡片 = 填入输入框,点 ✏️ = 编辑/删除。 */
4438
+ .template-card-ops {
4439
+ position: absolute;
4440
+ top: 7px;
4441
+ right: 7px;
4442
+ display: inline-flex;
4443
+ align-items: center;
4444
+ justify-content: center;
4445
+ width: 20px;
4446
+ height: 20px;
4447
+ border-radius: 6px;
4448
+ color: var(--text-faint);
4449
+ cursor: pointer;
4450
+ background: transparent;
4451
+ transition:
4452
+ background 0.15s,
4453
+ color 0.15s;
4454
+ }
4455
+ .template-card-ops:hover {
4456
+ background: var(--accent-soft);
4457
+ color: var(--accent);
4458
+ }
4459
+ .empty-template:hover {
4336
4460
  border-color: rgba(139, 92, 246, 0.5);
4337
4461
  background: var(--accent-soft);
4338
- color: var(--text);
4339
- transform: translateY(-1px);
4340
4462
  box-shadow: 0 8px 22px rgba(139, 92, 246, 0.16);
4341
4463
  }
4464
+ .empty-template.add {
4465
+ border-style: dashed;
4466
+ }
4467
+ .empty-template.add:hover {
4468
+ border-color: rgba(139, 92, 246, 0.6);
4469
+ }
4342
4470
 
4343
- .empty-example-icon {
4471
+ .empty-template-icon {
4344
4472
  font-size: 17px;
4345
4473
  flex-shrink: 0;
4474
+ line-height: 1.5;
4475
+ }
4476
+ .empty-template.add .empty-template-icon {
4477
+ display: inline-flex;
4478
+ align-items: center;
4479
+ justify-content: center;
4480
+ width: 20px;
4481
+ height: 20px;
4482
+ color: var(--text-faint);
4483
+ }
4484
+
4485
+ .empty-template-main {
4486
+ display: flex;
4487
+ flex-direction: column;
4488
+ gap: 2px;
4489
+ min-width: 0;
4490
+ }
4491
+
4492
+ .empty-template-title {
4493
+ font-size: 13px;
4494
+ font-weight: 600;
4495
+ color: var(--text);
4496
+ white-space: nowrap;
4497
+ overflow: hidden;
4498
+ text-overflow: ellipsis;
4499
+ }
4500
+
4501
+ .empty-template-desc {
4502
+ font-size: 11.5px;
4503
+ color: var(--text-faint);
4504
+ line-height: 1.45;
4505
+ display: -webkit-box;
4506
+ -webkit-line-clamp: 2;
4507
+ -webkit-box-orient: vertical;
4508
+ overflow: hidden;
4509
+ }
4510
+
4511
+ .empty-templates-foot {
4512
+ margin-top: 10px;
4513
+ display: flex;
4514
+ justify-content: center;
4515
+ }
4516
+
4517
+ .empty-templates-reset {
4518
+ display: inline-flex;
4519
+ align-items: center;
4520
+ gap: 5px;
4521
+ border: none;
4522
+ background: transparent;
4523
+ color: var(--text-faint);
4524
+ font-size: 11.5px;
4525
+ cursor: pointer;
4526
+ padding: 4px 8px;
4527
+ border-radius: 6px;
4528
+ transition: color 0.15s, background 0.15s;
4529
+ }
4530
+ .empty-templates-reset:hover {
4531
+ color: var(--text-dim);
4532
+ background: var(--bg-elev);
4533
+ }
4534
+
4535
+ /* ---- 提示词模板 modal ---- */
4536
+ .template-modal {
4537
+ max-width: 620px;
4538
+ }
4539
+
4540
+ /* 模板库(选择器)弹窗:列所有模板卡片 */
4541
+ .template-picker {
4542
+ max-width: 720px;
4543
+ }
4544
+
4545
+ .template-picker-head {
4546
+ display: flex;
4547
+ align-items: center;
4548
+ gap: 10px;
4549
+ }
4550
+
4551
+ .template-picker-title {
4552
+ flex: 1;
4553
+ font-size: 15px;
4554
+ font-weight: 650;
4555
+ color: var(--text);
4556
+ }
4557
+
4558
+ .template-picker-hint {
4559
+ font-size: 11.5px;
4560
+ color: var(--text-faint);
4561
+ }
4562
+
4563
+ .template-picker-grid {
4564
+ display: grid;
4565
+ grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
4566
+ gap: 10px;
4567
+ }
4568
+
4569
+ .template-picker-foot {
4570
+ display: flex;
4571
+ justify-content: center;
4572
+ margin-top: 4px;
4573
+ }
4574
+
4575
+ .template-modal-head {
4576
+ display: flex;
4577
+ align-items: center;
4578
+ gap: 10px;
4579
+ }
4580
+
4581
+ .template-modal-icon {
4582
+ font-size: 20px;
4583
+ flex-shrink: 0;
4346
4584
  }
4347
4585
 
4348
- .empty-example-text {
4586
+ .template-modal-badge {
4587
+ flex-shrink: 0;
4588
+ font-size: 11px;
4589
+ font-weight: 700;
4590
+ color: var(--accent);
4591
+ border: 1px solid var(--accent);
4592
+ border-radius: 999px;
4593
+ padding: 1px 8px;
4349
4594
  white-space: nowrap;
4595
+ }
4596
+
4597
+ .template-modal-title {
4598
+ flex: 1;
4599
+ font-size: 15px;
4600
+ font-weight: 650;
4601
+ color: var(--text);
4602
+ min-width: 0;
4350
4603
  overflow: hidden;
4351
4604
  text-overflow: ellipsis;
4605
+ white-space: nowrap;
4606
+ }
4607
+
4608
+ .template-modal-close {
4609
+ width: 30px;
4610
+ height: 30px;
4611
+ padding: 0;
4612
+ border-radius: 50%;
4613
+ flex-shrink: 0;
4614
+ display: inline-flex;
4615
+ align-items: center;
4616
+ justify-content: center;
4617
+ color: var(--text-dim);
4618
+ background: transparent;
4619
+ }
4620
+
4621
+ .template-field {
4622
+ display: flex;
4623
+ flex-direction: column;
4624
+ gap: 5px;
4625
+ }
4626
+
4627
+ .template-field-label {
4628
+ font-size: 11.5px;
4629
+ font-weight: 600;
4630
+ color: var(--text-dim);
4631
+ }
4632
+
4633
+ .template-field-input {
4634
+ border: 1px solid var(--border);
4635
+ border-radius: 8px;
4636
+ background: var(--bg-elev);
4637
+ color: var(--text);
4638
+ font-size: 13px;
4639
+ padding: 7px 10px;
4640
+ outline: none;
4641
+ transition: border-color 0.15s;
4642
+ }
4643
+ .template-field-input:focus {
4644
+ border-color: var(--accent);
4645
+ }
4646
+ .template-field-input.icon {
4647
+ width: 72px;
4648
+ text-align: center;
4649
+ font-size: 16px;
4650
+ }
4651
+
4652
+ .template-field-prompt {
4653
+ border: 1px solid var(--border);
4654
+ border-radius: 8px;
4655
+ background: var(--bg-elev);
4656
+ color: var(--text);
4657
+ font-size: 13px;
4658
+ line-height: 1.6;
4659
+ padding: 9px 10px;
4660
+ resize: none;
4661
+ overflow: hidden;
4662
+ outline: none;
4663
+ min-height: 96px;
4664
+ transition: border-color 0.15s;
4665
+ }
4666
+ .template-field-prompt:focus {
4667
+ border-color: var(--accent);
4668
+ }
4669
+
4670
+ .template-error {
4671
+ font-size: 12px;
4672
+ color: var(--red);
4673
+ }
4674
+
4675
+ .template-modal-actions {
4676
+ display: flex;
4677
+ align-items: center;
4678
+ justify-content: space-between;
4679
+ gap: 8px;
4680
+ flex-wrap: wrap;
4681
+ }
4682
+
4683
+ .template-modal-actions-left,
4684
+ .template-modal-actions-right {
4685
+ display: flex;
4686
+ align-items: center;
4687
+ gap: 8px;
4688
+ flex-wrap: wrap;
4689
+ }
4690
+
4691
+ .template-btn {
4692
+ font-size: 12.5px;
4693
+ padding: 6px 12px;
4694
+ border-radius: 8px;
4695
+ /* 显式主题背景,避免浏览器默认按钮灰(紫晕等主题下与文字对比度差) */
4696
+ background: var(--bg-elev);
4697
+ border-color: var(--border);
4698
+ color: var(--text-dim);
4699
+ }
4700
+ .template-btn:hover {
4701
+ border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
4702
+ color: var(--text);
4703
+ }
4704
+ .template-btn.ghost {
4705
+ background: transparent;
4706
+ }
4707
+ .template-btn.ghost.danger {
4708
+ color: var(--red);
4709
+ border-color: color-mix(in srgb, var(--red) 45%, var(--border));
4710
+ }
4711
+ .template-btn.fill,
4712
+ .template-btn.send {
4713
+ font-weight: 600;
4714
+ }
4715
+ .template-btn.fill {
4716
+ background: var(--accent-soft);
4717
+ border-color: color-mix(in srgb, var(--accent) 60%, var(--border));
4718
+ color: var(--accent);
4719
+ }
4720
+ .template-btn.fill:hover {
4721
+ background: var(--accent-soft);
4722
+ color: var(--accent);
4723
+ filter: brightness(1.12);
4724
+ }
4725
+ .template-btn.send {
4726
+ background: var(--accent);
4727
+ border-color: var(--accent);
4728
+ color: #fff;
4729
+ }
4730
+ .template-btn.send:hover {
4731
+ filter: brightness(1.08);
4732
+ }
4733
+
4734
+ /* 模板弹窗右上角关闭钮:同样显式主题背景 */
4735
+ .template-modal-close {
4736
+ background: var(--bg-elev);
4737
+ border-color: var(--border);
4738
+ color: var(--text-dim);
4739
+ }
4740
+ .template-modal-close:hover {
4741
+ background: var(--accent-soft);
4742
+ color: var(--accent);
4352
4743
  }
4353
4744
 
4354
4745
  .streaming-wait,
@@ -4971,16 +5362,27 @@ span.msg-editor-hint svg {
4971
5362
  inset 0 1px 0 rgba(255, 255, 255, 0.7),
4972
5363
  0 4px 18px rgba(0, 0, 0, 0.28);
4973
5364
  }
4974
- .inputbox-row {
5365
+ /* 底部工具条(ChatGPT 风格,整合进输入框):左 = 附件 / 模型 / 思考强度,
5366
+ 右 = 发送 / 停止。与输入区之间用一条细分隔线划开。 */
5367
+ .composer-tools {
4975
5368
  display: flex;
4976
- align-items: flex-end;
4977
- gap: 10px;
5369
+ align-items: center;
5370
+ justify-content: space-between;
5371
+ gap: 8px;
5372
+ padding-top: 8px;
5373
+ border-top: 1px solid var(--border-soft);
5374
+ }
5375
+ .composer-tools-left {
5376
+ display: flex;
5377
+ align-items: center;
5378
+ gap: 6px;
4978
5379
  min-width: 0;
5380
+ flex-wrap: wrap;
4979
5381
  }
4980
- /* Mobile tools row (file / model / thinking / send) — desktop hides it,
4981
- phones show it under the textarea (see the ≤768px block). */
4982
- .input-tools {
4983
- display: none;
5382
+ .composer-tools-right {
5383
+ display: flex;
5384
+ align-items: center;
5385
+ flex-shrink: 0;
4984
5386
  }
4985
5387
  .inputbox:focus-within {
4986
5388
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
@@ -4991,7 +5393,8 @@ span.msg-editor-hint svg {
4991
5393
  }
4992
5394
 
4993
5395
  .inputbox textarea {
4994
- flex: 1;
5396
+ flex: none; /* 不能用 flex:1 —— flex-basis:0% 会覆盖 JS 设置的 inline height,
5397
+ * 导致自适应高度失效(输入多行也不长高、不出现滚动条) */
4995
5398
  resize: none;
4996
5399
  border: none;
4997
5400
  outline: none;
@@ -5070,11 +5473,13 @@ span.msg-editor-hint svg {
5070
5473
  }
5071
5474
 
5072
5475
  /* Paperclip: quiet until hovered. */
5073
- .inputbox .btn.attach-img {
5476
+ .inputbox .btn.attach-img,
5477
+ .inputbox .btn.tpl-open {
5074
5478
  border: none;
5075
5479
  color: var(--text-faint);
5076
5480
  }
5077
- .inputbox .btn.attach-img:hover:not(:disabled) {
5481
+ .inputbox .btn.attach-img:hover:not(:disabled),
5482
+ .inputbox .btn.tpl-open:hover {
5078
5483
  background: var(--accent-soft);
5079
5484
  color: var(--accent);
5080
5485
  }
@@ -7046,49 +7451,35 @@ span.msg-editor-hint svg {
7046
7451
  display: none;
7047
7452
  }
7048
7453
 
7049
- /* ---- input becomes two lines: textarea, then tools below ---- */
7050
- .input-tools {
7051
- display: flex;
7052
- align-items: center;
7053
- justify-content: space-between;
7054
- gap: 6px;
7055
- flex-wrap: nowrap;
7056
- }
7057
- .input-tools-left,
7058
- .input-tools-right {
7059
- display: flex;
7060
- align-items: center;
7061
- gap: 6px;
7062
- min-width: 0;
7063
- }
7064
- .input-tools-right {
7065
- flex-shrink: 0;
7066
- }
7067
- .inputbox-row .attach-img,
7068
- .inputbox-row .inputbox-actions {
7069
- display: none;
7070
- }
7071
- /* Keep labels readable in the input tools row (the global chip rule
7072
- above hides them) and give the model name room to truncate. */
7073
- .input-tools .chip > span:not(.update-dot) {
7454
+ /* ---- composer: 输入框内底部工具条(模型/思考/附件 左,发送/停止 右)。
7455
+ 恢复 chip 标签显示(上面的全局规则会隐藏它们),并让模型名可截断。 ---- */
7456
+ .composer-tools .chip > span:not(.update-dot) {
7074
7457
  display: inline;
7075
7458
  }
7076
- .input-tools .chip-model {
7077
- max-width: 80px;
7459
+ .composer-tools .chip-model {
7460
+ max-width: 96px;
7078
7461
  }
7079
- /* Compress chips so model + thinking + attach + send fit one line on
7080
- narrow phones: allow shrinking with ellipsis instead of wrapping. */
7081
- .input-tools .chip {
7462
+ .composer-tools .chip {
7082
7463
  padding: 5px 8px;
7083
7464
  flex-shrink: 1;
7084
7465
  min-width: 0;
7085
7466
  }
7086
- .input-tools .chip .chip-sub,
7087
- .input-tools .chip .chip-model {
7467
+ .composer-tools .chip .chip-sub,
7468
+ .composer-tools .chip .chip-model {
7088
7469
  overflow: hidden;
7089
7470
  text-overflow: ellipsis;
7090
7471
  min-width: 0;
7091
7472
  }
7473
+ /* 超窄屏下工具条可换行,避免挤压发送按钮。 */
7474
+ .composer-tools {
7475
+ flex-wrap: wrap;
7476
+ }
7477
+ .composer-tools-left {
7478
+ flex: 1 1 auto;
7479
+ }
7480
+ .composer-tools-right {
7481
+ flex-shrink: 0;
7482
+ }
7092
7483
  .topbar-actions {
7093
7484
  gap: 6px;
7094
7485
  flex-wrap: wrap;
@@ -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-B71Da7xx.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-BdeKFOaT.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};