dsh-ssh-manage 0.3.0 → 0.3.1

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/README.en.md CHANGED
@@ -45,7 +45,7 @@ No more jumping between a terminal and DSH, and no need to remember where each h
45
45
 
46
46
  - Click "Connect" to open a real PTY shell, not a one-command-at-a-time console.
47
47
  - Multiple hosts stay as tabs: switching to another DSH session and coming back re-attaches to the existing shell and replays roughly the last 256 KB of output; only closing the tab ends the session.
48
- - xterm.js 6.0.0 rendering with 256 colors, cursor, scrollback, selection copy, paste and resize.
48
+ - xterm.js 6.0.0 rendering with 256 colors, cursor, scrollback, selection copy, paste, resize, in-terminal search, font-size controls and a right-click copy/paste menu.
49
49
  - Terminal theme follows the DSH light/dark theme; the session bar has quick actions for address, password status, test, files, details, clear and close.
50
50
  - Output is streamed over a same-origin HTTP/SSE connection; input, resize and close use same-origin HTTP POST. A tested WebSocket channel is kept as a fallback.
51
51
  - Clear status and a "Reconnect" button when the backend is unavailable — no silent hang.
@@ -96,16 +96,16 @@ Creating a host requires alias, hostname and password. The password is not writt
96
96
 
97
97
  ### From npm (recommended)
98
98
 
99
- npm package: [`dsh-ssh-manage`](https://www.npmjs.com/package/dsh-ssh-manage) (current version `0.3.0`).
99
+ npm package: [`dsh-ssh-manage`](https://www.npmjs.com/package/dsh-ssh-manage) (current version `0.3.1`).
100
100
 
101
101
  ```text
102
- plugin_manager action=install_bundle target=dsh-ssh-manage@0.3.0
102
+ plugin_manager action=install_bundle target=dsh-ssh-manage@0.3.1
103
103
  ```
104
104
 
105
105
  Or with the DSH CLI:
106
106
 
107
107
  ```bash
108
- dsh plugin add dsh-ssh-manage@0.3.0
108
+ dsh plugin add dsh-ssh-manage@0.3.1
109
109
  ```
110
110
 
111
111
  After installation, refresh the Web page; the sidebar shows an "SSH Hosts" entry with id `dsh-ssh-manage`.
@@ -137,7 +137,7 @@ and make sure the package is resolvable by the profile (for example `link:` to t
137
137
 
138
138
  | | Requirement |
139
139
  | --- | --- |
140
- | **DSH** | **`>=0.2.1-rc.3 <0.3.0`** (validated on DSH Desktop `0.2.1-rc.3`) |
140
+ | **DSH** | **`>=0.2.1-rc.3 <0.3.1`** (validated on DSH Desktop `0.2.1-rc.3`) |
141
141
  | **Node.js** | `>=20` (follows the DSH runtime) |
142
142
  | **Platform** | Validated on macOS; the test suite only uses Node built-ins and runs cross-platform |
143
143
  | **Network** | Reachable SSH port (22 by default, or the configured port) |
@@ -211,7 +211,7 @@ npm test
211
211
  | `node scripts/test-sse.mjs` | HTTP/SSE PTY end-to-end against a real ssh2 mock server + 401 auth |
212
212
  | `npm test` | All of the above |
213
213
 
214
- The terminal uses vendored xterm.js 6.0.0 (MIT, see `assets/LICENSE.xterm`) and @xterm/addon-fit 0.11.0 (MIT, see `assets/LICENSE.addon-fit`).
214
+ The terminal uses vendored xterm.js 6.0.0 (MIT, see `assets/LICENSE.xterm`), @xterm/addon-fit 0.11.0 (MIT, see `assets/LICENSE.addon-fit`) and @xterm/addon-search 0.16.0 (MIT, see `assets/LICENSE.addon-search`).
215
215
 
216
216
  ## Known limitations
217
217
 
@@ -221,7 +221,7 @@ The terminal uses vendored xterm.js 6.0.0 (MIT, see `assets/LICENSE.xterm`) and
221
221
  - **Config editing scope**: the editor only changes `Host`, `HostName`, `User`, `Port` and plugin metadata; maintain other SSH directives in `~/.ssh/config`.
222
222
  - **Batch commands** run one command; they are not an interactive terminal. Per-host output is capped at 1 MB and marked `truncated` when exceeded.
223
223
  - **File size**: SFTP files are capped at 10 MB.
224
- - **xterm assets**: the first terminal open loads about 500 KB of xterm.js from the same origin (no CDN).
224
+ - **xterm assets**: the first terminal open loads about 500 KB of xterm.js basics; the search addon loads on demand, about 556 KiB total from the same origin (no CDN).
225
225
 
226
226
  ## Contributing
227
227
 
package/README.md CHANGED
@@ -45,7 +45,7 @@
45
45
 
46
46
  - 点「连接」打开真正的 PTY shell,不是一条命令一条命令地执行。
47
47
  - 多台主机以标签页常驻:切换到其它 DSH 会话再回来,终端会重新附着到原来的 shell,并回放最近约 256 KB 输出;关闭标签、Host 退出,或 30 分钟无输出/输入/心跳才会结束会话。
48
- - xterm.js 6.0.0 渲染,支持 256 色、光标、滚动回看、选中复制、粘贴、窗口 resize。
48
+ - xterm.js 6.0.0 渲染,支持 256 色、光标、滚动回看、选中复制、粘贴、窗口 resize、终端内搜索、字号调整和右键复制/粘贴菜单。
49
49
  - 终端主题跟随 DSH 明暗主题;会话顶部有地址、密码状态、测试连接、文件、详情、清屏、关闭等快捷操作。
50
50
  - 输出走同源 HTTP/SSE 长连接,输入 / 尺寸 / 关闭走同源 HTTP POST;插件同时保留经过测试的 WebSocket 备用通道。
51
51
  - 断线或后端未加载时显示明确的状态与「重新连接」,不会静默卡死。
@@ -98,16 +98,16 @@
98
98
 
99
99
  ### 从 npm 安装(推荐)
100
100
 
101
- npm 包:[`dsh-ssh-manage`](https://www.npmjs.com/package/dsh-ssh-manage)(当前版本 `0.3.0`)。
101
+ npm 包:[`dsh-ssh-manage`](https://www.npmjs.com/package/dsh-ssh-manage)(当前版本 `0.3.1`)。
102
102
 
103
103
  ```text
104
- plugin_manager action=install_bundle target=dsh-ssh-manage@0.3.0
104
+ plugin_manager action=install_bundle target=dsh-ssh-manage@0.3.1
105
105
  ```
106
106
 
107
107
  或使用 DSH CLI:
108
108
 
109
109
  ```bash
110
- dsh plugin add dsh-ssh-manage@0.3.0
110
+ dsh plugin add dsh-ssh-manage@0.3.1
111
111
  ```
112
112
 
113
113
  安装后刷新 Web 页面,左侧栏会出现「SSH 主机」入口,入口 id 为 `dsh-ssh-manage`。
@@ -139,7 +139,7 @@ plugin_manager action=install_bundle target=<仓库绝对路径>/dsh-ssh-manage
139
139
 
140
140
  | | 要求 |
141
141
  | --- | --- |
142
- | **DSH** | **`>=0.2.1-rc.3 <0.3.0`**(实机验证版本:DSH Desktop `0.2.1-rc.3`) |
142
+ | **DSH** | **`>=0.2.1-rc.3 <0.3.1`**(实机验证版本:DSH Desktop `0.2.1-rc.3`) |
143
143
  | **Node.js** | `>=20`(跟随 DSH 内置运行时) |
144
144
  | **平台** | 实机验证 macOS;测试套件只依赖 Node 内置模块,可跨平台运行 |
145
145
  | **网络** | 需要能访问目标 SSH 主机的 22 端口(或配置的端口) |
@@ -214,7 +214,7 @@ npm test
214
214
  | `node scripts/test-sse.mjs` | 真实 ssh2 mock 服务器上的 HTTP/SSE PTY 端到端 + 401 鉴权 |
215
215
  | `npm test` | 以上全部 |
216
216
 
217
- 终端组件使用随插件分发的 xterm.js 6.0.0(MIT,见 `assets/LICENSE.xterm`)与 @xterm/addon-fit 0.11.0(MIT,见 `assets/LICENSE.addon-fit`)。
217
+ 终端组件使用随插件分发的 xterm.js 6.0.0(MIT,见 `assets/LICENSE.xterm`)、@xterm/addon-fit 0.11.0(MIT,见 `assets/LICENSE.addon-fit`)与 @xterm/addon-search 0.16.0(MIT,见 `assets/LICENSE.addon-search`)。
218
218
 
219
219
  ## 已知限制
220
220
 
@@ -224,7 +224,7 @@ npm test
224
224
  - **配置编辑范围**:编辑器只修改 `Host`、`HostName`、`User`、`Port` 与插件元数据;其它 SSH 指令请在 `~/.ssh/config` 中维护。
225
225
  - **批量命令**:一次执行一条命令,不等同于交互式终端;单台输出上限 1 MB,超出会标记 `truncated`。
226
226
  - **文件大小**:SFTP 单文件上限 10 MB。
227
- - **xterm 资源**:首次打开会加载约 500 KB 的 xterm.js 资源(本地同源,不访问 CDN)。
227
+ - **xterm 资源**:首次打开会加载约 500 KB 的 xterm.js 基础资源;搜索组件按需加载,总计约 556 KiB(本地同源,不访问 CDN)。
228
228
 
229
229
  ## 参与贡献
230
230
 
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2017, The xterm.js authors (https://github.com/xtermjs/xterm.js)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,2 @@
1
+ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SearchAddon=t():e.SearchAddon=t()}(globalThis,(()=>(()=>{"use strict";var e={864:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DecorationManager=void 0;const i=s(540);class r extends i.Disposable{constructor(e){super(),this._terminal=e,this._highlightDecorations=[],this._highlightedLines=new Set,this._register((0,i.toDisposable)((()=>this.clearHighlightDecorations())))}createHighlightDecorations(e,t){this.clearHighlightDecorations();for(const s of e){const e=this._createResultDecorations(s,t,!1);if(e)for(const t of e)this._storeDecoration(t,s)}}createActiveDecoration(e,t){const s=this._createResultDecorations(e,t,!0);if(s)return{decorations:s,match:e,dispose(){(0,i.dispose)(s)}}}clearHighlightDecorations(){(0,i.dispose)(this._highlightDecorations),this._highlightDecorations=[],this._highlightedLines.clear()}_storeDecoration(e,t){this._highlightedLines.add(e.marker.line),this._highlightDecorations.push({decoration:e,match:t,dispose(){e.dispose()}})}_applyStyles(e,t,s){e.classList.contains("xterm-find-result-decoration")||(e.classList.add("xterm-find-result-decoration"),t&&(e.style.outline=`1px solid ${t}`)),s&&e.classList.add("xterm-find-active-result-decoration")}_createResultDecorations(e,t,s){const r=[];let n=e.col,o=e.size,a=-this._terminal.buffer.active.baseY-this._terminal.buffer.active.cursorY+e.row;for(;o>0;){const e=Math.min(this._terminal.cols-n,o);r.push([a,n,e]),n=0,o-=e,a++}const l=[];for(const e of r){const r=this._terminal.registerMarker(e[0]),n=this._terminal.registerDecoration({marker:r,x:e[1],width:e[2],backgroundColor:s?t.activeMatchBackground:t.matchBackground,overviewRulerOptions:this._highlightedLines.has(r.line)?void 0:{color:s?t.activeMatchColorOverviewRuler:t.matchOverviewRuler,position:"center"}});if(n){const e=[];e.push(r),e.push(n.onRender((e=>this._applyStyles(e,s?t.activeMatchBorder:t.matchBorder,!1)))),e.push(n.onDispose((()=>(0,i.dispose)(e)))),l.push(n)}}return 0===l.length?void 0:l}}t.DecorationManager=r},615:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SearchEngine=void 0,t.SearchEngine=class{constructor(e,t){this._terminal=e,this._lineCache=t}find(e,t,s,i){if(!e||0===e.length)return void this._terminal.clearSelection();if(s>this._terminal.cols)throw new Error(`Invalid col: ${s} to search in terminal of ${this._terminal.cols} cols`);this._lineCache.initLinesCache();const r={startRow:t,startCol:s};let n=this._findInLine(e,r,i);if(!n)for(let s=t+1;s<this._terminal.buffer.active.baseY+this._terminal.rows&&(r.startRow=s,r.startCol=0,n=this._findInLine(e,r,i),!n);s++);return n}findNextWithSelection(e,t,s){if(!e||0===e.length)return void this._terminal.clearSelection();const i=this._terminal.getSelectionPosition();this._terminal.clearSelection();let r=0,n=0;i&&(s===e?(r=i.end.x,n=i.end.y):(r=i.start.x,n=i.start.y)),this._lineCache.initLinesCache();const o={startRow:n,startCol:r};let a=this._findInLine(e,o,t);if(!a)for(let s=n+1;s<this._terminal.buffer.active.baseY+this._terminal.rows&&(o.startRow=s,o.startCol=0,a=this._findInLine(e,o,t),!a);s++);if(!a&&0!==n)for(let s=0;s<n&&(o.startRow=s,o.startCol=0,a=this._findInLine(e,o,t),!a);s++);return!a&&i&&(o.startRow=i.start.y,o.startCol=0,a=this._findInLine(e,o,t)),a}findPreviousWithSelection(e,t,s){if(!e||0===e.length)return void this._terminal.clearSelection();const i=this._terminal.getSelectionPosition();this._terminal.clearSelection();let r=this._terminal.buffer.active.baseY+this._terminal.rows-1,n=this._terminal.cols;const o=!0;this._lineCache.initLinesCache();const a={startRow:r,startCol:n};let l;if(i&&(a.startRow=r=i.start.y,a.startCol=n=i.start.x,s!==e&&(l=this._findInLine(e,a,t,!1),l||(a.startRow=r=i.end.y,a.startCol=n=i.end.x))),l||(l=this._findInLine(e,a,t,o)),!l){a.startCol=Math.max(a.startCol,this._terminal.cols);for(let s=r-1;s>=0&&(a.startRow=s,l=this._findInLine(e,a,t,o),!l);s--);}if(!l&&r!==this._terminal.buffer.active.baseY+this._terminal.rows-1)for(let s=this._terminal.buffer.active.baseY+this._terminal.rows-1;s>=r&&(a.startRow=s,l=this._findInLine(e,a,t,o),!l);s--);return l}_isWholeWord(e,t,s){return(0===e||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(t[e-1]))&&(e+s.length===t.length||" ~!@#$%^&*()+`-=[]{}|\\;:\"',./<>?".includes(t[e+s.length]))}_findInLine(e,t,s={},i=!1){const r=t.startRow,n=t.startCol,o=this._terminal.buffer.active.getLine(r);if(o?.isWrapped)return i?void(t.startCol+=this._terminal.cols):(t.startRow--,t.startCol+=this._terminal.cols,this._findInLine(e,t,s));let a=this._lineCache.getLineFromCache(r);a||(a=this._lineCache.translateBufferLineToStringWithWrap(r,!0),this._lineCache.setLineInCache(r,a));const[l,h]=a,c=this._bufferColsToStringOffset(r,n);let u=e,d=l;s.regex||(u=s.caseSensitive?e:e.toLowerCase(),d=s.caseSensitive?l:l.toLowerCase());let f=-1;if(s.regex){const t=RegExp(u,s.caseSensitive?"g":"gi");let r;if(i)for(;r=t.exec(d.slice(0,c));)f=t.lastIndex-r[0].length,e=r[0],t.lastIndex-=e.length-1;else r=t.exec(d.slice(c)),r&&r[0].length>0&&(f=c+(t.lastIndex-r[0].length),e=r[0])}else i?c-u.length>=0&&(f=d.lastIndexOf(u,c-u.length)):f=d.indexOf(u,c);if(f>=0){if(s.wholeWord&&!this._isWholeWord(f,d,e))return;let t=0;for(;t<h.length-1&&f>=h[t+1];)t++;let i=t;for(;i<h.length-1&&f+e.length>=h[i+1];)i++;const n=f-h[t],o=f+e.length-h[i],a=this._stringLengthToBufferSize(r+t,n);return{term:e,col:a,row:r+t,size:this._stringLengthToBufferSize(r+i,o)-a+this._terminal.cols*(i-t)}}}_stringLengthToBufferSize(e,t){const s=this._terminal.buffer.active.getLine(e);if(!s)return 0;for(let e=0;e<t;e++){const i=s.getCell(e);if(!i)break;const r=i.getChars();r.length>1&&(t-=r.length-1);const n=s.getCell(e+1);n&&0===n.getWidth()&&t++}return t}_bufferColsToStringOffset(e,t){let s=e,i=0,r=this._terminal.buffer.active.getLine(s);for(;t>0&&r;){for(let e=0;e<t&&e<this._terminal.cols;e++){const t=r.getCell(e);if(!t)break;t.getWidth()&&(i+=0===t.getCode()?1:t.getChars().length)}if(s++,r=this._terminal.buffer.active.getLine(s),r&&!r.isWrapped)break;t-=this._terminal.cols}return i}}},149:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SearchLineCache=void 0;const i=s(540),r=s(940);class n extends i.Disposable{constructor(e){super(),this._terminal=e,this._linesCacheTimeout=this._register(new i.MutableDisposable),this._linesCacheDisposables=this._register(new i.MutableDisposable),this._register((0,i.toDisposable)((()=>this._destroyLinesCache())))}initLinesCache(){this._linesCache||(this._linesCache=new Array(this._terminal.buffer.active.length),this._linesCacheDisposables.value=(0,i.combinedDisposable)(this._terminal.onLineFeed((()=>this._destroyLinesCache())),this._terminal.onCursorMove((()=>this._destroyLinesCache())),this._terminal.onResize((()=>this._destroyLinesCache())))),this._linesCacheTimeout.value=(0,r.disposableTimeout)((()=>this._destroyLinesCache()),15e3)}_destroyLinesCache(){this._linesCache=void 0,this._linesCacheDisposables.clear(),this._linesCacheTimeout.clear()}getLineFromCache(e){return this._linesCache?.[e]}setLineInCache(e,t){this._linesCache&&(this._linesCache[e]=t)}translateBufferLineToStringWithWrap(e,t){const s=[],i=[0];let r=this._terminal.buffer.active.getLine(e);for(;r;){const n=this._terminal.buffer.active.getLine(e+1),o=!!n&&n.isWrapped;let a=r.translateToString(!o&&t);if(o&&n){const e=r.getCell(r.length-1);e&&0===e.getCode()&&1===e.getWidth()&&2===n.getCell(0)?.getWidth()&&(a=a.slice(0,-1))}if(s.push(a),!o)break;i.push(i[i.length-1]+a.length),e++,r=n}return[s.join(""),i]}}t.SearchLineCache=n},438:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SearchResultTracker=void 0;const i=s(276),r=s(540);class n extends r.Disposable{constructor(){super(...arguments),this._searchResults=[],this._onDidChangeResults=this._register(new i.Emitter)}get onDidChangeResults(){return this._onDidChangeResults.event}get searchResults(){return this._searchResults}get selectedDecoration(){return this._selectedDecoration}set selectedDecoration(e){this._selectedDecoration=e}updateResults(e,t){this._searchResults=e.slice(0,t)}clearResults(){this._searchResults=[]}clearSelectedDecoration(){this._selectedDecoration&&(this._selectedDecoration.dispose(),this._selectedDecoration=void 0)}findResultIndex(e){for(let t=0;t<this._searchResults.length;t++){const s=this._searchResults[t];if(s.row===e.row&&s.col===e.col&&s.size===e.size)return t}return-1}fireResultsChanged(e){if(!e)return;let t=-1;this._selectedDecoration&&(t=this.findResultIndex(this._selectedDecoration.match)),this._onDidChangeResults.fire({resultIndex:t,resultCount:this._searchResults.length})}reset(){this.clearSelectedDecoration(),this.clearResults()}}t.SearchResultTracker=n},772:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.SearchState=void 0,t.SearchState=class{get cachedSearchTerm(){return this._cachedSearchTerm}set cachedSearchTerm(e){this._cachedSearchTerm=e}get lastSearchOptions(){return this._lastSearchOptions}set lastSearchOptions(e){this._lastSearchOptions=e}isValidSearchTerm(e){return!!(e&&e.length>0)}didOptionsChange(e){return!this._lastSearchOptions||!!e&&(this._lastSearchOptions.caseSensitive!==e.caseSensitive||this._lastSearchOptions.regex!==e.regex||this._lastSearchOptions.wholeWord!==e.wholeWord)}shouldUpdateHighlighting(e,t){return!!t?.decorations&&(void 0===this._cachedSearchTerm||e!==this._cachedSearchTerm||this.didOptionsChange(t))}clearCachedTerm(){this._cachedSearchTerm=void 0}reset(){this._cachedSearchTerm=void 0,this._lastSearchOptions=void 0}}},732:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Permutation=t.CallbackIterable=t.ArrayQueue=t.booleanComparator=t.numberComparator=t.CompareResult=void 0,t.tail=function(e,t=0){return e[e.length-(1+t)]},t.tail2=function(e){if(0===e.length)throw new Error("Invalid tail call");return[e.slice(0,e.length-1),e[e.length-1]]},t.equals=function(e,t,s=(e,t)=>e===t){if(e===t)return!0;if(!e||!t)return!1;if(e.length!==t.length)return!1;for(let i=0,r=e.length;i<r;i++)if(!s(e[i],t[i]))return!1;return!0},t.removeFastWithoutKeepingOrder=function(e,t){const s=e.length-1;t<s&&(e[t]=e[s]),e.pop()},t.binarySearch=function(e,t,s){return n(e.length,(i=>s(e[i],t)))},t.binarySearch2=n,t.quickSelect=function e(t,s,i){if((t|=0)>=s.length)throw new TypeError("invalid index");const r=s[Math.floor(s.length*Math.random())],n=[],o=[],a=[];for(const e of s){const t=i(e,r);t<0?n.push(e):t>0?o.push(e):a.push(e)}return t<n.length?e(t,n,i):t<n.length+a.length?a[0]:e(t-(n.length+a.length),o,i)},t.groupBy=function(e,t){const s=[];let i;for(const r of e.slice(0).sort(t))i&&0===t(i[0],r)?i.push(r):(i=[r],s.push(i));return s},t.groupAdjacentBy=function*(e,t){let s,i;for(const r of e)void 0!==i&&t(i,r)?s.push(r):(s&&(yield s),s=[r]),i=r;s&&(yield s)},t.forEachAdjacent=function(e,t){for(let s=0;s<=e.length;s++)t(0===s?void 0:e[s-1],s===e.length?void 0:e[s])},t.forEachWithNeighbors=function(e,t){for(let s=0;s<e.length;s++)t(0===s?void 0:e[s-1],e[s],s+1===e.length?void 0:e[s+1])},t.sortedDiff=o,t.delta=function(e,t,s){const i=o(e,t,s),r=[],n=[];for(const t of i)r.push(...e.slice(t.start,t.start+t.deleteCount)),n.push(...t.toInsert);return{removed:r,added:n}},t.top=function(e,t,s){if(0===s)return[];const i=e.slice(0,s).sort(t);return a(e,t,i,s,e.length),i},t.topAsync=function(e,t,s,r,n){return 0===s?Promise.resolve([]):new Promise(((o,l)=>{(async()=>{const o=e.length,l=e.slice(0,s).sort(t);for(let h=s,c=Math.min(s+r,o);h<o;h=c,c=Math.min(c+r,o)){if(h>s&&await new Promise((e=>setTimeout(e))),n&&n.isCancellationRequested)throw new i.CancellationError;a(e,t,l,h,c)}return l})().then(o,l)}))},t.coalesce=function(e){return e.filter((e=>!!e))},t.coalesceInPlace=function(e){let t=0;for(let s=0;s<e.length;s++)e[s]&&(e[t]=e[s],t+=1);e.length=t},t.move=function(e,t,s){e.splice(s,0,e.splice(t,1)[0])},t.isFalsyOrEmpty=function(e){return!Array.isArray(e)||0===e.length},t.isNonEmptyArray=function(e){return Array.isArray(e)&&e.length>0},t.distinct=function(e,t=e=>e){const s=new Set;return e.filter((e=>{const i=t(e);return!s.has(i)&&(s.add(i),!0)}))},t.uniqueFilter=function(e){const t=new Set;return s=>{const i=e(s);return!t.has(i)&&(t.add(i),!0)}},t.firstOrDefault=function(e,t){return e.length>0?e[0]:t},t.lastOrDefault=function(e,t){return e.length>0?e[e.length-1]:t},t.commonPrefixLength=function(e,t,s=(e,t)=>e===t){let i=0;for(let r=0,n=Math.min(e.length,t.length);r<n&&s(e[r],t[r]);r++)i++;return i},t.range=function(e,t){let s="number"==typeof t?e:0;"number"==typeof t?s=e:(s=0,t=e);const i=[];if(s<=t)for(let e=s;e<t;e++)i.push(e);else for(let e=s;e>t;e--)i.push(e);return i},t.index=function(e,t,s){return e.reduce(((e,i)=>(e[t(i)]=s?s(i):i,e)),Object.create(null))},t.insert=function(e,t){return e.push(t),()=>l(e,t)},t.remove=l,t.arrayInsert=function(e,t,s){const i=e.slice(0,t),r=e.slice(t);return i.concat(s,r)},t.shuffle=function(e,t){let s;if("number"==typeof t){let e=t;s=()=>{const t=179426549*Math.sin(e++);return t-Math.floor(t)}}else s=Math.random;for(let t=e.length-1;t>0;t-=1){const i=Math.floor(s()*(t+1)),r=e[t];e[t]=e[i],e[i]=r}},t.pushToStart=function(e,t){const s=e.indexOf(t);s>-1&&(e.splice(s,1),e.unshift(t))},t.pushToEnd=function(e,t){const s=e.indexOf(t);s>-1&&(e.splice(s,1),e.push(t))},t.pushMany=function(e,t){for(const s of t)e.push(s)},t.mapArrayOrNot=function(e,t){return Array.isArray(e)?e.map(t):t(e)},t.asArray=function(e){return Array.isArray(e)?e:[e]},t.getRandomElement=function(e){return e[Math.floor(Math.random()*e.length)]},t.insertInto=h,t.splice=function(e,t,s,i){const r=c(e,t);let n=e.splice(r,s);return void 0===n&&(n=[]),h(e,r,i),n},t.compareBy=function(e,t){return(s,i)=>t(e(s),e(i))},t.tieBreakComparators=function(...e){return(t,s)=>{for(const i of e){const e=i(t,s);if(!u.isNeitherLessOrGreaterThan(e))return e}return u.neitherLessOrGreaterThan}},t.reverseOrder=function(e){return(t,s)=>-e(t,s)};const i=s(577),r=s(411);function n(e,t){let s=0,i=e-1;for(;s<=i;){const e=(s+i)/2|0,r=t(e);if(r<0)s=e+1;else{if(!(r>0))return e;i=e-1}}return-(s+1)}function o(e,t,s){const i=[];function r(e,t,s){if(0===t&&0===s.length)return;const r=i[i.length-1];r&&r.start+r.deleteCount===e?(r.deleteCount+=t,r.toInsert.push(...s)):i.push({start:e,deleteCount:t,toInsert:s})}let n=0,o=0;for(;;){if(n===e.length){r(n,0,t.slice(o));break}if(o===t.length){r(n,e.length-n,[]);break}const i=e[n],a=t[o],l=s(i,a);0===l?(n+=1,o+=1):l<0?(r(n,1,[]),n+=1):l>0&&(r(n,0,[a]),o+=1)}return i}function a(e,t,s,i,n){for(const o=s.length;i<n;i++){const n=e[i];if(t(n,s[o-1])<0){s.pop();const e=(0,r.findFirstIdxMonotonousOrArrLen)(s,(e=>t(n,e)<0));s.splice(e,0,n)}}}function l(e,t){const s=e.indexOf(t);if(s>-1)return e.splice(s,1),t}function h(e,t,s){const i=c(e,t),r=e.length,n=s.length;e.length=r+n;for(let t=r-1;t>=i;t--)e[t+n]=e[t];for(let t=0;t<n;t++)e[t+i]=s[t]}function c(e,t){return t<0?Math.max(t+e.length,0):Math.min(t,e.length)}var u;!function(e){e.isLessThan=function(e){return e<0},e.isLessThanOrEqual=function(e){return e<=0},e.isGreaterThan=function(e){return e>0},e.isNeitherLessOrGreaterThan=function(e){return 0===e},e.greaterThan=1,e.lessThan=-1,e.neitherLessOrGreaterThan=0}(u||(t.CompareResult=u={})),t.numberComparator=(e,t)=>e-t,t.booleanComparator=(e,s)=>(0,t.numberComparator)(e?1:0,s?1:0),t.ArrayQueue=class{constructor(e){this.items=e,this.firstIdx=0,this.lastIdx=this.items.length-1}get length(){return this.lastIdx-this.firstIdx+1}takeWhile(e){let t=this.firstIdx;for(;t<this.items.length&&e(this.items[t]);)t++;const s=t===this.firstIdx?null:this.items.slice(this.firstIdx,t);return this.firstIdx=t,s}takeFromEndWhile(e){let t=this.lastIdx;for(;t>=0&&e(this.items[t]);)t--;const s=t===this.lastIdx?null:this.items.slice(t+1,this.lastIdx+1);return this.lastIdx=t,s}peek(){if(0!==this.length)return this.items[this.firstIdx]}peekLast(){if(0!==this.length)return this.items[this.lastIdx]}dequeue(){const e=this.items[this.firstIdx];return this.firstIdx++,e}removeLast(){const e=this.items[this.lastIdx];return this.lastIdx--,e}takeCount(e){const t=this.items.slice(this.firstIdx,this.firstIdx+e);return this.firstIdx+=e,t}};class d{static{this.empty=new d((e=>{}))}constructor(e){this.iterate=e}forEach(e){this.iterate((t=>(e(t),!0)))}toArray(){const e=[];return this.iterate((t=>(e.push(t),!0))),e}filter(e){return new d((t=>this.iterate((s=>!e(s)||t(s)))))}map(e){return new d((t=>this.iterate((s=>t(e(s))))))}some(e){let t=!1;return this.iterate((s=>(t=e(s),!t))),t}findFirst(e){let t;return this.iterate((s=>!e(s)||(t=s,!1))),t}findLast(e){let t;return this.iterate((s=>(e(s)&&(t=s),!0))),t}findLastMaxBy(e){let t,s=!0;return this.iterate((i=>((s||u.isGreaterThan(e(i,t)))&&(s=!1,t=i),!0))),t}}t.CallbackIterable=d;class f{constructor(e){this._indexMap=e}static createSortPermutation(e,t){const s=Array.from(e.keys()).sort(((s,i)=>t(e[s],e[i])));return new f(s)}apply(e){return e.map(((t,s)=>e[this._indexMap[s]]))}inverse(){const e=this._indexMap.slice();for(let t=0;t<this._indexMap.length;t++)e[this._indexMap[t]]=t;return new f(e)}}t.Permutation=f},411:(e,t)=>{function s(e,t,s=e.length-1){for(let i=s;i>=0;i--)if(t(e[i]))return i;return-1}function i(e,t,s=0,i=e.length){let r=s,n=i;for(;r<n;){const s=Math.floor((r+n)/2);t(e[s])?r=s+1:n=s}return r-1}function r(e,t,s=0,i=e.length){let r=s,n=i;for(;r<n;){const s=Math.floor((r+n)/2);t(e[s])?n=s:r=s+1}return r}Object.defineProperty(t,"__esModule",{value:!0}),t.MonotonousArray=void 0,t.findLast=function(e,t){const i=s(e,t);if(-1!==i)return e[i]},t.findLastIdx=s,t.findLastMonotonous=function(e,t){const s=i(e,t);return-1===s?void 0:e[s]},t.findLastIdxMonotonous=i,t.findFirstMonotonous=function(e,t){const s=r(e,t);return s===e.length?void 0:e[s]},t.findFirstIdxMonotonousOrArrLen=r,t.findFirstIdxMonotonous=function(e,t,s=0,i=e.length){const n=r(e,t,s,i);return n===e.length?-1:n},t.findFirstMax=o,t.findLastMax=function(e,t){if(0===e.length)return;let s=e[0];for(let i=1;i<e.length;i++){const r=e[i];t(r,s)>=0&&(s=r)}return s},t.findFirstMin=function(e,t){return o(e,((e,s)=>-t(e,s)))},t.findMaxIdx=function(e,t){if(0===e.length)return-1;let s=0;for(let i=1;i<e.length;i++)t(e[i],e[s])>0&&(s=i);return s},t.mapFindFirst=function(e,t){for(const s of e){const e=t(s);if(void 0!==e)return e}};class n{static{this.assertInvariants=!1}constructor(e){this._array=e,this._findLastMonotonousLastIdx=0}findLastMonotonous(e){if(n.assertInvariants){if(this._prevFindLastPredicate)for(const t of this._array)if(this._prevFindLastPredicate(t)&&!e(t))throw new Error("MonotonousArray: current predicate must be weaker than (or equal to) the previous predicate.");this._prevFindLastPredicate=e}const t=i(this._array,e,this._findLastMonotonousLastIdx);return this._findLastMonotonousLastIdx=t+1,-1===t?void 0:this._array[t]}}function o(e,t){if(0===e.length)return;let s=e[0];for(let i=1;i<e.length;i++){const r=e[i];t(r,s)>0&&(s=r)}return s}t.MonotonousArray=n},940:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.AsyncIterableSource=t.CancelableAsyncIterableObject=t.AsyncIterableObject=t.LazyStatefulPromise=t.StatefulPromise=t.Promises=t.DeferredPromise=t.IntervalCounter=t.TaskSequentializer=t.GlobalIdleValue=t.AbstractIdleValue=t._runWhenIdle=t.runWhenGlobalIdle=t.ThrottledWorker=t.RunOnceWorker=t.ProcessTimeRunOnceScheduler=t.RunOnceScheduler=t.IntervalTimer=t.TimeoutTimer=t.LimitedQueue=t.Queue=t.Limiter=t.AutoOpenBarrier=t.Barrier=t.ThrottledDelayer=t.Delayer=t.SequencerByKey=t.Sequencer=t.Throttler=void 0,t.isThenable=c,t.createCancelablePromise=u,t.raceCancellation=function(e,t,s){return new Promise(((i,r)=>{const n=t.onCancellationRequested((()=>{n.dispose(),i(s)}));e.then(i,r).finally((()=>n.dispose()))}))},t.raceCancellationError=function(e,t){return new Promise(((s,i)=>{const n=t.onCancellationRequested((()=>{n.dispose(),i(new r.CancellationError)}));e.then(s,i).finally((()=>n.dispose()))}))},t.raceCancellablePromises=async function(e){let t=-1;const s=e.map(((e,s)=>e.then((e=>(t=s,e)))));try{return await Promise.race(s)}finally{e.forEach(((e,s)=>{s!==t&&e.cancel()}))}},t.raceTimeout=function(e,t,s){let i;const r=setTimeout((()=>{i?.(void 0),s?.()}),t);return Promise.race([e.finally((()=>clearTimeout(r))),new Promise((e=>i=e))])},t.asPromise=function(e){return new Promise(((t,s)=>{const i=e();c(i)?i.then(t,s):t(i)}))},t.promiseWithResolvers=d,t.timeout=m,t.disposableTimeout=function(e,t=0,s){const i=setTimeout((()=>{e(),s&&r.dispose()}),t),r=(0,o.toDisposable)((()=>{clearTimeout(i),s?.deleteAndLeak(r)}));return s?.add(r),r},t.sequence=function(e){const t=[];let s=0;const i=e.length;return Promise.resolve(null).then((function r(n){null!=n&&t.push(n);const o=s<i?e[s++]():null;return o?o.then(r):Promise.resolve(t)}))},t.first=function(e,t=e=>!!e,s=null){let i=0;const r=e.length,n=()=>{if(i>=r)return Promise.resolve(s);const o=e[i++];return Promise.resolve(o()).then((e=>t(e)?Promise.resolve(e):n()))};return n()},t.firstParallel=function(e,t=e=>!!e,s=null){if(0===e.length)return Promise.resolve(s);let i=e.length;const r=()=>{i=-1;for(const t of e)t.cancel?.()};return new Promise(((n,o)=>{for(const a of e)a.then((e=>{--i>=0&&t(e)?(r(),n(e)):0===i&&n(s)})).catch((e=>{--i>=0&&(r(),o(e))}))}))},t.retry=async function(e,t,s){let i;for(let r=0;r<s;r++)try{return await e()}catch(e){i=e,await m(t)}throw i},t.createCancelableAsyncIterable=function(e){const t=new i.CancellationTokenSource,s=e(t.token);return new T(t,(async e=>{const i=t.token.onCancellationRequested((()=>{i.dispose(),t.dispose(),e.reject(new r.CancellationError)}));try{for await(const i of s){if(t.token.isCancellationRequested)return;e.emitOne(i)}i.dispose(),t.dispose()}catch(s){i.dispose(),t.dispose(),e.reject(s)}}))};const i=s(473),r=s(577),n=s(276),o=s(540),a=s(973),l=s(329),h=s(764);function c(e){return!!e&&"function"==typeof e.then}function u(e){const t=new i.CancellationTokenSource,s=e(t.token),n=new Promise(((e,i)=>{const n=t.token.onCancellationRequested((()=>{n.dispose(),i(new r.CancellationError)}));Promise.resolve(s).then((s=>{n.dispose(),t.dispose(),e(s)}),(e=>{n.dispose(),t.dispose(),i(e)}))}));return new class{cancel(){t.cancel(),t.dispose()}then(e,t){return n.then(e,t)}catch(e){return this.then(void 0,e)}finally(e){return n.finally(e)}}}function d(){let e,t;return{promise:new Promise(((s,i)=>{e=s,t=i})),resolve:e,reject:t}}class f{constructor(){this.isDisposed=!1,this.activePromise=null,this.queuedPromise=null,this.queuedPromiseFactory=null}queue(e){if(this.isDisposed)return Promise.reject(new Error("Throttler is disposed"));if(this.activePromise){if(this.queuedPromiseFactory=e,!this.queuedPromise){const e=()=>{if(this.queuedPromise=null,this.isDisposed)return;const e=this.queue(this.queuedPromiseFactory);return this.queuedPromiseFactory=null,e};this.queuedPromise=new Promise((t=>{this.activePromise.then(e,e).then(t)}))}return new Promise(((e,t)=>{this.queuedPromise.then(e,t)}))}return this.activePromise=e(),new Promise(((e,t)=>{this.activePromise.then((t=>{this.activePromise=null,e(t)}),(e=>{this.activePromise=null,t(e)}))}))}dispose(){this.isDisposed=!0}}t.Throttler=f,t.Sequencer=class{constructor(){this.current=Promise.resolve(null)}queue(e){return this.current=this.current.then((()=>e()),(()=>e()))}},t.SequencerByKey=class{constructor(){this.promiseMap=new Map}queue(e,t){const s=(this.promiseMap.get(e)??Promise.resolve()).catch((()=>{})).then(t).finally((()=>{this.promiseMap.get(e)===s&&this.promiseMap.delete(e)}));return this.promiseMap.set(e,s),s}};class p{constructor(e){this.defaultDelay=e,this.deferred=null,this.completionPromise=null,this.doResolve=null,this.doReject=null,this.task=null}trigger(e,t=this.defaultDelay){this.task=e,this.cancelTimeout(),this.completionPromise||(this.completionPromise=new Promise(((e,t)=>{this.doResolve=e,this.doReject=t})).then((()=>{if(this.completionPromise=null,this.doResolve=null,this.task){const e=this.task;return this.task=null,e()}})));const s=()=>{this.deferred=null,this.doResolve?.(null)};return this.deferred=t===l.MicrotaskDelay?(e=>{let t=!0;return queueMicrotask((()=>{t&&(t=!1,e())})),{isTriggered:()=>t,dispose:()=>{t=!1}}})(s):((e,t)=>{let s=!0;const i=setTimeout((()=>{s=!1,t()}),e);return{isTriggered:()=>s,dispose:()=>{clearTimeout(i),s=!1}}})(t,s),this.completionPromise}isTriggered(){return!!this.deferred?.isTriggered()}cancel(){this.cancelTimeout(),this.completionPromise&&(this.doReject?.(new r.CancellationError),this.completionPromise=null)}cancelTimeout(){this.deferred?.dispose(),this.deferred=null}dispose(){this.cancel()}}t.Delayer=p,t.ThrottledDelayer=class{constructor(e){this.delayer=new p(e),this.throttler=new f}trigger(e,t){return this.delayer.trigger((()=>this.throttler.queue(e)),t)}isTriggered(){return this.delayer.isTriggered()}cancel(){this.delayer.cancel()}dispose(){this.delayer.dispose(),this.throttler.dispose()}};class _{constructor(){this._isOpen=!1,this._promise=new Promise(((e,t)=>{this._completePromise=e}))}isOpen(){return this._isOpen}open(){this._isOpen=!0,this._completePromise(!0)}wait(){return this._promise}}function m(e,t){return t?new Promise(((s,i)=>{const n=setTimeout((()=>{o.dispose(),s()}),e),o=t.onCancellationRequested((()=>{clearTimeout(n),o.dispose(),i(new r.CancellationError)}))})):u((t=>m(e,t)))}t.Barrier=_,t.AutoOpenBarrier=class extends _{constructor(e){super(),this._timeout=setTimeout((()=>this.open()),e)}open(){clearTimeout(this._timeout),super.open()}};class g{constructor(e){this._size=0,this._isDisposed=!1,this.maxDegreeOfParalellism=e,this.outstandingPromises=[],this.runningPromises=0,this._onDrained=new n.Emitter}whenIdle(){return this.size>0?n.Event.toPromise(this.onDrained):Promise.resolve()}get onDrained(){return this._onDrained.event}get size(){return this._size}queue(e){if(this._isDisposed)throw new Error("Object has been disposed");return this._size++,new Promise(((t,s)=>{this.outstandingPromises.push({factory:e,c:t,e:s}),this.consume()}))}consume(){for(;this.outstandingPromises.length&&this.runningPromises<this.maxDegreeOfParalellism;){const e=this.outstandingPromises.shift();this.runningPromises++;const t=e.factory();t.then(e.c,e.e),t.then((()=>this.consumed()),(()=>this.consumed()))}}consumed(){this._isDisposed||(this.runningPromises--,0==--this._size&&this._onDrained.fire(),this.outstandingPromises.length>0&&this.consume())}clear(){if(this._isDisposed)throw new Error("Object has been disposed");this.outstandingPromises.length=0,this._size=this.runningPromises}dispose(){this._isDisposed=!0,this.outstandingPromises.length=0,this._size=0,this._onDrained.dispose()}}t.Limiter=g,t.Queue=class extends g{constructor(){super(1)}},t.LimitedQueue=class{constructor(){this.sequentializer=new w,this.tasks=0}queue(e){return this.sequentializer.isRunning()?this.sequentializer.queue((()=>this.sequentializer.run(this.tasks++,e()))):this.sequentializer.run(this.tasks++,e())}},t.TimeoutTimer=class{constructor(e,t){this._isDisposed=!1,this._token=-1,"function"==typeof e&&"number"==typeof t&&this.setIfNotSet(e,t)}dispose(){this.cancel(),this._isDisposed=!0}cancel(){-1!==this._token&&(clearTimeout(this._token),this._token=-1)}cancelAndSet(e,t){if(this._isDisposed)throw new r.BugIndicatingError("Calling 'cancelAndSet' on a disposed TimeoutTimer");this.cancel(),this._token=setTimeout((()=>{this._token=-1,e()}),t)}setIfNotSet(e,t){if(this._isDisposed)throw new r.BugIndicatingError("Calling 'setIfNotSet' on a disposed TimeoutTimer");-1===this._token&&(this._token=setTimeout((()=>{this._token=-1,e()}),t))}},t.IntervalTimer=class{constructor(){this.disposable=void 0,this.isDisposed=!1}cancel(){this.disposable?.dispose(),this.disposable=void 0}cancelAndSet(e,t,s=globalThis){if(this.isDisposed)throw new r.BugIndicatingError("Calling 'cancelAndSet' on a disposed IntervalTimer");this.cancel();const i=s.setInterval((()=>{e()}),t);this.disposable=(0,o.toDisposable)((()=>{s.clearInterval(i),this.disposable=void 0}))}dispose(){this.cancel(),this.isDisposed=!0}};class v{constructor(e,t){this.timeoutToken=-1,this.runner=e,this.timeout=t,this.timeoutHandler=this.onTimeout.bind(this)}dispose(){this.cancel(),this.runner=null}cancel(){this.isScheduled()&&(clearTimeout(this.timeoutToken),this.timeoutToken=-1)}schedule(e=this.timeout){this.cancel(),this.timeoutToken=setTimeout(this.timeoutHandler,e)}get delay(){return this.timeout}set delay(e){this.timeout=e}isScheduled(){return-1!==this.timeoutToken}flush(){this.isScheduled()&&(this.cancel(),this.doRun())}onTimeout(){this.timeoutToken=-1,this.runner&&this.doRun()}doRun(){this.runner?.()}}t.RunOnceScheduler=v,t.ProcessTimeRunOnceScheduler=class{constructor(e,t){t%1e3!=0&&console.warn(`ProcessTimeRunOnceScheduler resolution is 1s, ${t}ms is not a multiple of 1000ms.`),this.runner=e,this.timeout=t,this.counter=0,this.intervalToken=-1,this.intervalHandler=this.onInterval.bind(this)}dispose(){this.cancel(),this.runner=null}cancel(){this.isScheduled()&&(clearInterval(this.intervalToken),this.intervalToken=-1)}schedule(e=this.timeout){e%1e3!=0&&console.warn(`ProcessTimeRunOnceScheduler resolution is 1s, ${e}ms is not a multiple of 1000ms.`),this.cancel(),this.counter=Math.ceil(e/1e3),this.intervalToken=setInterval(this.intervalHandler,1e3)}isScheduled(){return-1!==this.intervalToken}onInterval(){this.counter--,this.counter>0||(clearInterval(this.intervalToken),this.intervalToken=-1,this.runner?.())}},t.RunOnceWorker=class extends v{constructor(e,t){super(e,t),this.units=[]}work(e){this.units.push(e),this.isScheduled()||this.schedule()}doRun(){const e=this.units;this.units=[],this.runner?.(e)}dispose(){this.units=[],super.dispose()}};class b extends o.Disposable{constructor(e,t){super(),this.options=e,this.handler=t,this.pendingWork=[],this.throttler=this._register(new o.MutableDisposable),this.disposed=!1}get pending(){return this.pendingWork.length}work(e){if(this.disposed)return!1;if("number"==typeof this.options.maxBufferedWork)if(this.throttler.value){if(this.pending+e.length>this.options.maxBufferedWork)return!1}else if(this.pending+e.length-this.options.maxWorkChunkSize>this.options.maxBufferedWork)return!1;for(const t of e)this.pendingWork.push(t);return this.throttler.value||this.doWork(),!0}doWork(){this.handler(this.pendingWork.splice(0,this.options.maxWorkChunkSize)),this.pendingWork.length>0&&(this.throttler.value=new v((()=>{this.throttler.clear(),this.doWork()}),this.options.throttleDelay),this.throttler.value.schedule())}dispose(){super.dispose(),this.disposed=!0}}t.ThrottledWorker=b,"function"!=typeof globalThis.requestIdleCallback||"function"!=typeof globalThis.cancelIdleCallback?t._runWhenIdle=(e,t)=>{(0,a.setTimeout0)((()=>{if(s)return;const e=Date.now()+15,i={didTimeout:!0,timeRemaining:()=>Math.max(0,e-Date.now())};t(Object.freeze(i))}));let s=!1;return{dispose(){s||(s=!0)}}}:t._runWhenIdle=(e,t,s)=>{const i=e.requestIdleCallback(t,"number"==typeof s?{timeout:s}:void 0);let r=!1;return{dispose(){r||(r=!0,e.cancelIdleCallback(i))}}},t.runWhenGlobalIdle=e=>(0,t._runWhenIdle)(globalThis,e);class y{constructor(e,s){this._didRun=!1,this._executor=()=>{try{this._value=s()}catch(e){this._error=e}finally{this._didRun=!0}},this._handle=(0,t._runWhenIdle)(e,(()=>this._executor()))}dispose(){this._handle.dispose()}get value(){if(this._didRun||(this._handle.dispose(),this._executor()),this._error)throw this._error;return this._value}get isInitialized(){return this._didRun}}t.AbstractIdleValue=y,t.GlobalIdleValue=class extends y{constructor(e){super(globalThis,e)}};class w{isRunning(e){return"number"==typeof e?this._running?.taskId===e:!!this._running}get running(){return this._running?.promise}cancelRunning(){this._running?.cancel()}run(e,t,s){return this._running={taskId:e,cancel:()=>s?.(),promise:t},t.then((()=>this.doneRunning(e)),(()=>this.doneRunning(e))),t}doneRunning(e){this._running&&e===this._running.taskId&&(this._running=void 0,this.runQueued())}runQueued(){if(this._queued){const e=this._queued;this._queued=void 0,e.run().then(e.promiseResolve,e.promiseReject)}}queue(e){if(this._queued)this._queued.run=e;else{const{promise:t,resolve:s,reject:i}=d();this._queued={run:e,promise:t,promiseResolve:s,promiseReject:i}}return this._queued.promise}hasQueued(){return!!this._queued}async join(){return this._queued?.promise??this._running?.promise}}var D,S,E;t.TaskSequentializer=w,t.IntervalCounter=class{constructor(e,t=()=>Date.now()){this.interval=e,this.nowFn=t,this.lastIncrementTime=0,this.value=0}increment(){const e=this.nowFn();return e-this.lastIncrementTime>this.interval&&(this.lastIncrementTime=e,this.value=0),this.value++,this.value}},function(e){e[e.Resolved=0]="Resolved",e[e.Rejected=1]="Rejected"}(D||(D={}));class k{get isRejected(){return this.outcome?.outcome===D.Rejected}get isResolved(){return this.outcome?.outcome===D.Resolved}get isSettled(){return!!this.outcome}get value(){return this.outcome?.outcome===D.Resolved?this.outcome?.value:void 0}constructor(){this.p=new Promise(((e,t)=>{this.completeCallback=e,this.errorCallback=t}))}complete(e){return new Promise((t=>{this.completeCallback(e),this.outcome={outcome:D.Resolved,value:e},t()}))}error(e){return new Promise((t=>{this.errorCallback(e),this.outcome={outcome:D.Rejected,value:e},t()}))}cancel(){return this.error(new r.CancellationError)}}t.DeferredPromise=k,function(e){e.settled=async function(e){let t;const s=await Promise.all(e.map((e=>e.then((e=>e),(e=>{t||(t=e)})))));if(void 0!==t)throw t;return s},e.withAsyncBody=function(e){return new Promise((async(t,s)=>{try{await e(t,s)}catch(e){s(e)}}))}}(S||(t.Promises=S={}));class C{get value(){return this._value}get error(){return this._error}get isResolved(){return this._isResolved}constructor(e){this._value=void 0,this._error=void 0,this._isResolved=!1,this.promise=e.then((e=>(this._value=e,this._isResolved=!0,e)),(e=>{throw this._error=e,this._isResolved=!0,e}))}requireValue(){if(!this._isResolved)throw new r.BugIndicatingError("Promise is not resolved yet");if(this._error)throw this._error;return this._value}}t.StatefulPromise=C,t.LazyStatefulPromise=class{constructor(e){this._compute=e,this._promise=new h.Lazy((()=>new C(this._compute())))}requireValue(){return this._promise.value.requireValue()}getPromise(){return this._promise.value.promise}get currentValue(){return this._promise.rawValue?.value}},function(e){e[e.Initial=0]="Initial",e[e.DoneOK=1]="DoneOK",e[e.DoneError=2]="DoneError"}(E||(E={}));class L{static fromArray(e){return new L((t=>{t.emitMany(e)}))}static fromPromise(e){return new L((async t=>{t.emitMany(await e)}))}static fromPromises(e){return new L((async t=>{await Promise.all(e.map((async e=>t.emitOne(await e))))}))}static merge(e){return new L((async t=>{await Promise.all(e.map((async e=>{for await(const s of e)t.emitOne(s)})))}))}static{this.EMPTY=L.fromArray([])}constructor(e,t){this._state=E.Initial,this._results=[],this._error=null,this._onReturn=t,this._onStateChanged=new n.Emitter,queueMicrotask((async()=>{const t={emitOne:e=>this.emitOne(e),emitMany:e=>this.emitMany(e),reject:e=>this.reject(e)};try{await Promise.resolve(e(t)),this.resolve()}catch(e){this.reject(e)}finally{t.emitOne=void 0,t.emitMany=void 0,t.reject=void 0}}))}[Symbol.asyncIterator](){let e=0;return{next:async()=>{for(;;){if(this._state===E.DoneError)throw this._error;if(e<this._results.length)return{done:!1,value:this._results[e++]};if(this._state===E.DoneOK)return{done:!0,value:void 0};await n.Event.toPromise(this._onStateChanged.event)}},return:async()=>(this._onReturn?.(),{done:!0,value:void 0})}}static map(e,t){return new L((async s=>{for await(const i of e)s.emitOne(t(i))}))}map(e){return L.map(this,e)}static filter(e,t){return new L((async s=>{for await(const i of e)t(i)&&s.emitOne(i)}))}filter(e){return L.filter(this,e)}static coalesce(e){return L.filter(e,(e=>!!e))}coalesce(){return L.coalesce(this)}static async toPromise(e){const t=[];for await(const s of e)t.push(s);return t}toPromise(){return L.toPromise(this)}emitOne(e){this._state===E.Initial&&(this._results.push(e),this._onStateChanged.fire())}emitMany(e){this._state===E.Initial&&(this._results=this._results.concat(e),this._onStateChanged.fire())}resolve(){this._state===E.Initial&&(this._state=E.DoneOK,this._onStateChanged.fire())}reject(e){this._state===E.Initial&&(this._state=E.DoneError,this._error=e,this._onStateChanged.fire())}}t.AsyncIterableObject=L;class T extends L{constructor(e,t){super(t),this._source=e}cancel(){this._source.cancel()}}t.CancelableAsyncIterableObject=T,t.AsyncIterableSource=class{constructor(e){let t,s;this._deferred=new k,this._asyncIterable=new L((e=>{if(!t)return s&&e.emitMany(s),this._errorFn=t=>e.reject(t),this._emitFn=t=>e.emitOne(t),this._deferred.p;e.reject(t)}),e),this._emitFn=e=>{s||(s=[]),s.push(e)},this._errorFn=e=>{t||(t=e)}}get asyncIterable(){return this._asyncIterable}resolve(){this._deferred.complete()}reject(e){this._errorFn(e),this._deferred.complete()}emitOne(e){this._emitFn(e)}}},473:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.CancellationTokenSource=t.CancellationToken=void 0,t.cancelOnDispose=function(e){const t=new a;return e.add({dispose(){t.cancel()}}),t.token};const i=s(276),r=Object.freeze((function(e,t){const s=setTimeout(e.bind(t),0);return{dispose(){clearTimeout(s)}}}));var n;!function(e){e.isCancellationToken=function(t){return t===e.None||t===e.Cancelled||t instanceof o||!(!t||"object"!=typeof t)&&"boolean"==typeof t.isCancellationRequested&&"function"==typeof t.onCancellationRequested},e.None=Object.freeze({isCancellationRequested:!1,onCancellationRequested:i.Event.None}),e.Cancelled=Object.freeze({isCancellationRequested:!0,onCancellationRequested:r})}(n||(t.CancellationToken=n={}));class o{constructor(){this._isCancelled=!1,this._emitter=null}cancel(){this._isCancelled||(this._isCancelled=!0,this._emitter&&(this._emitter.fire(void 0),this.dispose()))}get isCancellationRequested(){return this._isCancelled}get onCancellationRequested(){return this._isCancelled?r:(this._emitter||(this._emitter=new i.Emitter),this._emitter.event)}dispose(){this._emitter&&(this._emitter.dispose(),this._emitter=null)}}class a{constructor(e){this._token=void 0,this._parentListener=void 0,this._parentListener=e&&e.onCancellationRequested(this.cancel,this)}get token(){return this._token||(this._token=new o),this._token}cancel(){this._token?this._token instanceof o&&this._token.cancel():this._token=n.Cancelled}dispose(e=!1){e&&this.cancel(),this._parentListener?.dispose(),this._token?this._token instanceof o&&this._token.dispose():this._token=n.None}}t.CancellationTokenSource=a},33:(e,t)=>{var s;Object.defineProperty(t,"__esModule",{value:!0}),t.SetWithKey=void 0,t.groupBy=function(e,t){const s=Object.create(null);for(const i of e){const e=t(i);let r=s[e];r||(r=s[e]=[]),r.push(i)}return s},t.diffSets=function(e,t){const s=[],i=[];for(const i of e)t.has(i)||s.push(i);for(const s of t)e.has(s)||i.push(s);return{removed:s,added:i}},t.diffMaps=function(e,t){const s=[],i=[];for(const[i,r]of e)t.has(i)||s.push(r);for(const[s,r]of t)e.has(s)||i.push(r);return{removed:s,added:i}},t.intersection=function(e,t){const s=new Set;for(const i of t)e.has(i)&&s.add(i);return s};class i{static{s=Symbol.toStringTag}constructor(e,t){this.toKey=t,this._map=new Map,this[s]="SetWithKey";for(const t of e)this.add(t)}get size(){return this._map.size}add(e){const t=this.toKey(e);return this._map.set(t,e),this}delete(e){return this._map.delete(this.toKey(e))}has(e){return this._map.has(this.toKey(e))}*entries(){for(const e of this._map.values())yield[e,e]}keys(){return this.values()}*values(){for(const e of this._map.values())yield e}clear(){this._map.clear()}forEach(e,t){this._map.forEach((s=>e.call(t,s,s,this)))}[Symbol.iterator](){return this.values()}}t.SetWithKey=i},577:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.BugIndicatingError=t.ErrorNoTelemetry=t.ExpectedError=t.NotSupportedError=t.NotImplementedError=t.ReadonlyError=t.CancellationError=t.errorHandler=t.ErrorHandler=void 0,t.setUnexpectedErrorHandler=function(e){t.errorHandler.setUnexpectedErrorHandler(e)},t.isSigPipeError=function(e){if(!e||"object"!=typeof e)return!1;const t=e;return"EPIPE"===t.code&&"WRITE"===t.syscall?.toUpperCase()},t.onUnexpectedError=function(e){r(e)||t.errorHandler.onUnexpectedError(e)},t.onUnexpectedExternalError=function(e){r(e)||t.errorHandler.onUnexpectedExternalError(e)},t.transformErrorForSerialization=function(e){if(e instanceof Error){const{name:t,message:s}=e;return{$isError:!0,name:t,message:s,stack:e.stacktrace||e.stack,noTelemetry:c.isErrorNoTelemetry(e)}}return e},t.transformErrorFromSerialization=function(e){let t;return e.noTelemetry?t=new c:(t=new Error,t.name=e.name),t.message=e.message,t.stack=e.stack,t},t.isCancellationError=r,t.canceled=function(){const e=new Error(i);return e.name=e.message,e},t.illegalArgument=function(e){return e?new Error(`Illegal argument: ${e}`):new Error("Illegal argument")},t.illegalState=function(e){return e?new Error(`Illegal state: ${e}`):new Error("Illegal state")},t.getErrorMessage=function(e){return e?e.message?e.message:e.stack?e.stack.split("\n")[0]:String(e):"Error"};class s{constructor(){this.listeners=[],this.unexpectedErrorHandler=function(e){setTimeout((()=>{if(e.stack){if(c.isErrorNoTelemetry(e))throw new c(e.message+"\n\n"+e.stack);throw new Error(e.message+"\n\n"+e.stack)}throw e}),0)}}addListener(e){return this.listeners.push(e),()=>{this._removeListener(e)}}emit(e){this.listeners.forEach((t=>{t(e)}))}_removeListener(e){this.listeners.splice(this.listeners.indexOf(e),1)}setUnexpectedErrorHandler(e){this.unexpectedErrorHandler=e}getUnexpectedErrorHandler(){return this.unexpectedErrorHandler}onUnexpectedError(e){this.unexpectedErrorHandler(e),this.emit(e)}onUnexpectedExternalError(e){this.unexpectedErrorHandler(e)}}t.ErrorHandler=s,t.errorHandler=new s;const i="Canceled";function r(e){return e instanceof n||e instanceof Error&&e.name===i&&e.message===i}class n extends Error{constructor(){super(i),this.name=this.message}}t.CancellationError=n;class o extends TypeError{constructor(e){super(e?`${e} is read-only and cannot be changed`:"Cannot change read-only property")}}t.ReadonlyError=o;class a extends Error{constructor(e){super("NotImplemented"),e&&(this.message=e)}}t.NotImplementedError=a;class l extends Error{constructor(e){super("NotSupported"),e&&(this.message=e)}}t.NotSupportedError=l;class h extends Error{constructor(){super(...arguments),this.isExpected=!0}}t.ExpectedError=h;class c extends Error{constructor(e){super(e),this.name="CodeExpectedError"}static fromError(e){if(e instanceof c)return e;const t=new c;return t.message=e.message,t.stack=e.stack,t}static isErrorNoTelemetry(e){return"CodeExpectedError"===e.name}}t.ErrorNoTelemetry=c;class u extends Error{constructor(e){super(e||"An unexpected bug occurred."),Object.setPrototypeOf(this,u.prototype)}}t.BugIndicatingError=u},276:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.ValueWithChangeEvent=t.Relay=t.EventBufferer=t.DynamicListEventMultiplexer=t.EventMultiplexer=t.MicrotaskEmitter=t.DebounceEmitter=t.PauseableEmitter=t.AsyncEmitter=t.createEventDeliveryQueue=t.Emitter=t.ListenerRefusalError=t.ListenerLeakError=t.EventProfiling=t.Event=void 0,t.setGlobalLeakWarningThreshold=function(e){const t=c;return c=e,{dispose(){c=t}}};const i=s(577),r=s(355),n=s(540),o=s(711),a=s(79);var l;!function(e){function t(e){return(t,s=null,i)=>{let r,n=!1;return r=e((e=>{if(!n)return r?r.dispose():n=!0,t.call(s,e)}),null,i),n&&r.dispose(),r}}function s(e,t,s){return r(((s,i=null,r)=>e((e=>s.call(i,t(e))),null,r)),s)}function i(e,t,s){return r(((s,i=null,r)=>e((e=>t(e)&&s.call(i,e)),null,r)),s)}function r(e,t){let s;const i=new g({onWillAddFirstListener(){s=e(i.fire,i)},onDidRemoveLastListener(){s?.dispose()}});return t?.add(i),i.event}function o(e,t,s=100,i=!1,r=!1,n,o){let a,l,h,c,u=0;const d=new g({leakWarningThreshold:n,onWillAddFirstListener(){a=e((e=>{u++,l=t(l,e),i&&!h&&(d.fire(l),l=void 0),c=()=>{const e=l;l=void 0,h=void 0,(!i||u>1)&&d.fire(e),u=0},"number"==typeof s?(clearTimeout(h),h=setTimeout(c,s)):void 0===h&&(h=0,queueMicrotask(c))}))},onWillRemoveListener(){r&&u>0&&c?.()},onDidRemoveLastListener(){c=void 0,a.dispose()}});return o?.add(d),d.event}e.None=()=>n.Disposable.None,e.defer=function(e,t){return o(e,(()=>{}),0,void 0,!0,void 0,t)},e.once=t,e.map=s,e.forEach=function(e,t,s){return r(((s,i=null,r)=>e((e=>{t(e),s.call(i,e)}),null,r)),s)},e.filter=i,e.signal=function(e){return e},e.any=function(...e){return(t,s=null,i)=>{return r=(0,n.combinedDisposable)(...e.map((e=>e((e=>t.call(s,e)))))),(o=i)instanceof Array?o.push(r):o&&o.add(r),r;var r,o}},e.reduce=function(e,t,i,r){let n=i;return s(e,(e=>(n=t(n,e),n)),r)},e.debounce=o,e.accumulate=function(t,s=0,i){return e.debounce(t,((e,t)=>e?(e.push(t),e):[t]),s,void 0,!0,void 0,i)},e.latch=function(e,t=(e,t)=>e===t,s){let r,n=!0;return i(e,(e=>{const s=n||!t(e,r);return n=!1,r=e,s}),s)},e.split=function(t,s,i){return[e.filter(t,s,i),e.filter(t,(e=>!s(e)),i)]},e.buffer=function(e,t=!1,s=[],i){let r=s.slice(),n=e((e=>{r?r.push(e):a.fire(e)}));i&&i.add(n);const o=()=>{r?.forEach((e=>a.fire(e))),r=null},a=new g({onWillAddFirstListener(){n||(n=e((e=>a.fire(e))),i&&i.add(n))},onDidAddFirstListener(){r&&(t?setTimeout(o):o())},onDidRemoveLastListener(){n&&n.dispose(),n=null}});return i&&i.add(a),a.event},e.chain=function(e,t){return(s,i,r)=>{const n=t(new l);return e((function(e){const t=n.evaluate(e);t!==a&&s.call(i,t)}),void 0,r)}};const a=Symbol("HaltChainable");class l{constructor(){this.steps=[]}map(e){return this.steps.push(e),this}forEach(e){return this.steps.push((t=>(e(t),t))),this}filter(e){return this.steps.push((t=>e(t)?t:a)),this}reduce(e,t){let s=t;return this.steps.push((t=>(s=e(s,t),s))),this}latch(e=(e,t)=>e===t){let t,s=!0;return this.steps.push((i=>{const r=s||!e(i,t);return s=!1,t=i,r?i:a})),this}evaluate(e){for(const t of this.steps)if((e=t(e))===a)break;return e}}e.fromNodeEventEmitter=function(e,t,s=e=>e){const i=(...e)=>r.fire(s(...e)),r=new g({onWillAddFirstListener:()=>e.on(t,i),onDidRemoveLastListener:()=>e.removeListener(t,i)});return r.event},e.fromDOMEventEmitter=function(e,t,s=e=>e){const i=(...e)=>r.fire(s(...e)),r=new g({onWillAddFirstListener:()=>e.addEventListener(t,i),onDidRemoveLastListener:()=>e.removeEventListener(t,i)});return r.event},e.toPromise=function(e){return new Promise((s=>t(e)(s)))},e.fromPromise=function(e){const t=new g;return e.then((e=>{t.fire(e)}),(()=>{t.fire(void 0)})).finally((()=>{t.dispose()})),t.event},e.forward=function(e,t){return e((e=>t.fire(e)))},e.runAndSubscribe=function(e,t,s){return t(s),e((e=>t(e)))};class h{constructor(e,t){this._observable=e,this._counter=0,this._hasChanged=!1;const s={onWillAddFirstListener:()=>{e.addObserver(this)},onDidRemoveLastListener:()=>{e.removeObserver(this)}};this.emitter=new g(s),t&&t.add(this.emitter)}beginUpdate(e){this._counter++}handlePossibleChange(e){}handleChange(e,t){this._hasChanged=!0}endUpdate(e){this._counter--,0===this._counter&&(this._observable.reportChanges(),this._hasChanged&&(this._hasChanged=!1,this.emitter.fire(this._observable.get())))}}e.fromObservable=function(e,t){return new h(e,t).emitter.event},e.fromObservableLight=function(e){return(t,s,i)=>{let r=0,o=!1;const a={beginUpdate(){r++},endUpdate(){r--,0===r&&(e.reportChanges(),o&&(o=!1,t.call(s)))},handlePossibleChange(){},handleChange(){o=!0}};e.addObserver(a),e.reportChanges();const l={dispose(){e.removeObserver(a)}};return i instanceof n.DisposableStore?i.add(l):Array.isArray(i)&&i.push(l),l}}}(l||(t.Event=l={}));class h{static{this.all=new Set}static{this._idPool=0}constructor(e){this.listenerCount=0,this.invocationCount=0,this.elapsedOverall=0,this.durations=[],this.name=`${e}_${h._idPool++}`,h.all.add(this)}start(e){this._stopWatch=new a.StopWatch,this.listenerCount=e}stop(){if(this._stopWatch){const e=this._stopWatch.elapsed();this.durations.push(e),this.elapsedOverall+=e,this.invocationCount+=1,this._stopWatch=void 0}}}t.EventProfiling=h;let c=-1;class u{static{this._idPool=1}constructor(e,t,s=(u._idPool++).toString(16).padStart(3,"0")){this._errorHandler=e,this.threshold=t,this.name=s,this._warnCountdown=0}dispose(){this._stacks?.clear()}check(e,t){const s=this.threshold;if(s<=0||t<s)return;this._stacks||(this._stacks=new Map);const i=this._stacks.get(e.value)||0;if(this._stacks.set(e.value,i+1),this._warnCountdown-=1,this._warnCountdown<=0){this._warnCountdown=.5*s;const[e,i]=this.getMostFrequentStack(),r=`[${this.name}] potential listener LEAK detected, having ${t} listeners already. MOST frequent listener (${i}):`;console.warn(r),console.warn(e);const n=new f(r,e);this._errorHandler(n)}return()=>{const t=this._stacks.get(e.value)||0;this._stacks.set(e.value,t-1)}}getMostFrequentStack(){if(!this._stacks)return;let e,t=0;for(const[s,i]of this._stacks)(!e||t<i)&&(e=[s,i],t=i);return e}}class d{static create(){const e=new Error;return new d(e.stack??"")}constructor(e){this.value=e}print(){console.warn(this.value.split("\n").slice(2).join("\n"))}}class f extends Error{constructor(e,t){super(e),this.name="ListenerLeakError",this.stack=t}}t.ListenerLeakError=f;class p extends Error{constructor(e,t){super(e),this.name="ListenerRefusalError",this.stack=t}}t.ListenerRefusalError=p;let _=0;class m{constructor(e){this.value=e,this.id=_++}}class g{constructor(e){this._size=0,this._options=e,this._leakageMon=c>0||this._options?.leakWarningThreshold?new u(e?.onListenerError??i.onUnexpectedError,this._options?.leakWarningThreshold??c):void 0,this._perfMon=this._options?._profName?new h(this._options._profName):void 0,this._deliveryQueue=this._options?.deliveryQueue}dispose(){this._disposed||(this._disposed=!0,this._deliveryQueue?.current===this&&this._deliveryQueue.reset(),this._listeners&&(this._listeners=void 0,this._size=0),this._options?.onDidRemoveLastListener?.(),this._leakageMon?.dispose())}get event(){return this._event??=(e,t,s)=>{if(this._leakageMon&&this._size>this._leakageMon.threshold**2){const e=`[${this._leakageMon.name}] REFUSES to accept new listeners because it exceeded its threshold by far (${this._size} vs ${this._leakageMon.threshold})`;console.warn(e);const t=this._leakageMon.getMostFrequentStack()??["UNKNOWN stack",-1],s=new p(`${e}. HINT: Stack shows most frequent listener (${t[1]}-times)`,t[0]);return(this._options?.onListenerError||i.onUnexpectedError)(s),n.Disposable.None}if(this._disposed)return n.Disposable.None;t&&(e=e.bind(t));const r=new m(e);let o;this._leakageMon&&this._size>=Math.ceil(.2*this._leakageMon.threshold)&&(r.stack=d.create(),o=this._leakageMon.check(r.stack,this._size+1)),this._listeners?this._listeners instanceof m?(this._deliveryQueue??=new v,this._listeners=[this._listeners,r]):this._listeners.push(r):(this._options?.onWillAddFirstListener?.(this),this._listeners=r,this._options?.onDidAddFirstListener?.(this)),this._size++;const a=(0,n.toDisposable)((()=>{o?.(),this._removeListener(r)}));return s instanceof n.DisposableStore?s.add(a):Array.isArray(s)&&s.push(a),a},this._event}_removeListener(e){if(this._options?.onWillRemoveListener?.(this),!this._listeners)return;if(1===this._size)return this._listeners=void 0,this._options?.onDidRemoveLastListener?.(this),void(this._size=0);const t=this._listeners,s=t.indexOf(e);if(-1===s)throw console.log("disposed?",this._disposed),console.log("size?",this._size),console.log("arr?",JSON.stringify(this._listeners)),new Error("Attempted to dispose unknown listener");this._size--,t[s]=void 0;const i=this._deliveryQueue.current===this;if(2*this._size<=t.length){let e=0;for(let s=0;s<t.length;s++)t[s]?t[e++]=t[s]:i&&(this._deliveryQueue.end--,e<this._deliveryQueue.i&&this._deliveryQueue.i--);t.length=e}}_deliver(e,t){if(!e)return;const s=this._options?.onListenerError||i.onUnexpectedError;if(s)try{e.value(t)}catch(e){s(e)}else e.value(t)}_deliverQueue(e){const t=e.current._listeners;for(;e.i<e.end;)this._deliver(t[e.i++],e.value);e.reset()}fire(e){if(this._deliveryQueue?.current&&(this._deliverQueue(this._deliveryQueue),this._perfMon?.stop()),this._perfMon?.start(this._size),this._listeners)if(this._listeners instanceof m)this._deliver(this._listeners,e);else{const t=this._deliveryQueue;t.enqueue(this,e,this._listeners.length),this._deliverQueue(t)}this._perfMon?.stop()}hasListeners(){return this._size>0}}t.Emitter=g,t.createEventDeliveryQueue=()=>new v;class v{constructor(){this.i=-1,this.end=0}enqueue(e,t,s){this.i=0,this.end=s,this.current=e,this.value=t}reset(){this.i=this.end,this.current=void 0,this.value=void 0}}t.AsyncEmitter=class extends g{async fireAsync(e,t,s){if(this._listeners)for(this._asyncDeliveryQueue||(this._asyncDeliveryQueue=new o.LinkedList),((e,t)=>{if(e instanceof m)t(e);else for(let s=0;s<e.length;s++){const i=e[s];i&&t(i)}})(this._listeners,(t=>this._asyncDeliveryQueue.push([t.value,e])));this._asyncDeliveryQueue.size>0&&!t.isCancellationRequested;){const[e,r]=this._asyncDeliveryQueue.shift(),n=[],o={...r,token:t,waitUntil:t=>{if(Object.isFrozen(n))throw new Error("waitUntil can NOT be called asynchronous");s&&(t=s(t,e)),n.push(t)}};try{e(o)}catch(e){(0,i.onUnexpectedError)(e);continue}Object.freeze(n),await Promise.allSettled(n).then((e=>{for(const t of e)"rejected"===t.status&&(0,i.onUnexpectedError)(t.reason)}))}}};class b extends g{get isPaused(){return 0!==this._isPaused}constructor(e){super(e),this._isPaused=0,this._eventQueue=new o.LinkedList,this._mergeFn=e?.merge}pause(){this._isPaused++}resume(){if(0!==this._isPaused&&0==--this._isPaused)if(this._mergeFn){if(this._eventQueue.size>0){const e=Array.from(this._eventQueue);this._eventQueue.clear(),super.fire(this._mergeFn(e))}}else for(;!this._isPaused&&0!==this._eventQueue.size;)super.fire(this._eventQueue.shift())}fire(e){this._size&&(0!==this._isPaused?this._eventQueue.push(e):super.fire(e))}}t.PauseableEmitter=b,t.DebounceEmitter=class extends b{constructor(e){super(e),this._delay=e.delay??100}fire(e){this._handle||(this.pause(),this._handle=setTimeout((()=>{this._handle=void 0,this.resume()}),this._delay)),super.fire(e)}},t.MicrotaskEmitter=class extends g{constructor(e){super(e),this._queuedEvents=[],this._mergeFn=e?.merge}fire(e){this.hasListeners()&&(this._queuedEvents.push(e),1===this._queuedEvents.length&&queueMicrotask((()=>{this._mergeFn?super.fire(this._mergeFn(this._queuedEvents)):this._queuedEvents.forEach((e=>super.fire(e))),this._queuedEvents=[]})))}};class y{constructor(){this.hasListeners=!1,this.events=[],this.emitter=new g({onWillAddFirstListener:()=>this.onFirstListenerAdd(),onDidRemoveLastListener:()=>this.onLastListenerRemove()})}get event(){return this.emitter.event}add(e){const t={event:e,listener:null};return this.events.push(t),this.hasListeners&&this.hook(t),(0,n.toDisposable)((0,r.createSingleCallFunction)((()=>{this.hasListeners&&this.unhook(t);const e=this.events.indexOf(t);this.events.splice(e,1)})))}onFirstListenerAdd(){this.hasListeners=!0,this.events.forEach((e=>this.hook(e)))}onLastListenerRemove(){this.hasListeners=!1,this.events.forEach((e=>this.unhook(e)))}hook(e){e.listener=e.event((e=>this.emitter.fire(e)))}unhook(e){e.listener?.dispose(),e.listener=null}dispose(){this.emitter.dispose();for(const e of this.events)e.listener?.dispose();this.events=[]}}t.EventMultiplexer=y,t.DynamicListEventMultiplexer=class{constructor(e,t,s,i){this._store=new n.DisposableStore;const r=this._store.add(new y),o=this._store.add(new n.DisposableMap);function a(e){o.set(e,r.add(i(e)))}for(const t of e)a(t);this._store.add(t((e=>{a(e)}))),this._store.add(s((e=>{o.deleteAndDispose(e)}))),this.event=r.event}dispose(){this._store.dispose()}},t.EventBufferer=class{constructor(){this.data=[]}wrapEvent(e,t,s){return(i,r,n)=>e((e=>{const n=this.data[this.data.length-1];if(!t)return void(n?n.buffers.push((()=>i.call(r,e))):i.call(r,e));const o=n;o?(o.items??=[],o.items.push(e),0===o.buffers.length&&n.buffers.push((()=>{o.reducedResult??=s?o.items.reduce(t,s):o.items.reduce(t),i.call(r,o.reducedResult)}))):i.call(r,t(s,e))}),void 0,n)}bufferEvents(e){const t={buffers:new Array};this.data.push(t);const s=e();return this.data.pop(),t.buffers.forEach((e=>e())),s}},t.Relay=class{constructor(){this.listening=!1,this.inputEvent=l.None,this.inputEventListener=n.Disposable.None,this.emitter=new g({onDidAddFirstListener:()=>{this.listening=!0,this.inputEventListener=this.inputEvent(this.emitter.fire,this.emitter)},onDidRemoveLastListener:()=>{this.listening=!1,this.inputEventListener.dispose()}}),this.event=this.emitter.event}set input(e){this.inputEvent=e,this.listening&&(this.inputEventListener.dispose(),this.inputEventListener=e(this.emitter.fire,this.emitter))}dispose(){this.inputEventListener.dispose(),this.emitter.dispose()}},t.ValueWithChangeEvent=class{static const(e){return new w(e)}constructor(e){this._value=e,this._onDidChange=new g,this.onDidChange=this._onDidChange.event}get value(){return this._value}set value(e){e!==this._value&&(this._value=e,this._onDidChange.fire(void 0))}};class w{constructor(e){this.value=e,this.onDidChange=l.None}}},355:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.createSingleCallFunction=function(e,t){const s=this;let i,r=!1;return function(){if(r)return i;if(r=!0,t)try{i=e.apply(s,arguments)}finally{t()}else i=e.apply(s,arguments);return i}}},956:(e,t)=>{var s;Object.defineProperty(t,"__esModule",{value:!0}),t.Iterable=void 0,function(e){function t(e){return e&&"object"==typeof e&&"function"==typeof e[Symbol.iterator]}e.is=t;const s=Object.freeze([]);function*i(e){yield e}e.empty=function(){return s},e.single=i,e.wrap=function(e){return t(e)?e:i(e)},e.from=function(e){return e||s},e.reverse=function*(e){for(let t=e.length-1;t>=0;t--)yield e[t]},e.isEmpty=function(e){return!e||!0===e[Symbol.iterator]().next().done},e.first=function(e){return e[Symbol.iterator]().next().value},e.some=function(e,t){let s=0;for(const i of e)if(t(i,s++))return!0;return!1},e.find=function(e,t){for(const s of e)if(t(s))return s},e.filter=function*(e,t){for(const s of e)t(s)&&(yield s)},e.map=function*(e,t){let s=0;for(const i of e)yield t(i,s++)},e.flatMap=function*(e,t){let s=0;for(const i of e)yield*t(i,s++)},e.concat=function*(...e){for(const t of e)yield*t},e.reduce=function(e,t,s){let i=s;for(const s of e)i=t(i,s);return i},e.slice=function*(e,t,s=e.length){for(t<0&&(t+=e.length),s<0?s+=e.length:s>e.length&&(s=e.length);t<s;t++)yield e[t]},e.consume=function(t,s=Number.POSITIVE_INFINITY){const i=[];if(0===s)return[i,t];const r=t[Symbol.iterator]();for(let t=0;t<s;t++){const t=r.next();if(t.done)return[i,e.empty()];i.push(t.value)}return[i,{[Symbol.iterator]:()=>r}]},e.asyncToArray=async function(e){const t=[];for await(const s of e)t.push(s);return Promise.resolve(t)}}(s||(t.Iterable=s={}))},764:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.Lazy=void 0,t.Lazy=class{constructor(e){this.executor=e,this._didRun=!1}get hasValue(){return this._didRun}get value(){if(!this._didRun)try{this._value=this.executor()}catch(e){this._error=e}finally{this._didRun=!0}if(this._error)throw this._error;return this._value}get rawValue(){return this._value}}},540:(e,t,s)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.DisposableMap=t.ImmortalReference=t.AsyncReferenceCollection=t.ReferenceCollection=t.SafeDisposable=t.RefCountedDisposable=t.MandatoryMutableDisposable=t.MutableDisposable=t.Disposable=t.DisposableStore=t.DisposableTracker=void 0,t.setDisposableTracker=function(e){l=e},t.trackDisposable=c,t.markAsDisposed=u,t.markAsSingleton=function(e){return l?.markAsSingleton(e),e},t.isDisposable=f,t.dispose=p,t.disposeIfDisposable=function(e){for(const t of e)f(t)&&t.dispose();return[]},t.combinedDisposable=function(...e){const t=_((()=>p(e)));return function(e,t){if(l)for(const s of e)l.setParent(s,t)}(e,t),t},t.toDisposable=_,t.disposeOnReturn=function(e){const t=new m;try{e(t)}finally{t.dispose()}};const i=s(732),r=s(33),n=s(714),o=s(355),a=s(956);let l=null;class h{constructor(){this.livingDisposables=new Map}static{this.idx=0}getDisposableData(e){let t=this.livingDisposables.get(e);return t||(t={parent:null,source:null,isSingleton:!1,value:e,idx:h.idx++},this.livingDisposables.set(e,t)),t}trackDisposable(e){const t=this.getDisposableData(e);t.source||(t.source=(new Error).stack)}setParent(e,t){this.getDisposableData(e).parent=t}markAsDisposed(e){this.livingDisposables.delete(e)}markAsSingleton(e){this.getDisposableData(e).isSingleton=!0}getRootParent(e,t){const s=t.get(e);if(s)return s;const i=e.parent?this.getRootParent(this.getDisposableData(e.parent),t):e;return t.set(e,i),i}getTrackedDisposables(){const e=new Map;return[...this.livingDisposables.entries()].filter((([,t])=>null!==t.source&&!this.getRootParent(t,e).isSingleton)).flatMap((([e])=>e))}computeLeakingDisposables(e=10,t){let s;if(t)s=t;else{const e=new Map,t=[...this.livingDisposables.values()].filter((t=>null!==t.source&&!this.getRootParent(t,e).isSingleton));if(0===t.length)return;const i=new Set(t.map((e=>e.value)));if(s=t.filter((e=>!(e.parent&&i.has(e.parent)))),0===s.length)throw new Error("There are cyclic diposable chains!")}if(!s)return;function o(e){const t=e.source.split("\n").map((e=>e.trim().replace("at ",""))).filter((e=>""!==e));return function(e,t){for(;e.length>0&&t.some((t=>"string"==typeof t?t===e[0]:e[0].match(t)));)e.shift()}(t,["Error",/^trackDisposable \(.*\)$/,/^DisposableTracker.trackDisposable \(.*\)$/]),t.reverse()}const a=new n.SetMap;for(const e of s){const t=o(e);for(let s=0;s<=t.length;s++)a.add(t.slice(0,s).join("\n"),e)}s.sort((0,i.compareBy)((e=>e.idx),i.numberComparator));let l="",h=0;for(const t of s.slice(0,e)){h++;const e=o(t),i=[];for(let t=0;t<e.length;t++){let n=e[t];n=`(shared with ${a.get(e.slice(0,t+1).join("\n")).size}/${s.length} leaks) at ${n}`;const l=a.get(e.slice(0,t).join("\n")),h=(0,r.groupBy)([...l].map((e=>o(e)[t])),(e=>e));delete h[e[t]];for(const[e,t]of Object.entries(h))i.unshift(` - stacktraces of ${t.length} other leaks continue with ${e}`);i.unshift(n)}l+=`\n\n\n==================== Leaking disposable ${h}/${s.length}: ${t.value.constructor.name} ====================\n${i.join("\n")}\n============================================================\n\n`}return s.length>e&&(l+=`\n\n\n... and ${s.length-e} more leaking disposables\n\n`),{leaks:s,details:l}}}function c(e){return l?.trackDisposable(e),e}function u(e){l?.markAsDisposed(e)}function d(e,t){l?.setParent(e,t)}function f(e){return"object"==typeof e&&null!==e&&"function"==typeof e.dispose&&0===e.dispose.length}function p(e){if(a.Iterable.is(e)){const t=[];for(const s of e)if(s)try{s.dispose()}catch(e){t.push(e)}if(1===t.length)throw t[0];if(t.length>1)throw new AggregateError(t,"Encountered errors while disposing of store");return Array.isArray(e)?[]:e}if(e)return e.dispose(),e}function _(e){const t=c({dispose:(0,o.createSingleCallFunction)((()=>{u(t),e()}))});return t}t.DisposableTracker=h;class m{static{this.DISABLE_DISPOSED_WARNING=!1}constructor(){this._toDispose=new Set,this._isDisposed=!1,c(this)}dispose(){this._isDisposed||(u(this),this._isDisposed=!0,this.clear())}get isDisposed(){return this._isDisposed}clear(){if(0!==this._toDispose.size)try{p(this._toDispose)}finally{this._toDispose.clear()}}add(e){if(!e)return e;if(e===this)throw new Error("Cannot register a disposable on itself!");return d(e,this),this._isDisposed?m.DISABLE_DISPOSED_WARNING||console.warn(new Error("Trying to add a disposable to a DisposableStore that has already been disposed of. The added object will be leaked!").stack):this._toDispose.add(e),e}delete(e){if(e){if(e===this)throw new Error("Cannot dispose a disposable on itself!");this._toDispose.delete(e),e.dispose()}}deleteAndLeak(e){e&&this._toDispose.has(e)&&(this._toDispose.delete(e),d(e,null))}}t.DisposableStore=m;class g{static{this.None=Object.freeze({dispose(){}})}constructor(){this._store=new m,c(this),d(this._store,this)}dispose(){u(this),this._store.dispose()}_register(e){if(e===this)throw new Error("Cannot register a disposable on itself!");return this._store.add(e)}}t.Disposable=g;class v{constructor(){this._isDisposed=!1,c(this)}get value(){return this._isDisposed?void 0:this._value}set value(e){this._isDisposed||e===this._value||(this._value?.dispose(),e&&d(e,this),this._value=e)}clear(){this.value=void 0}dispose(){this._isDisposed=!0,u(this),this._value?.dispose(),this._value=void 0}clearAndLeak(){const e=this._value;return this._value=void 0,e&&d(e,null),e}}t.MutableDisposable=v,t.MandatoryMutableDisposable=class{constructor(e){this._disposable=new v,this._isDisposed=!1,this._disposable.value=e}get value(){return this._disposable.value}set value(e){this._isDisposed||e===this._disposable.value||(this._disposable.value=e)}dispose(){this._isDisposed=!0,this._disposable.dispose()}},t.RefCountedDisposable=class{constructor(e){this._disposable=e,this._counter=1}acquire(){return this._counter++,this}release(){return 0==--this._counter&&this._disposable.dispose(),this}},t.SafeDisposable=class{constructor(){this.dispose=()=>{},this.unset=()=>{},this.isset=()=>!1,c(this)}set(e){let t=e;return this.unset=()=>t=void 0,this.isset=()=>void 0!==t,this.dispose=()=>{t&&(t(),t=void 0,u(this))},this}},t.ReferenceCollection=class{constructor(){this.references=new Map}acquire(e,...t){let s=this.references.get(e);s||(s={counter:0,object:this.createReferencedObject(e,...t)},this.references.set(e,s));const{object:i}=s,r=(0,o.createSingleCallFunction)((()=>{0==--s.counter&&(this.destroyReferencedObject(e,s.object),this.references.delete(e))}));return s.counter++,{object:i,dispose:r}}},t.AsyncReferenceCollection=class{constructor(e){this.referenceCollection=e}async acquire(e,...t){const s=this.referenceCollection.acquire(e,...t);try{return{object:await s.object,dispose:()=>s.dispose()}}catch(e){throw s.dispose(),e}}},t.ImmortalReference=class{constructor(e){this.object=e}dispose(){}};class b{constructor(){this._store=new Map,this._isDisposed=!1,c(this)}dispose(){u(this),this._isDisposed=!0,this.clearAndDisposeAll()}clearAndDisposeAll(){if(this._store.size)try{p(this._store.values())}finally{this._store.clear()}}has(e){return this._store.has(e)}get size(){return this._store.size}get(e){return this._store.get(e)}set(e,t,s=!1){this._isDisposed&&console.warn(new Error("Trying to add a disposable to a DisposableMap that has already been disposed of. The added object will be leaked!").stack),s||this._store.get(e)?.dispose(),this._store.set(e,t)}deleteAndDispose(e){this._store.get(e)?.dispose(),this._store.delete(e)}deleteAndLeak(e){const t=this._store.get(e);return this._store.delete(e),t}keys(){return this._store.keys()}values(){return this._store.values()}[Symbol.iterator](){return this._store[Symbol.iterator]()}}t.DisposableMap=b},711:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.LinkedList=void 0;class s{static{this.Undefined=new s(void 0)}constructor(e){this.element=e,this.next=s.Undefined,this.prev=s.Undefined}}class i{constructor(){this._first=s.Undefined,this._last=s.Undefined,this._size=0}get size(){return this._size}isEmpty(){return this._first===s.Undefined}clear(){let e=this._first;for(;e!==s.Undefined;){const t=e.next;e.prev=s.Undefined,e.next=s.Undefined,e=t}this._first=s.Undefined,this._last=s.Undefined,this._size=0}unshift(e){return this._insert(e,!1)}push(e){return this._insert(e,!0)}_insert(e,t){const i=new s(e);if(this._first===s.Undefined)this._first=i,this._last=i;else if(t){const e=this._last;this._last=i,i.prev=e,e.next=i}else{const e=this._first;this._first=i,i.next=e,e.prev=i}this._size+=1;let r=!1;return()=>{r||(r=!0,this._remove(i))}}shift(){if(this._first!==s.Undefined){const e=this._first.element;return this._remove(this._first),e}}pop(){if(this._last!==s.Undefined){const e=this._last.element;return this._remove(this._last),e}}_remove(e){if(e.prev!==s.Undefined&&e.next!==s.Undefined){const t=e.prev;t.next=e.next,e.next.prev=t}else e.prev===s.Undefined&&e.next===s.Undefined?(this._first=s.Undefined,this._last=s.Undefined):e.next===s.Undefined?(this._last=this._last.prev,this._last.next=s.Undefined):e.prev===s.Undefined&&(this._first=this._first.next,this._first.prev=s.Undefined);this._size-=1}*[Symbol.iterator](){let e=this._first;for(;e!==s.Undefined;)yield e.element,e=e.next}}t.LinkedList=i},714:(e,t)=>{var s;Object.defineProperty(t,"__esModule",{value:!0}),t.SetMap=t.BidirectionalMap=t.CounterSet=t.Touch=void 0,t.getOrSet=function(e,t,s){let i=e.get(t);return void 0===i&&(i=s,e.set(t,i)),i},t.mapToString=function(e){const t=[];return e.forEach(((e,s)=>{t.push(`${s} => ${e}`)})),`Map(${e.size}) {${t.join(", ")}}`},t.setToString=function(e){const t=[];return e.forEach((e=>{t.push(e)})),`Set(${e.size}) {${t.join(", ")}}`},t.mapsStrictEqualIgnoreOrder=function(e,t){if(e===t)return!0;if(e.size!==t.size)return!1;for(const[s,i]of e)if(!t.has(s)||t.get(s)!==i)return!1;for(const[s]of t)if(!e.has(s))return!1;return!0},function(e){e[e.None=0]="None",e[e.AsOld=1]="AsOld",e[e.AsNew=2]="AsNew"}(s||(t.Touch=s={})),t.CounterSet=class{constructor(){this.map=new Map}add(e){return this.map.set(e,(this.map.get(e)||0)+1),this}delete(e){let t=this.map.get(e)||0;return 0!==t&&(t--,0===t?this.map.delete(e):this.map.set(e,t),!0)}has(e){return this.map.has(e)}},t.BidirectionalMap=class{constructor(e){if(this._m1=new Map,this._m2=new Map,e)for(const[t,s]of e)this.set(t,s)}clear(){this._m1.clear(),this._m2.clear()}set(e,t){this._m1.set(e,t),this._m2.set(t,e)}get(e){return this._m1.get(e)}getKey(e){return this._m2.get(e)}delete(e){const t=this._m1.get(e);return void 0!==t&&(this._m1.delete(e),this._m2.delete(t),!0)}forEach(e,t){this._m1.forEach(((s,i)=>{e.call(t,s,i,this)}))}keys(){return this._m1.keys()}values(){return this._m1.values()}},t.SetMap=class{constructor(){this.map=new Map}add(e,t){let s=this.map.get(e);s||(s=new Set,this.map.set(e,s)),s.add(t)}delete(e,t){const s=this.map.get(e);s&&(s.delete(t),0===s.size&&this.map.delete(e))}forEach(e,t){const s=this.map.get(e);s&&s.forEach(t)}get(e){return this.map.get(e)||new Set}}},973:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.isAndroid=t.isEdge=t.isSafari=t.isFirefox=t.isChrome=t.OS=t.OperatingSystem=t.setTimeout0=t.setTimeout0IsFaster=t.translationsConfigFile=t.platformLocale=t.locale=t.Language=t.language=t.userAgent=t.platform=t.isCI=t.isMobile=t.isIOS=t.webWorkerOrigin=t.isWebWorker=t.isWeb=t.isElectron=t.isNative=t.isLinuxSnap=t.isLinux=t.isMacintosh=t.isWindows=t.Platform=t.LANGUAGE_DEFAULT=void 0,t.PlatformToString=function(e){switch(e){case w.Web:return"Web";case w.Mac:return"Mac";case w.Linux:return"Linux";case w.Windows:return"Windows"}},t.isLittleEndian=function(){if(!C){C=!0;const e=new Uint8Array(2);e[0]=1,e[1]=2;const t=new Uint16Array(e.buffer);k=513===t[0]}return k},t.isBigSurOrNewer=function(e){return parseFloat(e)>=20},t.LANGUAGE_DEFAULT="en";let s,i,r,n=!1,o=!1,a=!1,l=!1,h=!1,c=!1,u=!1,d=!1,f=!1,p=!1,_=t.LANGUAGE_DEFAULT,m=t.LANGUAGE_DEFAULT;const g=globalThis;let v;void 0!==g.vscode&&void 0!==g.vscode.process?v=g.vscode.process:"undefined"!=typeof process&&"string"==typeof process?.versions?.node&&(v=process);const b="string"==typeof v?.versions?.electron,y=b&&"renderer"===v?.type;if("object"==typeof v){n="win32"===v.platform,o="darwin"===v.platform,a="linux"===v.platform,l=a&&!!v.env.SNAP&&!!v.env.SNAP_REVISION,u=b,f=!!v.env.CI||!!v.env.BUILD_ARTIFACTSTAGINGDIRECTORY,s=t.LANGUAGE_DEFAULT,_=t.LANGUAGE_DEFAULT;const e=v.env.VSCODE_NLS_CONFIG;if(e)try{const r=JSON.parse(e);s=r.userLocale,m=r.osLocale,_=r.resolvedLanguage||t.LANGUAGE_DEFAULT,i=r.languagePack?.translationsConfigFile}catch(e){}h=!0}else"object"!=typeof navigator||y?console.error("Unable to resolve platform."):(r=navigator.userAgent,n=r.indexOf("Windows")>=0,o=r.indexOf("Macintosh")>=0,d=(r.indexOf("Macintosh")>=0||r.indexOf("iPad")>=0||r.indexOf("iPhone")>=0)&&!!navigator.maxTouchPoints&&navigator.maxTouchPoints>0,a=r.indexOf("Linux")>=0,p=r?.indexOf("Mobi")>=0,c=!0,_=globalThis._VSCODE_NLS_LANGUAGE||t.LANGUAGE_DEFAULT,s=navigator.language.toLowerCase(),m=s);var w;!function(e){e[e.Web=0]="Web",e[e.Mac=1]="Mac",e[e.Linux=2]="Linux",e[e.Windows=3]="Windows"}(w||(t.Platform=w={}));let D=w.Web;var S,E;o?D=w.Mac:n?D=w.Windows:a&&(D=w.Linux),t.isWindows=n,t.isMacintosh=o,t.isLinux=a,t.isLinuxSnap=l,t.isNative=h,t.isElectron=u,t.isWeb=c,t.isWebWorker=c&&"function"==typeof g.importScripts,t.webWorkerOrigin=t.isWebWorker?g.origin:void 0,t.isIOS=d,t.isMobile=p,t.isCI=f,t.platform=D,t.userAgent=r,t.language=_,function(e){e.value=function(){return t.language},e.isDefaultVariant=function(){return 2===t.language.length?"en"===t.language:t.language.length>=3&&"e"===t.language[0]&&"n"===t.language[1]&&"-"===t.language[2]},e.isDefault=function(){return"en"===t.language}}(S||(t.Language=S={})),t.locale=s,t.platformLocale=m,t.translationsConfigFile=i,t.setTimeout0IsFaster="function"==typeof g.postMessage&&!g.importScripts,t.setTimeout0=(()=>{if(t.setTimeout0IsFaster){const e=[];g.addEventListener("message",(t=>{if(t.data&&t.data.vscodeScheduleAsyncWork)for(let s=0,i=e.length;s<i;s++){const i=e[s];if(i.id===t.data.vscodeScheduleAsyncWork)return e.splice(s,1),void i.callback()}}));let t=0;return s=>{const i=++t;e.push({id:i,callback:s}),g.postMessage({vscodeScheduleAsyncWork:i},"*")}}return e=>setTimeout(e)})(),function(e){e[e.Windows=1]="Windows",e[e.Macintosh=2]="Macintosh",e[e.Linux=3]="Linux"}(E||(t.OperatingSystem=E={})),t.OS=o||d?E.Macintosh:n?E.Windows:E.Linux;let k=!0,C=!1;t.isChrome=!!(t.userAgent&&t.userAgent.indexOf("Chrome")>=0),t.isFirefox=!!(t.userAgent&&t.userAgent.indexOf("Firefox")>=0),t.isSafari=!!(!t.isChrome&&t.userAgent&&t.userAgent.indexOf("Safari")>=0),t.isEdge=!!(t.userAgent&&t.userAgent.indexOf("Edg/")>=0),t.isAndroid=!!(t.userAgent&&t.userAgent.indexOf("Android")>=0)},79:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.StopWatch=void 0;const s=globalThis.performance&&"function"==typeof globalThis.performance.now;class i{static create(e){return new i(e)}constructor(e){this._now=s&&!1===e?Date.now:globalThis.performance.now.bind(globalThis.performance),this._startTime=this._now(),this._stopTime=-1}stop(){this._stopTime=this._now()}reset(){this._startTime=this._now(),this._stopTime=-1}elapsed(){return-1!==this._stopTime?this._stopTime-this._startTime:this._now()-this._startTime}}t.StopWatch=i},329:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.MicrotaskDelay=void 0,t.MicrotaskDelay=Symbol("MicrotaskDelay")}},t={};function s(i){var r=t[i];if(void 0!==r)return r.exports;var n=t[i]={exports:{}};return e[i](n,n.exports,s),n.exports}var i={};return(()=>{var e=i;Object.defineProperty(e,"__esModule",{value:!0}),e.SearchAddon=void 0;const t=s(540),r=s(940),n=s(149),o=s(772),a=s(615),l=s(864),h=s(438);class c extends t.Disposable{get onDidChangeResults(){return this._resultTracker.onDidChangeResults}constructor(e){super(),this._highlightTimeout=this._register(new t.MutableDisposable),this._lineCache=this._register(new t.MutableDisposable),this._state=new o.SearchState,this._resultTracker=this._register(new h.SearchResultTracker),this._highlightLimit=e?.highlightLimit??1e3}activate(e){this._terminal=e,this._lineCache.value=new n.SearchLineCache(e),this._engine=new a.SearchEngine(e,this._lineCache.value),this._decorationManager=new l.DecorationManager(e),this._register(this._terminal.onWriteParsed((()=>this._updateMatches()))),this._register(this._terminal.onResize((()=>this._updateMatches()))),this._register((0,t.toDisposable)((()=>this.clearDecorations())))}_updateMatches(){this._highlightTimeout.clear(),this._state.cachedSearchTerm&&this._state.lastSearchOptions?.decorations&&(this._highlightTimeout.value=(0,r.disposableTimeout)((()=>{const e=this._state.cachedSearchTerm;this._state.clearCachedTerm(),this.findPrevious(e,{...this._state.lastSearchOptions,incremental:!0},{noScroll:!0})}),200))}clearDecorations(e){this._resultTracker.clearSelectedDecoration(),this._decorationManager?.clearHighlightDecorations(),this._resultTracker.clearResults(),e||this._state.clearCachedTerm()}clearActiveDecoration(){this._resultTracker.clearSelectedDecoration()}findNext(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);const i=this._findNextAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,i}_highlightAllMatches(e,t){if(!this._terminal||!this._engine||!this._decorationManager)throw new Error("Cannot use addon until it has been loaded");if(!this._state.isValidSearchTerm(e))return void this.clearDecorations();this.clearDecorations(!0);const s=[];let i,r=this._engine.find(e,0,0,t);for(;r&&(i?.row!==r.row||i?.col!==r.col)&&!(s.length>=this._highlightLimit);)i=r,s.push(i),r=this._engine.find(e,i.col+i.term.length>=this._terminal.cols?i.row+1:i.row,i.col+i.term.length>=this._terminal.cols?0:i.col+1,t);this._resultTracker.updateResults(s,this._highlightLimit),t.decorations&&this._decorationManager.createHighlightDecorations(s,t.decorations)}_findNextAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;const i=this._engine.findNextWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(i,t?.decorations,s?.noScroll)}findPrevious(e,t,s){if(!this._terminal||!this._engine)throw new Error("Cannot use addon until it has been loaded");this._state.lastSearchOptions=t,this._state.shouldUpdateHighlighting(e,t)&&this._highlightAllMatches(e,t);const i=this._findPreviousAndSelect(e,t,s);return this._fireResults(t),this._state.cachedSearchTerm=e,i}_fireResults(e){this._resultTracker.fireResultsChanged(!!e?.decorations)}_findPreviousAndSelect(e,t,s){if(!this._terminal||!this._engine)return!1;if(!this._state.isValidSearchTerm(e))return this._terminal.clearSelection(),this.clearDecorations(),!1;const i=this._engine.findPreviousWithSelection(e,t,this._state.cachedSearchTerm);return this._selectResult(i,t?.decorations,s?.noScroll)}_selectResult(e,t,s){if(!this._terminal||!this._decorationManager)return!1;if(this._resultTracker.clearSelectedDecoration(),!e)return this._terminal.clearSelection(),!1;if(this._terminal.select(e.col,e.row,e.size),t){const s=this._decorationManager.createActiveDecoration(e,t);s&&(this._resultTracker.selectedDecoration=s)}if(!s&&(e.row>=this._terminal.buffer.active.viewportY+this._terminal.rows||e.row<this._terminal.buffer.active.viewportY)){let t=e.row-this._terminal.buffer.active.viewportY;t-=Math.floor(this._terminal.rows/2),this._terminal.scrollLines(t)}return!0}}e.SearchAddon=c})(),i})()));
2
+ //# sourceMappingURL=addon-search.js.map
package/client.js CHANGED
@@ -161,6 +161,21 @@ window.__ModuleLoader__.load({
161
161
  'terminal.openDetails': ['打开主机详情', 'Open details'],
162
162
  'terminal.assetsError': ['终端组件加载失败:{message}。如果刚更新插件,请重启 DSH 后重试。', 'Could not load the terminal component: {message}. If the plugin was just updated, restart DSH and retry.'],
163
163
  'terminal.resyncFailed': ['终端输出曾中断,已尝试重新同步;如仍异常请重连。', 'Terminal output was interrupted; attempted a resync. Reconnect if problems persist.'],
164
+ 'terminal.search': ['搜索终端', 'Search terminal'],
165
+ 'terminal.searchNext': ['下一个', 'Next match'],
166
+ 'terminal.searchPrevious': ['上一个', 'Previous match'],
167
+ 'terminal.searchCase': ['区分大小写', 'Match case'],
168
+ 'terminal.searchClose': ['关闭搜索', 'Close search'],
169
+ 'terminal.fontSmaller': ['缩小字号', 'Smaller terminal font'],
170
+ 'terminal.fontLarger': ['放大字号', 'Larger terminal font'],
171
+ 'terminal.menu.copy': ['复制', 'Copy'],
172
+ 'terminal.menu.paste': ['粘贴', 'Paste'],
173
+ 'terminal.menu.selectAll': ['全选', 'Select all'],
174
+ 'terminal.menu.clear': ['清屏', 'Clear'],
175
+ 'terminal.menu.title': ['终端菜单', 'Terminal menu'],
176
+ 'terminal.searchUnavailable': ['终端搜索加载失败,请重启 DSH 后重试。', 'Terminal search failed to load; restart DSH and retry.'],
177
+ 'terminal.copyFailed': ['复制失败,请检查浏览器剪贴板权限。', 'Copy failed; check browser clipboard permissions.'],
178
+ 'terminal.pasteFailed': ['粘贴失败,请检查浏览器剪贴板权限。', 'Paste failed; check browser clipboard permissions.'],
164
179
  'terminal.backendHint': ['无法连接到插件后端。如果刚更新插件,请重启 DSH 后重试。', 'Cannot reach the plugin backend. If the plugin was just updated, restart DSH and retry.'],
165
180
  'terminal.passwordMissing': ['该主机还没有保存密码,请先打开「主机详情」设置服务器密码。', 'No password stored for this host. Open Details and set the server password first.'],
166
181
  'drawer.exit': ['退出码 {code}', 'exit {code}'],
@@ -1152,6 +1167,25 @@ window.__ModuleLoader__.load({
1152
1167
  }
1153
1168
  }
1154
1169
 
1170
+ const TERMINAL_FONT_KEY = 'dsh-ssh-manage:terminal-font-size'
1171
+ const TERMINAL_FONT_MIN = 10
1172
+ const TERMINAL_FONT_MAX = 20
1173
+
1174
+ function clampTerminalFontSize(value) {
1175
+ const numeric = Number(value)
1176
+ if (!Number.isFinite(numeric)) return 13
1177
+ return Math.min(TERMINAL_FONT_MAX, Math.max(TERMINAL_FONT_MIN, Math.round(numeric)))
1178
+ }
1179
+
1180
+ function readTerminalFontSize() {
1181
+ try {
1182
+ const stored = window.localStorage.getItem(TERMINAL_FONT_KEY)
1183
+ return stored === null ? 13 : clampTerminalFontSize(stored)
1184
+ } catch {
1185
+ return 13
1186
+ }
1187
+ }
1188
+
1155
1189
  function App({ ctx }) {
1156
1190
  const t = useT(ctx)
1157
1191
  const localeId = useLocaleId(ctx)
@@ -1187,6 +1221,7 @@ window.__ModuleLoader__.load({
1187
1221
  )
1188
1222
  const [activeSessionId, setActiveSessionId] = React.useState(() => persistentPanelState.activeSessionId)
1189
1223
  const [treeWidth, setTreeWidth] = React.useState(readTreeWidth)
1224
+ const [terminalFontSize, setTerminalFontSize] = React.useState(readTerminalFontSize)
1190
1225
  const [clearSignals, setClearSignals] = React.useState({})
1191
1226
  const [sessionStates, setSessionStates] = React.useState({})
1192
1227
  const toastTimer = React.useRef(null)
@@ -1226,6 +1261,12 @@ window.__ModuleLoader__.load({
1226
1261
  } catch {}
1227
1262
  }, [treeWidth])
1228
1263
 
1264
+ React.useEffect(() => {
1265
+ try {
1266
+ window.localStorage.setItem(TERMINAL_FONT_KEY, String(terminalFontSize))
1267
+ } catch {}
1268
+ }, [terminalFontSize])
1269
+
1229
1270
  React.useEffect(() => {
1230
1271
  for (const session of sessions) ptyActiveIds.add(session.id)
1231
1272
  }, [sessions])
@@ -1717,6 +1758,8 @@ window.__ModuleLoader__.load({
1717
1758
  groupsCloseGuard,
1718
1759
  treeWidth,
1719
1760
  setTreeWidth,
1761
+ terminalFontSize,
1762
+ setTerminalFontSize,
1720
1763
  sessions,
1721
1764
  activeSessionId,
1722
1765
  sessionStates,
@@ -2833,6 +2876,24 @@ window.__ModuleLoader__.load({
2833
2876
  },
2834
2877
  h(IconServer, { size: 15 }),
2835
2878
  ),
2879
+ h(
2880
+ IconButton,
2881
+ {
2882
+ title: t('terminal.fontSmaller'),
2883
+ disabled: model.terminalFontSize <= TERMINAL_FONT_MIN,
2884
+ onClick: () => model.setTerminalFontSize((value) => Math.max(TERMINAL_FONT_MIN, value - 1)),
2885
+ },
2886
+ h('span', { className: 'ssh-fontGlyph' }, 'A−'),
2887
+ ),
2888
+ h(
2889
+ IconButton,
2890
+ {
2891
+ title: t('terminal.fontLarger'),
2892
+ disabled: model.terminalFontSize >= TERMINAL_FONT_MAX,
2893
+ onClick: () => model.setTerminalFontSize((value) => Math.min(TERMINAL_FONT_MAX, value + 1)),
2894
+ },
2895
+ h('span', { className: 'ssh-fontGlyph' }, 'A+'),
2896
+ ),
2836
2897
  h(
2837
2898
  IconButton,
2838
2899
  {
@@ -2869,6 +2930,7 @@ window.__ModuleLoader__.load({
2869
2930
  model,
2870
2931
  host,
2871
2932
  sessionId: session.id,
2933
+ fontSize: model.terminalFontSize,
2872
2934
  clearSignal: clearSignals[session.id] ?? 0,
2873
2935
  active: isVisible && session.id === activeSession.id,
2874
2936
  })
@@ -2969,6 +3031,14 @@ window.__ModuleLoader__.load({
2969
3031
  css: 'dsh-ssh-manage-xterm-css',
2970
3032
  script: 'dsh-ssh-manage-xterm-script',
2971
3033
  fit: 'dsh-ssh-manage-xterm-fit',
3034
+ search: 'dsh-ssh-manage-xterm-search',
3035
+ }
3036
+
3037
+ function terminalAssetReady(id) {
3038
+ if (id === TERMINAL_ASSET_IDS.script) return Boolean(window.Terminal)
3039
+ if (id === TERMINAL_ASSET_IDS.fit) return Boolean(window.FitAddon && window.FitAddon.FitAddon)
3040
+ if (id === TERMINAL_ASSET_IDS.search) return Boolean(window.SearchAddon && window.SearchAddon.SearchAddon)
3041
+ return false
2972
3042
  }
2973
3043
  let terminalAssetsPromise = null
2974
3044
 
@@ -2976,10 +3046,7 @@ window.__ModuleLoader__.load({
2976
3046
  return new Promise((resolve, reject) => {
2977
3047
  const existing = document.getElementById(id)
2978
3048
  if (existing) {
2979
- const ready =
2980
- id === TERMINAL_ASSET_IDS.script
2981
- ? Boolean(window.Terminal)
2982
- : Boolean(window.FitAddon && window.FitAddon.FitAddon)
3049
+ const ready = terminalAssetReady(id)
2983
3050
  if (ready) {
2984
3051
  resolve()
2985
3052
  return
@@ -3003,8 +3070,12 @@ window.__ModuleLoader__.load({
3003
3070
  }
3004
3071
 
3005
3072
  function loadTerminalAssets() {
3006
- if (window.Terminal && window.FitAddon && window.FitAddon.FitAddon) {
3007
- return Promise.resolve({ Terminal: window.Terminal, FitAddon: window.FitAddon.FitAddon })
3073
+ if (window.Terminal && window.FitAddon && window.FitAddon.FitAddon && window.SearchAddon?.SearchAddon) {
3074
+ return Promise.resolve({
3075
+ Terminal: window.Terminal,
3076
+ FitAddon: window.FitAddon.FitAddon,
3077
+ SearchAddon: window.SearchAddon.SearchAddon,
3078
+ })
3008
3079
  }
3009
3080
  if (terminalAssetsPromise) return terminalAssetsPromise
3010
3081
  if (!document.getElementById(TERMINAL_ASSET_IDS.css)) {
@@ -3016,9 +3087,17 @@ window.__ModuleLoader__.load({
3016
3087
  }
3017
3088
  terminalAssetsPromise = loadScriptAsset(TERMINAL_ASSET_IDS.script, '/dsh-ssh-manage/assets/xterm.js')
3018
3089
  .then(() => loadScriptAsset(TERMINAL_ASSET_IDS.fit, '/dsh-ssh-manage/assets/addon-fit.js'))
3090
+ // Search is optional: a missing/blocked addon must not break the terminal.
3091
+ .then(() => loadScriptAsset(TERMINAL_ASSET_IDS.search, '/dsh-ssh-manage/assets/addon-search.js').catch(() => null))
3019
3092
  .then(() => {
3020
- if (!window.Terminal || !window.FitAddon || !window.FitAddon.FitAddon) throw new Error('Terminal assets did not initialize')
3021
- return { Terminal: window.Terminal, FitAddon: window.FitAddon.FitAddon }
3093
+ if (!window.Terminal || !window.FitAddon || !window.FitAddon.FitAddon) {
3094
+ throw new Error('Terminal assets did not initialize')
3095
+ }
3096
+ return {
3097
+ Terminal: window.Terminal,
3098
+ FitAddon: window.FitAddon.FitAddon,
3099
+ SearchAddon: window.SearchAddon?.SearchAddon ?? null,
3100
+ }
3022
3101
  })
3023
3102
  .catch((error) => {
3024
3103
  terminalAssetsPromise = null
@@ -3315,6 +3394,29 @@ window.__ModuleLoader__.load({
3315
3394
  void ptyPost(PTY_CLEAR_ROUTE, { id }, 15_000).catch(() => {})
3316
3395
  }
3317
3396
 
3397
+ async function copyTextToClipboard(text) {
3398
+ if (!text) return false
3399
+ try {
3400
+ if (navigator.clipboard?.writeText) {
3401
+ await navigator.clipboard.writeText(text)
3402
+ return true
3403
+ }
3404
+ } catch {}
3405
+ try {
3406
+ const textarea = document.createElement('textarea')
3407
+ textarea.value = text
3408
+ textarea.style.position = 'fixed'
3409
+ textarea.style.opacity = '0'
3410
+ document.body.appendChild(textarea)
3411
+ textarea.select()
3412
+ const copied = document.execCommand('copy')
3413
+ textarea.remove()
3414
+ return copied
3415
+ } catch {
3416
+ return false
3417
+ }
3418
+ }
3419
+
3318
3420
  function decodeBase64(text) {
3319
3421
  const binary = atob(String(text ?? ''))
3320
3422
  const bytes = new Uint8Array(binary.length)
@@ -3322,15 +3424,25 @@ window.__ModuleLoader__.load({
3322
3424
  return bytes
3323
3425
  }
3324
3426
 
3325
- function TerminalPane({ model, host, sessionId, active, clearSignal }) {
3427
+ function TerminalPane({ model, host, sessionId, active, clearSignal, fontSize }) {
3326
3428
  const { t } = model
3327
3429
  const hostRef = React.useRef(host)
3328
3430
  hostRef.current = host
3329
3431
  const containerRef = React.useRef(null)
3330
3432
  const termRef = React.useRef(null)
3331
3433
  const fitRef = React.useRef(null)
3434
+ const searchAddonRef = React.useRef(null)
3435
+ const searchInputRef = React.useRef(null)
3436
+ const menuRef = React.useRef(null)
3437
+ const fontSizeRef = React.useRef(fontSize)
3438
+ fontSizeRef.current = fontSize
3332
3439
  const activeRef = React.useRef(active === true)
3333
3440
  const [status, setStatus] = React.useState('loading')
3441
+ const [searchOpen, setSearchOpen] = React.useState(false)
3442
+ const searchOpenRef = React.useRef(false)
3443
+ const [searchText, setSearchText] = React.useState('')
3444
+ const [searchCase, setSearchCase] = React.useState(false)
3445
+ const [menu, setMenu] = React.useState(null)
3334
3446
  const [message, setMessage] = React.useState('')
3335
3447
  const [retryToken, setRetryToken] = React.useState(0)
3336
3448
  const clearRequested = React.useRef(false)
@@ -3370,6 +3482,131 @@ window.__ModuleLoader__.load({
3370
3482
  } catch {}
3371
3483
  }, [clearSignal])
3372
3484
 
3485
+ React.useEffect(() => {
3486
+ const term = termRef.current
3487
+ if (!term) return
3488
+ try {
3489
+ if (term.options.fontSize !== fontSize) {
3490
+ term.options.fontSize = fontSize
3491
+ fitRef.current?.fit()
3492
+ }
3493
+ } catch {}
3494
+ }, [fontSize])
3495
+
3496
+ const openSearch = () => {
3497
+ if (!searchAddonRef.current) {
3498
+ try { model.notify?.(t('terminal.searchUnavailable'), 'error') } catch {}
3499
+ return
3500
+ }
3501
+ searchOpenRef.current = true
3502
+ setSearchOpen(true)
3503
+ requestAnimationFrame(() => searchInputRef.current?.focus())
3504
+ }
3505
+
3506
+ const closeSearch = () => {
3507
+ searchOpenRef.current = false
3508
+ setSearchOpen(false)
3509
+ try { searchAddonRef.current?.clearDecorations?.() } catch {}
3510
+ try { termRef.current?.focus() } catch {}
3511
+ }
3512
+
3513
+ const findInTerminal = (direction, caseSensitive = searchCase) => {
3514
+ const addon = searchAddonRef.current
3515
+ const text = searchText.trim()
3516
+ if (!addon) return
3517
+ try {
3518
+ if (text === '') addon.clearDecorations?.()
3519
+ else if (direction < 0) addon.findPrevious(text, { caseSensitive })
3520
+ else addon.findNext(text, { caseSensitive })
3521
+ } catch {}
3522
+ }
3523
+
3524
+ const updateSearchText = (value) => {
3525
+ setSearchText(value)
3526
+ const addon = searchAddonRef.current
3527
+ if (!addon) return
3528
+ try {
3529
+ if (value.trim() === '') addon.clearDecorations?.()
3530
+ else addon.findNext(value.trim(), { caseSensitive: searchCase })
3531
+ } catch {}
3532
+ }
3533
+
3534
+ const terminalMenuAction = (action) => {
3535
+ const term = termRef.current
3536
+ setMenu(null)
3537
+ if (!term) return
3538
+ const refocus = () => {
3539
+ requestAnimationFrame(() => {
3540
+ try { termRef.current?.focus() } catch {}
3541
+ })
3542
+ }
3543
+ if (action === 'selectAll') {
3544
+ try { term.selectAll() } catch {}
3545
+ refocus()
3546
+ return
3547
+ }
3548
+ if (action === 'clear') {
3549
+ // Route through App so clearRequested/clearEpoch and the host buffer
3550
+ // stay in sync with the session-bar clear button.
3551
+ if (typeof model.clearSession === 'function') model.clearSession(sessionId)
3552
+ else clearPtySession(sessionId)
3553
+ try { term.clear(); term.write('\x1b[H\x1b[2J') } catch {}
3554
+ refocus()
3555
+ return
3556
+ }
3557
+ if (action === 'copy') {
3558
+ const text = term.getSelection()
3559
+ void copyTextToClipboard(text).then((ok) => {
3560
+ if (!ok) {
3561
+ try { model.notify?.(t('terminal.copyFailed'), 'error') } catch {}
3562
+ }
3563
+ refocus()
3564
+ })
3565
+ return
3566
+ }
3567
+ if (action === 'paste') {
3568
+ if (!navigator.clipboard?.readText) {
3569
+ try { model.notify?.(t('terminal.pasteFailed'), 'error') } catch {}
3570
+ refocus()
3571
+ return
3572
+ }
3573
+ navigator.clipboard.readText().then((text) => {
3574
+ if (text) {
3575
+ try { term.paste(text) } catch {}
3576
+ }
3577
+ refocus()
3578
+ }).catch(() => {
3579
+ try { model.notify?.(t('terminal.pasteFailed'), 'error') } catch {}
3580
+ refocus()
3581
+ })
3582
+ }
3583
+ }
3584
+
3585
+ React.useEffect(() => {
3586
+ if (!menu) return undefined
3587
+ const close = () => setMenu(null)
3588
+ const onKey = (event) => {
3589
+ if (event.key !== 'Escape') return
3590
+ event.preventDefault()
3591
+ event.stopPropagation()
3592
+ setMenu(null)
3593
+ try { termRef.current?.focus() } catch {}
3594
+ }
3595
+ const onDown = (event) => {
3596
+ if (menuRef.current && menuRef.current.contains(event.target)) return
3597
+ setMenu(null)
3598
+ }
3599
+ document.addEventListener('mousedown', onDown)
3600
+ document.addEventListener('keydown', onKey, true)
3601
+ requestAnimationFrame(() => {
3602
+ menuRef.current?.querySelector('button')?.focus()
3603
+ })
3604
+ return () => {
3605
+ document.removeEventListener('mousedown', onDown)
3606
+ document.removeEventListener('keydown', onKey, true)
3607
+ }
3608
+ }, [menu])
3609
+
3373
3610
  React.useEffect(() => {
3374
3611
  const container = containerRef.current
3375
3612
  if (!container) return undefined
@@ -3434,7 +3671,7 @@ window.__ModuleLoader__.load({
3434
3671
  term = new Terminal({
3435
3672
  cursorBlink: true,
3436
3673
  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace',
3437
- fontSize: 13,
3674
+ fontSize: fontSizeRef.current ?? 13,
3438
3675
  lineHeight: 1.2,
3439
3676
  scrollback: 5000,
3440
3677
  allowProposedApi: true,
@@ -3444,9 +3681,39 @@ window.__ModuleLoader__.load({
3444
3681
  })
3445
3682
  fit = new FitAddon()
3446
3683
  term.loadAddon(fit)
3684
+ if (assets.SearchAddon) {
3685
+ const searchAddon = new assets.SearchAddon()
3686
+ term.loadAddon(searchAddon)
3687
+ searchAddonRef.current = searchAddon
3688
+ }
3447
3689
  term.open(container)
3448
3690
  termRef.current = term
3449
3691
  fitRef.current = fit
3692
+ term.attachCustomKeyEventHandler((event) => {
3693
+ if (event.type !== 'keydown') return true
3694
+ const meta = event.metaKey || event.ctrlKey
3695
+ if (meta && event.key.toLowerCase() === 'f') {
3696
+ event.preventDefault()
3697
+ openSearch()
3698
+ return false
3699
+ }
3700
+ if (meta && (event.key === '=' || event.key === '+')) {
3701
+ event.preventDefault()
3702
+ model.setTerminalFontSize((value) => Math.min(TERMINAL_FONT_MAX, value + 1))
3703
+ return false
3704
+ }
3705
+ if (meta && (event.key === '-' || event.key === '_')) {
3706
+ event.preventDefault()
3707
+ model.setTerminalFontSize((value) => Math.max(TERMINAL_FONT_MIN, value - 1))
3708
+ return false
3709
+ }
3710
+ if (event.key === 'Escape' && searchOpenRef.current) {
3711
+ event.preventDefault()
3712
+ closeSearch()
3713
+ return false
3714
+ }
3715
+ return true
3716
+ })
3450
3717
  try { fit.fit() } catch {}
3451
3718
  themeUnsub = subscribeTerminalTheme(() => {
3452
3719
  if (removed || !term) return
@@ -3691,6 +3958,7 @@ window.__ModuleLoader__.load({
3691
3958
  }
3692
3959
  termRef.current = null
3693
3960
  fitRef.current = null
3961
+ searchAddonRef.current = null
3694
3962
  }
3695
3963
  }, [sessionId, retryToken])
3696
3964
 
@@ -3698,8 +3966,81 @@ window.__ModuleLoader__.load({
3698
3966
  const showOverlay = status !== 'ready'
3699
3967
  return h(
3700
3968
  'div',
3701
- { className: 'ssh-terminalPane' },
3969
+ {
3970
+ className: 'ssh-terminalPane',
3971
+ onContextMenu: (event) => {
3972
+ if (!termRef.current || status !== 'ready') return
3973
+ if (event.target?.closest?.('.ssh-terminalSearch')) return
3974
+ event.preventDefault()
3975
+ const rect = event.currentTarget.getBoundingClientRect()
3976
+ setMenu({
3977
+ x: Math.max(0, Math.min(event.clientX - rect.left, rect.width - 170)),
3978
+ y: Math.max(0, Math.min(event.clientY - rect.top, rect.height - 150)),
3979
+ })
3980
+ },
3981
+ onMouseDown: () => setMenu(null),
3982
+ },
3702
3983
  h('div', { className: 'ssh-terminalHost', ref: containerRef }),
3984
+ searchOpen
3985
+ ? h(
3986
+ 'div',
3987
+ {
3988
+ className: 'ssh-terminalSearch',
3989
+ onMouseDown: (event) => event.stopPropagation(),
3990
+ },
3991
+ h(IconSearch, { size: 13 }),
3992
+ h('input', {
3993
+ ref: searchInputRef,
3994
+ className: 'ssh-terminalSearchInput',
3995
+ value: searchText,
3996
+ placeholder: t('terminal.search'),
3997
+ 'aria-label': t('terminal.search'),
3998
+ onChange: (event) => updateSearchText(event.target.value),
3999
+ onKeyDown: (event) => {
4000
+ event.stopPropagation()
4001
+ if (event.key === 'Escape') closeSearch()
4002
+ else if (event.key === 'Enter') findInTerminal(event.shiftKey ? -1 : 1)
4003
+ },
4004
+ }),
4005
+ h('button', {
4006
+ type: 'button',
4007
+ className: cx('ssh-terminalSearchBtn', searchCase && 'on'),
4008
+ title: t('terminal.searchCase'),
4009
+ 'aria-pressed': searchCase,
4010
+ onMouseDown: (event) => event.preventDefault(),
4011
+ onClick: () => {
4012
+ const next = !searchCase
4013
+ setSearchCase(next)
4014
+ if (searchText.trim()) findInTerminal(1, next)
4015
+ },
4016
+ }, 'Aa'),
4017
+ h('button', { type: 'button', className: 'ssh-terminalSearchBtn', title: t('terminal.searchPrevious'), 'aria-label': t('terminal.searchPrevious'), onMouseDown: (event) => event.preventDefault(), onClick: () => findInTerminal(-1) }, h(IconChevronLeft, { size: 12 })),
4018
+ h('button', { type: 'button', className: 'ssh-terminalSearchBtn', title: t('terminal.searchNext'), 'aria-label': t('terminal.searchNext'), onMouseDown: (event) => event.preventDefault(), onClick: () => findInTerminal(1) }, h(IconChevronRight, { size: 12 })),
4019
+ h('button', { type: 'button', className: 'ssh-terminalSearchBtn', title: t('terminal.searchClose'), 'aria-label': t('terminal.searchClose'), onClick: closeSearch }, h(IconClose, { size: 12 })),
4020
+ )
4021
+ : null,
4022
+ menu
4023
+ ? h(
4024
+ 'div',
4025
+ {
4026
+ ref: menuRef,
4027
+ className: 'ssh-terminalMenu',
4028
+ role: 'menu',
4029
+ 'aria-label': t('terminal.menu.title'),
4030
+ style: { left: menu.x, top: menu.y },
4031
+ onMouseDown: (event) => event.stopPropagation(),
4032
+ },
4033
+ ['copy', 'paste', 'selectAll', 'clear'].map((action) =>
4034
+ h('button', {
4035
+ key: action,
4036
+ type: 'button',
4037
+ role: 'menuitem',
4038
+ className: 'ssh-terminalMenuItem',
4039
+ onClick: () => terminalMenuAction(action),
4040
+ }, t(`terminal.menu.${action}`)),
4041
+ ),
4042
+ )
4043
+ : null,
3703
4044
  showOverlay
3704
4045
  ? h(
3705
4046
  'div',
@@ -4949,6 +5290,16 @@ body.ssh-col-resizing,body.ssh-col-resizing *{cursor:col-resize!important;user-s
4949
5290
  .ssh-terminalOverlayActions{display:flex;gap:8px;flex-wrap:wrap;justify-content:center}
4950
5291
  .ssh-sessionLayer{flex:1;min-height:0;display:flex;flex-direction:column;background:var(--ssh-bg)}
4951
5292
  .ssh-sessionState{width:6px;height:6px;border-radius:50%;background:var(--ssh-dim);flex:0 0 auto}
5293
+ .ssh-fontGlyph{font-size:10.5px;font-weight:600;letter-spacing:-.4px}
5294
+ .ssh-terminalSearch{position:absolute;top:8px;right:18px;z-index:5;max-width:calc(100% - 24px);display:flex;align-items:center;gap:5px;padding:5px 7px;border:.5px solid var(--ssh-border-strong);border-radius:10px;background:var(--ssh-layer-1);box-shadow:var(--ssh-shadow);color:var(--ssh-text-3)}
5295
+ .ssh-terminalSearchInput{width:min(180px,42vw);max-width:100%;height:24px;padding:0 7px;border:.5px solid var(--ssh-border);border-radius:6px;background:var(--ssh-bg);color:var(--ssh-text);font:inherit;font-size:12px;outline:none}
5296
+ .ssh-terminalSearchInput:focus{border-color:var(--ssh-brand)}
5297
+ .ssh-terminalSearchBtn{appearance:none;display:inline-flex;align-items:center;justify-content:center;height:24px;min-width:24px;padding:0 5px;border:0;border-radius:6px;background:transparent;color:var(--ssh-text-2);font:inherit;font-size:11px;cursor:pointer}
5298
+ .ssh-terminalSearchBtn:hover{background:var(--ssh-hover);color:var(--ssh-text)}
5299
+ .ssh-terminalSearchBtn.on{background:color-mix(in srgb,var(--ssh-brand) 15%,transparent);color:var(--ssh-brand)}
5300
+ .ssh-terminalMenu{position:absolute;z-index:7;min-width:150px;padding:4px;border:.5px solid var(--ssh-border-strong);border-radius:9px;background:var(--ssh-layer-1);box-shadow:var(--ssh-shadow)}
5301
+ .ssh-terminalMenuItem{appearance:none;display:flex;align-items:center;width:100%;height:28px;padding:0 9px;border:0;border-radius:6px;background:transparent;color:var(--ssh-text-2);font:inherit;font-size:12px;text-align:left;cursor:pointer}
5302
+ .ssh-terminalMenuItem:hover{background:var(--ssh-hover);color:var(--ssh-text)}
4952
5303
  .ssh-sessionState.loading,.ssh-sessionState.connecting{background:var(--ssh-warn)}
4953
5304
  .ssh-sessionState.ready{background:var(--ssh-success)}
4954
5305
  .ssh-sessionState.error,.ssh-sessionState.closed{background:var(--ssh-danger)}
package/index.js CHANGED
@@ -28,6 +28,7 @@ const ASSETS = [
28
28
  { path: '/dsh-ssh-manage/assets/xterm.js', file: 'xterm.js', contentType: 'text/javascript; charset=utf-8' },
29
29
  { path: '/dsh-ssh-manage/assets/xterm.css', file: 'xterm.css', contentType: 'text/css; charset=utf-8' },
30
30
  { path: '/dsh-ssh-manage/assets/addon-fit.js', file: 'addon-fit.js', contentType: 'text/javascript; charset=utf-8' },
31
+ { path: '/dsh-ssh-manage/assets/addon-search.js', file: 'addon-search.js', contentType: 'text/javascript; charset=utf-8' },
31
32
  ]
32
33
  const MAX_BODY_BYTES = 16 * 1024 * 1024
33
34
  const ACTIONS = ['overview', 'list_hosts', 'save_host', 'delete_host', 'set_metadata', 'save_password', 'delete_password', 'test_connection', 'inspect_host', 'exec', 'batch_exec', 'sftp_list', 'sftp_upload', 'sftp_download']
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-ssh-manage",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "A DSH sidebar plugin for managing SSH host profiles with a real interactive PTY terminal.",
5
5
  "license": "MIT",
6
6
  "private": false,