tabminal 3.0.22 → 3.0.24

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tabminal",
3
- "version": "3.0.22",
3
+ "version": "3.0.24",
4
4
  "description": "Tab(ter)minal, a Cloud-Native terminal and ACP agent workspace for desktop, tablet, and phone.",
5
5
  "type": "module",
6
6
  "bin": {
package/public/app.js CHANGED
@@ -1,9 +1,11 @@
1
- import { Terminal } from 'https://cdn.jsdelivr.net/npm/xterm@5.3.0/+esm';
2
- import { FitAddon } from 'https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/+esm';
3
- import { WebLinksAddon } from 'https://cdn.jsdelivr.net/npm/xterm-addon-web-links@0.9.0/+esm';
4
- import { CanvasAddon } from 'https://cdn.jsdelivr.net/npm/xterm-addon-canvas@0.5.0/+esm';
5
- import { SearchAddon } from 'https://cdn.jsdelivr.net/npm/xterm-addon-search@0.13.0/+esm';
6
- import DOMPurify from 'https://cdn.jsdelivr.net/npm/dompurify/+esm';
1
+ import { Terminal } from 'https://cdn.jsdelivr.net/npm/@xterm/xterm@6.0.0/+esm';
2
+ import { FitAddon } from 'https://cdn.jsdelivr.net/npm/@xterm/addon-fit@0.11.0/+esm';
3
+ import { WebLinksAddon } from 'https://cdn.jsdelivr.net/npm/@xterm/addon-web-links@0.12.0/+esm';
4
+ import { CanvasAddon } from 'https://cdn.jsdelivr.net/npm/@xterm/addon-canvas@0.7.0/+esm';
5
+ import { SearchAddon } from 'https://cdn.jsdelivr.net/npm/@xterm/addon-search@0.16.0/+esm';
6
+ import { ProgressAddon } from 'https://cdn.jsdelivr.net/npm/@xterm/addon-progress@0.2.0/+esm';
7
+ import { LigaturesAddon } from 'https://cdn.jsdelivr.net/npm/@xterm/addon-ligatures@0.10.0/+esm';
8
+ import DOMPurify from 'https://cdn.jsdelivr.net/npm/dompurify@3.3.3/+esm';
7
9
  import {
8
10
  normalizeBaseUrl,
9
11
  getServerEndpointKeyFromUrl,
@@ -143,11 +145,11 @@ const PDFJS_WORKER_URL = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${PDFJS_VERSIO
143
145
  const MARKDOWN_IT_MODULE_URL = 'https://cdn.jsdelivr.net/npm/markdown-it@14.1.1/+esm';
144
146
  const MARKDOWN_TASK_LISTS_MODULE_URL = 'https://cdn.jsdelivr.net/npm/markdown-it-task-lists@2.1.1/+esm';
145
147
  const MARKDOWN_KATEX_MODULE_URL = 'https://cdn.jsdelivr.net/npm/@traptitech/markdown-it-katex@3.6.0/+esm';
146
- const KATEX_MODULE_URL = 'https://cdn.jsdelivr.net/npm/katex@0.16.25/+esm';
148
+ const KATEX_MODULE_URL = 'https://cdn.jsdelivr.net/npm/katex@0.16.45/+esm';
147
149
  const HIGHLIGHT_JS_MODULE_URL = 'https://cdn.jsdelivr.net/npm/highlight.js@11.11.1/+esm';
148
- const MARKDOWN_PREVIEW_GITHUB_CSS_URL = 'https://cdn.jsdelivr.net/npm/github-markdown-css@5.8.1/github-markdown-dark.min.css';
150
+ const MARKDOWN_PREVIEW_GITHUB_CSS_URL = 'https://cdn.jsdelivr.net/npm/github-markdown-css@5.9.0/github-markdown-dark.min.css';
149
151
  const MARKDOWN_PREVIEW_HIGHLIGHT_CSS_URL = 'https://cdn.jsdelivr.net/npm/highlight.js@11.11.1/styles/github-dark.css';
150
- const MARKDOWN_PREVIEW_KATEX_CSS_URL = 'https://cdn.jsdelivr.net/npm/katex@0.16.25/dist/katex.min.css';
152
+ const MARKDOWN_PREVIEW_KATEX_CSS_URL = 'https://cdn.jsdelivr.net/npm/katex@0.16.45/dist/katex.min.css';
151
153
  const CLOSE_ICON_SVG = '<svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
152
154
  const AGENT_ICON_SVG = '<svg viewBox="0 0 24 24" width="17" height="17" stroke="currentColor" stroke-width="1.8" fill="none" stroke-linecap="round" stroke-linejoin="round"><rect x="7" y="7" width="10" height="10" rx="2"></rect><path d="M9 7V5"></path><path d="M15 7V5"></path><path d="M12 17v2"></path><path d="M5 12H3"></path><path d="M21 12h-2"></path><path d="M9 11h.01"></path><path d="M15 11h.01"></path><path d="M9.5 14c.7.67 1.53 1 2.5 1s1.8-.33 2.5-1"></path></svg>';
153
155
  const TERMINAL_TAB_ICON_SVG = '<svg viewBox="0 0 24 24" width="15" height="15" stroke="currentColor" stroke-width="1.8" fill="none" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"></rect><path d="m8 10 3 2-3 2"></path><path d="M13 15h4"></path></svg>';
@@ -177,8 +179,18 @@ const MAIN_TERMINAL_THEME = {
177
179
  foreground: '#839496',
178
180
  cursor: '#93a1a1',
179
181
  cursorAccent: '#002b36',
180
- selectionBackground: '#073642'
182
+ selectionBackground: '#073642',
183
+ overviewRulerBorder: '#073642'
181
184
  };
185
+ const TERMINAL_SEARCH_DECORATIONS = {
186
+ matchBackground: '#073642',
187
+ matchBorder: '#2aa198',
188
+ matchOverviewRuler: '#2aa198',
189
+ activeMatchBackground: '#0b4f5d',
190
+ activeMatchBorder: '#b58900',
191
+ activeMatchColorOverviewRuler: '#b58900'
192
+ };
193
+ const TERMINAL_LIGATURE_FEATURE_SETTINGS = '"calt" on, "liga" on';
182
194
  const serverModalState = {
183
195
  mode: 'add',
184
196
  targetServerId: null
@@ -382,6 +394,120 @@ function buildMainTerminalTheme() {
382
394
  };
383
395
  }
384
396
 
397
+ function buildTerminalOverviewRulerOptions() {
398
+ return {
399
+ width: IS_MOBILE ? 5 : 8,
400
+ showTopBorder: true,
401
+ showBottomBorder: true
402
+ };
403
+ }
404
+
405
+ function buildTerminalBaseOptions(overrides = {}) {
406
+ return {
407
+ allowProposedApi: true,
408
+ allowTransparency: true,
409
+ convertEol: true,
410
+ fontFamily: TERMINAL_FONT_FAMILY,
411
+ fontSize: getTerminalFontSize(),
412
+ fontWeight: '450',
413
+ fontWeightBold: '700',
414
+ customGlyphs: true,
415
+ reflowCursorLine: true,
416
+ rescaleOverlappingGlyphs: true,
417
+ ...overrides
418
+ };
419
+ }
420
+
421
+ function normalizeTerminalProgressState(progress) {
422
+ const state = Number(progress?.state);
423
+ const value = Number(progress?.value);
424
+ if (!Number.isFinite(state) || state <= 0 || state > 4) {
425
+ return null;
426
+ }
427
+ return {
428
+ state,
429
+ value: Number.isFinite(value)
430
+ ? Math.max(0, Math.min(100, Math.round(value)))
431
+ : 0
432
+ };
433
+ }
434
+
435
+ function formatTerminalProgressLabel(progress) {
436
+ if (!progress) {
437
+ return '';
438
+ }
439
+ if (progress.state === 3) {
440
+ return 'PROGRESS: Working…';
441
+ }
442
+ if (progress.state === 2) {
443
+ return `PROGRESS: Error ${progress.value}%`;
444
+ }
445
+ if (progress.state === 4) {
446
+ return `PROGRESS: Paused ${progress.value}%`;
447
+ }
448
+ return `PROGRESS: ${progress.value}%`;
449
+ }
450
+
451
+ function getTerminalProgressTone(progress) {
452
+ if (!progress) {
453
+ return '';
454
+ }
455
+ if (progress.state === 2) {
456
+ return 'error';
457
+ }
458
+ if (progress.state === 4) {
459
+ return 'warning';
460
+ }
461
+ if (progress.state === 3) {
462
+ return 'running';
463
+ }
464
+ return 'normal';
465
+ }
466
+
467
+ function loadTerminalAddonSafely(term, addon, label) {
468
+ if (!term || !addon) {
469
+ return null;
470
+ }
471
+ try {
472
+ term.loadAddon(addon);
473
+ return addon;
474
+ } catch (error) {
475
+ console.warn(`Failed to load terminal addon (${label})`, error);
476
+ return null;
477
+ }
478
+ }
479
+
480
+ function disposeTerminalAddonSafely(addon, label) {
481
+ if (!addon || typeof addon.dispose !== 'function') {
482
+ return;
483
+ }
484
+ try {
485
+ addon.dispose();
486
+ } catch (error) {
487
+ console.warn(`Failed to dispose terminal addon (${label})`, error);
488
+ }
489
+ }
490
+
491
+ function createTerminalLigaturesAddon() {
492
+ return new LigaturesAddon({
493
+ fontFeatureSettings: TERMINAL_LIGATURE_FEATURE_SETTINGS
494
+ });
495
+ }
496
+
497
+ function attachTerminalToHost(term, host) {
498
+ if (!term || !host) {
499
+ return false;
500
+ }
501
+ if (!term.element) {
502
+ term.open(host);
503
+ return true;
504
+ }
505
+ if (!host.contains(term.element)) {
506
+ host.appendChild(term.element);
507
+ }
508
+ return false;
509
+ }
510
+
385
511
  function workspaceKeyToFilePath(key) {
386
512
  if (typeof key !== 'string' || key.length === 0) return '';
387
513
  if (key.startsWith(MARKDOWN_PREVIEW_WORKSPACE_TAB_PREFIX)) {
@@ -4076,7 +4202,7 @@ class EditorManager {
4076
4202
  }
4077
4203
 
4078
4204
  initMonaco() {
4079
- require.config({ paths: { 'vs': 'https://cdn.jsdelivr.net/npm/monaco-editor@0.44.0/min/vs' }});
4205
+ require.config({ paths: { 'vs': 'https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs' }});
4080
4206
  require(['vs/editor/editor.main'], (monaco) => {
4081
4207
  this.monacoInstance = monaco;
4082
4208
  this.editor = monaco.editor.create(this.monacoContainer, {
@@ -6818,20 +6944,30 @@ class EditorManager {
6818
6944
  }px`;
6819
6945
  host.appendChild(terminalNode);
6820
6946
 
6821
- const embeddedTerm = new Terminal({
6947
+ const embeddedTerm = new Terminal(buildTerminalBaseOptions({
6822
6948
  disableStdin: true,
6823
- convertEol: true,
6824
6949
  cursorBlink: false,
6825
6950
  cursorStyle: 'bar',
6826
6951
  theme: buildMainTerminalTheme(),
6827
6952
  scrollback: 2000,
6828
6953
  fontSize: getTerminalFontSize(),
6829
6954
  fontFamily: TERMINAL_FONT_FAMILY
6830
- });
6955
+ }));
6831
6956
  const fitAddon = new FitAddon();
6832
- embeddedTerm.loadAddon(fitAddon);
6833
- embeddedTerm.loadAddon(new CanvasAddon());
6957
+ const canvasAddon = new CanvasAddon();
6958
+ const ligaturesAddon = createTerminalLigaturesAddon();
6959
+ loadTerminalAddonSafely(embeddedTerm, fitAddon, 'embedded-fit');
6834
6960
  embeddedTerm.open(terminalNode);
6961
+ loadTerminalAddonSafely(
6962
+ embeddedTerm,
6963
+ ligaturesAddon,
6964
+ 'embedded-ligatures'
6965
+ );
6966
+ loadTerminalAddonSafely(
6967
+ embeddedTerm,
6968
+ canvasAddon,
6969
+ 'embedded-canvas'
6970
+ );
6835
6971
  renderEmbeddedAgentTerminal(
6836
6972
  embeddedTerm,
6837
6973
  terminalNode,
@@ -6865,6 +7001,12 @@ class EditorManager {
6865
7001
  layout: layoutTerminal
6866
7002
  };
6867
7003
  }
7004
+ this.trackAgentTimelineDisposable(host, {
7005
+ dispose() {
7006
+ disposeTerminalAddonSafely(ligaturesAddon, 'embedded-ligatures');
7007
+ disposeTerminalAddonSafely(canvasAddon, 'embedded-canvas');
7008
+ }
7009
+ });
6868
7010
  this.trackAgentTimelineDisposable(host, embeddedTerm);
6869
7011
  this.trackAgentTimelineDisposable(host, fitAddon);
6870
7012
 
@@ -8504,6 +8646,13 @@ class Session {
8504
8646
  this.lastExecutionEntry = null;
8505
8647
  this.needsAttention = false;
8506
8648
  this.lastNotifiedExecutionId = '';
8649
+ this.terminalProgress = null;
8650
+ this.previewCanvasAddon = null;
8651
+ this.mainCanvasAddon = null;
8652
+ this.mainLigaturesAddon = null;
8653
+ this.mainProgressAddon = null;
8654
+ this.mainProgressSubscription = null;
8655
+ this.mainDeferredAddonsLoaded = false;
8507
8656
  const legacyEditorState = data.editorState
8508
8657
  && typeof data.editorState === 'object'
8509
8658
  ? data.editorState
@@ -8600,7 +8749,7 @@ class Session {
8600
8749
  }
8601
8750
 
8602
8751
  _createTerminals() {
8603
- this.previewTerm = new Terminal({
8752
+ this.previewTerm = new Terminal(buildTerminalBaseOptions({
8604
8753
  disableStdin: true,
8605
8754
  cursorBlink: false,
8606
8755
  allowTransparency: true,
@@ -8613,29 +8762,59 @@ class Session {
8613
8762
  cursor: 'transparent',
8614
8763
  selectionBackground: 'transparent'
8615
8764
  }
8616
- });
8765
+ }));
8617
8766
 
8618
8767
  if (window.innerWidth >= 768) {
8619
- this.previewTerm.loadAddon(new CanvasAddon());
8768
+ this.previewCanvasAddon = new CanvasAddon();
8769
+ loadTerminalAddonSafely(
8770
+ this.previewTerm,
8771
+ this.previewCanvasAddon,
8772
+ 'preview-canvas'
8773
+ );
8774
+ } else {
8775
+ this.previewCanvasAddon = null;
8620
8776
  }
8621
8777
 
8622
- this.mainTerm = new Terminal({
8623
- allowTransparency: true,
8624
- convertEol: true,
8778
+ this.mainTerm = new Terminal(buildTerminalBaseOptions({
8625
8779
  cursorBlink: true,
8626
- fontFamily: TERMINAL_FONT_FAMILY,
8627
- fontSize: getTerminalFontSize(),
8628
8780
  rows: this.rows,
8629
8781
  cols: this.cols,
8630
- theme: buildMainTerminalTheme()
8631
- });
8782
+ theme: buildMainTerminalTheme(),
8783
+ overviewRuler: buildTerminalOverviewRulerOptions()
8784
+ }));
8632
8785
  this.mainFitAddon = new FitAddon();
8633
8786
  this.mainLinksAddon = new WebLinksAddon();
8634
8787
  this.searchAddon = new SearchAddon();
8635
- this.mainTerm.loadAddon(this.mainFitAddon);
8636
- this.mainTerm.loadAddon(this.mainLinksAddon);
8637
- this.mainTerm.loadAddon(this.searchAddon);
8638
- this.mainTerm.loadAddon(new CanvasAddon());
8788
+ this.mainProgressAddon = new ProgressAddon();
8789
+ this.mainCanvasAddon = new CanvasAddon();
8790
+ this.mainLigaturesAddon = createTerminalLigaturesAddon();
8791
+ this.mainDeferredAddonsLoaded = false;
8792
+ loadTerminalAddonSafely(this.mainTerm, this.mainFitAddon, 'fit');
8793
+ loadTerminalAddonSafely(this.mainTerm, this.mainLinksAddon, 'weblinks');
8794
+ loadTerminalAddonSafely(this.mainTerm, this.searchAddon, 'search');
8795
+ loadTerminalAddonSafely(
8796
+ this.mainTerm,
8797
+ this.mainProgressAddon,
8798
+ 'progress'
8799
+ );
8800
+ loadTerminalAddonSafely(
8801
+ this.mainTerm,
8802
+ this.mainCanvasAddon,
8803
+ 'canvas'
8804
+ );
8805
+ if (this.mainProgressAddon?.onChange) {
8806
+ this.mainProgressSubscription = this.mainProgressAddon.onChange(
8807
+ (progress) => {
8808
+ this.terminalProgress = normalizeTerminalProgressState(
8809
+ progress
8810
+ );
8811
+ this.updateTabUI();
8812
+ }
8813
+ );
8814
+ if (this.terminalProgress) {
8815
+ this.mainProgressAddon.progress = this.terminalProgress;
8816
+ }
8817
+ }
8639
8818
 
8640
8819
  this.mainTerm.onData((data) => {
8641
8820
  if (this.isRestoring) return;
@@ -8654,6 +8833,35 @@ class Session {
8654
8833
  });
8655
8834
  }
8656
8835
 
8836
+ activateMainTerminalDeferredAddons() {
8837
+ if (
8838
+ !this.mainTerm
8839
+ || !this.mainTerm.element
8840
+ || this.mainDeferredAddonsLoaded
8841
+ ) {
8842
+ return;
8843
+ }
8844
+ loadTerminalAddonSafely(
8845
+ this.mainTerm,
8846
+ this.mainLigaturesAddon,
8847
+ 'ligatures'
8848
+ );
8849
+ this.mainDeferredAddonsLoaded = true;
8850
+ }
8851
+
8852
+ disposeTerminalAddons() {
8853
+ disposeTerminalAddonSafely(this.previewCanvasAddon, 'preview-canvas');
8854
+ this.previewCanvasAddon = null;
8855
+ this.mainProgressSubscription?.dispose?.();
8856
+ this.mainProgressSubscription = null;
8857
+ this.mainProgressAddon = null;
8858
+ disposeTerminalAddonSafely(this.mainLigaturesAddon, 'ligatures');
8859
+ this.mainLigaturesAddon = null;
8860
+ disposeTerminalAddonSafely(this.mainCanvasAddon, 'canvas');
8861
+ this.mainCanvasAddon = null;
8862
+ this.mainDeferredAddonsLoaded = false;
8863
+ }
8864
+
8657
8865
  recreateTerminals() {
8658
8866
  const wasActive = state.activeSessionKey === this.key;
8659
8867
  const previewWrapper = this.wrapperElement;
@@ -8661,6 +8869,7 @@ class Session {
8661
8869
  this.unbindTerminalControlClaim();
8662
8870
 
8663
8871
  try {
8872
+ this.disposeTerminalAddons();
8664
8873
  this.previewTerm?.dispose();
8665
8874
  } catch (e) {
8666
8875
  if (!e.message?.includes('onRequestRedraw')) {
@@ -8680,13 +8889,16 @@ class Session {
8680
8889
 
8681
8890
  if (previewWrapper && window.innerWidth >= 768) {
8682
8891
  previewWrapper.innerHTML = '';
8683
- this.previewTerm.open(previewWrapper);
8892
+ attachTerminalToHost(this.previewTerm, previewWrapper);
8684
8893
  this.updatePreviewScale();
8685
8894
  }
8686
8895
 
8687
8896
  if (wasActive && terminalEl) {
8688
8897
  terminalEl.innerHTML = '';
8689
- this.mainTerm.open(terminalEl);
8898
+ const opened = attachTerminalToHost(this.mainTerm, terminalEl);
8899
+ if (opened) {
8900
+ this.activateMainTerminalDeferredAddons();
8901
+ }
8690
8902
  this.bindTerminalControlClaim();
8691
8903
  if (this.fitMainTerminalIfVisible()) {
8692
8904
  this.mainTerm.focus();
@@ -8974,6 +9186,27 @@ class Session {
8974
9186
  }
8975
9187
  }
8976
9188
 
9189
+ const metaProgressEl = tab.querySelector('.meta-progress');
9190
+ if (metaProgressEl) {
9191
+ const progressLabel = formatTerminalProgressLabel(
9192
+ this.terminalProgress
9193
+ );
9194
+ if (progressLabel) {
9195
+ metaProgressEl.textContent = progressLabel;
9196
+ metaProgressEl.hidden = false;
9197
+ const tone = getTerminalProgressTone(this.terminalProgress);
9198
+ if (tone) {
9199
+ metaProgressEl.dataset.tone = tone;
9200
+ } else {
9201
+ delete metaProgressEl.dataset.tone;
9202
+ }
9203
+ } else {
9204
+ metaProgressEl.textContent = '';
9205
+ metaProgressEl.hidden = true;
9206
+ delete metaProgressEl.dataset.tone;
9207
+ }
9208
+ }
9209
+
8977
9210
  syncSessionTabMinimumHeight(tab);
8978
9211
  if (this.wrapperElement && window.innerWidth >= 768) {
8979
9212
  this.schedulePreviewRelayout();
@@ -9312,7 +9545,8 @@ class Session {
9312
9545
  clearTimeout(this.retryTimer);
9313
9546
  this.socket?.close();
9314
9547
  this.unbindTerminalControlClaim();
9315
-
9548
+ this.disposeTerminalAddons();
9549
+
9316
9550
  try {
9317
9551
  if (this.previewTerm) this.previewTerm.dispose();
9318
9552
  } catch (e) {
@@ -15122,7 +15356,10 @@ function renderTabs() {
15122
15356
  // Only mount on Desktop to save resources and avoid visual clutter on mobile
15123
15357
  if (window.innerWidth >= 768) {
15124
15358
  session.wrapperElement = tab.querySelector('.preview-terminal-wrapper');
15125
- session.previewTerm.open(session.wrapperElement);
15359
+ attachTerminalToHost(
15360
+ session.previewTerm,
15361
+ session.wrapperElement
15362
+ );
15126
15363
  session.updatePreviewScale();
15127
15364
  }
15128
15365
  session.updateTabUI();
@@ -15347,11 +15584,16 @@ function createTabElement(session) {
15347
15584
 
15348
15585
  metaTime.textContent = `SINCE: ${mm}-${dd} ${hhStr}:${min} ${ampm}`;
15349
15586
 
15587
+ const metaProgress = document.createElement('div');
15588
+ metaProgress.className = 'meta meta-progress';
15589
+ metaProgress.hidden = true;
15590
+
15350
15591
  overlay.appendChild(title);
15351
15592
  overlay.appendChild(metaId);
15352
15593
  overlay.appendChild(metaServer);
15353
15594
  overlay.appendChild(metaCwd);
15354
15595
  overlay.appendChild(metaTime);
15596
+ overlay.appendChild(metaProgress);
15355
15597
 
15356
15598
  tab.appendChild(previewContainer);
15357
15599
  tab.appendChild(overlay);
@@ -15920,7 +16162,10 @@ async function switchToSession(sessionKey, options = {}) {
15920
16162
  terminalEl.innerHTML = '';
15921
16163
 
15922
16164
  // Mount new session
15923
- session.mainTerm.open(terminalEl);
16165
+ const opened = attachTerminalToHost(session.mainTerm, terminalEl);
16166
+ if (opened) {
16167
+ session.activateMainTerminalDeferredAddons();
16168
+ }
15924
16169
  session.bindTerminalControlClaim();
15925
16170
  session.fitMainTerminalIfVisible();
15926
16171
  if (session.isMainTerminalVisible()) {
@@ -16720,6 +16965,14 @@ let searchOptions = {
16720
16965
  regex: false
16721
16966
  };
16722
16967
 
16968
+ function buildTerminalSearchOptions(options = {}) {
16969
+ return {
16970
+ ...searchOptions,
16971
+ ...options,
16972
+ decorations: TERMINAL_SEARCH_DECORATIONS
16973
+ };
16974
+ }
16975
+
16723
16976
  if (searchBar) {
16724
16977
  const updateUI = (found) => {
16725
16978
  if (!found) {
@@ -16739,8 +16992,11 @@ if (searchBar) {
16739
16992
  const term = searchInput.value;
16740
16993
 
16741
16994
  let found = false;
16742
- if (forward) found = addon.findNext(term, searchOptions);
16743
- else found = addon.findPrevious(term, searchOptions);
16995
+ if (forward) {
16996
+ found = addon.findNext(term, buildTerminalSearchOptions());
16997
+ } else {
16998
+ found = addon.findPrevious(term, buildTerminalSearchOptions());
16999
+ }
16744
17000
 
16745
17001
  updateUI(found);
16746
17002
  };
@@ -16763,6 +17019,8 @@ if (searchBar) {
16763
17019
  if (!state.activeSessionKey) return;
16764
17020
  const term = e.target.value;
16765
17021
  if (!term) {
17022
+ state.sessions.get(state.activeSessionKey)?.searchAddon
17023
+ ?.clearDecorations();
16766
17024
  updateUI(false);
16767
17025
  searchResults.textContent = ''; // Empty when clear? Or No results? VS Code clears.
16768
17026
  // But user asked for "No results always".
@@ -16771,10 +17029,11 @@ if (searchBar) {
16771
17029
  }
16772
17030
 
16773
17031
  // Incremental search
16774
- const found = state.sessions.get(state.activeSessionKey).searchAddon.findNext(term, {
16775
- incremental: true,
16776
- ...searchOptions
16777
- });
17032
+ const found = state.sessions.get(state.activeSessionKey)
17033
+ .searchAddon.findNext(
17034
+ term,
17035
+ buildTerminalSearchOptions({ incremental: true })
17036
+ );
16778
17037
 
16779
17038
  updateUI(found);
16780
17039
  });
@@ -16786,6 +17045,8 @@ if (searchBar) {
16786
17045
  }
16787
17046
  if (e.key === 'Escape') {
16788
17047
  e.preventDefault();
17048
+ state.sessions.get(state.activeSessionKey)?.searchAddon
17049
+ ?.clearDecorations();
16789
17050
  searchBar.style.display = 'none';
16790
17051
  state.sessions.get(state.activeSessionKey)?.mainTerm.focus();
16791
17052
  }
@@ -16795,6 +17056,8 @@ if (searchBar) {
16795
17056
  searchPrev.addEventListener('click', () => doSearch(false));
16796
17057
 
16797
17058
  searchClose.addEventListener('click', () => {
17059
+ state.sessions.get(state.activeSessionKey)?.searchAddon
17060
+ ?.clearDecorations();
16798
17061
  searchBar.style.display = 'none';
16799
17062
  state.sessions.get(state.activeSessionKey)?.mainTerm.focus();
16800
17063
  });
package/public/index.html CHANGED
@@ -355,7 +355,7 @@
355
355
  })();
356
356
  })();
357
357
  </script>
358
- <script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.44.0/min/vs/loader.js"></script>
358
+ <script src="https://cdn.jsdelivr.net/npm/monaco-editor@0.55.1/min/vs/loader.js"></script>
359
359
  </head>
360
360
 
361
361
  <body>
package/public/styles.css CHANGED
@@ -1,4 +1,4 @@
1
- @import url('https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css');
1
+ @import url('https://cdn.jsdelivr.net/npm/@xterm/xterm@6.0.0/css/xterm.css');
2
2
 
3
3
  /* Monaspace Neon */
4
4
  @font-face {
@@ -756,6 +756,22 @@ body {
756
756
  font-weight: 600;
757
757
  }
758
758
 
759
+ .tab-info-overlay .meta.meta-progress {
760
+ font-weight: 600;
761
+ }
762
+
763
+ .tab-info-overlay .meta.meta-progress[data-tone="running"] {
764
+ color: #2aa198;
765
+ }
766
+
767
+ .tab-info-overlay .meta.meta-progress[data-tone="warning"] {
768
+ color: #b58900;
769
+ }
770
+
771
+ .tab-info-overlay .meta.meta-progress[data-tone="error"] {
772
+ color: #dc322f;
773
+ }
774
+
759
775
  .tab-info-overlay .title {
760
776
  display: flex;
761
777
  align-items: center;