tabby-bianbu-mcp 0.8.4 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  All notable changes to `tabby-bianbu-mcp` will be documented in this file.
4
4
 
5
+ ## [0.9.0] - 2026-03-23
6
+
7
+ ### Added
8
+ - **Maintenance progress UI**: step-by-step progress bar with 4 phases (Upload → Launch → Wait → Verify), animated step dots, percentage bar, elapsed timer, and status label
9
+ - **Cancel button**: abort a running upgrade/repair at any phase
10
+ - **Cancellation support**: `AbortSignal` propagated through upload and wait loops for clean cancellation
11
+ - **Chunk upload progress**: `uploadTextViaChunked` reports per-chunk byte progress to the UI
12
+ - **Consecutive-failure abort**: `waitForInstallerCompletion` aborts early after 10 consecutive health check failures instead of waiting for full timeout
13
+
14
+ ### Improved
15
+ - **Error display**: errors now show in a bordered red box with the failed step name prefixed (e.g. `[upload] connection refused`)
16
+ - **Error context**: error messages include which step failed, making debugging easier
17
+
18
+ ## [0.8.5] - 2026-03-23
19
+
20
+ ### Fixed
21
+ - **Installer upload E2BIG**: switched `pushInstallerAndUpgrade` from `writeTextFile` (single 88KB JSON-RPC payload) to chunked upload (32KB chunks), fixing `spawn E2BIG` on repair/upgrade
22
+
5
23
  ## [0.8.4] - 2026-03-23
6
24
 
7
25
  ### Changed (Remote MCP Server v1.5.0)
@@ -5,5 +5,5 @@
5
5
  "serverVersion": "1.5.0",
6
6
  "sha256": "6b70a7f973a8f4204ab012ff2b88875cebcf1e3912604c996f354ba64b323890",
7
7
  "bytes": 87798,
8
- "generatedAt": "2026-03-23T10:47:44.847Z"
8
+ "generatedAt": "2026-03-23T11:17:27.264Z"
9
9
  }
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@angular/common"),require("@angular/core"),require("@angular/forms"),require("fs"),require("tabby-core"),require("tabby-settings"),require("tabby-terminal"));else if("function"==typeof define&&define.amd)define(["@angular/common","@angular/core","@angular/forms","fs","tabby-core","tabby-settings","tabby-terminal"],t);else{var s="object"==typeof exports?t(require("@angular/common"),require("@angular/core"),require("@angular/forms"),require("fs"),require("tabby-core"),require("tabby-settings"),require("tabby-terminal")):t(e["@angular/common"],e["@angular/core"],e["@angular/forms"],e.fs,e["tabby-core"],e["tabby-settings"],e["tabby-terminal"]);for(var i in s)("object"==typeof exports?exports:e)[i]=s[i]}}(global,(e,t,s,i,n,o,r)=>{return a={102(e,t,s){var i=s(169);e.exports=(i.default||i).apply(i,[])},426(e,t,s){var i=s(295);e.exports=(i.default||i).apply(i,[])},169(e,t,s){s(766),e.exports=function(e){return""+'<div style="height:100%;display:flex;flex-direction:column;background:rgba(30,30,30,.96);color:#e4e4e4;font-family:&quot;Segoe UI Variable&quot;,&quot;Segoe UI&quot;,system-ui,-apple-system,sans-serif;font-size:13px;overflow:hidden"><div class="toolbar" style="display:flex;align-items:center;gap:6px;padding:6px 12px;background:rgba(255,255,255,.04);border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;min-height:40px"><div class="btn-group" style="display:flex;gap:2px;background:rgba(255,255,255,.06);border-radius:6px;padding:2px"><button type="button" (click)="goBack()" [disabled]="historyIndex &lt;= 0" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:14px;opacity:.8" title="Back">←</button><button type="button" (click)="goForward()" [disabled]="historyIndex &gt;= history.length - 1" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:14px;opacity:.8" title="Forward">→</button><button type="button" (click)="goUp()" [disabled]="currentPath === &quot;.&quot; || currentPath === &quot;/&quot;" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:14px;opacity:.8" title="Up">↑</button></div><div class="breadcrumbs" style="display:flex;align-items:center;gap:2px;flex:1;min-width:0;background:rgba(255,255,255,.05);border-radius:6px;padding:0 8px;height:30px;overflow:hidden"><span *ngFor="let crumb of breadcrumbs; let i = index" (click)="navigateBreadcrumb(i)" style="cursor:pointer;padding:2px 4px;border-radius:3px;white-space:nowrap;opacity:.85;font-size:12px" [style.font-weight]="i === breadcrumbs.length - 1 ? &quot;600&quot; : &quot;400&quot;">{{ crumb }}<span *ngIf="i &lt; breadcrumbs.length - 1" style="opacity:.4;margin-left:4px">›</span></span></div><input id="bianbu-path-input" type="text" [(ngModel)]="pathInput" (keyup.enter)="navigateToInput()" placeholder="Enter path…" style="width:200px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08);border-radius:6px;padding:4px 10px;color:#e4e4e4;font-size:12px;height:30px;outline:none"><div class="btn-group" style="display:flex;gap:2px;background:rgba(255,255,255,.06);border-radius:6px;padding:2px"><button type="button" (click)="refresh()" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:13px;opacity:.8" title="Refresh (F5)">⟳</button><button type="button" (click)="openCreateFilePrompt()" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:13px;opacity:.8" title="New file (Ctrl+N)">+📄</button><button type="button" (click)="openCreateDirectoryPrompt()" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:13px;opacity:.8" title="New folder (Ctrl+Shift+N)">+📁</button></div><label style="background:rgba(255,255,255,.06);border-radius:6px;padding:4px 10px;cursor:pointer;font-size:12px;height:30px;display:flex;align-items:center;gap:4px;opacity:.85">⬆ Upload<input type="file" multiple (change)="uploadFile($event)" style="display:none"></label><button type="button" (click)="toggleDetailPane()" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:13px;opacity:.8" [style.opacity]="detailPaneVisible ? &quot;1&quot; : &quot;.5&quot;" title="Toggle preview">☰</button><label style="display:flex;align-items:center;gap:4px;margin-left:4px;opacity:.7;font-size:11px;cursor:pointer"><input type="checkbox" [(ngModel)]="asRoot" (ngModelChange)="refresh()">root</label></div><div class="search-bar" style="display:flex;align-items:center;gap:8px;padding:4px 12px;flex-shrink:0"><input type="text" [(ngModel)]="searchText" (ngModelChange)="applyFilter()" placeholder="🔍 Filter files…" style="flex:1;max-width:280px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.06);border-radius:6px;padding:4px 10px;color:#e4e4e4;font-size:12px;height:28px;outline:none"><span style="opacity:.5;font-size:11px;white-space:nowrap">{{ filteredItems.length }} items</span><span *ngIf="selectionSummary" style="opacity:.5;font-size:11px">• {{ selectionSummary }}</span><span style="opacity:.5;font-size:11px;margin-left:auto">{{ totalSize }}</span></div><div class="main" style="flex:1;display:flex;overflow:hidden"><div class="file-list-pane" style="flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:300px" (dragover)="onDragOver($event)" (dragleave)="onDragLeave()" (drop)="onDrop($event)"><div *ngIf="dragActive" style="position:absolute;inset:0;z-index:10;background:rgba(74,222,128,.12);display:flex;align-items:center;justify-content:center;border:2px dashed rgba(74,222,128,.5);border-radius:8px;pointer-events:none"><span style="font-size:16px;color:#4ade80">Drop files to upload</span></div><div class="table-header" style="display:flex;padding:0 12px;background:rgba(255,255,255,.03);border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;user-select:none"><span style="flex:5;padding:6px 4px;cursor:pointer;font-size:12px;font-weight:600;opacity:.7" (click)="toggleSort(&quot;name&quot;)">Name{{ sortIndicator(\'name\') }}</span><span style="flex:1.5;padding:6px 4px;cursor:pointer;font-size:12px;font-weight:600;opacity:.7;text-align:right" (click)="toggleSort(&quot;size&quot;)">Size{{ sortIndicator(\'size\') }}</span><span style="flex:2.5;padding:6px 4px;cursor:pointer;font-size:12px;font-weight:600;opacity:.7" (click)="toggleSort(&quot;date&quot;)">Modified{{ sortIndicator(\'date\') }}</span><span style="flex:1.2;padding:6px 4px;cursor:pointer;font-size:12px;font-weight:600;opacity:.7" (click)="toggleSort(&quot;type&quot;)">Type{{ sortIndicator(\'type\') }}</span></div><div class="file-list" style="flex:1;overflow-y:auto;overflow-x:hidden"><div *ngFor="let item of filteredItems; let i = index" (click)="selectItem(item, $event)" (dblclick)="openItem(item)" (contextmenu)="showContextMenu($event, item)" style="display:flex;padding:0 12px;cursor:default;border-bottom:1px solid rgba(255,255,255,.02);transition:background .1s" [style.background]="isSelected(i) ? &quot;rgba(98,100,167,.35)&quot; : &quot;transparent&quot;"><span style="flex:5;padding:5px 4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:6px"><span style="font-size:15px;flex-shrink:0">{{ fileIcon(item) }}</span><span style="font-weight:500">{{ baseName(item.path) }}</span></span><span style="flex:1.5;padding:5px 4px;opacity:.6;text-align:right;font-variant-numeric:tabular-nums">{{ item.is_dir ? \'—\' : formatSize(item.size) }}</span><span style="flex:2.5;padding:5px 4px;opacity:.5;font-variant-numeric:tabular-nums">{{ formatDate(item.modified) }}</span><span style="flex:1.2;padding:5px 4px;opacity:.5">{{ fileType(item) }}</span></div><div *ngIf="!filteredItems.length &amp;&amp; !busy" style="padding:40px;text-align:center;opacity:.4"><div style="font-size:32px;margin-bottom:8px">📂</div><div>{{ searchText ? \'No matches\' : \'Empty directory\' }}</div></div></div></div><div class="detail-pane" *ngIf="detailPaneVisible" style="width:340px;border-left:1px solid rgba(255,255,255,.06);display:flex;flex-direction:column;flex-shrink:0;background:rgba(255,255,255,.02)"><div class="detail-header" style="padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.06);display:flex;align-items:center;gap:8px;flex-shrink:0"><span style="font-size:18px">{{ selectedItem ? fileIcon(selectedItem) : \'📄\' }}</span><span style="font-weight:600;font-size:13px;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{ selectedPath ? baseName(selectedPath) : \'No selection\' }}</span><button *ngIf="selectedPath" type="button" (click)="downloadSelected()" style="background:rgba(255,255,255,.08);border:none;color:#e4e4e4;padding:3px 8px;border-radius:4px;cursor:pointer;font-size:11px">⬇</button><button *ngIf="selectedPath &amp;&amp; selectedIsText" type="button" (click)="saveSelected()" style="background:rgba(59,130,246,.6);border:none;color:white;padding:3px 8px;border-radius:4px;cursor:pointer;font-size:11px">Save</button></div><div class="detail-content" style="flex:1;overflow:auto;padding:0"><textarea *ngIf="selectedPath &amp;&amp; selectedIsText" [(ngModel)]="selectedContent" style="width:100%;height:100%;background:transparent;border:none;color:#d4d4d8;font-family:&quot;Cascadia Code&quot;,&quot;Fira Code&quot;,&quot;JetBrains Mono&quot;,monospace;font-size:12px;padding:10px 14px;resize:none;outline:none;line-height:1.5;tab-size:4;box-sizing:border-box"></textarea><div *ngIf="selectedPath &amp;&amp; !selectedIsText" style="padding:30px;text-align:center;opacity:.5"><div style="font-size:28px;margin-bottom:8px">{{ selectedItem ? fileIcon(selectedItem) : \'📄\' }}</div><div>Binary file</div><button type="button" (click)="downloadSelected()" style="margin-top:12px;background:rgba(255,255,255,.08);border:none;color:#e4e4e4;padding:6px 16px;border-radius:6px;cursor:pointer;font-size:12px">Download</button></div><div *ngIf="!selectedPath" style="padding:30px;text-align:center;opacity:.3"><div style="font-size:28px;margin-bottom:8px">👆</div><div style="font-size:12px">Select a file to preview</div></div></div></div></div><div class="status-bar" style="display:flex;align-items:center;gap:12px;padding:4px 12px;background:rgba(255,255,255,.03);border-top:1px solid rgba(255,255,255,.06);flex-shrink:0;font-size:11px;opacity:.6;min-height:24px"><span>{{ status }}</span><span *ngIf="transfers.length" (click)="transfersVisible = !transfersVisible" style="margin-left:auto;cursor:pointer;opacity:.8">{{ activeTransferLabel }}</span></div><div *ngIf="contextMenuVisible" style="position:fixed;z-index:100;background:rgba(45,45,45,.98);border:1px solid rgba(255,255,255,.12);border-radius:8px;padding:4px;min-width:160px;backdrop-filter:blur(16px);box-shadow:0 8px 32px rgba(0,0,0,.4)" [style.left.px]="contextMenuX" [style.top.px]="contextMenuY"><button type="button" (click)="openItem(contextItem); hideContextMenu()" style="display:block;width:100%;text-align:left;background:none;border:none;color:#e4e4e4;padding:6px 12px;border-radius:4px;cursor:pointer;font-size:12px">Open</button><button type="button" (click)="openRenamePrompt(contextItem); hideContextMenu()" style="display:block;width:100%;text-align:left;background:none;border:none;color:#e4e4e4;padding:6px 12px;border-radius:4px;cursor:pointer;font-size:12px">Rename</button><div style="height:1px;background:rgba(255,255,255,.08);margin:2px 8px"></div><button type="button" (click)="deleteItem(contextItem); hideContextMenu()" style="display:block;width:100%;text-align:left;background:none;border:none;color:#f87171;padding:6px 12px;border-radius:4px;cursor:pointer;font-size:12px">Delete</button></div><div *ngIf="promptVisible" style="position:fixed;inset:0;z-index:200;background:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;backdrop-filter:blur(4px)"><div style="background:rgba(45,45,45,.98);border:1px solid rgba(255,255,255,.1);border-radius:12px;padding:24px;width:380px;box-shadow:0 16px 48px rgba(0,0,0,.5)"><h3 style="margin:0 0 16px 0;font-size:15px;font-weight:600">{{ promptTitle }}</h3><input type="text" [(ngModel)]="promptValue" (keyup.enter)="confirmPrompt()" (keyup.escape)="closePrompt()" autofocus style="width:100%;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-radius:6px;padding:8px 12px;color:#e4e4e4;font-size:13px;outline:none;box-sizing:border-box"><div style="display:flex;gap:8px;margin-top:16px;justify-content:flex-end"><button type="button" (click)="closePrompt()" style="background:rgba(255,255,255,.08);border:none;color:#e4e4e4;padding:6px 20px;border-radius:6px;cursor:pointer;font-size:12px">Cancel</button><button type="button" (click)="confirmPrompt()" style="background:rgba(59,130,246,.7);border:none;color:white;padding:6px 20px;border-radius:6px;cursor:pointer;font-size:12px">Confirm</button></div></div></div><div *ngIf="transfersVisible &amp;&amp; transfers.length" style="position:fixed;right:16px;bottom:40px;width:380px;max-height:45vh;background:rgba(40,40,40,.98);border:1px solid rgba(255,255,255,.1);border-radius:12px;z-index:50;overflow:hidden;box-shadow:0 12px 40px rgba(0,0,0,.4);backdrop-filter:blur(16px)"><div style="padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.06);display:flex;align-items:center"><span style="font-weight:600;font-size:13px;flex:1">Transfers</span><button type="button" (click)="transfersVisible = false" style="background:none;border:none;color:#e4e4e4;cursor:pointer;font-size:16px;opacity:.6">×</button></div><div style="overflow-y:auto;max-height:calc(45vh - 44px)"><div *ngFor="let transfer of transfers" style="padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.04)"><div style="display:flex;align-items:center;gap:6px;margin-bottom:4px"><span style="font-size:11px">{{ transfer.direction === \'upload\' ? \'⬆\' : \'⬇\' }}</span><span style="font-size:12px;font-weight:500;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{ transfer.name }}</span><span style="font-size:10px;opacity:.5;padding:1px 6px;border-radius:3px;background:rgba(255,255,255,.06)">{{ transfer.status }}</span><button *ngIf="transfer.status === &quot;running&quot; || transfer.status === &quot;queued&quot;" type="button" (click)="cancelTransfer(transfer)" style="background:none;border:none;color:#f87171;cursor:pointer;font-size:11px;padding:2px 4px">✕</button></div><div *ngIf="transfer.bytesTotal" style="height:3px;background:rgba(255,255,255,.08);border-radius:2px;overflow:hidden"><div style="height:100%;border-radius:2px;transition:width .2s" [style.width.%]="transferPercent(transfer) || 0" [style.background]="transfer.status === &quot;error&quot; ? &quot;#f87171&quot; : transfer.status === &quot;done&quot; ? &quot;#4ade80&quot; : &quot;#3b82f6&quot;"></div></div><div style="display:flex;gap:8px;margin-top:3px;font-size:10px;opacity:.4"><span>{{ formatSize(transfer.bytesDone) }} / {{ formatSize(transfer.bytesTotal) }}</span><span>{{ transferRate(transfer) }}</span></div></div></div></div></div>'}},295(e,t,s){s(766),e.exports=function(e){return""+'<div style="padding:20px;display:flex;flex-direction:column;gap:16px;font-family:&quot;Segoe UI Variable&quot;,&quot;Segoe UI&quot;,system-ui,sans-serif;max-width:720px"><div style="padding:16px 20px;border-radius:10px;background:linear-gradient(135deg,rgba(25,53,103,.9),rgba(17,94,89,.85));color:white"><h2 style="margin:0 0 4px 0;font-size:18px;font-weight:600">Bianbu MCP</h2><p style="margin:0;opacity:.85;font-size:13px">Connect to your Bianbu Cloud VM via MCP.</p></div><div class="card" style="padding:16px 20px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08)"><h3 style="margin:0 0 14px 0;font-size:14px;font-weight:600">Connection</h3><div class="field" style="display:flex;align-items:center;gap:8px;margin-bottom:10px"><label style="width:80px;font-size:12px;opacity:.7;flex-shrink:0">Name</label><input class="form-control" type="text" [(ngModel)]="settings.name" (ngModelChange)="save()" placeholder="bianbu" style="flex:1;max-width:180px"></div><div class="field" style="display:flex;align-items:center;gap:0;margin-bottom:10px"><label style="width:80px;font-size:12px;opacity:.7;flex-shrink:0">Endpoint</label><span style="background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-right:none;border-radius:6px 0 0 6px;padding:5px 10px;font-size:12px;color:#93c5fd;white-space:nowrap">https://</span><input class="form-control" type="text" [(ngModel)]="settings.domain" (ngModelChange)="save()" placeholder="your-domain.example.com" style="flex:1;border-radius:0;border-left:none;border-right:none"><span style="background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-left:none;border-radius:0 6px 6px 0;padding:5px 10px;font-size:12px;color:#93c5fd;white-space:nowrap">/mcp</span></div><div class="field" style="display:flex;align-items:center;gap:8px;margin-bottom:14px"><label style="width:80px;font-size:12px;opacity:.7;flex-shrink:0">API Key</label><input class="form-control" type="password" [(ngModel)]="settings.apiKey" (ngModelChange)="save()" placeholder="your-x-api-key" style="flex:1"></div><div style="display:flex;gap:8px;flex-wrap:wrap"><button class="btn btn-primary" type="button" (click)="testConnection()" [disabled]="diagnosticsBusy || validationErrors.length &gt; 0" style="font-size:12px;padding:5px 14px">Test connection</button><button class="btn btn-secondary" type="button" (click)="openShell()" style="font-size:12px;padding:5px 14px">Open Shell</button><button class="btn btn-secondary" type="button" (click)="openFiles()" style="font-size:12px;padding:5px 14px">Open Files</button></div><div *ngIf="validationErrors.length" style="margin-top:10px;color:#fca5a5;font-size:12px"><div *ngFor="let e of validationErrors">⚠ {{ e }}</div></div></div><div class="card" style="padding:16px 20px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08)"><div style="display:flex;align-items:center;cursor:pointer" (click)="advancedVisible = !advancedVisible"><h3 style="margin:0;font-size:14px;font-weight:600;flex:1">Remote status & maintenance</h3><span style="opacity:.5;font-size:12px">{{ advancedVisible ? \'▼\' : \'▶\' }}</span></div><div *ngIf="remoteHealth || lastError" style="margin-top:12px;display:grid;grid-template-columns:repeat(2,1fr);gap:6px;font-size:12px"><div style="opacity:.6">Script: {{ remoteHealth?.scriptVersion || \'unknown\' }}</div><div style="opacity:.6">Server: {{ remoteHealth?.serverVersion || \'unknown\' }}</div><div style="opacity:.6">Transport: {{ remoteHealth?.transportMode || \'unknown\' }}</div><div style="opacity:.6">Last check: {{ lastDiagnosticAt || \'never\' }}</div></div><div *ngIf="lastError" style="margin-top:8px;color:#fca5a5;font-size:12px;white-space:pre-wrap">{{ lastError }}</div><div *ngIf="advancedVisible" style="margin-top:14px"><div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px"><button class="btn btn-secondary" type="button" (click)="refreshHealth()" [disabled]="diagnosticsBusy || validationErrors.length &gt; 0" style="font-size:11px;padding:4px 12px">Fetch health</button><button class="btn btn-primary" type="button" (click)="pushUpgrade(&quot;up&quot;)" [disabled]="maintenanceBusy || validationErrors.length &gt; 0" style="font-size:11px;padding:4px 12px">Push upgrade</button><button class="btn btn-secondary" type="button" (click)="pushUpgrade(&quot;repair&quot;)" [disabled]="maintenanceBusy || validationErrors.length &gt; 0" style="font-size:11px;padding:4px 12px">Push repair</button></div><div *ngIf="lastMaintenanceAt" style="font-size:11px;opacity:.6;margin-bottom:8px"><div>Last maintenance: {{ lastMaintenanceAt }}</div><div *ngIf="latestMaintenanceSession">Session: {{ latestMaintenanceSession.sessionName }}</div></div><div *ngIf="latestMaintenanceSession" style="display:flex;gap:8px;margin-bottom:12px"><button class="btn btn-secondary" type="button" (click)="downloadLocalMaintenanceLog()" [disabled]="maintenanceBusy" style="font-size:11px;padding:4px 12px">Local log</button><button class="btn btn-secondary" type="button" (click)="downloadRemoteMaintenanceLog()" [disabled]="maintenanceBusy || validationErrors.length &gt; 0" style="font-size:11px;padding:4px 12px">Remote log</button></div><div *ngIf="remoteHealth" style="margin-top:8px;font-size:11px;opacity:.5"><div>FILE_ROOT: {{ remoteHealth.fileRoot || \'unknown\' }}</div><div>Bundled installer: script={{ bundledInstaller?.scriptVersion || \'?\' }} server={{ bundledInstaller?.serverVersion || \'?\' }}</div><div>Capabilities: rename={{ remoteHealth.supports?.renamePath ? \'✓\' : \'✗\' }} shell={{ remoteHealth.supports?.shellSession ? \'✓\' : \'✗\' }} pty={{ remoteHealth.supports?.ptySession ? \'✓\' : \'✗\' }} chunked={{ remoteHealth.supports?.chunkedTransfers ? \'✓\' : \'✗\' }} parallel={{ remoteHealth.supports?.parallelChunkOffsets ? \'✓\' : \'✗\' }} ratelimit={{ remoteHealth.supports?.rateLimiting ? \'✓\' : \'✗\' }}</div></div><div class="grid" style="display:grid;grid-template-columns:160px 1fr;gap:8px;align-items:center;margin-top:12px;font-size:12px"><label style="opacity:.6">Installer path</label><input class="form-control" type="text" [(ngModel)]="settings.installerRemotePath" (ngModelChange)="save()" style="font-size:12px"><label style="opacity:.6">As root</label><input type="checkbox" [(ngModel)]="settings.maintenanceAsRoot" (ngModelChange)="save()"><label style="opacity:.6">Reconnect poll (ms)</label><input class="form-control" type="number" min="500" [(ngModel)]="settings.reconnectPollMs" (ngModelChange)="save()" style="font-size:12px;max-width:120px"><label style="opacity:.6">Health timeout (ms)</label><input class="form-control" type="number" min="5000" [(ngModel)]="settings.upgradeHealthTimeoutMs" (ngModelChange)="save()" style="font-size:12px;max-width:120px"></div></div></div><div class="card" style="padding:16px 20px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08)"><div style="display:flex;align-items:center;cursor:pointer" (click)="advancedVisible = advancedVisible"><h3 style="margin:0;font-size:14px;font-weight:600;flex:1">Performance tuning</h3><span style="opacity:.5;font-size:12px"></span></div><div class="grid" style="display:grid;grid-template-columns:160px 1fr;gap:8px;align-items:center;margin-top:12px;font-size:12px"><label style="opacity:.6">Interactive slots</label><input class="form-control" type="number" min="1" step="1" [(ngModel)]="settings.interactiveConcurrency" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Transfer slots</label><input class="form-control" type="number" min="1" max="30" step="1" [(ngModel)]="settings.transferConcurrency" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Concurrent files</label><input class="form-control" type="number" min="1" max="10" step="1" [(ngModel)]="settings.maxConcurrentFiles" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Worker cadence (ms)</label><input class="form-control" type="number" min="0" step="10" [(ngModel)]="settings.workerCadenceMs" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Max retries</label><input class="form-control" type="number" min="0" [(ngModel)]="settings.maxRetries" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Retry base (ms)</label><input class="form-control" type="number" min="0" [(ngModel)]="settings.retryBaseMs" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Upload chunk (bytes)</label><input class="form-control" type="number" min="16384" step="1024" [(ngModel)]="settings.uploadChunkBytes" (ngModelChange)="save()" style="font-size:12px;max-width:120px"><label style="opacity:.6">Download chunk (bytes)</label><input class="form-control" type="number" min="16384" step="1024" [(ngModel)]="settings.downloadChunkBytes" (ngModelChange)="save()" style="font-size:12px;max-width:120px"><label style="opacity:.6">Notes</label><textarea class="form-control" rows="2" [(ngModel)]="settings.notes" (ngModelChange)="save()" placeholder="Optional notes" style="font-size:12px"></textarea></div></div><div class="card" style="padding:16px 20px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08)"><h3 style="margin:0 0 8px 0;font-size:14px;font-weight:600">Copyable MCP snippet</h3><pre style="white-space:pre-wrap;margin:0;font-size:12px;opacity:.85;background:rgba(0,0,0,.2);padding:12px;border-radius:6px">{{ sampleJson }}</pre></div><div style="font-size:11px;opacity:.4;padding:4px 0">💡 MCP URL = https://‹domain›/mcp • API key from Bianbu Cloud console • Shell and Files are MCP-backed, not SSH/SFTP</div></div>'}},766(e,t,s){"use strict";var i=Object.prototype.hasOwnProperty;function n(e,t){return Array.isArray(e)?function(e,t){for(var s,i="",o="",r=Array.isArray(t),a=0;a<e.length;a++)(s=n(e[a]))&&(r&&t[a]&&(s=l(s)),i=i+o+s,o=" ");return i}(e,t):e&&"object"==typeof e?function(e){var t="",s="";for(var n in e)n&&e[n]&&i.call(e,n)&&(t=t+s+n,s=" ");return t}(e):e||""}function o(e){if(!e)return"";if("object"==typeof e){var t="";for(var s in e)i.call(e,s)&&(t=t+s+":"+e[s]+";");return t}return e+""}function r(e,t,s,i){if(!1===t||null==t||!t&&("class"===e||"style"===e))return"";if(!0===t)return" "+(i?e:e+'="'+e+'"');var n=typeof t;return"object"!==n&&"function"!==n||"function"!=typeof t.toJSON||(t=t.toJSON()),"string"==typeof t||(t=JSON.stringify(t),s||-1===t.indexOf('"'))?(s&&(t=l(t))," "+e+'="'+t+'"'):" "+e+"='"+t.replace(/'/g,"&#39;")+"'"}t.merge=function e(t,s){if(1===arguments.length){for(var i=t[0],n=1;n<t.length;n++)i=e(i,t[n]);return i}for(var r in s)if("class"===r){var a=t[r]||[];t[r]=(Array.isArray(a)?a:[a]).concat(s[r]||[])}else if("style"===r){a=(a=o(t[r]))&&";"!==a[a.length-1]?a+";":a;var l=o(s[r]);l=l&&";"!==l[l.length-1]?l+";":l,t[r]=a+l}else t[r]=s[r];return t},t.classes=n,t.style=o,t.attr=r,t.attrs=function(e,t){var s="";for(var a in e)if(i.call(e,a)){var l=e[a];if("class"===a){s=r(a,l=n(l),!1,t)+s;continue}"style"===a&&(l=o(l)),s+=r(a,l,!1,t)}return s};var a=/["&<>]/;function l(e){var t=""+e,s=a.exec(t);if(!s)return e;var i,n,o,r="";for(i=s.index,n=0;i<t.length;i++){switch(t.charCodeAt(i)){case 34:o="&quot;";break;case 38:o="&amp;";break;case 60:o="&lt;";break;case 62:o="&gt;";break;default:continue}n!==i&&(r+=t.substring(n,i)),n=i+1,r+=o}return n!==i?r+t.substring(n,i):r}t.escape=l,t.rethrow=function e(t,i,n,o){if(!(t instanceof Error))throw t;if(!("undefined"==typeof window&&i||o))throw t.message+=" on line "+n,t;try{o=o||s(947).readFileSync(i,"utf8")}catch(s){e(t,null,n)}var r=3,a=o.split("\n"),l=Math.max(n-r,0),c=Math.min(a.length,n+r);throw r=a.slice(l,c).map(function(e,t){var s=t+l+1;return(s==n?" > ":" ")+s+"| "+e}).join("\n"),t.path=i,t.message=(i||"Pug")+":"+n+"\n"+r+"\n\n"+t.message,t}},40(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},n=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuCloudCommandProvider=void 0;const o=s(860),r=s(650),a=s(678),l=s(241);let c=class extends r.CommandProvider{constructor(e){super(),this.app=e}async provide(){return[{id:"bianbu-cloud-shell",label:"Open Bianbu Cloud Shell",sublabel:"Remote shell over MCP run_command",locations:[r.CommandLocation.StartPage],run:async()=>{this.app.openNewTab({type:a.BianbuCloudShellTabComponent})}},{id:"bianbu-cloud-files",label:"Open Bianbu Cloud Files",sublabel:"File manager over MCP file tools",locations:[r.CommandLocation.StartPage],run:async()=>{this.app.openNewTab({type:l.BianbuCloudFilesTabComponent})}}]}};c=i([(0,o.Injectable)(),n("design:paramtypes",[r.AppService])],c),t.BianbuCloudCommandProvider=c},889(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuMcpConfigProvider=void 0;const i=s(650);class n extends i.ConfigProvider{constructor(){super(...arguments),this.defaults={bianbuMcp:{name:"bianbu",domain:"",apiKey:"",maxRetries:2,retryBaseMs:1e3,interactiveConcurrency:2,transferConcurrency:30,workerCadenceMs:0,uploadChunkBytes:65536,downloadChunkBytes:262144,maxConcurrentFiles:3,notes:"",installerRemotePath:"/tmp/bianbu_agent_proxy.sh",maintenanceAsRoot:!0,reconnectPollMs:2e3,upgradeHealthTimeoutMs:12e4}}}}t.BianbuMcpConfigProvider=n},241(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},n=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuCloudFilesTabComponent=void 0;const o=s(860),r=s(650),a=s(885);let l=class extends r.BaseTabComponent{constructor(e,t,s,i){super(e),this.mcp=t,this.notifications=s,this.platform=i,this.currentPath=".",this.pathInput=".",this.asRoot=!1,this.busy=!1,this.items=[],this.filteredItems=[],this.selectedPath="",this.selectedContent="",this.selectedIsText=!1,this.status="Ready",this.dragActive=!1,this.searchText="",this.history=["."],this.historyIndex=0,this.selectedIndex=-1,this.contextMenuVisible=!1,this.contextMenuX=0,this.contextMenuY=0,this.contextItem=null,this.promptVisible=!1,this.promptTitle="",this.promptPlaceholder="",this.promptValue="",this.promptAction=null,this.promptTarget=null,this.transfersVisible=!0,this.transfers=[],this.transferSeq=1,this.transferQueue=[],this.transferQueueRunning=!1,this.sortKey="name",this.sortAsc=!0,this.selectedIndices=new Set,this.lastClickIndex=-1,this.detailPaneVisible=!0,this.advancedTransfersExpanded=!1,this.setTitle("Bianbu Cloud Files"),this.icon="folder-open"}ngOnInit(){this.refresh().catch(()=>null)}get breadcrumbs(){if(!this.currentPath||"."===this.currentPath)return["."];const e=this.currentPath.replace(/\\/g,"/");if("/"===e)return["/"];const t=e.split("/").filter(Boolean);return e.startsWith("/")?["/"].concat(t):t}get selectedItem(){var e;return null!==(e=this.filteredItems[this.selectedIndex])&&void 0!==e?e:null}onDocumentClick(){this.hideContextMenu()}onKeyDown(e){var t;const s=e.target,i=null===(t=null==s?void 0:s.tagName)||void 0===t?void 0:t.toLowerCase(),n=["input","textarea"].includes(i||"")||this.promptVisible;if("F5"===e.key)return e.preventDefault(),void this.refresh();if(e.altKey&&"ArrowUp"===e.key)return e.preventDefault(),void this.goUp();if(e.altKey&&"ArrowLeft"===e.key)return e.preventDefault(),void this.goBack();if(e.altKey&&"ArrowRight"===e.key)return e.preventDefault(),void this.goForward();if(e.ctrlKey&&"l"===e.key.toLowerCase()){e.preventDefault();const t=document.getElementById("bianbu-path-input");return null==t||t.focus(),void(null==t||t.select())}return e.ctrlKey&&e.shiftKey&&"n"===e.key.toLowerCase()?(e.preventDefault(),void this.openCreateDirectoryPrompt()):e.ctrlKey&&!e.shiftKey&&"n"===e.key.toLowerCase()?(e.preventDefault(),void this.openCreateFilePrompt()):n?void 0:"Backspace"===e.key?(e.preventDefault(),void this.goUp()):"Delete"===e.key&&this.selectedItem?(e.preventDefault(),void this.deleteItem(this.selectedItem)):"F2"===e.key&&this.selectedItem?(e.preventDefault(),void this.openRenamePrompt(this.selectedItem)):"Enter"===e.key&&this.selectedItem?(e.preventDefault(),void this.openItem(this.selectedItem)):"ArrowDown"===e.key?(e.preventDefault(),void this.moveSelection(1)):"ArrowUp"===e.key?(e.preventDefault(),void this.moveSelection(-1)):void 0}async refresh(){this.busy=!0,this.status="Loading directory…",this.pathInput=this.currentPath,this.setProgress(.25);try{const e=await this.mcp.listDirectory(this.currentPath||".",this.asRoot);this.items=e.items||[],this.applyFilter(),this.status=`Loaded ${this.items.length} item(s)`,this.filteredItems.length&&this.selectedIndex<0&&(this.selectedIndex=0)}catch(e){this.notifications.error("Failed to list directory",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e)}finally{this.busy=!1,this.setProgress(null)}}applyFilter(){const e=this.searchText.trim().toLowerCase();this.filteredItems=this.items.filter(t=>{const s=this.baseName(t.path).toLowerCase();return!e||s.includes(e)||t.path.toLowerCase().includes(e)}),this.sortItems(),this.selectedIndex>=this.filteredItems.length&&(this.selectedIndex=this.filteredItems.length-1)}sortItems(){this.filteredItems.sort((e,t)=>{if(e.is_dir&&!t.is_dir)return-1;if(!e.is_dir&&t.is_dir)return 1;let s=0;switch(this.sortKey){case"name":s=this.baseName(e.path).localeCompare(this.baseName(t.path));break;case"size":s=(e.size||0)-(t.size||0);break;case"date":s=(e.modified||"").localeCompare(t.modified||"");break;case"type":{const i=e.is_dir?"":e.path.split(".").pop()||"",n=t.is_dir?"":t.path.split(".").pop()||"";s=i.localeCompare(n);break}}return this.sortAsc?s:-s})}navigateToInput(){this.navigate(this.pathInput||".")}navigate(e,t=!0){this.currentPath=e||".",this.pathInput=this.currentPath,t&&(this.history=this.history.slice(0,this.historyIndex+1),this.history.push(this.currentPath),this.historyIndex=this.history.length-1),this.clearPreview(),this.selectedIndex=-1,this.refresh()}navigateBreadcrumb(e){if("."===this.currentPath&&0===e)return void this.navigate(".",!0);const t=this.breadcrumbs;if("/"===t[0])return 0===e?void this.navigate("/",!0):void this.navigate("/"+t.slice(1,e+1).join("/"),!0);this.navigate(t.slice(0,e+1).join("/"),!0)}goBack(){this.historyIndex<=0||(this.historyIndex-=1,this.navigate(this.history[this.historyIndex],!1))}goForward(){this.historyIndex>=this.history.length-1||(this.historyIndex+=1,this.navigate(this.history[this.historyIndex],!1))}goUp(){if("."===this.currentPath||"/"===this.currentPath)return;const e=this.currentPath.replace(/\\/g,"/"),t=e.split("/").slice(0,-1).join("/")||(e.startsWith("/")?"/":".");this.navigate(t,!0)}moveSelection(e){this.filteredItems.length?this.selectedIndex<0?this.selectedIndex=0:this.selectedIndex=Math.max(0,Math.min(this.filteredItems.length-1,this.selectedIndex+e)):this.selectedIndex=-1}selectItem(e,t){const s=this.filteredItems.indexOf(e);if((null==t?void 0:t.ctrlKey)||(null==t?void 0:t.metaKey))this.selectedIndices.has(s)?this.selectedIndices.delete(s):this.selectedIndices.add(s);else if((null==t?void 0:t.shiftKey)&&this.lastClickIndex>=0){const e=Math.min(this.lastClickIndex,s),t=Math.max(this.lastClickIndex,s);for(let s=e;s<=t;s++)this.selectedIndices.add(s)}else this.selectedIndices.clear(),this.selectedIndices.add(s);this.lastClickIndex=s,this.selectedIndex=s}async openItem(e){if(this.selectItem(e),e.is_dir)this.navigate(e.path,!0);else{this.busy=!0,this.status=`Opening ${e.path}`,this.selectedPath=e.path,this.selectedIsText=this.isTextLike(e.path);try{if(this.selectedIsText){const t=await this.mcp.readTextFile(e.path,524288,this.asRoot);this.selectedContent=t.content||"",this.status=`Opened ${e.path}`}else this.selectedContent="",this.status=`Binary / non-text file selected: ${e.path}`}catch(e){this.notifications.error("Failed to open file",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e),this.selectedContent=""}finally{this.busy=!1}}}async saveSelected(){if(this.selectedPath&&this.selectedIsText){this.busy=!0,this.status=`Saving ${this.selectedPath}`;try{await this.mcp.writeTextFile(this.selectedPath,this.selectedContent,this.asRoot),this.notifications.notice("File saved"),this.status=`Saved ${this.selectedPath}`,await this.refresh()}catch(e){this.notifications.error("Failed to save file",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e)}finally{this.busy=!1}}}openCreateDirectoryPrompt(){this.promptVisible=!0,this.promptTitle="Create new folder",this.promptPlaceholder="Folder name",this.promptValue="",this.promptAction="mkdir",this.promptTarget=null}openCreateFilePrompt(){this.promptVisible=!0,this.promptTitle="Create new file",this.promptPlaceholder="File name",this.promptValue="",this.promptAction="newfile",this.promptTarget=null}openRenamePrompt(e){this.promptVisible=!0,this.promptTitle="Rename",this.promptPlaceholder="New name",this.promptValue=this.baseName(e.path),this.promptAction="rename",this.promptTarget=e}closePrompt(){this.promptVisible=!1,this.promptAction=null,this.promptTarget=null,this.promptValue=""}async confirmPrompt(){const e=this.promptValue.trim();if(e&&this.promptAction)return"mkdir"===this.promptAction?(await this.createDirectory(e),void this.closePrompt()):"newfile"===this.promptAction?(await this.createFile(e),void this.closePrompt()):void("rename"===this.promptAction&&this.promptTarget&&(await this.renameItem(this.promptTarget,e),this.closePrompt()));this.closePrompt()}async createDirectory(e){const t=this.joinPath(this.currentPath,e);this.busy=!0;try{await this.mcp.makeDirectory(t,this.asRoot),await this.refresh(),this.notifications.notice("Directory created")}catch(e){this.notifications.error("Failed to create directory",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e)}finally{this.busy=!1}}async createFile(e){const t=this.joinPath(this.currentPath,e);this.busy=!0;try{await this.mcp.writeTextFile(t,"",this.asRoot),await this.refresh(),this.notifications.notice("File created")}catch(e){this.notifications.error("Failed to create file",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e)}finally{this.busy=!1}}async renameItem(e,t){const s=e.path.split("/").slice(0,-1).join("/")||".",i=this.joinPath(s,t);try{await this.mcp.renamePath(e.path,i,this.asRoot),this.notifications.notice("Path renamed"),this.selectedPath===e.path&&(this.selectedPath=i),await this.refresh()}catch(e){const t=String((null==e?void 0:e.message)||e);this.notifications.error("Rename failed",t),this.status=t}}async deleteItem(e){this.busy=!0;try{await this.mcp.deletePath(e.path,!!e.is_dir,this.asRoot),this.selectedPath===e.path&&this.clearPreview(),await this.refresh(),this.notifications.notice("Path deleted")}catch(e){this.notifications.error("Failed to delete path",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e)}finally{this.busy=!1}}showContextMenu(e,t){e.preventDefault(),e.stopPropagation(),this.selectItem(t),this.contextItem=t,this.contextMenuVisible=!0,this.contextMenuX=e.clientX,this.contextMenuY=e.clientY}hideContextMenu(){this.contextMenuVisible=!1,this.contextItem=null}async uploadFile(e){const t=e.target,s=Array.from(t.files||[]);if(s.length){for(const e of s)this.enqueueUpload(e);t.value=""}}createTransfer(e,t,s,i,n="queued"){return{id:this.transferSeq++,name:e,direction:t,status:n,bytesDone:0,bytesTotal:s,startedAt:Date.now(),controller:i}}cancelTransfer(e){var t;"running"!==e.status&&"queued"!==e.status||(null===(t=e.controller)||void 0===t||t.abort(),e.status="cancelled",e.finishedAt=Date.now())}transferPercent(e){return e.bytesTotal?Math.max(0,Math.min(100,Math.round(e.bytesDone/e.bytesTotal*100))):null}transferRate(e){const t=e.finishedAt||Date.now(),s=Math.max(1,(t-e.startedAt)/1e3),i=e.bytesDone||0;return`${Math.round(i/s/1024)} KB/s`}async uploadDroppedFile(e){this.enqueueUpload(e)}onDragOver(e){e.preventDefault(),this.dragActive=!0}onDragLeave(){this.dragActive=!1}async onDrop(e){var t;e.preventDefault(),this.dragActive=!1;const s=Array.from((null===(t=e.dataTransfer)||void 0===t?void 0:t.files)||[]);if(s.length)for(const e of s)this.enqueueUpload(e)}async downloadSelected(){this.selectedPath&&this.enqueueDownload(this.selectedPath)}enqueueUpload(e){const t=new AbortController,s=this.createTransfer(e.name,"upload",e.size,t,"queued");this.queueTransferJob(s,()=>this.runUploadTransfer(e,s))}enqueueDownload(e){const t=new AbortController,s=this.createTransfer(this.baseName(e),"download",null,t,"queued");this.queueTransferJob(s,()=>this.runDownloadTransfer(e,s))}queueTransferJob(e,t){this.transfers.unshift(e),this.transferQueue.push(async()=>{"cancelled"!==e.status&&(e.status="running",e.startedAt=Date.now(),await t())}),this.pumpTransferQueue()}async pumpTransferQueue(){var e;if(!this.transferQueueRunning){this.transferQueueRunning=!0;try{const t=Math.max(1,Number(null!==(e=this.mcp.settings.maxConcurrentFiles)&&void 0!==e?e:3)),s=[],i=async()=>{for(;this.transferQueue.length||s.length;){for(;s.length<t&&this.transferQueue.length;){const e=this.transferQueue.shift();if(!e)continue;const t=e().finally(()=>{const e=s.indexOf(t);e>=0&&s.splice(e,1)});s.push(t)}s.length&&await Promise.race(s)}};await i()}finally{this.transferQueueRunning=!1}}}async runUploadTransfer(e,t){var s,i,n;let o=null;try{const r=this.joinPath(this.currentPath,e.name),a=Math.max(16384,Number(null!==(s=this.mcp.settings.uploadChunkBytes)&&void 0!==s?s:32768)),l=Math.max(1,Math.min(Number(null!==(i=this.mcp.settings.transferConcurrency)&&void 0!==i?i:30),Math.ceil(e.size/a)||1));o=await this.mcp.uploadChunkedBegin(r,this.asRoot,e.size,a);const c=[];for(let t=0;t<e.size;t+=a)c.push(t);let d=null;const u=Array.from({length:l},async()=>{for(var s,i;!(null===(s=t.controller)||void 0===s?void 0:s.signal.aborted);){const s=c.shift();if(void 0===s)return;if(d)return;try{const n=new Uint8Array(await e.slice(s,Math.min(e.size,s+a)).arrayBuffer());await this.mcp.uploadChunkedPart(o.upload_id,this.uint8ToBase64(n),s,null===(i=t.controller)||void 0===i?void 0:i.signal),t.bytesDone+=n.length}catch(e){return void(d=d||e)}}});if(await Promise.all(u),null===(n=t.controller)||void 0===n?void 0:n.signal.aborted)return await this.mcp.uploadChunkedAbort(o.upload_id).catch(()=>null),t.status="cancelled",void(t.finishedAt=Date.now());if(d)throw d;await this.mcp.uploadChunkedFinish(o.upload_id),t.bytesDone=e.size,t.status="done",t.finishedAt=Date.now(),this.notifications.notice(`Uploaded ${e.name}`),await this.refresh()}catch(e){(null==o?void 0:o.upload_id)&&await this.mcp.uploadChunkedAbort(o.upload_id).catch(()=>null),"cancelled"!==t.status&&(t.status="error",t.error=String((null==e?void 0:e.message)||e),t.finishedAt=Date.now(),this.notifications.error("Upload failed",t.error),this.status=t.error)}}async runDownloadTransfer(e,t){var s,i,n,o;let r=null,a=null;try{const o=Math.max(16384,Number(null!==(s=this.mcp.settings.downloadChunkBytes)&&void 0!==s?s:131072));if(r=await this.mcp.downloadChunkedBegin(e,this.asRoot,o),t.bytesTotal=r.total_size,a=await this.platform.startDownload(this.baseName(e)||"download.bin",420,r.total_size||0),!a)return t.status="cancelled",t.finishedAt=Date.now(),void await this.mcp.downloadChunkedClose(r.download_id).catch(()=>null);const l=[];for(let e=0;e<Number(r.total_size||0);e+=o)l.push(e);const c=Math.max(1,Math.min(Number(null!==(i=this.mcp.settings.transferConcurrency)&&void 0!==i?i:30),l.length||1)),d=new Map;let u=0,h=null,p=!1;const m=async()=>{for(;d.has(u);){const e=d.get(u);d.delete(u),await a.write(e),u+=e.length}},f=(async()=>{for(;!p||d.size>0;)await m(),(!p||d.size>0)&&await new Promise(e=>setTimeout(e,10));await m()})(),g=Array.from({length:c},async()=>{for(var e,s;!(null===(e=t.controller)||void 0===e?void 0:e.signal.aborted);){const e=l.shift();if(void 0===e)return;if(h)return;try{const i=await this.mcp.downloadChunkedPart(r.download_id,e,o,null===(s=t.controller)||void 0===s?void 0:s.signal),n=this.base64ToUint8(i.content_base64);d.set(e,n),t.bytesDone+=n.length}catch(e){return void(h=h||e)}}});if(await Promise.all(g),p=!0,await f,null===(n=t.controller)||void 0===n?void 0:n.signal.aborted)return await this.mcp.downloadChunkedClose(r.download_id).catch(()=>null),a.close(),t.status="cancelled",void(t.finishedAt=Date.now());if(h)throw h;await this.mcp.downloadChunkedClose(r.download_id),a.close(),t.status="done",t.finishedAt=Date.now(),this.notifications.notice(`Downloaded ${this.baseName(e)}`)}catch(e){null===(o=null==a?void 0:a.close)||void 0===o||o.call(a),(null==r?void 0:r.download_id)&&await this.mcp.downloadChunkedClose(r.download_id).catch(()=>null),"cancelled"!==t.status&&(t.status="error",t.error=String((null==e?void 0:e.message)||e),t.finishedAt=Date.now(),this.notifications.error("Download failed",t.error),this.status=t.error)}}formatSize(e){return null==e?"—":e<1024?`${e} B`:e<1048576?`${(e/1024).toFixed(1)} KB`:e<1073741824?`${(e/1048576).toFixed(1)} MB`:`${(e/1073741824).toFixed(2)} GB`}formatDate(e){if(!e)return"—";try{const t=new Date(e);return isNaN(t.getTime())?"—":`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")} ${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`}catch{return"—"}}fileIcon(e){return e.is_dir?"📁":{js:"📜",ts:"📜",mjs:"📜",jsx:"📜",tsx:"📜",py:"🐍",sh:"⚙️",bash:"⚙️",json:"📋",yaml:"📋",yml:"📋",toml:"📋",xml:"📋",md:"📝",txt:"📄",csv:"📊",html:"🌐",css:"🎨",scss:"🎨",jpg:"🖼️",jpeg:"🖼️",png:"🖼️",gif:"🖼️",svg:"🖼️",webp:"🖼️",ico:"🖼️",zip:"📦",tar:"📦",gz:"📦",bz2:"📦",xz:"📦","7z":"📦",rar:"📦",pdf:"📕",doc:"📘",docx:"📘",xls:"📗",xlsx:"📗",ppt:"📙",pptx:"📙",mp3:"🎵",wav:"🎵",flac:"🎵",ogg:"🎵",mp4:"🎬",mkv:"🎬",avi:"🎬",mov:"🎬",webm:"🎬",c:"📜",cpp:"📜",h:"📜",hpp:"📜",java:"📜",go:"📜",rs:"📜",rb:"📜",php:"📜",sql:"🗃️",db:"🗃️",sqlite:"🗃️",log:"📃",ini:"⚙️",cfg:"⚙️",conf:"⚙️",env:"🔒",key:"🔑",pem:"🔑",crt:"🔑"}[(e.path.split(".").pop()||"").toLowerCase()]||"📄"}fileType(e){if(e.is_dir)return"Folder";const t=(e.path.split(".").pop()||"").toLowerCase();return t&&t!==e.path?t.toUpperCase():"File"}toggleSort(e){this.sortKey===e?this.sortAsc=!this.sortAsc:(this.sortKey=e,this.sortAsc=!0),this.sortItems()}sortIndicator(e){return this.sortKey!==e?"":this.sortAsc?" ▲":" ▼"}get totalSize(){const e=this.filteredItems.reduce((e,t)=>e+(t.size||0),0);return this.formatSize(e)}get selectionSummary(){const e=this.selectedIndices.size;return e<=1?"":`${e} selected`}isSelected(e){return this.selectedIndices.has(e)}get activeTransferLabel(){let e=0;for(const t of this.transfers)"running"!==t.status&&"queued"!==t.status||e++;return e?"⬆⬇ "+e+" active":"✓ Transfers done"}toggleDetailPane(){this.detailPaneVisible=!this.detailPaneVisible}clearPreview(){this.selectedPath="",this.selectedContent="",this.selectedIsText=!1}baseName(e){return e.split("/").pop()||e}isTextLike(e){const t=e.toLowerCase();return[".txt",".md",".json",".yaml",".yml",".xml",".ini",".cfg",".conf",".log",".sh",".py",".js",".ts",".tsx",".jsx",".html",".css",".scss",".c",".cpp",".h",".hpp",".java",".go",".rs",".sql"].some(e=>t.endsWith(e))}joinPath(e,t){return e&&"."!==e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}uint8ToBase64(e){let t="";for(let s=0;s<e.length;s+=32768)t+=String.fromCharCode(...e.subarray(s,s+32768));return btoa(t)}base64ToUint8(e){const t=atob(e),s=new Uint8Array(t.length);for(let e=0;e<t.length;e++)s[e]=t.charCodeAt(e);return s}};i([(0,o.HostListener)("document:click"),n("design:type",Function),n("design:paramtypes",[]),n("design:returntype",void 0)],l.prototype,"onDocumentClick",null),i([(0,o.HostListener)("document:keydown",["$event"]),n("design:type",Function),n("design:paramtypes",[KeyboardEvent]),n("design:returntype",void 0)],l.prototype,"onKeyDown",null),l=i([(0,o.Component)({template:s(102)}),n("design:paramtypes",[o.Injector,a.BianbuMcpService,r.NotificationsService,r.PlatformService])],l),t.BianbuCloudFilesTabComponent=l},440(e,t,s){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,s,i){void 0===i&&(i=s);var n=Object.getOwnPropertyDescriptor(t,s);n&&!("get"in n?!t.__esModule:n.writable||n.configurable)||(n={enumerable:!0,get:function(){return t[s]}}),Object.defineProperty(e,i,n)}:function(e,t,s,i){void 0===i&&(i=s),e[i]=t[s]}),n=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var s in e)"default"!==s&&Object.prototype.hasOwnProperty.call(e,s)&&i(t,e,s);return n(t,e),t};Object.defineProperty(t,"__esModule",{value:!0});const a=s(860),l=s(358),c=s(182),d=r(s(650)),u=s(700),h=s(889),p=s(717),m=s(645),f=s(40),g=s(885),y=s(678),b=s(241),x=s(104);let v=class{};v=o([(0,a.NgModule)({imports:[l.CommonModule,c.FormsModule,d.default],providers:[g.BianbuMcpService,{provide:d.ConfigProvider,useClass:h.BianbuMcpConfigProvider,multi:!0},{provide:u.SettingsTabProvider,useClass:p.BianbuMcpSettingsTabProvider,multi:!0},{provide:d.CommandProvider,useClass:f.BianbuCloudCommandProvider,multi:!0},{provide:d.ProfileProvider,useClass:x.BianbuCloudProfileProvider,multi:!0}],declarations:[m.BianbuMcpSettingsComponent,y.BianbuCloudShellTabComponent,b.BianbuCloudFilesTabComponent],entryComponents:[m.BianbuMcpSettingsComponent,y.BianbuCloudShellTabComponent,b.BianbuCloudFilesTabComponent]})],v),t.default=v},885(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},n=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuMcpService=void 0;const o=s(860),r=s(650),a=s(979),l=s(935);function c(){const e=new Error("Request aborted");return e.name="AbortError",e}class d{constructor(e,t){this.concurrency=e,this.baseCadenceMs=t,this.queue=[],this.waiters=[],this.started=!1,this.stopped=!1,this.currentCadenceMs=t}stop(){this.stopped=!0;const e={run:()=>Promise.resolve(),resolve:()=>{},reject:()=>{},cleanup:()=>{}};for(const t of this.waiters)t(e);this.waiters.length=0}enqueue(e,t){return(null==t?void 0:t.aborted)?Promise.reject(c()):new Promise((s,i)=>{const n={run:e,resolve:s,reject:i,signal:t,cleanup:()=>{}};if(t){const e=()=>{const e=this.queue.indexOf(n);e>=0&&(this.queue.splice(e,1),n.cleanup(),i(c()))};t.addEventListener("abort",e,{once:!0}),n.cleanup=()=>t.removeEventListener("abort",e)}this.queue.push(n),this.dispatch(),this.startWorkers()})}startWorkers(){if(!this.started){this.started=!0;for(let e=0;e<this.concurrency;e++)this.workerLoop()}}dispatch(){for(;this.queue.length&&this.waiters.length;){const e=this.waiters.shift(),t=this.queue.shift();e&&t&&e(t)}}async take(){return this.queue.length?this.queue.shift():new Promise(e=>this.waiters.push(e))}notifyThrottled(){this.currentCadenceMs=Math.min(4*this.baseCadenceMs||2e3,Math.max(200,2*this.currentCadenceMs))}notifySuccess(){this.currentCadenceMs=Math.max(0,this.currentCadenceMs-10)}async workerLoop(){for(var e;!this.stopped;){const t=await this.take();if(this.stopped)return;if(null===(e=t.signal)||void 0===e?void 0:e.aborted)t.cleanup(),t.reject(c());else try{const e=await t.run();t.resolve(e),this.currentCadenceMs=Math.max(0,this.currentCadenceMs-10)}catch(e){t.reject(e),/429|too many/i.test(String((null==e?void 0:e.message)||""))&&(this.currentCadenceMs=Math.min(4*this.baseCadenceMs||2e3,Math.max(200,2*this.currentCadenceMs)))}finally{t.cleanup()}this.currentCadenceMs>0&&await new Promise(e=>setTimeout(e,this.currentCadenceMs))}}}let u=class{constructor(e){this.config=e,this.bundledInstallerCache=null,this.interactiveLane=new d(2,0),this.latestMaintenanceSessionValue=null,this.transferLane=new d(30,0),this.schedulerKey=""}get settings(){return this.config.store.bianbuMcp}get validationErrors(){return(0,a.validateConnectionSettings)(this.settings)}get bundledInstaller(){return this.bundledInstallerCache||(this.bundledInstallerCache=(0,a.loadBundledInstaller)(__dirname)),this.bundledInstallerCache}get normalizedUrl(){const e=this.settings;if(!e.domain)return"";const t=String(e.domain||"").trim().replace(/^https?:\/\//i,"").replace(/\/mcp\/?$/i,"").replace(/\/+$/,"");return t?`https://${t}/mcp`:""}get latestMaintenanceSession(){return this.latestMaintenanceSessionValue}ensureScheduler(){var e,t,s;const i=Math.max(1,Number(null!==(e=this.settings.interactiveConcurrency)&&void 0!==e?e:2)),n=Math.max(1,Number(null!==(t=this.settings.transferConcurrency)&&void 0!==t?t:30)),o=Math.max(0,Number(null!==(s=this.settings.workerCadenceMs)&&void 0!==s?s:0)),r=`${i}:${n}:${o}`;r!==this.schedulerKey&&(this.schedulerKey=r,this.interactiveLane.stop(),this.transferLane.stop(),this.interactiveLane=new d(i,o),this.transferLane=new d(n,o))}sleep(e){return new Promise(t=>setTimeout(t,e))}isMissingPathError(e){return/(file|path) not found:/i.test(String((null==e?void 0:e.message)||e||""))}async readRemoteTextIfExists(e,t,s){try{const i=await this.readTextFile(e,t,s);return String((null==i?void 0:i.content)||"")}catch(e){if(this.isMissingPathError(e))return null;throw e}}async readRemoteLogSnippet(e,t){return String(await this.readRemoteTextIfExists(e,262144,t)||"").trim()}createMaintenanceSession(e,t,s){const i=(new Date).toISOString(),n=(0,l.createSessionLog)({action:e,asRoot:s,kind:"maintenance",remotePath:t,sessionName:(0,l.createSessionName)("maintenance",e,i),startedAt:i});return this.latestMaintenanceSessionValue=n,n}logSession(e,t,s,i){(0,l.appendSessionLogEntry)(e,{level:t,message:s,details:i,timestamp:(new Date).toISOString()})}getLatestMaintenanceLocalLogDownloadPayload(){if(!this.latestMaintenanceSessionValue)throw new Error("No maintenance session log is available yet");return(0,l.buildLocalLogDownloadPayload)(this.latestMaintenanceSessionValue)}async getLatestMaintenanceRemoteLogDownloadPayload(){const e=this.latestMaintenanceSessionValue;if(!e)throw new Error("No maintenance session log is available yet");if(!e.remoteLogPath)throw new Error("No remote log path is recorded for the latest maintenance session");const t=await this.readRemoteTextIfExists(e.remoteLogPath,1048576,Boolean(e.asRoot)),s=e.remoteStatusPath?await this.readRemoteTextIfExists(e.remoteStatusPath,131072,Boolean(e.asRoot)):null;return(0,l.buildRemoteLogDownloadPayload)({session:e,remoteLogText:t,remoteStatusText:s})}shouldRetryStatus(e){return[429,502,503,504].includes(e)}parseBody(e){try{return JSON.parse(e)}catch{const t=e.split(/\r?\n/).map(e=>e.trim()).filter(e=>e.startsWith("data:")).map(e=>e.slice(5).trim()).filter(Boolean);for(let e=t.length-1;e>=0;e--)try{return JSON.parse(t[e])}catch{}}return{error:{message:e||"Invalid MCP response"}}}laneForTool(e){return e.startsWith("upload_chunked_")||e.startsWith("download_chunked_")?"transfer":"interactive"}async executeRequest(e,t,s=!1){var i,n,o,r,a,l,c,d;const u=this.settings,h=this.normalizedUrl;if(!h)throw new Error("MCP URL is required");const p=s?0:Math.max(0,Number(null!==(i=u.maxRetries)&&void 0!==i?i:2)),m=Math.max(100,Number(null!==(n=u.retryBaseMs)&&void 0!==n?n:1e3));let f="",g=0,y=null;for(let s=0;s<=p;s++){try{const s=await fetch(h,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json, text/event-stream","MCP-Protocol-Version":"2025-11-25","X-API-KEY":u.apiKey},body:JSON.stringify(e),signal:t}),i=await s.text();if(f=i,g=s.status,s.ok&&!this.shouldRetryStatus(s.status)){const e=this.parseBody(i);if(e.error)throw new Error(e.error.message||"MCP error");if((null===(o=e.result)||void 0===o?void 0:o.isError)&&(null===(l=null===(a=null===(r=e.result)||void 0===r?void 0:r.content)||void 0===a?void 0:a[0])||void 0===l?void 0:l.text))throw new Error(e.result.content[0].text);return void 0!==(null===(c=e.result)||void 0===c?void 0:c.structuredContent)?e.result.structuredContent:e.result}if(!this.shouldRetryStatus(s.status)){const e=this.parseBody(i);if(null===(d=e.error)||void 0===d?void 0:d.message)throw new Error(e.error.message);throw new Error(`MCP request failed with status ${s.status}: ${i}`)}}catch(e){if(y=e,(null==t?void 0:t.aborted)||"AbortError"===(null==e?void 0:e.name))throw e;if(s===p)break}s<p&&await this.sleep(m*(s+1))}throw y||new Error(`MCP request failed with status ${g}: ${f}`)}async request(e,t,s="interactive"){return this.ensureScheduler(),("transfer"===s?this.transferLane:this.interactiveLane).enqueue(()=>this.executeRequest(e,t),t)}async callTool(e,t,s,i){return this.request({jsonrpc:"2.0",id:`${e}-${Date.now()}-${Math.random().toString(16).slice(2)}`,method:"tools/call",params:{name:e,arguments:t}},s,i||this.laneForTool(e))}async healthRaw(e){return this.callTool("health",{},e,"interactive")}async getHealth(e){const t=await this.healthRaw(e);return(0,a.parseRemoteHealth)(t)}async health(){return this.healthRaw()}async runCommand(e,t,s,i){return this.callTool("run_command",{command:e,cwd:t,timeout_seconds:s,as_root:i},void 0,"interactive")}async openShellSession(e,t){return this.callTool("open_shell_session",{cwd:e,as_root:t},void 0,"interactive")}async execShellSession(e,t,s){return this.callTool("exec_shell_session",{session_id:e,command:t,timeout_seconds:s},void 0,"interactive")}async closeShellSession(e){return this.callTool("close_shell_session",{session_id:e},void 0,"interactive")}async openPtySession(e,t,s,i){return this.callTool("open_pty_session",{cwd:e,as_root:t,cols:s,rows:i},void 0,"interactive")}async writePtyInput(e,t){return this.executePtyRequest("write_pty_input",{session_id:e,data_base64:t},void 0,!0)}async readPtyOutputDirect(e,t){return this.executePtyRequest("read_pty_output",{session_id:e,timeout_ms:5e3},t)}async resizePty(e,t,s){return this.executePtyRequest("resize_pty",{session_id:e,cols:t,rows:s})}async closePtySession(e){return this.executePtyRequest("close_pty_session",{session_id:e})}async executePtyRequest(e,t,s,i=!1){return this.executeRequest({jsonrpc:"2.0",id:`pty-${Date.now()}-${Math.random().toString(16).slice(2)}`,method:"tools/call",params:{name:e,arguments:t}},s,i)}async listDirectory(e,t){return this.callTool("list_directory",{path:e,as_root:t},void 0,"interactive")}async readTextFile(e,t,s){return this.callTool("read_text_file",{path:e,max_bytes:t,encoding:"utf-8",as_root:s},void 0,"interactive")}async writeTextFile(e,t,s){return this.callTool("write_text_file",{path:e,content:t,overwrite:!0,encoding:"utf-8",as_root:s},void 0,"interactive")}async makeDirectory(e,t){return this.callTool("make_directory",{path:e,parents:!0,as_root:t},void 0,"interactive")}async deletePath(e,t,s){return this.callTool("delete_path",{path:e,recursive:t,as_root:s},void 0,"interactive")}async renamePath(e,t,s){return this.callTool("rename_path",{path:e,dest:t,as_root:s},void 0,"interactive")}async uploadBinaryFile(e,t,s,i){return this.callTool("upload_binary_file",{path:e,content_base64:t,overwrite:!0,as_root:s},i,"interactive")}async uploadChunkedBegin(e,t,s,i){return this.callTool("upload_chunked_begin",{path:e,overwrite:!0,as_root:t,total_size:s,chunk_bytes:i},void 0,"transfer")}async uploadChunkedPart(e,t,s,i){return this.callTool("upload_chunked_part",{upload_id:e,content_base64:t,offset:s},i,"transfer")}async uploadChunkedFinish(e){return this.callTool("upload_chunked_finish",{upload_id:e},void 0,"transfer")}async uploadChunkedAbort(e){return this.callTool("upload_chunked_abort",{upload_id:e},void 0,"transfer")}async downloadBinaryFile(e,t,s){return this.callTool("download_binary_file",{path:e,max_bytes:67108864,as_root:t},s,"interactive")}async downloadChunkedBegin(e,t,s=131072){return this.callTool("download_chunked_begin",{path:e,as_root:t,chunk_bytes:s},void 0,"transfer")}async downloadChunkedPart(e,t,s,i){return this.callTool("download_chunked_part",{download_id:e,offset:t,chunk_bytes:s},i,"transfer")}async downloadChunkedClose(e){return this.callTool("download_chunked_close",{download_id:e},void 0,"transfer")}async waitForHealth(e){const t=Math.max(5e3,Number(e.timeoutMs||12e4)),s=Math.max(500,Number(e.intervalMs||2e3)),i=Date.now()+t;let n=null;for(;Date.now()<i;){try{return await this.getHealth()}catch(e){n=e}await this.sleep(s)}throw new Error(`Remote health check did not recover within ${t} ms: ${String((null==n?void 0:n.message)||n||"unknown error")}`)}async waitForInstallerCompletion(e){var t,s,i;const n=Math.max(5e3,Number(e.timeoutMs||12e4)),o=Math.max(500,Number(e.intervalMs||2e3)),r=Date.now()+n;let l=null,c=null,d=null;for(;Date.now()<r;){try{c=await this.getHealth(),this.logSession(e.session,"info","Remote health poll succeeded",`script=${c.scriptVersion||"unknown"} server=${c.serverVersion||"unknown"} transport=${c.transportMode||"unknown"}`)}catch(t){l=t,this.logSession(e.session,"warn","Remote health poll failed",String((null==t?void 0:t.message)||t)),await this.sleep(o);continue}try{const i=await this.readRemoteTextIfExists(e.statusPath,65536,e.asRoot);if(i){if(d=(0,a.parseRemoteInstallerStatus)(i),this.logSession(e.session,"info","Remote installer status file detected",`ok=${d.ok} exit=${null!==(t=d.exitCode)&&void 0!==t?t:"unknown"} session=${d.sessionName||"unknown"}`),d.sessionName&&d.sessionName!==e.expectedSessionName)throw new Error(`Remote status session_name=${d.sessionName} does not match expected ${e.expectedSessionName}`);if(!d.ok){const t=await this.readRemoteLogSnippet(e.logPath,e.asRoot),i=t?` Remote log:\n${t}`:` Remote log path: ${e.logPath}`;throw new Error(`Remote ${e.action} exited with code ${null!==(s=d.exitCode)&&void 0!==s?s:"unknown"}.${i}`)}if(c.scriptVersion===e.expectedScriptVersion&&c.serverVersion===e.expectedServerVersion)return this.logSession(e.session,"info","Remote installer finished with expected versions"),{health:c,status:d};l=new Error(`Remote installer completed, but health reports script=${c.scriptVersion||"unknown"} server=${c.serverVersion||"unknown"} instead of expected script=${e.expectedScriptVersion} server=${e.expectedServerVersion}`),this.logSession(e.session,"warn","Remote installer completed before expected versions were observed",String(l.message||l))}else this.logSession(e.session,"info","Remote installer status file not ready yet",e.statusPath)}catch(t){l=t,this.logSession(e.session,"error","Remote installer completion check failed",String((null==t?void 0:t.message)||t))}await this.sleep(o)}const u=c?await this.readRemoteLogSnippet(e.logPath,e.asRoot).catch(()=>""):"",h=d?` Last status: ok=${d.ok} exit=${null!==(i=d.exitCode)&&void 0!==i?i:"unknown"} finished_at=${d.finishedAt||"unknown"} session_name=${d.sessionName||"unknown"}.`:` Status file path: ${e.statusPath}.`,p=u?` Remote log:\n${u}`:` Remote log path: ${e.logPath}`;throw new Error(`Remote ${e.action} did not complete within ${n} ms.${h} Last error: ${String((null==l?void 0:l.message)||l||"unknown error")}.${p}`)}async pushInstallerAndUpgrade(e={}){var t,s,i,n,o;const r=this.bundledInstaller,c=String(e.remotePath||this.settings.installerRemotePath||"/tmp/bianbu_agent_proxy.sh").trim(),d=null!==(t=e.asRoot)&&void 0!==t?t:Boolean(this.settings.maintenanceAsRoot),u=e.action||"up",h=Number(null!==(i=null!==(s=e.reconnectPollMs)&&void 0!==s?s:this.settings.reconnectPollMs)&&void 0!==i?i:2e3),p=Number(null!==(o=null!==(n=e.healthTimeoutMs)&&void 0!==n?n:this.settings.upgradeHealthTimeoutMs)&&void 0!==o?o:12e4);if(!c)throw new Error("Remote installer path is required");const m=this.createMaintenanceSession(u,c,d),f=(0,a.remoteInstallerLogPath)(c),g=(0,a.remoteInstallerStatusPath)(c);m.remoteLogPath=f,m.remoteStatusPath=g,this.logSession(m,"info","Starting remote maintenance session",`remote_path=${c} action=${u}`);try{this.logSession(m,"info","Uploading bundled installer to remote host",c),await this.writeTextFile(c,r.script,d);const e=await this.runCommand((0,a.buildDetachedInstallerCommand)(c,u,f,g,m.sessionName),".",30,d);this.logSession(m,"info","Detached installer command launched",JSON.stringify(e,null,2));const{health:t,status:s}=await this.waitForInstallerCompletion({action:u,asRoot:d,expectedSessionName:m.sessionName,expectedScriptVersion:r.metadata.scriptVersion,expectedServerVersion:r.metadata.serverVersion,intervalMs:h,logPath:f,session:m,statusPath:g,timeoutMs:p});return(0,l.finishSessionLog)(m,"done"),this.logSession(m,"info","Remote maintenance session finished successfully"),{action:u,asRoot:d,health:t,installer:r.metadata,logPath:f,remotePath:c,session:m,start:e,status:s,statusPath:g}}catch(e){const t=String((null==e?void 0:e.message)||e);throw this.logSession(m,"error","Remote maintenance session failed",t),(0,l.finishSessionLog)(m,"error",void 0,t),e}}};u=i([(0,o.Injectable)(),n("design:paramtypes",[r.ConfigService])],u),t.BianbuMcpService=u},104(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuCloudProfileProvider=void 0;const i=s(650),n=s(678),o=s(241);class r extends i.ProfileProvider{constructor(){super(...arguments),this.id="bianbu-cloud",this.name="Bianbu Cloud",this.configDefaults={}}async getBuiltinProfiles(){return[{id:"bianbu-cloud-shell",type:"bianbu-cloud",name:"Bianbu Cloud Shell",icon:"terminal",color:"#2b6cb0",group:"Bianbu Cloud",disableDynamicTitle:!1,behaviorOnSessionEnd:"keep",weight:0,isBuiltin:!0,isTemplate:!1,options:{kind:"shell"}},{id:"bianbu-cloud-files",type:"bianbu-cloud",name:"Bianbu Cloud Files",icon:"folder-open",color:"#0f766e",group:"Bianbu Cloud",disableDynamicTitle:!0,behaviorOnSessionEnd:"keep",weight:1,isBuiltin:!0,isTemplate:!1,options:{kind:"files"}}]}async getNewTabParameters(e){return"files"===e.options.kind?{type:o.BianbuCloudFilesTabComponent,inputs:{profile:e}}:{type:n.BianbuCloudShellTabComponent,inputs:{profile:e}}}getSuggestedName(){return null}getDescription(e){var t;return"files"===(null===(t=e.options)||void 0===t?void 0:t.kind)?"Explorer-like file access backed by MCP file tools":"Terminal-like shell session backed by MCP run_command"}}t.BianbuCloudProfileProvider=r},215(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuPtySession=void 0;const i=s(349);class n extends i.BaseSession{constructor(e,t){super(e),this.mcp=t,this.sessionId=null,this.alive=!1,this.pollAbort=null,this.inputQueue=[],this.inputFlushTimer=null,this.initialCols=80,this.initialRows=24,this.lastCols=0,this.lastRows=0,this.resizeTimer=null}async start(e={}){this.open=!0,this.initialCols=e.cols||80,this.initialRows=e.rows||24;const t=await this.mcp.openPtySession(e.cwd||".",e.asRoot||!1,this.initialCols,this.initialRows);this.sessionId=t.session_id,this.alive=!0,this.lastCols=this.initialCols,this.lastRows=this.initialRows,this.startPollLoop()}write(e){this.alive&&this.sessionId&&(this.inputQueue.push(e),this.inputFlushTimer||(this.inputFlushTimer=setTimeout(()=>this.flushInput(),4)))}resize(e,t){this.sessionId&&this.alive&&(e===this.lastCols&&t===this.lastRows||(this.lastCols=e,this.lastRows=t,this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{this.resizeTimer=null,this.sessionId&&this.alive&&this.mcp.resizePty(this.sessionId,e,t).catch(()=>{})},100)))}kill(){this.cleanup()}async gracefullyKillProcess(){await this.cleanup()}supportsWorkingDirectory(){return!1}async getWorkingDirectory(){return null}async destroy(){await this.cleanup(),await super.destroy()}async flushInput(){var e;if(this.inputFlushTimer=null,!this.inputQueue.length||!this.sessionId||!this.alive)return;const t=Buffer.concat(this.inputQueue);this.inputQueue=[];try{const s=await this.mcp.writePtyInput(this.sessionId,t.toString("base64"));(null===(e=null==s?void 0:s.output)||void 0===e?void 0:e.data_base64)&&this.emitOutput(Buffer.from(s.output.data_base64,"base64")),(null==s?void 0:s.output)&&!s.output.alive&&(this.alive=!1,this.emitOutput(Buffer.from("\r\n[Process exited]\r\n")))}catch(e){this.logger.error("PTY write error",e)}}startPollLoop(){this.pollAbort=new AbortController,this.pollLoop()}async pollLoop(){for(;this.alive&&this.open;)try{const e=await this.mcp.readPtyOutputDirect(this.sessionId,this.pollAbort.signal);if((null==e?void 0:e.data_base64)&&this.emitOutput(Buffer.from(e.data_base64,"base64")),!(null==e?void 0:e.alive)){this.alive=!1,this.emitOutput(Buffer.from("\r\n[Process exited]\r\n"));break}}catch(e){if("AbortError"===(null==e?void 0:e.name))break;this.logger.warn("PTY poll error, retrying in 1s",e),await new Promise(e=>setTimeout(e,1e3))}}async cleanup(){var e;if(this.alive=!1,this.open=!1,null===(e=this.pollAbort)||void 0===e||e.abort(),this.pollAbort=null,this.inputFlushTimer&&(clearTimeout(this.inputFlushTimer),this.inputFlushTimer=null),this.resizeTimer&&(clearTimeout(this.resizeTimer),this.resizeTimer=null),this.sessionId){const e=this.sessionId;this.sessionId=null,await this.mcp.closePtySession(e).catch(()=>{})}}}t.BianbuPtySession=n},979(e,t,s){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.parseRemoteHealth=t.loadBundledInstaller=t.parseRemoteInstallerStatus=t.buildDetachedInstallerCommand=t.remoteInstallerStatusPath=t.remoteInstallerLogPath=t.appendRemoteSuffix=t.remoteDirName=t.shellQuote=t.validateConnectionSettings=t.normalizeMcpUrl=void 0;const n=s(982),o=i(s(947)),r=i(s(928));function a(e){return`'${String(e).replace(/'/g,"'\"'\"'")}'`}function l(e){const t=String(e||".").replace(/\\/g,"/"),s=t.lastIndexOf("/");return s<0?".":t.slice(0,s)||"/"}function c(e,t){return`${String(e||".").replace(/\\/g,"/")}${t}`}function d(e){return c(e,".log")}function u(e){return c(e,".status.json")}function h(e){return(0,n.createHash)("sha256").update(e,"utf8").digest("hex")}t.normalizeMcpUrl=function(e){return String(e||"").trim().replace(/\/+$/,"")},t.validateConnectionSettings=function(e){const t=[];return e.domain?/^https?:\/\//i.test(e.domain)&&t.push("Domain should not include https:// prefix"):t.push("MCP domain is required"),String((null==e?void 0:e.apiKey)||"").trim()||t.push("X-API-KEY is required"),t},t.shellQuote=a,t.remoteDirName=l,t.appendRemoteSuffix=c,t.remoteInstallerLogPath=d,t.remoteInstallerStatusPath=u,t.buildDetachedInstallerCommand=function(e,t,s=d(e),i=u(e),n=`maintenance-${t}`){const o=l(e),r=[`rm -f ${a(s)} ${a(i)}`,`export SESSION_NAME=${a(n)}`,`bash ${a(e)} ${t} > ${a(s)} 2>&1`,"__bianbu_rc=$?","__bianbu_ok=false",'[ "$__bianbu_rc" -eq 0 ] && __bianbu_ok=true','__bianbu_ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)"',`printf '{"ok":%s,"exit_code":%s,"finished_at":"%s","action":"%s","log_path":"%s","session_name":"%s"}\\n' "$__bianbu_ok" "$__bianbu_rc" "$__bianbu_ts" ${a(t)} ${a(s)} ${a(n)} > ${a(i)}`].join("; ");return[`mkdir -p ${a(o)}`,`chmod 700 ${a(e)}`,`nohup bash -lc ${a(r)} > /dev/null 2>&1 < /dev/null & printf '__BIANBU_UPGRADE_STARTED__%s\\n' "$!"`].join(" && ")},t.parseRemoteInstallerStatus=function(e){var t;const s="string"==typeof e?JSON.parse(String(e||"").trim()||"{}"):e||{},i=null!==(t=s.exit_code)&&void 0!==t?t:s.exitCode,n=null==i?null:Number(i);return{ok:"boolean"==typeof s.ok?s.ok:0===n,exitCode:Number.isFinite(n)?n:null,finishedAt:s.finished_at||s.finishedAt||null,action:s.action||null,logPath:s.log_path||s.logPath||null,sessionName:s.session_name||s.sessionName||null,raw:s}},t.loadBundledInstaller=function(e=__dirname){let t=null;for(const s of function(e){return[r.default.resolve(e,"../assets"),r.default.resolve(e,"../../assets"),r.default.resolve(process.cwd(),"assets")]}(e)){const e=r.default.join(s,"bianbu_agent_proxy.sh"),i=r.default.join(s,"bianbu_agent_proxy.meta.json"),n=o.default.existsSync(e),a=o.default.existsSync(i);if(n||a)try{const t=o.default.readFileSync(e,"utf8"),s=JSON.parse(o.default.readFileSync(i,"utf8"));if(!(null==s?void 0:s.sha256)||!(null==s?void 0:s.scriptVersion)||!(null==s?void 0:s.serverVersion))throw new Error(`Bundled installer metadata is incomplete at ${i}`);if(h(t)!==s.sha256)throw new Error(`Bundled installer SHA-256 mismatch for ${e}`);return{script:t,metadata:s}}catch(e){t=e;break}}throw new Error(`Unable to load bundled remote installer assets: ${String((null==t?void 0:t.message)||t)}`)},t.parseRemoteHealth=function(e){var t,s,i,n,o,r,a,l,c,d,u;const h=null!==(n=null!==(i=null!==(t=null==e?void 0:e.structuredContent)&&void 0!==t?t:null===(s=null==e?void 0:e.result)||void 0===s?void 0:s.structuredContent)&&void 0!==i?i:e)&&void 0!==n?n:{},p=Array.isArray(h.tools)?h.tools.map(e=>String(e)):[],m={renamePath:Boolean(null===(o=null==h?void 0:h.supports)||void 0===o?void 0:o.rename_path)||p.includes("rename_path"),shellSession:Boolean(null===(r=null==h?void 0:h.supports)||void 0===r?void 0:r.shell_session)||p.includes("open_shell_session"),chunkedTransfers:Boolean(null===(a=null==h?void 0:h.supports)||void 0===a?void 0:a.chunked_transfers)||p.includes("upload_chunked_begin")&&p.includes("download_chunked_begin"),parallelChunkOffsets:Boolean(null===(l=null==h?void 0:h.supports)||void 0===l?void 0:l.parallel_chunk_offsets),rateLimiting:Boolean(null===(c=null==h?void 0:h.supports)||void 0===c?void 0:c.rate_limiting),isoTimestamps:Boolean(null===(d=null==h?void 0:h.supports)||void 0===d?void 0:d.iso_timestamps),ptySession:Boolean(null===(u=null==h?void 0:h.supports)||void 0===u?void 0:u.pty_session)||p.includes("open_pty_session")};return{ok:!1!==h.ok,serverVersion:h.server_version||h.version||null,scriptVersion:h.script_version||null,transportMode:h.transport_mode||null,fileRoot:h.file_root||null,hasSudo:"boolean"==typeof h.has_sudo?h.has_sudo:null,tools:p,supports:m,raw:h}}},935(e,t){"use strict";function s(e){return String(e).padStart(2,"0")}function i(e=new Date){return new Date(e||Date.now()).toISOString().replace(/\.\d{3}Z$/,"Z")}function n(e=new Date){const t=new Date(e||Date.now());return[String(t.getUTCFullYear()),s(t.getUTCMonth()+1),s(t.getUTCDate()),"T",s(t.getUTCHours()),s(t.getUTCMinutes()),s(t.getUTCSeconds()),"Z"].join("")}function o(e){return String(e||"session").replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"session"}function r(e){const t=["# bianbu local session log",`session_name=${e.sessionName}`,`kind=${e.kind}`,`action=${e.action}`,`status=${e.status}`,`started_at=${e.startedAt}`,`finished_at=${e.finishedAt||""}`,`remote_path=${e.remotePath||""}`,`remote_log_path=${e.remoteLogPath||""}`,`remote_status_path=${e.remoteStatusPath||""}`,`as_root=${void 0===e.asRoot?"":String(e.asRoot)}`,"","--- local_log ---"],s=e.entries.length?e.entries.map(t=>function(e,t){const s=[`[${t.timestamp}] [${e}] [${t.level.toUpperCase()}] ${t.message}`],i=String(t.details||"").trim();if(i)for(const e of i.split(/\r?\n/))s.push(` ${e}`);return s.join("\n")}(e.sessionName,t)):["[no log entries recorded]"];return`${t.join("\n")}\n${s.join("\n")}\n`}Object.defineProperty(t,"__esModule",{value:!0}),t.buildRemoteLogDownloadPayload=t.buildLocalLogDownloadPayload=t.renderLocalSessionLog=t.finishSessionLog=t.appendSessionLogEntry=t.createSessionLog=t.createSessionName=t.toCompactUtcStamp=t.toIsoUtc=void 0,t.toIsoUtc=i,t.toCompactUtcStamp=n,t.createSessionName=function(e,t,s=new Date){return`${String(e||"session").trim()}-${String(t||"run").trim()}-${n(s)}`},t.createSessionLog=function(e){return{action:e.action,asRoot:e.asRoot,entries:[],kind:e.kind,remoteLogPath:e.remoteLogPath||null,remotePath:e.remotePath||null,remoteStatusPath:e.remoteStatusPath||null,sessionName:e.sessionName,startedAt:e.startedAt||i(),status:"running"}},t.appendSessionLogEntry=function(e,t){const s={timestamp:t.timestamp||i(),level:t.level,message:t.message,details:t.details||null};return e.entries.push(s),s},t.finishSessionLog=function(e,t,s=new Date,n){return e.status=t,e.finishedAt=i(s),e.error=n||null,e},t.renderLocalSessionLog=r,t.buildLocalLogDownloadPayload=function(e,t=new Date){return{fileName:`${o(e.sessionName)}-local-${n(t)}.log`,content:r(e)}},t.buildRemoteLogDownloadPayload=function(e){const t=i(e.downloadedAt),s=String(e.remoteStatusText||"").trim()||"[remote status unavailable]",r=String(e.remoteLogText||"").trim()||"[remote log unavailable]",a=e.session,l=["# bianbu remote session log",`downloaded_at=${t}`,`session_name=${a.sessionName}`,`kind=${a.kind}`,`action=${a.action}`,`status=${a.status}`,`started_at=${a.startedAt}`,`finished_at=${a.finishedAt||""}`,`remote_path=${a.remotePath||""}`,`remote_log_path=${a.remoteLogPath||""}`,`remote_status_path=${a.remoteStatusPath||""}`,"","--- remote_status ---",s,"","--- remote_log ---",r,""].join("\n");return{fileName:`${o(a.sessionName)}-remote-${n(e.downloadedAt)}.log`,content:l}}},645(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},n=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuMcpSettingsComponent=void 0;const o=s(860),r=s(650),a=s(241),l=s(678),c=s(885);let d=class{constructor(e,t,s,i,n){this.config=e,this.app=t,this.mcp=s,this.notifications=i,this.platform=n,this.diagnosticsBusy=!1,this.maintenanceBusy=!1,this.remoteHealth=null,this.lastDiagnosticAt="",this.lastMaintenanceAt="",this.lastMaintenanceSummary="",this.lastError="",this.advancedVisible=!1}get settings(){return this.config.store.bianbuMcp}get bundledInstaller(){try{return this.mcp.bundledInstaller.metadata}catch{return null}}get validationErrors(){return this.mcp.validationErrors}get latestMaintenanceSession(){return this.mcp.latestMaintenanceSession}get sampleJson(){const e=this.settings,t=String(e.domain||"").trim().replace(/^https?:\/\//i,"").replace(/\/+$/,"");return JSON.stringify({mcpServers:{[e.name||"bianbu"]:{type:"http",url:t?`https://${t}/mcp`:"https://your-domain.example.com/mcp",headers:{"X-API-KEY":e.apiKey?"••••••••":"your-x-api-key"}}}},null,2)}save(){this.config.save()}openShell(){this.app.openNewTab({type:l.BianbuCloudShellTabComponent})}openFiles(){this.app.openNewTab({type:a.BianbuCloudFilesTabComponent})}async testConnection(){await this.refreshHealth("Connection verified")}async refreshHealth(e="Remote health refreshed"){this.lastError="",this.diagnosticsBusy=!0;try{this.remoteHealth=await this.mcp.getHealth(),this.lastDiagnosticAt=(new Date).toLocaleString(),this.notifications.notice(e)}catch(e){this.lastError=String((null==e?void 0:e.message)||e),this.notifications.error("Bianbu MCP health check failed",this.lastError)}finally{this.diagnosticsBusy=!1}}async pushUpgrade(e="up"){var t,s,i,n;this.lastError="",this.maintenanceBusy=!0;try{const s=await this.mcp.pushInstallerAndUpgrade({action:e,asRoot:!!this.settings.maintenanceAsRoot,healthTimeoutMs:this.settings.upgradeHealthTimeoutMs,reconnectPollMs:this.settings.reconnectPollMs,remotePath:this.settings.installerRemotePath});this.remoteHealth=s.health,this.lastMaintenanceAt=(new Date).toLocaleString(),this.lastMaintenanceSummary=`session=${(null===(t=s.session)||void 0===t?void 0:t.sessionName)||"unknown"} action=${s.action} remotePath=${s.remotePath} logPath=${s.logPath} statusPath=${s.statusPath} script=${s.health.scriptVersion||"unknown"} server=${s.health.serverVersion||"unknown"}`,this.notifications.notice("repair"===e?"Remote repair finished":"Remote upgrade finished")}catch(t){this.lastMaintenanceAt=(new Date).toLocaleString(),this.lastMaintenanceSummary=`session=${(null===(s=this.latestMaintenanceSession)||void 0===s?void 0:s.sessionName)||"unknown"} action=${e} remotePath=${this.settings.installerRemotePath||"unknown"} logPath=${(null===(i=this.latestMaintenanceSession)||void 0===i?void 0:i.remoteLogPath)||"unknown"} statusPath=${(null===(n=this.latestMaintenanceSession)||void 0===n?void 0:n.remoteStatusPath)||"unknown"}`,this.lastError=String((null==t?void 0:t.message)||t),this.notifications.error("repair"===e?"Remote repair failed":"Remote upgrade failed",this.lastError)}finally{this.maintenanceBusy=!1}}async downloadLocalMaintenanceLog(){try{const e=this.mcp.getLatestMaintenanceLocalLogDownloadPayload();await this.downloadTextFile(e.fileName,e.content),this.notifications.notice("Local maintenance log downloaded")}catch(e){this.lastError=String((null==e?void 0:e.message)||e),this.notifications.error("Failed to download local maintenance log",this.lastError)}}async downloadRemoteMaintenanceLog(){try{const e=await this.mcp.getLatestMaintenanceRemoteLogDownloadPayload();await this.downloadTextFile(e.fileName,e.content),this.notifications.notice("Remote maintenance log downloaded")}catch(e){this.lastError=String((null==e?void 0:e.message)||e),this.notifications.error("Failed to download remote maintenance log",this.lastError)}}async downloadTextFile(e,t){const s=(new TextEncoder).encode(t),i=await this.platform.startDownload(e,420,s.length);if(!i)throw new Error("Download cancelled");try{await i.write(s),i.close()}catch(e){throw i.close(),e}}};d=i([(0,o.Component)({template:s(426)}),n("design:paramtypes",[r.ConfigService,r.AppService,c.BianbuMcpService,r.NotificationsService,r.PlatformService])],d),t.BianbuMcpSettingsComponent=d},717(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuMcpSettingsTabProvider=void 0;const n=s(860),o=s(700),r=s(645);let a=class extends o.SettingsTabProvider{constructor(){super(...arguments),this.id="bianbu-mcp",this.icon="plug",this.title="Bianbu MCP"}getComponentType(){return r.BianbuMcpSettingsComponent}};a=i([(0,n.Injectable)()],a),t.BianbuMcpSettingsTabProvider=a},864(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuShellSession=void 0;const i=s(349);class n extends i.BaseSession{constructor(e,t){super(e),this.mcp=t,this.cwd=".",this.currentLine="",this.cursorPos=0,this.running=!1,this.asRoot=!1,this.sessionId=null,this.history=[],this.historyIndex=-1,this.savedLine="",this.escBuffer="",this.escTimer=null}async start(e={}){this.open=!0,this.cwd=e.cwd||".",this.asRoot=e.asRoot||!1,this.emitText("Connected to Bianbu Cloud MCP shell\r\n");try{const e=await this.mcp.openShellSession(this.cwd,this.asRoot);this.sessionId=e.session_id||null,this.sessionId&&this.emitText("Using persistent shell session\r\n")}catch{this.sessionId=null,this.emitText("Using stateless command mode\r\n")}this.emitPrompt()}resize(e,t){}write(e){const t=e.toString("utf-8");for(const e of t)this.handleChar(e)}kill(){this.running=!1,this.closeRemoteSession()}async gracefullyKillProcess(){this.running=!1,await this.closeRemoteSession()}async destroy(){this.running=!1,await this.closeRemoteSession(),await super.destroy()}supportsWorkingDirectory(){return!0}async getWorkingDirectory(){return this.cwd}handleChar(e){if(this.escBuffer.length>0||""===e)if(this.escBuffer+=e,this.escTimer&&clearTimeout(this.escTimer),this.escBuffer.length>=3&&"["===this.escBuffer[1]){const e=this.escBuffer[this.escBuffer.length-1];if(e>="@"&&e<="~"){const e=this.escBuffer;return this.escBuffer="",void this.handleEscSequence(e)}if(this.escBuffer.length>8)return void(this.escBuffer="")}else 1===this.escBuffer.length?this.escTimer=setTimeout(()=>{this.escBuffer=""},50):this.escBuffer.length>2&&"["!==this.escBuffer[1]&&(this.escBuffer="");else if(this.running)""===e&&this.emitText("^C\r\n");else switch(e){case"\r":case"\n":this.emitText("\r\n"),this.currentLine.trim()?(this.addToHistory(this.currentLine),this.execute(this.currentLine)):this.emitPrompt(),this.currentLine="",this.cursorPos=0,this.historyIndex=-1,this.savedLine="";break;case"":case"\b":this.cursorPos>0&&(this.currentLine=this.currentLine.slice(0,this.cursorPos-1)+this.currentLine.slice(this.cursorPos),this.cursorPos--,this.redrawLine());break;case"":this.currentLine="",this.cursorPos=0,this.historyIndex=-1,this.savedLine="",this.emitText("^C\r\n"),this.emitPrompt();break;case"":this.cursorPos>0&&(this.cursorPos=0,this.redrawLine());break;case"":this.cursorPos<this.currentLine.length&&(this.cursorPos=this.currentLine.length,this.redrawLine());break;case"":this.cursorPos>0&&(this.currentLine=this.currentLine.slice(this.cursorPos),this.cursorPos=0,this.redrawLine());break;case"\v":this.cursorPos<this.currentLine.length&&(this.currentLine=this.currentLine.slice(0,this.cursorPos),this.redrawLine());break;case"":if(this.cursorPos>0){const e=this.currentLine.slice(0,this.cursorPos).replace(/\S+\s*$/,""),t=this.currentLine.slice(this.cursorPos);this.currentLine=e+t,this.cursorPos=e.length,this.redrawLine()}break;case"\f":this.emitText(""),this.emitPrompt(),this.emitText(this.currentLine),this.cursorPos<this.currentLine.length&&this.emitText(`[${this.currentLine.length-this.cursorPos}D`);break;case"\t":break;default:e>=" "&&(this.currentLine=this.currentLine.slice(0,this.cursorPos)+e+this.currentLine.slice(this.cursorPos),this.cursorPos++,this.redrawLine())}}handleEscSequence(e){if(!this.running)switch(e){case"":this.navigateHistory(1);break;case"":this.navigateHistory(-1);break;case"":this.cursorPos<this.currentLine.length&&(this.cursorPos++,this.emitText(""));break;case"":this.cursorPos>0&&(this.cursorPos--,this.emitText(""));break;case"":this.cursorPos=0,this.redrawLine();break;case"":this.cursorPos=this.currentLine.length,this.redrawLine();break;case"[3~":this.cursorPos<this.currentLine.length&&(this.currentLine=this.currentLine.slice(0,this.cursorPos)+this.currentLine.slice(this.cursorPos+1),this.redrawLine())}}navigateHistory(e){if(this.history.length){if(-1===this.historyIndex&&e>0)this.savedLine=this.currentLine,this.historyIndex=0;else if(e>0&&this.historyIndex<this.history.length-1)this.historyIndex++;else{if(!(e<0&&this.historyIndex>0))return e<0&&0===this.historyIndex?(this.historyIndex=-1,this.currentLine=this.savedLine,this.cursorPos=this.currentLine.length,void this.redrawLine()):void 0;this.historyIndex--}this.historyIndex>=0&&this.historyIndex<this.history.length&&(this.currentLine=this.history[this.historyIndex],this.cursorPos=this.currentLine.length,this.redrawLine())}}addToHistory(e){const t=e.trim();t&&(this.history.length>0&&this.history[0]===t||(this.history.unshift(t),this.history.length>200&&(this.history.length=200)))}redrawLine(){const e=this.getPrompt();this.emitText(`\r${e}${this.currentLine}`);const t=this.currentLine.length-this.cursorPos;t>0&&this.emitText(`[${t}D`)}async execute(e){var t,s;this.running=!0,this.emitText("⏳ Running...\r\n");try{let i;i=this.sessionId?await this.mcp.execShellSession(this.sessionId,e,120):await this.mcp.runCommand(e,this.cwd,120,this.asRoot);const n=(null==i?void 0:i.stdout)||(null===(s=null===(t=null==i?void 0:i.content)||void 0===t?void 0:t[0])||void 0===s?void 0:s.text)||"",o=(null==i?void 0:i.stderr)||"";n&&this.emitText(this.normalize(n)),o&&this.emitText(`${this.normalize(o)}`),null==(null==i?void 0:i.exit_code)||0===i.exit_code||o||this.emitText(`command exited with code ${i.exit_code}\r\n`),(null==i?void 0:i.cwd)&&(this.cwd=i.cwd)}catch(e){this.emitText(`${this.normalize(String((null==e?void 0:e.message)||e))}`)}finally{this.running=!1,this.emitPrompt()}}async closeRemoteSession(){if(this.sessionId){try{await this.mcp.closeShellSession(this.sessionId)}catch{}this.sessionId=null}}getPrompt(){return`[bianbu ${this.cwd}]${this.asRoot?"#":"$"} `}emitPrompt(){this.emitText(this.getPrompt())}emitText(e){this.emitOutput(Buffer.from(e,"utf-8"))}normalize(e){let t=e.replace(/\r?\n/g,"\r\n");return t.endsWith("\r\n")||(t+="\r\n"),t}}t.BianbuShellSession=n},678(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},n=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuCloudShellTabComponent=void 0;const o=s(860),r=s(349),a=s(650),l=s(885),c=s(864),d=s(215);let u=class extends r.BaseTerminalTabComponent{constructor(e,t,s){super(e),this.mcp=t,this.localNotifications=s,this.asRoot=!1,this.cwd=".",this.setTitle("Bianbu Cloud Shell"),this.icon="terminal",this.enableToolbar=!0,this.profile=this.profile||{id:"bianbu-cloud-shell",type:"bianbu-cloud",name:"Bianbu Cloud Shell",group:"Bianbu Cloud",options:{kind:"shell"},icon:"terminal",color:"#2b6cb0",disableDynamicTitle:!1,behaviorOnSessionEnd:"keep",weight:0,isBuiltin:!0,isTemplate:!1}}async onFrontendReady(){var e,t,s;let i;const n=await this.mcp.getHealth().catch(()=>null);if(null===(e=null==n?void 0:n.supports)||void 0===e?void 0:e.ptySession)try{const e=new d.BianbuPtySession(this.logger,this.mcp);i=e,this.setSession(i,!0),await e.start({cwd:this.cwd,asRoot:this.asRoot,cols:(null===(t=this.size)||void 0===t?void 0:t.columns)||80,rows:(null===(s=this.size)||void 0===s?void 0:s.rows)||24})}catch(e){this.logger.warn("PTY session failed, falling back to shell session",e);const t=new c.BianbuShellSession(this.logger,this.mcp);i=t,this.setSession(i,!0),await t.start({cwd:this.cwd,asRoot:this.asRoot})}else{const e=new c.BianbuShellSession(this.logger,this.mcp);i=e,this.setSession(i,!0),await e.start({cwd:this.cwd,asRoot:this.asRoot})}i.releaseInitialDataBuffer(),this.localNotifications.notice("Bianbu Cloud shell ready"),await super.onFrontendReady()}};i([(0,o.Input)(),n("design:type",Object)],u.prototype,"profile",void 0),i([(0,o.Input)(),n("design:type",Object)],u.prototype,"asRoot",void 0),i([(0,o.Input)(),n("design:type",Object)],u.prototype,"cwd",void 0),u=i([(0,o.Component)({template:r.BaseTerminalTabComponent.template,styles:r.BaseTerminalTabComponent.styles,animations:r.BaseTerminalTabComponent.animations}),n("design:paramtypes",[o.Injector,l.BianbuMcpService,a.NotificationsService])],u),t.BianbuCloudShellTabComponent=u},982(e){"use strict";e.exports=require("crypto")},928(e){"use strict";e.exports=require("path")},358(t){"use strict";t.exports=e},860(e){"use strict";e.exports=t},182(e){"use strict";e.exports=s},947(e){"use strict";e.exports=i},650(e){"use strict";e.exports=n},700(e){"use strict";e.exports=o},349(e){"use strict";e.exports=r}},l={},function e(t){var s=l[t];if(void 0!==s)return s.exports;var i=l[t]={exports:{}};return a[t].call(i.exports,i,i.exports,e),i.exports}(440);var a,l});
1
+ !function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("@angular/common"),require("@angular/core"),require("@angular/forms"),require("fs"),require("tabby-core"),require("tabby-settings"),require("tabby-terminal"));else if("function"==typeof define&&define.amd)define(["@angular/common","@angular/core","@angular/forms","fs","tabby-core","tabby-settings","tabby-terminal"],t);else{var s="object"==typeof exports?t(require("@angular/common"),require("@angular/core"),require("@angular/forms"),require("fs"),require("tabby-core"),require("tabby-settings"),require("tabby-terminal")):t(e["@angular/common"],e["@angular/core"],e["@angular/forms"],e.fs,e["tabby-core"],e["tabby-settings"],e["tabby-terminal"]);for(var i in s)("object"==typeof exports?exports:e)[i]=s[i]}}(global,(e,t,s,i,n,o,r)=>{return a={102(e,t,s){var i=s(169);e.exports=(i.default||i).apply(i,[])},426(e,t,s){var i=s(295);e.exports=(i.default||i).apply(i,[])},169(e,t,s){s(766),e.exports=function(e){return""+'<div style="height:100%;display:flex;flex-direction:column;background:rgba(30,30,30,.96);color:#e4e4e4;font-family:&quot;Segoe UI Variable&quot;,&quot;Segoe UI&quot;,system-ui,-apple-system,sans-serif;font-size:13px;overflow:hidden"><div class="toolbar" style="display:flex;align-items:center;gap:6px;padding:6px 12px;background:rgba(255,255,255,.04);border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;min-height:40px"><div class="btn-group" style="display:flex;gap:2px;background:rgba(255,255,255,.06);border-radius:6px;padding:2px"><button type="button" (click)="goBack()" [disabled]="historyIndex &lt;= 0" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:14px;opacity:.8" title="Back">←</button><button type="button" (click)="goForward()" [disabled]="historyIndex &gt;= history.length - 1" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:14px;opacity:.8" title="Forward">→</button><button type="button" (click)="goUp()" [disabled]="currentPath === &quot;.&quot; || currentPath === &quot;/&quot;" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:14px;opacity:.8" title="Up">↑</button></div><div class="breadcrumbs" style="display:flex;align-items:center;gap:2px;flex:1;min-width:0;background:rgba(255,255,255,.05);border-radius:6px;padding:0 8px;height:30px;overflow:hidden"><span *ngFor="let crumb of breadcrumbs; let i = index" (click)="navigateBreadcrumb(i)" style="cursor:pointer;padding:2px 4px;border-radius:3px;white-space:nowrap;opacity:.85;font-size:12px" [style.font-weight]="i === breadcrumbs.length - 1 ? &quot;600&quot; : &quot;400&quot;">{{ crumb }}<span *ngIf="i &lt; breadcrumbs.length - 1" style="opacity:.4;margin-left:4px">›</span></span></div><input id="bianbu-path-input" type="text" [(ngModel)]="pathInput" (keyup.enter)="navigateToInput()" placeholder="Enter path…" style="width:200px;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08);border-radius:6px;padding:4px 10px;color:#e4e4e4;font-size:12px;height:30px;outline:none"><div class="btn-group" style="display:flex;gap:2px;background:rgba(255,255,255,.06);border-radius:6px;padding:2px"><button type="button" (click)="refresh()" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:13px;opacity:.8" title="Refresh (F5)">⟳</button><button type="button" (click)="openCreateFilePrompt()" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:13px;opacity:.8" title="New file (Ctrl+N)">+📄</button><button type="button" (click)="openCreateDirectoryPrompt()" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:13px;opacity:.8" title="New folder (Ctrl+Shift+N)">+📁</button></div><label style="background:rgba(255,255,255,.06);border-radius:6px;padding:4px 10px;cursor:pointer;font-size:12px;height:30px;display:flex;align-items:center;gap:4px;opacity:.85">⬆ Upload<input type="file" multiple (change)="uploadFile($event)" style="display:none"></label><button type="button" (click)="toggleDetailPane()" style="background:none;border:none;color:#e4e4e4;padding:4px 8px;border-radius:4px;cursor:pointer;font-size:13px;opacity:.8" [style.opacity]="detailPaneVisible ? &quot;1&quot; : &quot;.5&quot;" title="Toggle preview">☰</button><label style="display:flex;align-items:center;gap:4px;margin-left:4px;opacity:.7;font-size:11px;cursor:pointer"><input type="checkbox" [(ngModel)]="asRoot" (ngModelChange)="refresh()">root</label></div><div class="search-bar" style="display:flex;align-items:center;gap:8px;padding:4px 12px;flex-shrink:0"><input type="text" [(ngModel)]="searchText" (ngModelChange)="applyFilter()" placeholder="🔍 Filter files…" style="flex:1;max-width:280px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.06);border-radius:6px;padding:4px 10px;color:#e4e4e4;font-size:12px;height:28px;outline:none"><span style="opacity:.5;font-size:11px;white-space:nowrap">{{ filteredItems.length }} items</span><span *ngIf="selectionSummary" style="opacity:.5;font-size:11px">• {{ selectionSummary }}</span><span style="opacity:.5;font-size:11px;margin-left:auto">{{ totalSize }}</span></div><div class="main" style="flex:1;display:flex;overflow:hidden"><div class="file-list-pane" style="flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:300px" (dragover)="onDragOver($event)" (dragleave)="onDragLeave()" (drop)="onDrop($event)"><div *ngIf="dragActive" style="position:absolute;inset:0;z-index:10;background:rgba(74,222,128,.12);display:flex;align-items:center;justify-content:center;border:2px dashed rgba(74,222,128,.5);border-radius:8px;pointer-events:none"><span style="font-size:16px;color:#4ade80">Drop files to upload</span></div><div class="table-header" style="display:flex;padding:0 12px;background:rgba(255,255,255,.03);border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;user-select:none"><span style="flex:5;padding:6px 4px;cursor:pointer;font-size:12px;font-weight:600;opacity:.7" (click)="toggleSort(&quot;name&quot;)">Name{{ sortIndicator(\'name\') }}</span><span style="flex:1.5;padding:6px 4px;cursor:pointer;font-size:12px;font-weight:600;opacity:.7;text-align:right" (click)="toggleSort(&quot;size&quot;)">Size{{ sortIndicator(\'size\') }}</span><span style="flex:2.5;padding:6px 4px;cursor:pointer;font-size:12px;font-weight:600;opacity:.7" (click)="toggleSort(&quot;date&quot;)">Modified{{ sortIndicator(\'date\') }}</span><span style="flex:1.2;padding:6px 4px;cursor:pointer;font-size:12px;font-weight:600;opacity:.7" (click)="toggleSort(&quot;type&quot;)">Type{{ sortIndicator(\'type\') }}</span></div><div class="file-list" style="flex:1;overflow-y:auto;overflow-x:hidden"><div *ngFor="let item of filteredItems; let i = index" (click)="selectItem(item, $event)" (dblclick)="openItem(item)" (contextmenu)="showContextMenu($event, item)" style="display:flex;padding:0 12px;cursor:default;border-bottom:1px solid rgba(255,255,255,.02);transition:background .1s" [style.background]="isSelected(i) ? &quot;rgba(98,100,167,.35)&quot; : &quot;transparent&quot;"><span style="flex:5;padding:5px 4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:6px"><span style="font-size:15px;flex-shrink:0">{{ fileIcon(item) }}</span><span style="font-weight:500">{{ baseName(item.path) }}</span></span><span style="flex:1.5;padding:5px 4px;opacity:.6;text-align:right;font-variant-numeric:tabular-nums">{{ item.is_dir ? \'—\' : formatSize(item.size) }}</span><span style="flex:2.5;padding:5px 4px;opacity:.5;font-variant-numeric:tabular-nums">{{ formatDate(item.modified) }}</span><span style="flex:1.2;padding:5px 4px;opacity:.5">{{ fileType(item) }}</span></div><div *ngIf="!filteredItems.length &amp;&amp; !busy" style="padding:40px;text-align:center;opacity:.4"><div style="font-size:32px;margin-bottom:8px">📂</div><div>{{ searchText ? \'No matches\' : \'Empty directory\' }}</div></div></div></div><div class="detail-pane" *ngIf="detailPaneVisible" style="width:340px;border-left:1px solid rgba(255,255,255,.06);display:flex;flex-direction:column;flex-shrink:0;background:rgba(255,255,255,.02)"><div class="detail-header" style="padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.06);display:flex;align-items:center;gap:8px;flex-shrink:0"><span style="font-size:18px">{{ selectedItem ? fileIcon(selectedItem) : \'📄\' }}</span><span style="font-weight:600;font-size:13px;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{ selectedPath ? baseName(selectedPath) : \'No selection\' }}</span><button *ngIf="selectedPath" type="button" (click)="downloadSelected()" style="background:rgba(255,255,255,.08);border:none;color:#e4e4e4;padding:3px 8px;border-radius:4px;cursor:pointer;font-size:11px">⬇</button><button *ngIf="selectedPath &amp;&amp; selectedIsText" type="button" (click)="saveSelected()" style="background:rgba(59,130,246,.6);border:none;color:white;padding:3px 8px;border-radius:4px;cursor:pointer;font-size:11px">Save</button></div><div class="detail-content" style="flex:1;overflow:auto;padding:0"><textarea *ngIf="selectedPath &amp;&amp; selectedIsText" [(ngModel)]="selectedContent" style="width:100%;height:100%;background:transparent;border:none;color:#d4d4d8;font-family:&quot;Cascadia Code&quot;,&quot;Fira Code&quot;,&quot;JetBrains Mono&quot;,monospace;font-size:12px;padding:10px 14px;resize:none;outline:none;line-height:1.5;tab-size:4;box-sizing:border-box"></textarea><div *ngIf="selectedPath &amp;&amp; !selectedIsText" style="padding:30px;text-align:center;opacity:.5"><div style="font-size:28px;margin-bottom:8px">{{ selectedItem ? fileIcon(selectedItem) : \'📄\' }}</div><div>Binary file</div><button type="button" (click)="downloadSelected()" style="margin-top:12px;background:rgba(255,255,255,.08);border:none;color:#e4e4e4;padding:6px 16px;border-radius:6px;cursor:pointer;font-size:12px">Download</button></div><div *ngIf="!selectedPath" style="padding:30px;text-align:center;opacity:.3"><div style="font-size:28px;margin-bottom:8px">👆</div><div style="font-size:12px">Select a file to preview</div></div></div></div></div><div class="status-bar" style="display:flex;align-items:center;gap:12px;padding:4px 12px;background:rgba(255,255,255,.03);border-top:1px solid rgba(255,255,255,.06);flex-shrink:0;font-size:11px;opacity:.6;min-height:24px"><span>{{ status }}</span><span *ngIf="transfers.length" (click)="transfersVisible = !transfersVisible" style="margin-left:auto;cursor:pointer;opacity:.8">{{ activeTransferLabel }}</span></div><div *ngIf="contextMenuVisible" style="position:fixed;z-index:100;background:rgba(45,45,45,.98);border:1px solid rgba(255,255,255,.12);border-radius:8px;padding:4px;min-width:160px;backdrop-filter:blur(16px);box-shadow:0 8px 32px rgba(0,0,0,.4)" [style.left.px]="contextMenuX" [style.top.px]="contextMenuY"><button type="button" (click)="openItem(contextItem); hideContextMenu()" style="display:block;width:100%;text-align:left;background:none;border:none;color:#e4e4e4;padding:6px 12px;border-radius:4px;cursor:pointer;font-size:12px">Open</button><button type="button" (click)="openRenamePrompt(contextItem); hideContextMenu()" style="display:block;width:100%;text-align:left;background:none;border:none;color:#e4e4e4;padding:6px 12px;border-radius:4px;cursor:pointer;font-size:12px">Rename</button><div style="height:1px;background:rgba(255,255,255,.08);margin:2px 8px"></div><button type="button" (click)="deleteItem(contextItem); hideContextMenu()" style="display:block;width:100%;text-align:left;background:none;border:none;color:#f87171;padding:6px 12px;border-radius:4px;cursor:pointer;font-size:12px">Delete</button></div><div *ngIf="promptVisible" style="position:fixed;inset:0;z-index:200;background:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;backdrop-filter:blur(4px)"><div style="background:rgba(45,45,45,.98);border:1px solid rgba(255,255,255,.1);border-radius:12px;padding:24px;width:380px;box-shadow:0 16px 48px rgba(0,0,0,.5)"><h3 style="margin:0 0 16px 0;font-size:15px;font-weight:600">{{ promptTitle }}</h3><input type="text" [(ngModel)]="promptValue" (keyup.enter)="confirmPrompt()" (keyup.escape)="closePrompt()" autofocus style="width:100%;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-radius:6px;padding:8px 12px;color:#e4e4e4;font-size:13px;outline:none;box-sizing:border-box"><div style="display:flex;gap:8px;margin-top:16px;justify-content:flex-end"><button type="button" (click)="closePrompt()" style="background:rgba(255,255,255,.08);border:none;color:#e4e4e4;padding:6px 20px;border-radius:6px;cursor:pointer;font-size:12px">Cancel</button><button type="button" (click)="confirmPrompt()" style="background:rgba(59,130,246,.7);border:none;color:white;padding:6px 20px;border-radius:6px;cursor:pointer;font-size:12px">Confirm</button></div></div></div><div *ngIf="transfersVisible &amp;&amp; transfers.length" style="position:fixed;right:16px;bottom:40px;width:380px;max-height:45vh;background:rgba(40,40,40,.98);border:1px solid rgba(255,255,255,.1);border-radius:12px;z-index:50;overflow:hidden;box-shadow:0 12px 40px rgba(0,0,0,.4);backdrop-filter:blur(16px)"><div style="padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.06);display:flex;align-items:center"><span style="font-weight:600;font-size:13px;flex:1">Transfers</span><button type="button" (click)="transfersVisible = false" style="background:none;border:none;color:#e4e4e4;cursor:pointer;font-size:16px;opacity:.6">×</button></div><div style="overflow-y:auto;max-height:calc(45vh - 44px)"><div *ngFor="let transfer of transfers" style="padding:10px 14px;border-bottom:1px solid rgba(255,255,255,.04)"><div style="display:flex;align-items:center;gap:6px;margin-bottom:4px"><span style="font-size:11px">{{ transfer.direction === \'upload\' ? \'⬆\' : \'⬇\' }}</span><span style="font-size:12px;font-weight:500;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">{{ transfer.name }}</span><span style="font-size:10px;opacity:.5;padding:1px 6px;border-radius:3px;background:rgba(255,255,255,.06)">{{ transfer.status }}</span><button *ngIf="transfer.status === &quot;running&quot; || transfer.status === &quot;queued&quot;" type="button" (click)="cancelTransfer(transfer)" style="background:none;border:none;color:#f87171;cursor:pointer;font-size:11px;padding:2px 4px">✕</button></div><div *ngIf="transfer.bytesTotal" style="height:3px;background:rgba(255,255,255,.08);border-radius:2px;overflow:hidden"><div style="height:100%;border-radius:2px;transition:width .2s" [style.width.%]="transferPercent(transfer) || 0" [style.background]="transfer.status === &quot;error&quot; ? &quot;#f87171&quot; : transfer.status === &quot;done&quot; ? &quot;#4ade80&quot; : &quot;#3b82f6&quot;"></div></div><div style="display:flex;gap:8px;margin-top:3px;font-size:10px;opacity:.4"><span>{{ formatSize(transfer.bytesDone) }} / {{ formatSize(transfer.bytesTotal) }}</span><span>{{ transferRate(transfer) }}</span></div></div></div></div></div>'}},295(e,t,s){s(766),e.exports=function(e){return""+'<div style="padding:20px;display:flex;flex-direction:column;gap:16px;font-family:&quot;Segoe UI Variable&quot;,&quot;Segoe UI&quot;,system-ui,sans-serif;max-width:720px"><div style="padding:16px 20px;border-radius:10px;background:linear-gradient(135deg,rgba(25,53,103,.9),rgba(17,94,89,.85));color:white"><h2 style="margin:0 0 4px 0;font-size:18px;font-weight:600">Bianbu MCP</h2><p style="margin:0;opacity:.85;font-size:13px">Connect to your Bianbu Cloud VM via MCP.</p></div><div class="card" style="padding:16px 20px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08)"><h3 style="margin:0 0 14px 0;font-size:14px;font-weight:600">Connection</h3><div class="field" style="display:flex;align-items:center;gap:8px;margin-bottom:10px"><label style="width:80px;font-size:12px;opacity:.7;flex-shrink:0">Name</label><input class="form-control" type="text" [(ngModel)]="settings.name" (ngModelChange)="save()" placeholder="bianbu" style="flex:1;max-width:180px"></div><div class="field" style="display:flex;align-items:center;gap:0;margin-bottom:10px"><label style="width:80px;font-size:12px;opacity:.7;flex-shrink:0">Endpoint</label><span style="background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-right:none;border-radius:6px 0 0 6px;padding:5px 10px;font-size:12px;color:#93c5fd;white-space:nowrap">https://</span><input class="form-control" type="text" [(ngModel)]="settings.domain" (ngModelChange)="save()" placeholder="your-domain.example.com" style="flex:1;border-radius:0;border-left:none;border-right:none"><span style="background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.1);border-left:none;border-radius:0 6px 6px 0;padding:5px 10px;font-size:12px;color:#93c5fd;white-space:nowrap">/mcp</span></div><div class="field" style="display:flex;align-items:center;gap:8px;margin-bottom:14px"><label style="width:80px;font-size:12px;opacity:.7;flex-shrink:0">API Key</label><input class="form-control" type="password" [(ngModel)]="settings.apiKey" (ngModelChange)="save()" placeholder="your-x-api-key" style="flex:1"></div><div style="display:flex;gap:8px;flex-wrap:wrap"><button class="btn btn-primary" type="button" (click)="testConnection()" [disabled]="diagnosticsBusy || validationErrors.length &gt; 0" style="font-size:12px;padding:5px 14px">Test connection</button><button class="btn btn-secondary" type="button" (click)="openShell()" style="font-size:12px;padding:5px 14px">Open Shell</button><button class="btn btn-secondary" type="button" (click)="openFiles()" style="font-size:12px;padding:5px 14px">Open Files</button></div><div *ngIf="validationErrors.length" style="margin-top:10px;color:#fca5a5;font-size:12px"><div *ngFor="let e of validationErrors">⚠ {{ e }}</div></div></div><div class="card" style="padding:16px 20px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08)"><div style="display:flex;align-items:center;cursor:pointer" (click)="advancedVisible = !advancedVisible"><h3 style="margin:0;font-size:14px;font-weight:600;flex:1">Remote status & maintenance</h3><span style="opacity:.5;font-size:12px">{{ advancedVisible ? \'▼\' : \'▶\' }}</span></div><div *ngIf="remoteHealth || lastError" style="margin-top:12px;display:grid;grid-template-columns:repeat(2,1fr);gap:6px;font-size:12px"><div style="opacity:.6">Script: {{ remoteHealth?.scriptVersion || \'unknown\' }}</div><div style="opacity:.6">Server: {{ remoteHealth?.serverVersion || \'unknown\' }}</div><div style="opacity:.6">Transport: {{ remoteHealth?.transportMode || \'unknown\' }}</div><div style="opacity:.6">Last check: {{ lastDiagnosticAt || \'never\' }}</div></div><div *ngIf="lastError" style="margin-top:8px;padding:10px 14px;border-radius:6px;background:rgba(239,68,68,.08);border:1px solid rgba(239,68,68,.25);color:#fca5a5;font-size:12px;white-space:pre-wrap;word-break:break-word;max-height:200px;overflow-y:auto">{{ lastError }}</div><div *ngIf="advancedVisible" style="margin-top:14px"><div style="display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px"><button class="btn btn-secondary" type="button" (click)="refreshHealth()" [disabled]="diagnosticsBusy || validationErrors.length &gt; 0" style="font-size:11px;padding:4px 12px">Fetch health</button><button class="btn btn-primary" type="button" (click)="pushUpgrade(&quot;up&quot;)" [disabled]="maintenanceBusy || validationErrors.length &gt; 0" style="font-size:11px;padding:4px 12px">Push upgrade</button><button class="btn btn-secondary" type="button" (click)="pushUpgrade(&quot;repair&quot;)" [disabled]="maintenanceBusy || validationErrors.length &gt; 0" style="font-size:11px;padding:4px 12px">Push repair</button></div><div *ngIf="maintenanceProgress" style="margin-bottom:14px;padding:12px 16px;border-radius:8px;background:rgba(0,0,0,.2);border:1px solid rgba(255,255,255,.06)"><div style="display:flex;align-items:center;gap:4px;margin-bottom:10px"><ng-container *ngFor="let stepName of [&quot;Upload&quot;,&quot;Launch&quot;,&quot;Wait&quot;,&quot;Verify&quot;]; let i = index"><div style="display:flex;align-items:center;gap:4px"><div style="width:20px;height:20px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600;transition:background .2s" [style.background]="maintenanceProgress.error &amp;&amp; i === maintenanceProgress.stepIndex ? &quot;rgba(239,68,68,.8)&quot; : i &lt; maintenanceProgress.stepIndex ? &quot;rgba(74,222,128,.7)&quot; : i === maintenanceProgress.stepIndex ? &quot;rgba(59,130,246,.8)&quot; : &quot;rgba(255,255,255,.08)&quot;" [style.color]="i &lt;= maintenanceProgress.stepIndex ? &quot;white&quot; : &quot;rgba(255,255,255,.3)&quot;"><span *ngIf="!maintenanceProgress.error &amp;&amp; i &lt; maintenanceProgress.stepIndex">✓</span><span *ngIf="maintenanceProgress.error &amp;&amp; i === maintenanceProgress.stepIndex">✗</span><span *ngIf="!(maintenanceProgress.error &amp;&amp; i === maintenanceProgress.stepIndex) &amp;&amp; !(i &lt; maintenanceProgress.stepIndex)">{{ i + 1 }}</span></div><span style="font-size:10px;margin-right:4px" [style.opacity]="i === maintenanceProgress.stepIndex ? &quot;.9&quot; : &quot;.4&quot;">{{ stepName }}</span></div><div *ngIf="i &lt; 3" style="width:16px;height:1px;background:rgba(255,255,255,.15);margin:0 2px"></div></ng-container></div><div style="height:4px;background:rgba(255,255,255,.08);border-radius:2px;overflow:hidden;margin-bottom:8px"><div style="height:100%;border-radius:2px;transition:width .3s ease" [style.width.%]="maintenanceProgress.percent" [style.background]="maintenanceProgress.error ? &quot;#f87171&quot; : maintenanceProgress.percent &gt;= 100 ? &quot;#4ade80&quot; : &quot;#3b82f6&quot;"></div></div><div style="display:flex;justify-content:space-between;align-items:center"><span style="font-size:12px;opacity:.8">{{ maintenanceProgress.label }}</span><span style="font-size:11px;opacity:.45">{{ maintenanceElapsed }}s</span></div><div *ngIf="maintenanceBusy" style="margin-top:10px;text-align:right"><button class="btn btn-sm" type="button" (click)="cancelMaintenance()" style="font-size:11px;padding:3px 14px;background:rgba(239,68,68,.15);border:1px solid rgba(239,68,68,.3);color:#fca5a5;border-radius:4px">Cancel</button></div></div><div *ngIf="lastMaintenanceAt" style="font-size:11px;opacity:.6;margin-bottom:8px"><div>Last maintenance: {{ lastMaintenanceAt }}</div><div *ngIf="latestMaintenanceSession">Session: {{ latestMaintenanceSession.sessionName }}</div></div><div *ngIf="latestMaintenanceSession" style="display:flex;gap:8px;margin-bottom:12px"><button class="btn btn-secondary" type="button" (click)="downloadLocalMaintenanceLog()" [disabled]="maintenanceBusy" style="font-size:11px;padding:4px 12px">Local log</button><button class="btn btn-secondary" type="button" (click)="downloadRemoteMaintenanceLog()" [disabled]="maintenanceBusy || validationErrors.length &gt; 0" style="font-size:11px;padding:4px 12px">Remote log</button></div><div *ngIf="remoteHealth" style="margin-top:8px;font-size:11px;opacity:.5"><div>FILE_ROOT: {{ remoteHealth.fileRoot || \'unknown\' }}</div><div>Bundled installer: script={{ bundledInstaller?.scriptVersion || \'?\' }} server={{ bundledInstaller?.serverVersion || \'?\' }}</div><div>Capabilities: rename={{ remoteHealth.supports?.renamePath ? \'✓\' : \'✗\' }} shell={{ remoteHealth.supports?.shellSession ? \'✓\' : \'✗\' }} pty={{ remoteHealth.supports?.ptySession ? \'✓\' : \'✗\' }} chunked={{ remoteHealth.supports?.chunkedTransfers ? \'✓\' : \'✗\' }} parallel={{ remoteHealth.supports?.parallelChunkOffsets ? \'✓\' : \'✗\' }} ratelimit={{ remoteHealth.supports?.rateLimiting ? \'✓\' : \'✗\' }}</div></div><div class="grid" style="display:grid;grid-template-columns:160px 1fr;gap:8px;align-items:center;margin-top:12px;font-size:12px"><label style="opacity:.6">Installer path</label><input class="form-control" type="text" [(ngModel)]="settings.installerRemotePath" (ngModelChange)="save()" style="font-size:12px"><label style="opacity:.6">As root</label><input type="checkbox" [(ngModel)]="settings.maintenanceAsRoot" (ngModelChange)="save()"><label style="opacity:.6">Reconnect poll (ms)</label><input class="form-control" type="number" min="500" [(ngModel)]="settings.reconnectPollMs" (ngModelChange)="save()" style="font-size:12px;max-width:120px"><label style="opacity:.6">Health timeout (ms)</label><input class="form-control" type="number" min="5000" [(ngModel)]="settings.upgradeHealthTimeoutMs" (ngModelChange)="save()" style="font-size:12px;max-width:120px"></div></div></div><div class="card" style="padding:16px 20px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08)"><div style="display:flex;align-items:center;cursor:pointer" (click)="advancedVisible = advancedVisible"><h3 style="margin:0;font-size:14px;font-weight:600;flex:1">Performance tuning</h3><span style="opacity:.5;font-size:12px"></span></div><div class="grid" style="display:grid;grid-template-columns:160px 1fr;gap:8px;align-items:center;margin-top:12px;font-size:12px"><label style="opacity:.6">Interactive slots</label><input class="form-control" type="number" min="1" step="1" [(ngModel)]="settings.interactiveConcurrency" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Transfer slots</label><input class="form-control" type="number" min="1" max="30" step="1" [(ngModel)]="settings.transferConcurrency" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Concurrent files</label><input class="form-control" type="number" min="1" max="10" step="1" [(ngModel)]="settings.maxConcurrentFiles" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Worker cadence (ms)</label><input class="form-control" type="number" min="0" step="10" [(ngModel)]="settings.workerCadenceMs" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Max retries</label><input class="form-control" type="number" min="0" [(ngModel)]="settings.maxRetries" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Retry base (ms)</label><input class="form-control" type="number" min="0" [(ngModel)]="settings.retryBaseMs" (ngModelChange)="save()" style="font-size:12px;max-width:100px"><label style="opacity:.6">Upload chunk (bytes)</label><input class="form-control" type="number" min="16384" step="1024" [(ngModel)]="settings.uploadChunkBytes" (ngModelChange)="save()" style="font-size:12px;max-width:120px"><label style="opacity:.6">Download chunk (bytes)</label><input class="form-control" type="number" min="16384" step="1024" [(ngModel)]="settings.downloadChunkBytes" (ngModelChange)="save()" style="font-size:12px;max-width:120px"><label style="opacity:.6">Notes</label><textarea class="form-control" rows="2" [(ngModel)]="settings.notes" (ngModelChange)="save()" placeholder="Optional notes" style="font-size:12px"></textarea></div></div><div class="card" style="padding:16px 20px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08)"><h3 style="margin:0 0 8px 0;font-size:14px;font-weight:600">Copyable MCP snippet</h3><pre style="white-space:pre-wrap;margin:0;font-size:12px;opacity:.85;background:rgba(0,0,0,.2);padding:12px;border-radius:6px">{{ sampleJson }}</pre></div><div style="font-size:11px;opacity:.4;padding:4px 0">💡 MCP URL = https://‹domain›/mcp • API key from Bianbu Cloud console • Shell and Files are MCP-backed, not SSH/SFTP</div></div>'}},766(e,t,s){"use strict";var i=Object.prototype.hasOwnProperty;function n(e,t){return Array.isArray(e)?function(e,t){for(var s,i="",o="",r=Array.isArray(t),a=0;a<e.length;a++)(s=n(e[a]))&&(r&&t[a]&&(s=l(s)),i=i+o+s,o=" ");return i}(e,t):e&&"object"==typeof e?function(e){var t="",s="";for(var n in e)n&&e[n]&&i.call(e,n)&&(t=t+s+n,s=" ");return t}(e):e||""}function o(e){if(!e)return"";if("object"==typeof e){var t="";for(var s in e)i.call(e,s)&&(t=t+s+":"+e[s]+";");return t}return e+""}function r(e,t,s,i){if(!1===t||null==t||!t&&("class"===e||"style"===e))return"";if(!0===t)return" "+(i?e:e+'="'+e+'"');var n=typeof t;return"object"!==n&&"function"!==n||"function"!=typeof t.toJSON||(t=t.toJSON()),"string"==typeof t||(t=JSON.stringify(t),s||-1===t.indexOf('"'))?(s&&(t=l(t))," "+e+'="'+t+'"'):" "+e+"='"+t.replace(/'/g,"&#39;")+"'"}t.merge=function e(t,s){if(1===arguments.length){for(var i=t[0],n=1;n<t.length;n++)i=e(i,t[n]);return i}for(var r in s)if("class"===r){var a=t[r]||[];t[r]=(Array.isArray(a)?a:[a]).concat(s[r]||[])}else if("style"===r){a=(a=o(t[r]))&&";"!==a[a.length-1]?a+";":a;var l=o(s[r]);l=l&&";"!==l[l.length-1]?l+";":l,t[r]=a+l}else t[r]=s[r];return t},t.classes=n,t.style=o,t.attr=r,t.attrs=function(e,t){var s="";for(var a in e)if(i.call(e,a)){var l=e[a];if("class"===a){s=r(a,l=n(l),!1,t)+s;continue}"style"===a&&(l=o(l)),s+=r(a,l,!1,t)}return s};var a=/["&<>]/;function l(e){var t=""+e,s=a.exec(t);if(!s)return e;var i,n,o,r="";for(i=s.index,n=0;i<t.length;i++){switch(t.charCodeAt(i)){case 34:o="&quot;";break;case 38:o="&amp;";break;case 60:o="&lt;";break;case 62:o="&gt;";break;default:continue}n!==i&&(r+=t.substring(n,i)),n=i+1,r+=o}return n!==i?r+t.substring(n,i):r}t.escape=l,t.rethrow=function e(t,i,n,o){if(!(t instanceof Error))throw t;if(!("undefined"==typeof window&&i||o))throw t.message+=" on line "+n,t;try{o=o||s(947).readFileSync(i,"utf8")}catch(s){e(t,null,n)}var r=3,a=o.split("\n"),l=Math.max(n-r,0),d=Math.min(a.length,n+r);throw r=a.slice(l,d).map(function(e,t){var s=t+l+1;return(s==n?" > ":" ")+s+"| "+e}).join("\n"),t.path=i,t.message=(i||"Pug")+":"+n+"\n"+r+"\n\n"+t.message,t}},40(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},n=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuCloudCommandProvider=void 0;const o=s(860),r=s(650),a=s(678),l=s(241);let d=class extends r.CommandProvider{constructor(e){super(),this.app=e}async provide(){return[{id:"bianbu-cloud-shell",label:"Open Bianbu Cloud Shell",sublabel:"Remote shell over MCP run_command",locations:[r.CommandLocation.StartPage],run:async()=>{this.app.openNewTab({type:a.BianbuCloudShellTabComponent})}},{id:"bianbu-cloud-files",label:"Open Bianbu Cloud Files",sublabel:"File manager over MCP file tools",locations:[r.CommandLocation.StartPage],run:async()=>{this.app.openNewTab({type:l.BianbuCloudFilesTabComponent})}}]}};d=i([(0,o.Injectable)(),n("design:paramtypes",[r.AppService])],d),t.BianbuCloudCommandProvider=d},889(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuMcpConfigProvider=void 0;const i=s(650);class n extends i.ConfigProvider{constructor(){super(...arguments),this.defaults={bianbuMcp:{name:"bianbu",domain:"",apiKey:"",maxRetries:2,retryBaseMs:1e3,interactiveConcurrency:2,transferConcurrency:30,workerCadenceMs:0,uploadChunkBytes:65536,downloadChunkBytes:262144,maxConcurrentFiles:3,notes:"",installerRemotePath:"/tmp/bianbu_agent_proxy.sh",maintenanceAsRoot:!0,reconnectPollMs:2e3,upgradeHealthTimeoutMs:12e4}}}}t.BianbuMcpConfigProvider=n},241(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},n=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuCloudFilesTabComponent=void 0;const o=s(860),r=s(650),a=s(885);let l=class extends r.BaseTabComponent{constructor(e,t,s,i){super(e),this.mcp=t,this.notifications=s,this.platform=i,this.currentPath=".",this.pathInput=".",this.asRoot=!1,this.busy=!1,this.items=[],this.filteredItems=[],this.selectedPath="",this.selectedContent="",this.selectedIsText=!1,this.status="Ready",this.dragActive=!1,this.searchText="",this.history=["."],this.historyIndex=0,this.selectedIndex=-1,this.contextMenuVisible=!1,this.contextMenuX=0,this.contextMenuY=0,this.contextItem=null,this.promptVisible=!1,this.promptTitle="",this.promptPlaceholder="",this.promptValue="",this.promptAction=null,this.promptTarget=null,this.transfersVisible=!0,this.transfers=[],this.transferSeq=1,this.transferQueue=[],this.transferQueueRunning=!1,this.sortKey="name",this.sortAsc=!0,this.selectedIndices=new Set,this.lastClickIndex=-1,this.detailPaneVisible=!0,this.advancedTransfersExpanded=!1,this.setTitle("Bianbu Cloud Files"),this.icon="folder-open"}ngOnInit(){this.refresh().catch(()=>null)}get breadcrumbs(){if(!this.currentPath||"."===this.currentPath)return["."];const e=this.currentPath.replace(/\\/g,"/");if("/"===e)return["/"];const t=e.split("/").filter(Boolean);return e.startsWith("/")?["/"].concat(t):t}get selectedItem(){var e;return null!==(e=this.filteredItems[this.selectedIndex])&&void 0!==e?e:null}onDocumentClick(){this.hideContextMenu()}onKeyDown(e){var t;const s=e.target,i=null===(t=null==s?void 0:s.tagName)||void 0===t?void 0:t.toLowerCase(),n=["input","textarea"].includes(i||"")||this.promptVisible;if("F5"===e.key)return e.preventDefault(),void this.refresh();if(e.altKey&&"ArrowUp"===e.key)return e.preventDefault(),void this.goUp();if(e.altKey&&"ArrowLeft"===e.key)return e.preventDefault(),void this.goBack();if(e.altKey&&"ArrowRight"===e.key)return e.preventDefault(),void this.goForward();if(e.ctrlKey&&"l"===e.key.toLowerCase()){e.preventDefault();const t=document.getElementById("bianbu-path-input");return null==t||t.focus(),void(null==t||t.select())}return e.ctrlKey&&e.shiftKey&&"n"===e.key.toLowerCase()?(e.preventDefault(),void this.openCreateDirectoryPrompt()):e.ctrlKey&&!e.shiftKey&&"n"===e.key.toLowerCase()?(e.preventDefault(),void this.openCreateFilePrompt()):n?void 0:"Backspace"===e.key?(e.preventDefault(),void this.goUp()):"Delete"===e.key&&this.selectedItem?(e.preventDefault(),void this.deleteItem(this.selectedItem)):"F2"===e.key&&this.selectedItem?(e.preventDefault(),void this.openRenamePrompt(this.selectedItem)):"Enter"===e.key&&this.selectedItem?(e.preventDefault(),void this.openItem(this.selectedItem)):"ArrowDown"===e.key?(e.preventDefault(),void this.moveSelection(1)):"ArrowUp"===e.key?(e.preventDefault(),void this.moveSelection(-1)):void 0}async refresh(){this.busy=!0,this.status="Loading directory…",this.pathInput=this.currentPath,this.setProgress(.25);try{const e=await this.mcp.listDirectory(this.currentPath||".",this.asRoot);this.items=e.items||[],this.applyFilter(),this.status=`Loaded ${this.items.length} item(s)`,this.filteredItems.length&&this.selectedIndex<0&&(this.selectedIndex=0)}catch(e){this.notifications.error("Failed to list directory",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e)}finally{this.busy=!1,this.setProgress(null)}}applyFilter(){const e=this.searchText.trim().toLowerCase();this.filteredItems=this.items.filter(t=>{const s=this.baseName(t.path).toLowerCase();return!e||s.includes(e)||t.path.toLowerCase().includes(e)}),this.sortItems(),this.selectedIndex>=this.filteredItems.length&&(this.selectedIndex=this.filteredItems.length-1)}sortItems(){this.filteredItems.sort((e,t)=>{if(e.is_dir&&!t.is_dir)return-1;if(!e.is_dir&&t.is_dir)return 1;let s=0;switch(this.sortKey){case"name":s=this.baseName(e.path).localeCompare(this.baseName(t.path));break;case"size":s=(e.size||0)-(t.size||0);break;case"date":s=(e.modified||"").localeCompare(t.modified||"");break;case"type":{const i=e.is_dir?"":e.path.split(".").pop()||"",n=t.is_dir?"":t.path.split(".").pop()||"";s=i.localeCompare(n);break}}return this.sortAsc?s:-s})}navigateToInput(){this.navigate(this.pathInput||".")}navigate(e,t=!0){this.currentPath=e||".",this.pathInput=this.currentPath,t&&(this.history=this.history.slice(0,this.historyIndex+1),this.history.push(this.currentPath),this.historyIndex=this.history.length-1),this.clearPreview(),this.selectedIndex=-1,this.refresh()}navigateBreadcrumb(e){if("."===this.currentPath&&0===e)return void this.navigate(".",!0);const t=this.breadcrumbs;if("/"===t[0])return 0===e?void this.navigate("/",!0):void this.navigate("/"+t.slice(1,e+1).join("/"),!0);this.navigate(t.slice(0,e+1).join("/"),!0)}goBack(){this.historyIndex<=0||(this.historyIndex-=1,this.navigate(this.history[this.historyIndex],!1))}goForward(){this.historyIndex>=this.history.length-1||(this.historyIndex+=1,this.navigate(this.history[this.historyIndex],!1))}goUp(){if("."===this.currentPath||"/"===this.currentPath)return;const e=this.currentPath.replace(/\\/g,"/"),t=e.split("/").slice(0,-1).join("/")||(e.startsWith("/")?"/":".");this.navigate(t,!0)}moveSelection(e){this.filteredItems.length?this.selectedIndex<0?this.selectedIndex=0:this.selectedIndex=Math.max(0,Math.min(this.filteredItems.length-1,this.selectedIndex+e)):this.selectedIndex=-1}selectItem(e,t){const s=this.filteredItems.indexOf(e);if((null==t?void 0:t.ctrlKey)||(null==t?void 0:t.metaKey))this.selectedIndices.has(s)?this.selectedIndices.delete(s):this.selectedIndices.add(s);else if((null==t?void 0:t.shiftKey)&&this.lastClickIndex>=0){const e=Math.min(this.lastClickIndex,s),t=Math.max(this.lastClickIndex,s);for(let s=e;s<=t;s++)this.selectedIndices.add(s)}else this.selectedIndices.clear(),this.selectedIndices.add(s);this.lastClickIndex=s,this.selectedIndex=s}async openItem(e){if(this.selectItem(e),e.is_dir)this.navigate(e.path,!0);else{this.busy=!0,this.status=`Opening ${e.path}`,this.selectedPath=e.path,this.selectedIsText=this.isTextLike(e.path);try{if(this.selectedIsText){const t=await this.mcp.readTextFile(e.path,524288,this.asRoot);this.selectedContent=t.content||"",this.status=`Opened ${e.path}`}else this.selectedContent="",this.status=`Binary / non-text file selected: ${e.path}`}catch(e){this.notifications.error("Failed to open file",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e),this.selectedContent=""}finally{this.busy=!1}}}async saveSelected(){if(this.selectedPath&&this.selectedIsText){this.busy=!0,this.status=`Saving ${this.selectedPath}`;try{await this.mcp.writeTextFile(this.selectedPath,this.selectedContent,this.asRoot),this.notifications.notice("File saved"),this.status=`Saved ${this.selectedPath}`,await this.refresh()}catch(e){this.notifications.error("Failed to save file",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e)}finally{this.busy=!1}}}openCreateDirectoryPrompt(){this.promptVisible=!0,this.promptTitle="Create new folder",this.promptPlaceholder="Folder name",this.promptValue="",this.promptAction="mkdir",this.promptTarget=null}openCreateFilePrompt(){this.promptVisible=!0,this.promptTitle="Create new file",this.promptPlaceholder="File name",this.promptValue="",this.promptAction="newfile",this.promptTarget=null}openRenamePrompt(e){this.promptVisible=!0,this.promptTitle="Rename",this.promptPlaceholder="New name",this.promptValue=this.baseName(e.path),this.promptAction="rename",this.promptTarget=e}closePrompt(){this.promptVisible=!1,this.promptAction=null,this.promptTarget=null,this.promptValue=""}async confirmPrompt(){const e=this.promptValue.trim();if(e&&this.promptAction)return"mkdir"===this.promptAction?(await this.createDirectory(e),void this.closePrompt()):"newfile"===this.promptAction?(await this.createFile(e),void this.closePrompt()):void("rename"===this.promptAction&&this.promptTarget&&(await this.renameItem(this.promptTarget,e),this.closePrompt()));this.closePrompt()}async createDirectory(e){const t=this.joinPath(this.currentPath,e);this.busy=!0;try{await this.mcp.makeDirectory(t,this.asRoot),await this.refresh(),this.notifications.notice("Directory created")}catch(e){this.notifications.error("Failed to create directory",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e)}finally{this.busy=!1}}async createFile(e){const t=this.joinPath(this.currentPath,e);this.busy=!0;try{await this.mcp.writeTextFile(t,"",this.asRoot),await this.refresh(),this.notifications.notice("File created")}catch(e){this.notifications.error("Failed to create file",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e)}finally{this.busy=!1}}async renameItem(e,t){const s=e.path.split("/").slice(0,-1).join("/")||".",i=this.joinPath(s,t);try{await this.mcp.renamePath(e.path,i,this.asRoot),this.notifications.notice("Path renamed"),this.selectedPath===e.path&&(this.selectedPath=i),await this.refresh()}catch(e){const t=String((null==e?void 0:e.message)||e);this.notifications.error("Rename failed",t),this.status=t}}async deleteItem(e){this.busy=!0;try{await this.mcp.deletePath(e.path,!!e.is_dir,this.asRoot),this.selectedPath===e.path&&this.clearPreview(),await this.refresh(),this.notifications.notice("Path deleted")}catch(e){this.notifications.error("Failed to delete path",String((null==e?void 0:e.message)||e)),this.status=String((null==e?void 0:e.message)||e)}finally{this.busy=!1}}showContextMenu(e,t){e.preventDefault(),e.stopPropagation(),this.selectItem(t),this.contextItem=t,this.contextMenuVisible=!0,this.contextMenuX=e.clientX,this.contextMenuY=e.clientY}hideContextMenu(){this.contextMenuVisible=!1,this.contextItem=null}async uploadFile(e){const t=e.target,s=Array.from(t.files||[]);if(s.length){for(const e of s)this.enqueueUpload(e);t.value=""}}createTransfer(e,t,s,i,n="queued"){return{id:this.transferSeq++,name:e,direction:t,status:n,bytesDone:0,bytesTotal:s,startedAt:Date.now(),controller:i}}cancelTransfer(e){var t;"running"!==e.status&&"queued"!==e.status||(null===(t=e.controller)||void 0===t||t.abort(),e.status="cancelled",e.finishedAt=Date.now())}transferPercent(e){return e.bytesTotal?Math.max(0,Math.min(100,Math.round(e.bytesDone/e.bytesTotal*100))):null}transferRate(e){const t=e.finishedAt||Date.now(),s=Math.max(1,(t-e.startedAt)/1e3),i=e.bytesDone||0;return`${Math.round(i/s/1024)} KB/s`}async uploadDroppedFile(e){this.enqueueUpload(e)}onDragOver(e){e.preventDefault(),this.dragActive=!0}onDragLeave(){this.dragActive=!1}async onDrop(e){var t;e.preventDefault(),this.dragActive=!1;const s=Array.from((null===(t=e.dataTransfer)||void 0===t?void 0:t.files)||[]);if(s.length)for(const e of s)this.enqueueUpload(e)}async downloadSelected(){this.selectedPath&&this.enqueueDownload(this.selectedPath)}enqueueUpload(e){const t=new AbortController,s=this.createTransfer(e.name,"upload",e.size,t,"queued");this.queueTransferJob(s,()=>this.runUploadTransfer(e,s))}enqueueDownload(e){const t=new AbortController,s=this.createTransfer(this.baseName(e),"download",null,t,"queued");this.queueTransferJob(s,()=>this.runDownloadTransfer(e,s))}queueTransferJob(e,t){this.transfers.unshift(e),this.transferQueue.push(async()=>{"cancelled"!==e.status&&(e.status="running",e.startedAt=Date.now(),await t())}),this.pumpTransferQueue()}async pumpTransferQueue(){var e;if(!this.transferQueueRunning){this.transferQueueRunning=!0;try{const t=Math.max(1,Number(null!==(e=this.mcp.settings.maxConcurrentFiles)&&void 0!==e?e:3)),s=[],i=async()=>{for(;this.transferQueue.length||s.length;){for(;s.length<t&&this.transferQueue.length;){const e=this.transferQueue.shift();if(!e)continue;const t=e().finally(()=>{const e=s.indexOf(t);e>=0&&s.splice(e,1)});s.push(t)}s.length&&await Promise.race(s)}};await i()}finally{this.transferQueueRunning=!1}}}async runUploadTransfer(e,t){var s,i,n;let o=null;try{const r=this.joinPath(this.currentPath,e.name),a=Math.max(16384,Number(null!==(s=this.mcp.settings.uploadChunkBytes)&&void 0!==s?s:32768)),l=Math.max(1,Math.min(Number(null!==(i=this.mcp.settings.transferConcurrency)&&void 0!==i?i:30),Math.ceil(e.size/a)||1));o=await this.mcp.uploadChunkedBegin(r,this.asRoot,e.size,a);const d=[];for(let t=0;t<e.size;t+=a)d.push(t);let c=null;const u=Array.from({length:l},async()=>{for(var s,i;!(null===(s=t.controller)||void 0===s?void 0:s.signal.aborted);){const s=d.shift();if(void 0===s)return;if(c)return;try{const n=new Uint8Array(await e.slice(s,Math.min(e.size,s+a)).arrayBuffer());await this.mcp.uploadChunkedPart(o.upload_id,this.uint8ToBase64(n),s,null===(i=t.controller)||void 0===i?void 0:i.signal),t.bytesDone+=n.length}catch(e){return void(c=c||e)}}});if(await Promise.all(u),null===(n=t.controller)||void 0===n?void 0:n.signal.aborted)return await this.mcp.uploadChunkedAbort(o.upload_id).catch(()=>null),t.status="cancelled",void(t.finishedAt=Date.now());if(c)throw c;await this.mcp.uploadChunkedFinish(o.upload_id),t.bytesDone=e.size,t.status="done",t.finishedAt=Date.now(),this.notifications.notice(`Uploaded ${e.name}`),await this.refresh()}catch(e){(null==o?void 0:o.upload_id)&&await this.mcp.uploadChunkedAbort(o.upload_id).catch(()=>null),"cancelled"!==t.status&&(t.status="error",t.error=String((null==e?void 0:e.message)||e),t.finishedAt=Date.now(),this.notifications.error("Upload failed",t.error),this.status=t.error)}}async runDownloadTransfer(e,t){var s,i,n,o;let r=null,a=null;try{const o=Math.max(16384,Number(null!==(s=this.mcp.settings.downloadChunkBytes)&&void 0!==s?s:131072));if(r=await this.mcp.downloadChunkedBegin(e,this.asRoot,o),t.bytesTotal=r.total_size,a=await this.platform.startDownload(this.baseName(e)||"download.bin",420,r.total_size||0),!a)return t.status="cancelled",t.finishedAt=Date.now(),void await this.mcp.downloadChunkedClose(r.download_id).catch(()=>null);const l=[];for(let e=0;e<Number(r.total_size||0);e+=o)l.push(e);const d=Math.max(1,Math.min(Number(null!==(i=this.mcp.settings.transferConcurrency)&&void 0!==i?i:30),l.length||1)),c=new Map;let u=0,p=null,h=!1;const m=async()=>{for(;c.has(u);){const e=c.get(u);c.delete(u),await a.write(e),u+=e.length}},g=(async()=>{for(;!h||c.size>0;)await m(),(!h||c.size>0)&&await new Promise(e=>setTimeout(e,10));await m()})(),f=Array.from({length:d},async()=>{for(var e,s;!(null===(e=t.controller)||void 0===e?void 0:e.signal.aborted);){const e=l.shift();if(void 0===e)return;if(p)return;try{const i=await this.mcp.downloadChunkedPart(r.download_id,e,o,null===(s=t.controller)||void 0===s?void 0:s.signal),n=this.base64ToUint8(i.content_base64);c.set(e,n),t.bytesDone+=n.length}catch(e){return void(p=p||e)}}});if(await Promise.all(f),h=!0,await g,null===(n=t.controller)||void 0===n?void 0:n.signal.aborted)return await this.mcp.downloadChunkedClose(r.download_id).catch(()=>null),a.close(),t.status="cancelled",void(t.finishedAt=Date.now());if(p)throw p;await this.mcp.downloadChunkedClose(r.download_id),a.close(),t.status="done",t.finishedAt=Date.now(),this.notifications.notice(`Downloaded ${this.baseName(e)}`)}catch(e){null===(o=null==a?void 0:a.close)||void 0===o||o.call(a),(null==r?void 0:r.download_id)&&await this.mcp.downloadChunkedClose(r.download_id).catch(()=>null),"cancelled"!==t.status&&(t.status="error",t.error=String((null==e?void 0:e.message)||e),t.finishedAt=Date.now(),this.notifications.error("Download failed",t.error),this.status=t.error)}}formatSize(e){return null==e?"—":e<1024?`${e} B`:e<1048576?`${(e/1024).toFixed(1)} KB`:e<1073741824?`${(e/1048576).toFixed(1)} MB`:`${(e/1073741824).toFixed(2)} GB`}formatDate(e){if(!e)return"—";try{const t=new Date(e);return isNaN(t.getTime())?"—":`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")} ${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`}catch{return"—"}}fileIcon(e){return e.is_dir?"📁":{js:"📜",ts:"📜",mjs:"📜",jsx:"📜",tsx:"📜",py:"🐍",sh:"⚙️",bash:"⚙️",json:"📋",yaml:"📋",yml:"📋",toml:"📋",xml:"📋",md:"📝",txt:"📄",csv:"📊",html:"🌐",css:"🎨",scss:"🎨",jpg:"🖼️",jpeg:"🖼️",png:"🖼️",gif:"🖼️",svg:"🖼️",webp:"🖼️",ico:"🖼️",zip:"📦",tar:"📦",gz:"📦",bz2:"📦",xz:"📦","7z":"📦",rar:"📦",pdf:"📕",doc:"📘",docx:"📘",xls:"📗",xlsx:"📗",ppt:"📙",pptx:"📙",mp3:"🎵",wav:"🎵",flac:"🎵",ogg:"🎵",mp4:"🎬",mkv:"🎬",avi:"🎬",mov:"🎬",webm:"🎬",c:"📜",cpp:"📜",h:"📜",hpp:"📜",java:"📜",go:"📜",rs:"📜",rb:"📜",php:"📜",sql:"🗃️",db:"🗃️",sqlite:"🗃️",log:"📃",ini:"⚙️",cfg:"⚙️",conf:"⚙️",env:"🔒",key:"🔑",pem:"🔑",crt:"🔑"}[(e.path.split(".").pop()||"").toLowerCase()]||"📄"}fileType(e){if(e.is_dir)return"Folder";const t=(e.path.split(".").pop()||"").toLowerCase();return t&&t!==e.path?t.toUpperCase():"File"}toggleSort(e){this.sortKey===e?this.sortAsc=!this.sortAsc:(this.sortKey=e,this.sortAsc=!0),this.sortItems()}sortIndicator(e){return this.sortKey!==e?"":this.sortAsc?" ▲":" ▼"}get totalSize(){const e=this.filteredItems.reduce((e,t)=>e+(t.size||0),0);return this.formatSize(e)}get selectionSummary(){const e=this.selectedIndices.size;return e<=1?"":`${e} selected`}isSelected(e){return this.selectedIndices.has(e)}get activeTransferLabel(){let e=0;for(const t of this.transfers)"running"!==t.status&&"queued"!==t.status||e++;return e?"⬆⬇ "+e+" active":"✓ Transfers done"}toggleDetailPane(){this.detailPaneVisible=!this.detailPaneVisible}clearPreview(){this.selectedPath="",this.selectedContent="",this.selectedIsText=!1}baseName(e){return e.split("/").pop()||e}isTextLike(e){const t=e.toLowerCase();return[".txt",".md",".json",".yaml",".yml",".xml",".ini",".cfg",".conf",".log",".sh",".py",".js",".ts",".tsx",".jsx",".html",".css",".scss",".c",".cpp",".h",".hpp",".java",".go",".rs",".sql"].some(e=>t.endsWith(e))}joinPath(e,t){return e&&"."!==e?e.endsWith("/")?`${e}${t}`:`${e}/${t}`:t}uint8ToBase64(e){let t="";for(let s=0;s<e.length;s+=32768)t+=String.fromCharCode(...e.subarray(s,s+32768));return btoa(t)}base64ToUint8(e){const t=atob(e),s=new Uint8Array(t.length);for(let e=0;e<t.length;e++)s[e]=t.charCodeAt(e);return s}};i([(0,o.HostListener)("document:click"),n("design:type",Function),n("design:paramtypes",[]),n("design:returntype",void 0)],l.prototype,"onDocumentClick",null),i([(0,o.HostListener)("document:keydown",["$event"]),n("design:type",Function),n("design:paramtypes",[KeyboardEvent]),n("design:returntype",void 0)],l.prototype,"onKeyDown",null),l=i([(0,o.Component)({template:s(102)}),n("design:paramtypes",[o.Injector,a.BianbuMcpService,r.NotificationsService,r.PlatformService])],l),t.BianbuCloudFilesTabComponent=l},440(e,t,s){"use strict";var i=this&&this.__createBinding||(Object.create?function(e,t,s,i){void 0===i&&(i=s);var n=Object.getOwnPropertyDescriptor(t,s);n&&!("get"in n?!t.__esModule:n.writable||n.configurable)||(n={enumerable:!0,get:function(){return t[s]}}),Object.defineProperty(e,i,n)}:function(e,t,s,i){void 0===i&&(i=s),e[i]=t[s]}),n=this&&this.__setModuleDefault||(Object.create?function(e,t){Object.defineProperty(e,"default",{enumerable:!0,value:t})}:function(e,t){e.default=t}),o=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},r=this&&this.__importStar||function(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var s in e)"default"!==s&&Object.prototype.hasOwnProperty.call(e,s)&&i(t,e,s);return n(t,e),t};Object.defineProperty(t,"__esModule",{value:!0});const a=s(860),l=s(358),d=s(182),c=r(s(650)),u=s(700),p=s(889),h=s(717),m=s(645),g=s(40),f=s(885),b=s(678),y=s(241),x=s(104);let v=class{};v=o([(0,a.NgModule)({imports:[l.CommonModule,d.FormsModule,c.default],providers:[f.BianbuMcpService,{provide:c.ConfigProvider,useClass:p.BianbuMcpConfigProvider,multi:!0},{provide:u.SettingsTabProvider,useClass:h.BianbuMcpSettingsTabProvider,multi:!0},{provide:c.CommandProvider,useClass:g.BianbuCloudCommandProvider,multi:!0},{provide:c.ProfileProvider,useClass:x.BianbuCloudProfileProvider,multi:!0}],declarations:[m.BianbuMcpSettingsComponent,b.BianbuCloudShellTabComponent,y.BianbuCloudFilesTabComponent],entryComponents:[m.BianbuMcpSettingsComponent,b.BianbuCloudShellTabComponent,y.BianbuCloudFilesTabComponent]})],v),t.default=v},885(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},n=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuMcpService=void 0;const o=s(860),r=s(650),a=s(979),l=s(935);function d(){const e=new Error("Request aborted");return e.name="AbortError",e}class c{constructor(e,t){this.concurrency=e,this.baseCadenceMs=t,this.queue=[],this.waiters=[],this.started=!1,this.stopped=!1,this.currentCadenceMs=t}stop(){this.stopped=!0;const e={run:()=>Promise.resolve(),resolve:()=>{},reject:()=>{},cleanup:()=>{}};for(const t of this.waiters)t(e);this.waiters.length=0}enqueue(e,t){return(null==t?void 0:t.aborted)?Promise.reject(d()):new Promise((s,i)=>{const n={run:e,resolve:s,reject:i,signal:t,cleanup:()=>{}};if(t){const e=()=>{const e=this.queue.indexOf(n);e>=0&&(this.queue.splice(e,1),n.cleanup(),i(d()))};t.addEventListener("abort",e,{once:!0}),n.cleanup=()=>t.removeEventListener("abort",e)}this.queue.push(n),this.dispatch(),this.startWorkers()})}startWorkers(){if(!this.started){this.started=!0;for(let e=0;e<this.concurrency;e++)this.workerLoop()}}dispatch(){for(;this.queue.length&&this.waiters.length;){const e=this.waiters.shift(),t=this.queue.shift();e&&t&&e(t)}}async take(){return this.queue.length?this.queue.shift():new Promise(e=>this.waiters.push(e))}notifyThrottled(){this.currentCadenceMs=Math.min(4*this.baseCadenceMs||2e3,Math.max(200,2*this.currentCadenceMs))}notifySuccess(){this.currentCadenceMs=Math.max(0,this.currentCadenceMs-10)}async workerLoop(){for(var e;!this.stopped;){const t=await this.take();if(this.stopped)return;if(null===(e=t.signal)||void 0===e?void 0:e.aborted)t.cleanup(),t.reject(d());else try{const e=await t.run();t.resolve(e),this.currentCadenceMs=Math.max(0,this.currentCadenceMs-10)}catch(e){t.reject(e),/429|too many/i.test(String((null==e?void 0:e.message)||""))&&(this.currentCadenceMs=Math.min(4*this.baseCadenceMs||2e3,Math.max(200,2*this.currentCadenceMs)))}finally{t.cleanup()}this.currentCadenceMs>0&&await new Promise(e=>setTimeout(e,this.currentCadenceMs))}}}let u=class{constructor(e){this.config=e,this.bundledInstallerCache=null,this.interactiveLane=new c(2,0),this.latestMaintenanceSessionValue=null,this.transferLane=new c(30,0),this.schedulerKey=""}get settings(){return this.config.store.bianbuMcp}get validationErrors(){return(0,a.validateConnectionSettings)(this.settings)}get bundledInstaller(){return this.bundledInstallerCache||(this.bundledInstallerCache=(0,a.loadBundledInstaller)(__dirname)),this.bundledInstallerCache}get normalizedUrl(){const e=this.settings;if(!e.domain)return"";const t=String(e.domain||"").trim().replace(/^https?:\/\//i,"").replace(/\/mcp\/?$/i,"").replace(/\/+$/,"");return t?`https://${t}/mcp`:""}get latestMaintenanceSession(){return this.latestMaintenanceSessionValue}ensureScheduler(){var e,t,s;const i=Math.max(1,Number(null!==(e=this.settings.interactiveConcurrency)&&void 0!==e?e:2)),n=Math.max(1,Number(null!==(t=this.settings.transferConcurrency)&&void 0!==t?t:30)),o=Math.max(0,Number(null!==(s=this.settings.workerCadenceMs)&&void 0!==s?s:0)),r=`${i}:${n}:${o}`;r!==this.schedulerKey&&(this.schedulerKey=r,this.interactiveLane.stop(),this.transferLane.stop(),this.interactiveLane=new c(i,o),this.transferLane=new c(n,o))}sleep(e){return new Promise(t=>setTimeout(t,e))}isMissingPathError(e){return/(file|path) not found:/i.test(String((null==e?void 0:e.message)||e||""))}async readRemoteTextIfExists(e,t,s){try{const i=await this.readTextFile(e,t,s);return String((null==i?void 0:i.content)||"")}catch(e){if(this.isMissingPathError(e))return null;throw e}}async readRemoteLogSnippet(e,t){return String(await this.readRemoteTextIfExists(e,262144,t)||"").trim()}createMaintenanceSession(e,t,s){const i=(new Date).toISOString(),n=(0,l.createSessionLog)({action:e,asRoot:s,kind:"maintenance",remotePath:t,sessionName:(0,l.createSessionName)("maintenance",e,i),startedAt:i});return this.latestMaintenanceSessionValue=n,n}logSession(e,t,s,i){(0,l.appendSessionLogEntry)(e,{level:t,message:s,details:i,timestamp:(new Date).toISOString()})}getLatestMaintenanceLocalLogDownloadPayload(){if(!this.latestMaintenanceSessionValue)throw new Error("No maintenance session log is available yet");return(0,l.buildLocalLogDownloadPayload)(this.latestMaintenanceSessionValue)}async getLatestMaintenanceRemoteLogDownloadPayload(){const e=this.latestMaintenanceSessionValue;if(!e)throw new Error("No maintenance session log is available yet");if(!e.remoteLogPath)throw new Error("No remote log path is recorded for the latest maintenance session");const t=await this.readRemoteTextIfExists(e.remoteLogPath,1048576,Boolean(e.asRoot)),s=e.remoteStatusPath?await this.readRemoteTextIfExists(e.remoteStatusPath,131072,Boolean(e.asRoot)):null;return(0,l.buildRemoteLogDownloadPayload)({session:e,remoteLogText:t,remoteStatusText:s})}shouldRetryStatus(e){return[429,502,503,504].includes(e)}parseBody(e){try{return JSON.parse(e)}catch{const t=e.split(/\r?\n/).map(e=>e.trim()).filter(e=>e.startsWith("data:")).map(e=>e.slice(5).trim()).filter(Boolean);for(let e=t.length-1;e>=0;e--)try{return JSON.parse(t[e])}catch{}}return{error:{message:e||"Invalid MCP response"}}}laneForTool(e){return e.startsWith("upload_chunked_")||e.startsWith("download_chunked_")?"transfer":"interactive"}async executeRequest(e,t,s=!1){var i,n,o,r,a,l,d,c;const u=this.settings,p=this.normalizedUrl;if(!p)throw new Error("MCP URL is required");const h=s?0:Math.max(0,Number(null!==(i=u.maxRetries)&&void 0!==i?i:2)),m=Math.max(100,Number(null!==(n=u.retryBaseMs)&&void 0!==n?n:1e3));let g="",f=0,b=null;for(let s=0;s<=h;s++){try{const s=await fetch(p,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json, text/event-stream","MCP-Protocol-Version":"2025-11-25","X-API-KEY":u.apiKey},body:JSON.stringify(e),signal:t}),i=await s.text();if(g=i,f=s.status,s.ok&&!this.shouldRetryStatus(s.status)){const e=this.parseBody(i);if(e.error)throw new Error(e.error.message||"MCP error");if((null===(o=e.result)||void 0===o?void 0:o.isError)&&(null===(l=null===(a=null===(r=e.result)||void 0===r?void 0:r.content)||void 0===a?void 0:a[0])||void 0===l?void 0:l.text))throw new Error(e.result.content[0].text);return void 0!==(null===(d=e.result)||void 0===d?void 0:d.structuredContent)?e.result.structuredContent:e.result}if(!this.shouldRetryStatus(s.status)){const e=this.parseBody(i);if(null===(c=e.error)||void 0===c?void 0:c.message)throw new Error(e.error.message);throw new Error(`MCP request failed with status ${s.status}: ${i}`)}}catch(e){if(b=e,(null==t?void 0:t.aborted)||"AbortError"===(null==e?void 0:e.name))throw e;if(s===h)break}s<h&&await this.sleep(m*(s+1))}throw b||new Error(`MCP request failed with status ${f}: ${g}`)}async request(e,t,s="interactive"){return this.ensureScheduler(),("transfer"===s?this.transferLane:this.interactiveLane).enqueue(()=>this.executeRequest(e,t),t)}async callTool(e,t,s,i){return this.request({jsonrpc:"2.0",id:`${e}-${Date.now()}-${Math.random().toString(16).slice(2)}`,method:"tools/call",params:{name:e,arguments:t}},s,i||this.laneForTool(e))}async healthRaw(e){return this.callTool("health",{},e,"interactive")}async getHealth(e){const t=await this.healthRaw(e);return(0,a.parseRemoteHealth)(t)}async health(){return this.healthRaw()}async runCommand(e,t,s,i){return this.callTool("run_command",{command:e,cwd:t,timeout_seconds:s,as_root:i},void 0,"interactive")}async openShellSession(e,t){return this.callTool("open_shell_session",{cwd:e,as_root:t},void 0,"interactive")}async execShellSession(e,t,s){return this.callTool("exec_shell_session",{session_id:e,command:t,timeout_seconds:s},void 0,"interactive")}async closeShellSession(e){return this.callTool("close_shell_session",{session_id:e},void 0,"interactive")}async openPtySession(e,t,s,i){return this.callTool("open_pty_session",{cwd:e,as_root:t,cols:s,rows:i},void 0,"interactive")}async writePtyInput(e,t){return this.executePtyRequest("write_pty_input",{session_id:e,data_base64:t},void 0,!0)}async readPtyOutputDirect(e,t){return this.executePtyRequest("read_pty_output",{session_id:e,timeout_ms:5e3},t)}async resizePty(e,t,s){return this.executePtyRequest("resize_pty",{session_id:e,cols:t,rows:s})}async closePtySession(e){return this.executePtyRequest("close_pty_session",{session_id:e})}async executePtyRequest(e,t,s,i=!1){return this.executeRequest({jsonrpc:"2.0",id:`pty-${Date.now()}-${Math.random().toString(16).slice(2)}`,method:"tools/call",params:{name:e,arguments:t}},s,i)}async listDirectory(e,t){return this.callTool("list_directory",{path:e,as_root:t},void 0,"interactive")}async readTextFile(e,t,s){return this.callTool("read_text_file",{path:e,max_bytes:t,encoding:"utf-8",as_root:s},void 0,"interactive")}async writeTextFile(e,t,s){return this.callTool("write_text_file",{path:e,content:t,overwrite:!0,encoding:"utf-8",as_root:s},void 0,"interactive")}async makeDirectory(e,t){return this.callTool("make_directory",{path:e,parents:!0,as_root:t},void 0,"interactive")}async deletePath(e,t,s){return this.callTool("delete_path",{path:e,recursive:t,as_root:s},void 0,"interactive")}async renamePath(e,t,s){return this.callTool("rename_path",{path:e,dest:t,as_root:s},void 0,"interactive")}async uploadBinaryFile(e,t,s,i){return this.callTool("upload_binary_file",{path:e,content_base64:t,overwrite:!0,as_root:s},i,"interactive")}async uploadChunkedBegin(e,t,s,i){return this.callTool("upload_chunked_begin",{path:e,overwrite:!0,as_root:t,total_size:s,chunk_bytes:i},void 0,"transfer")}async uploadChunkedPart(e,t,s,i){return this.callTool("upload_chunked_part",{upload_id:e,content_base64:t,offset:s},i,"transfer")}async uploadChunkedFinish(e){return this.callTool("upload_chunked_finish",{upload_id:e},void 0,"transfer")}async uploadChunkedAbort(e){return this.callTool("upload_chunked_abort",{upload_id:e},void 0,"transfer")}async uploadTextViaChunked(e,t,s,i){const n=Buffer.from(t,"utf-8"),o=32768,r=await this.uploadChunkedBegin(e,s,n.length,o),a=null==r?void 0:r.upload_id;if(!a)throw new Error("upload_chunked_begin did not return an upload_id");try{for(let e=0;e<n.length;e+=o){const t=n.subarray(e,e+o);await this.uploadChunkedPart(a,t.toString("base64"),e),null==i||i(Math.min(e+o,n.length),n.length)}await this.uploadChunkedFinish(a)}catch(e){throw await this.uploadChunkedAbort(a).catch(()=>{}),e}}async downloadBinaryFile(e,t,s){return this.callTool("download_binary_file",{path:e,max_bytes:67108864,as_root:t},s,"interactive")}async downloadChunkedBegin(e,t,s=131072){return this.callTool("download_chunked_begin",{path:e,as_root:t,chunk_bytes:s},void 0,"transfer")}async downloadChunkedPart(e,t,s,i){return this.callTool("download_chunked_part",{download_id:e,offset:t,chunk_bytes:s},i,"transfer")}async downloadChunkedClose(e){return this.callTool("download_chunked_close",{download_id:e},void 0,"transfer")}async waitForHealth(e){const t=Math.max(5e3,Number(e.timeoutMs||12e4)),s=Math.max(500,Number(e.intervalMs||2e3)),i=Date.now()+t;let n=null;for(;Date.now()<i;){try{return await this.getHealth()}catch(e){n=e}await this.sleep(s)}throw new Error(`Remote health check did not recover within ${t} ms: ${String((null==n?void 0:n.message)||n||"unknown error")}`)}async waitForInstallerCompletion(e){var t,s,i,n,o;const r=Math.max(5e3,Number(e.timeoutMs||12e4)),l=Math.max(500,Number(e.intervalMs||2e3)),d=Date.now(),c=d+r;let u=null,p=null,h=null,m=0;for(;Date.now()<c;){if(null===(t=e.signal)||void 0===t?void 0:t.aborted)throw new DOMException("Operation cancelled","AbortError");null===(s=e.onPoll)||void 0===s||s.call(e,Date.now()-d,r);try{p=await this.getHealth(),m=0,this.logSession(e.session,"info","Remote health poll succeeded",`script=${p.scriptVersion||"unknown"} server=${p.serverVersion||"unknown"} transport=${p.transportMode||"unknown"}`)}catch(t){if(u=t,m++,this.logSession(e.session,"warn","Remote health poll failed",String((null==t?void 0:t.message)||t)),m>=10)throw new Error(`Remote health check failed ${m} consecutive times. Last error: ${String((null==t?void 0:t.message)||t)}`);await this.sleep(l);continue}try{const t=await this.readRemoteTextIfExists(e.statusPath,65536,e.asRoot);if(t){if(h=(0,a.parseRemoteInstallerStatus)(t),this.logSession(e.session,"info","Remote installer status file detected",`ok=${h.ok} exit=${null!==(i=h.exitCode)&&void 0!==i?i:"unknown"} session=${h.sessionName||"unknown"}`),h.sessionName&&h.sessionName!==e.expectedSessionName)throw new Error(`Remote status session_name=${h.sessionName} does not match expected ${e.expectedSessionName}`);if(!h.ok){const t=await this.readRemoteLogSnippet(e.logPath,e.asRoot),s=t?` Remote log:\n${t}`:` Remote log path: ${e.logPath}`;throw new Error(`Remote ${e.action} exited with code ${null!==(n=h.exitCode)&&void 0!==n?n:"unknown"}.${s}`)}if(p.scriptVersion===e.expectedScriptVersion&&p.serverVersion===e.expectedServerVersion)return this.logSession(e.session,"info","Remote installer finished with expected versions"),{health:p,status:h};u=new Error(`Remote installer completed, but health reports script=${p.scriptVersion||"unknown"} server=${p.serverVersion||"unknown"} instead of expected script=${e.expectedScriptVersion} server=${e.expectedServerVersion}`),this.logSession(e.session,"warn","Remote installer completed before expected versions were observed",String(u.message||u))}else this.logSession(e.session,"info","Remote installer status file not ready yet",e.statusPath)}catch(t){u=t,this.logSession(e.session,"error","Remote installer completion check failed",String((null==t?void 0:t.message)||t))}await this.sleep(l)}const g=p?await this.readRemoteLogSnippet(e.logPath,e.asRoot).catch(()=>""):"",f=h?` Last status: ok=${h.ok} exit=${null!==(o=h.exitCode)&&void 0!==o?o:"unknown"} finished_at=${h.finishedAt||"unknown"} session_name=${h.sessionName||"unknown"}.`:` Status file path: ${e.statusPath}.`,b=g?` Remote log:\n${g}`:` Remote log path: ${e.logPath}`;throw new Error(`Remote ${e.action} did not complete within ${r} ms.${f} Last error: ${String((null==u?void 0:u.message)||u||"unknown error")}.${b}`)}async pushInstallerAndUpgrade(e={}){var t,s,i,n,o;const r=this.bundledInstaller,d=String(e.remotePath||this.settings.installerRemotePath||"/tmp/bianbu_agent_proxy.sh").trim(),c=null!==(t=e.asRoot)&&void 0!==t?t:Boolean(this.settings.maintenanceAsRoot),u=e.action||"up",p=Number(null!==(i=null!==(s=e.reconnectPollMs)&&void 0!==s?s:this.settings.reconnectPollMs)&&void 0!==i?i:2e3),h=Number(null!==(o=null!==(n=e.healthTimeoutMs)&&void 0!==n?n:this.settings.upgradeHealthTimeoutMs)&&void 0!==o?o:12e4),m=e.signal,g=e.onProgress,f=(Buffer.byteLength(r.script,"utf-8"),e=>`${Math.round(e/1024)}KB`);if(!d)throw new Error("Remote installer path is required");const b=this.createMaintenanceSession(u,d,c),y=(0,a.remoteInstallerLogPath)(d),x=(0,a.remoteInstallerStatusPath)(d);b.remoteLogPath=y,b.remoteStatusPath=x,this.logSession(b,"info","Starting remote maintenance session",`remote_path=${d} action=${u}`);const v=()=>{if(null==m?void 0:m.aborted)throw new DOMException("Operation cancelled","AbortError")};try{null==g||g({step:"upload",stepIndex:0,totalSteps:4,label:"Uploading script...",percent:0}),v(),this.logSession(b,"info","Uploading bundled installer to remote host",d),await this.uploadTextViaChunked(d,r.script,c,(e,t)=>{null==g||g({step:"upload",stepIndex:0,totalSteps:4,label:`Uploading script (${f(e)} / ${f(t)})`,percent:Math.round(e/t*30)})}),v(),null==g||g({step:"launch",stepIndex:1,totalSteps:4,label:"Launching installer...",percent:30});const e=await this.runCommand((0,a.buildDetachedInstallerCommand)(d,u,y,x,b.sessionName),".",30,c);this.logSession(b,"info","Detached installer command launched",JSON.stringify(e,null,2)),null==g||g({step:"wait",stepIndex:2,totalSteps:4,label:"Waiting for installer...",percent:40});const{health:t,status:s}=await this.waitForInstallerCompletion({action:u,asRoot:c,expectedSessionName:b.sessionName,expectedScriptVersion:r.metadata.scriptVersion,expectedServerVersion:r.metadata.serverVersion,intervalMs:p,logPath:y,onPoll:(e,t)=>{const s=40+Math.round(e/t*50),i=Math.round(e/1e3);null==g||g({step:"wait",stepIndex:2,totalSteps:4,label:`Waiting for installer... (${i}s)`,percent:Math.min(s,89)})},session:b,signal:m,statusPath:x,timeoutMs:h});return null==g||g({step:"verify",stepIndex:3,totalSteps:4,label:"Verified!",percent:100}),(0,l.finishSessionLog)(b,"done"),this.logSession(b,"info","Remote maintenance session finished successfully"),{action:u,asRoot:c,health:t,installer:r.metadata,logPath:y,remotePath:d,session:b,start:e,status:s,statusPath:x}}catch(e){const t=String((null==e?void 0:e.message)||e);throw this.logSession(b,"error","Remote maintenance session failed",t),(0,l.finishSessionLog)(b,"error",void 0,t),e}}};u=i([(0,o.Injectable)(),n("design:paramtypes",[r.ConfigService])],u),t.BianbuMcpService=u},104(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuCloudProfileProvider=void 0;const i=s(650),n=s(678),o=s(241);class r extends i.ProfileProvider{constructor(){super(...arguments),this.id="bianbu-cloud",this.name="Bianbu Cloud",this.configDefaults={}}async getBuiltinProfiles(){return[{id:"bianbu-cloud-shell",type:"bianbu-cloud",name:"Bianbu Cloud Shell",icon:"terminal",color:"#2b6cb0",group:"Bianbu Cloud",disableDynamicTitle:!1,behaviorOnSessionEnd:"keep",weight:0,isBuiltin:!0,isTemplate:!1,options:{kind:"shell"}},{id:"bianbu-cloud-files",type:"bianbu-cloud",name:"Bianbu Cloud Files",icon:"folder-open",color:"#0f766e",group:"Bianbu Cloud",disableDynamicTitle:!0,behaviorOnSessionEnd:"keep",weight:1,isBuiltin:!0,isTemplate:!1,options:{kind:"files"}}]}async getNewTabParameters(e){return"files"===e.options.kind?{type:o.BianbuCloudFilesTabComponent,inputs:{profile:e}}:{type:n.BianbuCloudShellTabComponent,inputs:{profile:e}}}getSuggestedName(){return null}getDescription(e){var t;return"files"===(null===(t=e.options)||void 0===t?void 0:t.kind)?"Explorer-like file access backed by MCP file tools":"Terminal-like shell session backed by MCP run_command"}}t.BianbuCloudProfileProvider=r},215(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuPtySession=void 0;const i=s(349);class n extends i.BaseSession{constructor(e,t){super(e),this.mcp=t,this.sessionId=null,this.alive=!1,this.pollAbort=null,this.inputQueue=[],this.inputFlushTimer=null,this.initialCols=80,this.initialRows=24,this.lastCols=0,this.lastRows=0,this.resizeTimer=null}async start(e={}){this.open=!0,this.initialCols=e.cols||80,this.initialRows=e.rows||24;const t=await this.mcp.openPtySession(e.cwd||".",e.asRoot||!1,this.initialCols,this.initialRows);this.sessionId=t.session_id,this.alive=!0,this.lastCols=this.initialCols,this.lastRows=this.initialRows,this.startPollLoop()}write(e){this.alive&&this.sessionId&&(this.inputQueue.push(e),this.inputFlushTimer||(this.inputFlushTimer=setTimeout(()=>this.flushInput(),4)))}resize(e,t){this.sessionId&&this.alive&&(e===this.lastCols&&t===this.lastRows||(this.lastCols=e,this.lastRows=t,this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(()=>{this.resizeTimer=null,this.sessionId&&this.alive&&this.mcp.resizePty(this.sessionId,e,t).catch(()=>{})},100)))}kill(){this.cleanup()}async gracefullyKillProcess(){await this.cleanup()}supportsWorkingDirectory(){return!1}async getWorkingDirectory(){return null}async destroy(){await this.cleanup(),await super.destroy()}async flushInput(){var e;if(this.inputFlushTimer=null,!this.inputQueue.length||!this.sessionId||!this.alive)return;const t=Buffer.concat(this.inputQueue);this.inputQueue=[];try{const s=await this.mcp.writePtyInput(this.sessionId,t.toString("base64"));(null===(e=null==s?void 0:s.output)||void 0===e?void 0:e.data_base64)&&this.emitOutput(Buffer.from(s.output.data_base64,"base64")),(null==s?void 0:s.output)&&!s.output.alive&&(this.alive=!1,this.emitOutput(Buffer.from("\r\n[Process exited]\r\n")))}catch(e){this.logger.error("PTY write error",e)}}startPollLoop(){this.pollAbort=new AbortController,this.pollLoop()}async pollLoop(){for(;this.alive&&this.open;)try{const e=await this.mcp.readPtyOutputDirect(this.sessionId,this.pollAbort.signal);if((null==e?void 0:e.data_base64)&&this.emitOutput(Buffer.from(e.data_base64,"base64")),!(null==e?void 0:e.alive)){this.alive=!1,this.emitOutput(Buffer.from("\r\n[Process exited]\r\n"));break}}catch(e){if("AbortError"===(null==e?void 0:e.name))break;this.logger.warn("PTY poll error, retrying in 1s",e),await new Promise(e=>setTimeout(e,1e3))}}async cleanup(){var e;if(this.alive=!1,this.open=!1,null===(e=this.pollAbort)||void 0===e||e.abort(),this.pollAbort=null,this.inputFlushTimer&&(clearTimeout(this.inputFlushTimer),this.inputFlushTimer=null),this.resizeTimer&&(clearTimeout(this.resizeTimer),this.resizeTimer=null),this.sessionId){const e=this.sessionId;this.sessionId=null,await this.mcp.closePtySession(e).catch(()=>{})}}}t.BianbuPtySession=n},979(e,t,s){"use strict";var i=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.parseRemoteHealth=t.loadBundledInstaller=t.parseRemoteInstallerStatus=t.buildDetachedInstallerCommand=t.remoteInstallerStatusPath=t.remoteInstallerLogPath=t.appendRemoteSuffix=t.remoteDirName=t.shellQuote=t.validateConnectionSettings=t.normalizeMcpUrl=void 0;const n=s(982),o=i(s(947)),r=i(s(928));function a(e){return`'${String(e).replace(/'/g,"'\"'\"'")}'`}function l(e){const t=String(e||".").replace(/\\/g,"/"),s=t.lastIndexOf("/");return s<0?".":t.slice(0,s)||"/"}function d(e,t){return`${String(e||".").replace(/\\/g,"/")}${t}`}function c(e){return d(e,".log")}function u(e){return d(e,".status.json")}function p(e){return(0,n.createHash)("sha256").update(e,"utf8").digest("hex")}t.normalizeMcpUrl=function(e){return String(e||"").trim().replace(/\/+$/,"")},t.validateConnectionSettings=function(e){const t=[];return e.domain?/^https?:\/\//i.test(e.domain)&&t.push("Domain should not include https:// prefix"):t.push("MCP domain is required"),String((null==e?void 0:e.apiKey)||"").trim()||t.push("X-API-KEY is required"),t},t.shellQuote=a,t.remoteDirName=l,t.appendRemoteSuffix=d,t.remoteInstallerLogPath=c,t.remoteInstallerStatusPath=u,t.buildDetachedInstallerCommand=function(e,t,s=c(e),i=u(e),n=`maintenance-${t}`){const o=l(e),r=[`rm -f ${a(s)} ${a(i)}`,`export SESSION_NAME=${a(n)}`,`bash ${a(e)} ${t} > ${a(s)} 2>&1`,"__bianbu_rc=$?","__bianbu_ok=false",'[ "$__bianbu_rc" -eq 0 ] && __bianbu_ok=true','__bianbu_ts="$(date -u +%Y-%m-%dT%H:%M:%SZ)"',`printf '{"ok":%s,"exit_code":%s,"finished_at":"%s","action":"%s","log_path":"%s","session_name":"%s"}\\n' "$__bianbu_ok" "$__bianbu_rc" "$__bianbu_ts" ${a(t)} ${a(s)} ${a(n)} > ${a(i)}`].join("; ");return[`mkdir -p ${a(o)}`,`chmod 700 ${a(e)}`,`nohup bash -lc ${a(r)} > /dev/null 2>&1 < /dev/null & printf '__BIANBU_UPGRADE_STARTED__%s\\n' "$!"`].join(" && ")},t.parseRemoteInstallerStatus=function(e){var t;const s="string"==typeof e?JSON.parse(String(e||"").trim()||"{}"):e||{},i=null!==(t=s.exit_code)&&void 0!==t?t:s.exitCode,n=null==i?null:Number(i);return{ok:"boolean"==typeof s.ok?s.ok:0===n,exitCode:Number.isFinite(n)?n:null,finishedAt:s.finished_at||s.finishedAt||null,action:s.action||null,logPath:s.log_path||s.logPath||null,sessionName:s.session_name||s.sessionName||null,raw:s}},t.loadBundledInstaller=function(e=__dirname){let t=null;for(const s of function(e){return[r.default.resolve(e,"../assets"),r.default.resolve(e,"../../assets"),r.default.resolve(process.cwd(),"assets")]}(e)){const e=r.default.join(s,"bianbu_agent_proxy.sh"),i=r.default.join(s,"bianbu_agent_proxy.meta.json"),n=o.default.existsSync(e),a=o.default.existsSync(i);if(n||a)try{const t=o.default.readFileSync(e,"utf8"),s=JSON.parse(o.default.readFileSync(i,"utf8"));if(!(null==s?void 0:s.sha256)||!(null==s?void 0:s.scriptVersion)||!(null==s?void 0:s.serverVersion))throw new Error(`Bundled installer metadata is incomplete at ${i}`);if(p(t)!==s.sha256)throw new Error(`Bundled installer SHA-256 mismatch for ${e}`);return{script:t,metadata:s}}catch(e){t=e;break}}throw new Error(`Unable to load bundled remote installer assets: ${String((null==t?void 0:t.message)||t)}`)},t.parseRemoteHealth=function(e){var t,s,i,n,o,r,a,l,d,c,u;const p=null!==(n=null!==(i=null!==(t=null==e?void 0:e.structuredContent)&&void 0!==t?t:null===(s=null==e?void 0:e.result)||void 0===s?void 0:s.structuredContent)&&void 0!==i?i:e)&&void 0!==n?n:{},h=Array.isArray(p.tools)?p.tools.map(e=>String(e)):[],m={renamePath:Boolean(null===(o=null==p?void 0:p.supports)||void 0===o?void 0:o.rename_path)||h.includes("rename_path"),shellSession:Boolean(null===(r=null==p?void 0:p.supports)||void 0===r?void 0:r.shell_session)||h.includes("open_shell_session"),chunkedTransfers:Boolean(null===(a=null==p?void 0:p.supports)||void 0===a?void 0:a.chunked_transfers)||h.includes("upload_chunked_begin")&&h.includes("download_chunked_begin"),parallelChunkOffsets:Boolean(null===(l=null==p?void 0:p.supports)||void 0===l?void 0:l.parallel_chunk_offsets),rateLimiting:Boolean(null===(d=null==p?void 0:p.supports)||void 0===d?void 0:d.rate_limiting),isoTimestamps:Boolean(null===(c=null==p?void 0:p.supports)||void 0===c?void 0:c.iso_timestamps),ptySession:Boolean(null===(u=null==p?void 0:p.supports)||void 0===u?void 0:u.pty_session)||h.includes("open_pty_session")};return{ok:!1!==p.ok,serverVersion:p.server_version||p.version||null,scriptVersion:p.script_version||null,transportMode:p.transport_mode||null,fileRoot:p.file_root||null,hasSudo:"boolean"==typeof p.has_sudo?p.has_sudo:null,tools:h,supports:m,raw:p}}},935(e,t){"use strict";function s(e){return String(e).padStart(2,"0")}function i(e=new Date){return new Date(e||Date.now()).toISOString().replace(/\.\d{3}Z$/,"Z")}function n(e=new Date){const t=new Date(e||Date.now());return[String(t.getUTCFullYear()),s(t.getUTCMonth()+1),s(t.getUTCDate()),"T",s(t.getUTCHours()),s(t.getUTCMinutes()),s(t.getUTCSeconds()),"Z"].join("")}function o(e){return String(e||"session").replace(/[^a-zA-Z0-9._-]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")||"session"}function r(e){const t=["# bianbu local session log",`session_name=${e.sessionName}`,`kind=${e.kind}`,`action=${e.action}`,`status=${e.status}`,`started_at=${e.startedAt}`,`finished_at=${e.finishedAt||""}`,`remote_path=${e.remotePath||""}`,`remote_log_path=${e.remoteLogPath||""}`,`remote_status_path=${e.remoteStatusPath||""}`,`as_root=${void 0===e.asRoot?"":String(e.asRoot)}`,"","--- local_log ---"],s=e.entries.length?e.entries.map(t=>function(e,t){const s=[`[${t.timestamp}] [${e}] [${t.level.toUpperCase()}] ${t.message}`],i=String(t.details||"").trim();if(i)for(const e of i.split(/\r?\n/))s.push(` ${e}`);return s.join("\n")}(e.sessionName,t)):["[no log entries recorded]"];return`${t.join("\n")}\n${s.join("\n")}\n`}Object.defineProperty(t,"__esModule",{value:!0}),t.buildRemoteLogDownloadPayload=t.buildLocalLogDownloadPayload=t.renderLocalSessionLog=t.finishSessionLog=t.appendSessionLogEntry=t.createSessionLog=t.createSessionName=t.toCompactUtcStamp=t.toIsoUtc=void 0,t.toIsoUtc=i,t.toCompactUtcStamp=n,t.createSessionName=function(e,t,s=new Date){return`${String(e||"session").trim()}-${String(t||"run").trim()}-${n(s)}`},t.createSessionLog=function(e){return{action:e.action,asRoot:e.asRoot,entries:[],kind:e.kind,remoteLogPath:e.remoteLogPath||null,remotePath:e.remotePath||null,remoteStatusPath:e.remoteStatusPath||null,sessionName:e.sessionName,startedAt:e.startedAt||i(),status:"running"}},t.appendSessionLogEntry=function(e,t){const s={timestamp:t.timestamp||i(),level:t.level,message:t.message,details:t.details||null};return e.entries.push(s),s},t.finishSessionLog=function(e,t,s=new Date,n){return e.status=t,e.finishedAt=i(s),e.error=n||null,e},t.renderLocalSessionLog=r,t.buildLocalLogDownloadPayload=function(e,t=new Date){return{fileName:`${o(e.sessionName)}-local-${n(t)}.log`,content:r(e)}},t.buildRemoteLogDownloadPayload=function(e){const t=i(e.downloadedAt),s=String(e.remoteStatusText||"").trim()||"[remote status unavailable]",r=String(e.remoteLogText||"").trim()||"[remote log unavailable]",a=e.session,l=["# bianbu remote session log",`downloaded_at=${t}`,`session_name=${a.sessionName}`,`kind=${a.kind}`,`action=${a.action}`,`status=${a.status}`,`started_at=${a.startedAt}`,`finished_at=${a.finishedAt||""}`,`remote_path=${a.remotePath||""}`,`remote_log_path=${a.remoteLogPath||""}`,`remote_status_path=${a.remoteStatusPath||""}`,"","--- remote_status ---",s,"","--- remote_log ---",r,""].join("\n");return{fileName:`${o(a.sessionName)}-remote-${n(e.downloadedAt)}.log`,content:l}}},645(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},n=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuMcpSettingsComponent=void 0;const o=s(860),r=s(650),a=s(241),l=s(678),d=s(885);let c=class{constructor(e,t,s,i,n){this.config=e,this.app=t,this.mcp=s,this.notifications=i,this.platform=n,this.diagnosticsBusy=!1,this.maintenanceBusy=!1,this.maintenanceProgress=null,this.maintenanceElapsed=0,this.remoteHealth=null,this.lastDiagnosticAt="",this.lastMaintenanceAt="",this.lastMaintenanceSummary="",this.lastError="",this.advancedVisible=!1,this.maintenanceAbort=null,this.elapsedTimer=null}get settings(){return this.config.store.bianbuMcp}get bundledInstaller(){try{return this.mcp.bundledInstaller.metadata}catch{return null}}get validationErrors(){return this.mcp.validationErrors}get latestMaintenanceSession(){return this.mcp.latestMaintenanceSession}get sampleJson(){const e=this.settings,t=String(e.domain||"").trim().replace(/^https?:\/\//i,"").replace(/\/+$/,"");return JSON.stringify({mcpServers:{[e.name||"bianbu"]:{type:"http",url:t?`https://${t}/mcp`:"https://your-domain.example.com/mcp",headers:{"X-API-KEY":e.apiKey?"••••••••":"your-x-api-key"}}}},null,2)}save(){this.config.save()}openShell(){this.app.openNewTab({type:l.BianbuCloudShellTabComponent})}openFiles(){this.app.openNewTab({type:a.BianbuCloudFilesTabComponent})}async testConnection(){await this.refreshHealth("Connection verified")}async refreshHealth(e="Remote health refreshed"){this.lastError="",this.diagnosticsBusy=!0;try{this.remoteHealth=await this.mcp.getHealth(),this.lastDiagnosticAt=(new Date).toLocaleString(),this.notifications.notice(e)}catch(e){this.lastError=String((null==e?void 0:e.message)||e),this.notifications.error("Bianbu MCP health check failed",this.lastError)}finally{this.diagnosticsBusy=!1}}async pushUpgrade(e="up"){var t,s,i,n,o;this.lastError="",this.maintenanceBusy=!0,this.maintenanceElapsed=0,this.maintenanceProgress={step:"upload",stepIndex:0,totalSteps:4,label:"Preparing...",percent:0};const r=new AbortController;this.maintenanceAbort=r,this.elapsedTimer=setInterval(()=>{this.maintenanceElapsed++},1e3);try{const s=await this.mcp.pushInstallerAndUpgrade({action:e,asRoot:!!this.settings.maintenanceAsRoot,healthTimeoutMs:this.settings.upgradeHealthTimeoutMs,onProgress:e=>{this.maintenanceProgress=e},reconnectPollMs:this.settings.reconnectPollMs,remotePath:this.settings.installerRemotePath,signal:r.signal});this.remoteHealth=s.health,this.lastMaintenanceAt=(new Date).toLocaleString(),this.lastMaintenanceSummary=`session=${(null===(t=s.session)||void 0===t?void 0:t.sessionName)||"unknown"} action=${s.action} remotePath=${s.remotePath} logPath=${s.logPath} statusPath=${s.statusPath} script=${s.health.scriptVersion||"unknown"} server=${s.health.serverVersion||"unknown"}`,this.notifications.notice("repair"===e?"Remote repair finished":"Remote upgrade finished")}catch(t){if(this.lastMaintenanceAt=(new Date).toLocaleString(),this.lastMaintenanceSummary=`session=${(null===(s=this.latestMaintenanceSession)||void 0===s?void 0:s.sessionName)||"unknown"} action=${e} remotePath=${this.settings.installerRemotePath||"unknown"} logPath=${(null===(i=this.latestMaintenanceSession)||void 0===i?void 0:i.remoteLogPath)||"unknown"} statusPath=${(null===(n=this.latestMaintenanceSession)||void 0===n?void 0:n.remoteStatusPath)||"unknown"}`,"AbortError"===(null==t?void 0:t.name))this.lastError="Operation cancelled by user",this.notifications.info("Maintenance cancelled");else{const s=(null===(o=this.maintenanceProgress)||void 0===o?void 0:o.step)||"unknown";this.lastError=`[${s}] ${String((null==t?void 0:t.message)||t)}`,this.maintenanceProgress&&(this.maintenanceProgress={...this.maintenanceProgress,error:!0,label:`Failed at: ${s}`}),this.notifications.error("repair"===e?"Remote repair failed":"Remote upgrade failed",this.lastError)}}finally{clearInterval(this.elapsedTimer),this.elapsedTimer=null,this.maintenanceAbort=null,this.maintenanceBusy=!1,setTimeout(()=>{this.maintenanceBusy||(this.maintenanceProgress=null)},5e3)}}cancelMaintenance(){var e;null===(e=this.maintenanceAbort)||void 0===e||e.abort()}async downloadLocalMaintenanceLog(){try{const e=this.mcp.getLatestMaintenanceLocalLogDownloadPayload();await this.downloadTextFile(e.fileName,e.content),this.notifications.notice("Local maintenance log downloaded")}catch(e){this.lastError=String((null==e?void 0:e.message)||e),this.notifications.error("Failed to download local maintenance log",this.lastError)}}async downloadRemoteMaintenanceLog(){try{const e=await this.mcp.getLatestMaintenanceRemoteLogDownloadPayload();await this.downloadTextFile(e.fileName,e.content),this.notifications.notice("Remote maintenance log downloaded")}catch(e){this.lastError=String((null==e?void 0:e.message)||e),this.notifications.error("Failed to download remote maintenance log",this.lastError)}}async downloadTextFile(e,t){const s=(new TextEncoder).encode(t),i=await this.platform.startDownload(e,420,s.length);if(!i)throw new Error("Download cancelled");try{await i.write(s),i.close()}catch(e){throw i.close(),e}}};c=i([(0,o.Component)({template:s(426)}),n("design:paramtypes",[r.ConfigService,r.AppService,d.BianbuMcpService,r.NotificationsService,r.PlatformService])],c),t.BianbuMcpSettingsComponent=c},717(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuMcpSettingsTabProvider=void 0;const n=s(860),o=s(700),r=s(645);let a=class extends o.SettingsTabProvider{constructor(){super(...arguments),this.id="bianbu-mcp",this.icon="plug",this.title="Bianbu MCP"}getComponentType(){return r.BianbuMcpSettingsComponent}};a=i([(0,n.Injectable)()],a),t.BianbuMcpSettingsTabProvider=a},864(e,t,s){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuShellSession=void 0;const i=s(349);class n extends i.BaseSession{constructor(e,t){super(e),this.mcp=t,this.cwd=".",this.currentLine="",this.cursorPos=0,this.running=!1,this.asRoot=!1,this.sessionId=null,this.history=[],this.historyIndex=-1,this.savedLine="",this.escBuffer="",this.escTimer=null}async start(e={}){this.open=!0,this.cwd=e.cwd||".",this.asRoot=e.asRoot||!1,this.emitText("Connected to Bianbu Cloud MCP shell\r\n");try{const e=await this.mcp.openShellSession(this.cwd,this.asRoot);this.sessionId=e.session_id||null,this.sessionId&&this.emitText("Using persistent shell session\r\n")}catch{this.sessionId=null,this.emitText("Using stateless command mode\r\n")}this.emitPrompt()}resize(e,t){}write(e){const t=e.toString("utf-8");for(const e of t)this.handleChar(e)}kill(){this.running=!1,this.closeRemoteSession()}async gracefullyKillProcess(){this.running=!1,await this.closeRemoteSession()}async destroy(){this.running=!1,await this.closeRemoteSession(),await super.destroy()}supportsWorkingDirectory(){return!0}async getWorkingDirectory(){return this.cwd}handleChar(e){if(this.escBuffer.length>0||""===e)if(this.escBuffer+=e,this.escTimer&&clearTimeout(this.escTimer),this.escBuffer.length>=3&&"["===this.escBuffer[1]){const e=this.escBuffer[this.escBuffer.length-1];if(e>="@"&&e<="~"){const e=this.escBuffer;return this.escBuffer="",void this.handleEscSequence(e)}if(this.escBuffer.length>8)return void(this.escBuffer="")}else 1===this.escBuffer.length?this.escTimer=setTimeout(()=>{this.escBuffer=""},50):this.escBuffer.length>2&&"["!==this.escBuffer[1]&&(this.escBuffer="");else if(this.running)""===e&&this.emitText("^C\r\n");else switch(e){case"\r":case"\n":this.emitText("\r\n"),this.currentLine.trim()?(this.addToHistory(this.currentLine),this.execute(this.currentLine)):this.emitPrompt(),this.currentLine="",this.cursorPos=0,this.historyIndex=-1,this.savedLine="";break;case"":case"\b":this.cursorPos>0&&(this.currentLine=this.currentLine.slice(0,this.cursorPos-1)+this.currentLine.slice(this.cursorPos),this.cursorPos--,this.redrawLine());break;case"":this.currentLine="",this.cursorPos=0,this.historyIndex=-1,this.savedLine="",this.emitText("^C\r\n"),this.emitPrompt();break;case"":this.cursorPos>0&&(this.cursorPos=0,this.redrawLine());break;case"":this.cursorPos<this.currentLine.length&&(this.cursorPos=this.currentLine.length,this.redrawLine());break;case"":this.cursorPos>0&&(this.currentLine=this.currentLine.slice(this.cursorPos),this.cursorPos=0,this.redrawLine());break;case"\v":this.cursorPos<this.currentLine.length&&(this.currentLine=this.currentLine.slice(0,this.cursorPos),this.redrawLine());break;case"":if(this.cursorPos>0){const e=this.currentLine.slice(0,this.cursorPos).replace(/\S+\s*$/,""),t=this.currentLine.slice(this.cursorPos);this.currentLine=e+t,this.cursorPos=e.length,this.redrawLine()}break;case"\f":this.emitText(""),this.emitPrompt(),this.emitText(this.currentLine),this.cursorPos<this.currentLine.length&&this.emitText(`[${this.currentLine.length-this.cursorPos}D`);break;case"\t":break;default:e>=" "&&(this.currentLine=this.currentLine.slice(0,this.cursorPos)+e+this.currentLine.slice(this.cursorPos),this.cursorPos++,this.redrawLine())}}handleEscSequence(e){if(!this.running)switch(e){case"":this.navigateHistory(1);break;case"":this.navigateHistory(-1);break;case"":this.cursorPos<this.currentLine.length&&(this.cursorPos++,this.emitText(""));break;case"":this.cursorPos>0&&(this.cursorPos--,this.emitText(""));break;case"":this.cursorPos=0,this.redrawLine();break;case"":this.cursorPos=this.currentLine.length,this.redrawLine();break;case"[3~":this.cursorPos<this.currentLine.length&&(this.currentLine=this.currentLine.slice(0,this.cursorPos)+this.currentLine.slice(this.cursorPos+1),this.redrawLine())}}navigateHistory(e){if(this.history.length){if(-1===this.historyIndex&&e>0)this.savedLine=this.currentLine,this.historyIndex=0;else if(e>0&&this.historyIndex<this.history.length-1)this.historyIndex++;else{if(!(e<0&&this.historyIndex>0))return e<0&&0===this.historyIndex?(this.historyIndex=-1,this.currentLine=this.savedLine,this.cursorPos=this.currentLine.length,void this.redrawLine()):void 0;this.historyIndex--}this.historyIndex>=0&&this.historyIndex<this.history.length&&(this.currentLine=this.history[this.historyIndex],this.cursorPos=this.currentLine.length,this.redrawLine())}}addToHistory(e){const t=e.trim();t&&(this.history.length>0&&this.history[0]===t||(this.history.unshift(t),this.history.length>200&&(this.history.length=200)))}redrawLine(){const e=this.getPrompt();this.emitText(`\r${e}${this.currentLine}`);const t=this.currentLine.length-this.cursorPos;t>0&&this.emitText(`[${t}D`)}async execute(e){var t,s;this.running=!0,this.emitText("⏳ Running...\r\n");try{let i;i=this.sessionId?await this.mcp.execShellSession(this.sessionId,e,120):await this.mcp.runCommand(e,this.cwd,120,this.asRoot);const n=(null==i?void 0:i.stdout)||(null===(s=null===(t=null==i?void 0:i.content)||void 0===t?void 0:t[0])||void 0===s?void 0:s.text)||"",o=(null==i?void 0:i.stderr)||"";n&&this.emitText(this.normalize(n)),o&&this.emitText(`${this.normalize(o)}`),null==(null==i?void 0:i.exit_code)||0===i.exit_code||o||this.emitText(`command exited with code ${i.exit_code}\r\n`),(null==i?void 0:i.cwd)&&(this.cwd=i.cwd)}catch(e){this.emitText(`${this.normalize(String((null==e?void 0:e.message)||e))}`)}finally{this.running=!1,this.emitPrompt()}}async closeRemoteSession(){if(this.sessionId){try{await this.mcp.closeShellSession(this.sessionId)}catch{}this.sessionId=null}}getPrompt(){return`[bianbu ${this.cwd}]${this.asRoot?"#":"$"} `}emitPrompt(){this.emitText(this.getPrompt())}emitText(e){this.emitOutput(Buffer.from(e,"utf-8"))}normalize(e){let t=e.replace(/\r?\n/g,"\r\n");return t.endsWith("\r\n")||(t+="\r\n"),t}}t.BianbuShellSession=n},678(e,t,s){"use strict";var i=this&&this.__decorate||function(e,t,s,i){var n,o=arguments.length,r=o<3?t:null===i?i=Object.getOwnPropertyDescriptor(t,s):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(e,t,s,i);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(r=(o<3?n(r):o>3?n(t,s,r):n(t,s))||r);return o>3&&r&&Object.defineProperty(t,s,r),r},n=this&&this.__metadata||function(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)};Object.defineProperty(t,"__esModule",{value:!0}),t.BianbuCloudShellTabComponent=void 0;const o=s(860),r=s(349),a=s(650),l=s(885),d=s(864),c=s(215);let u=class extends r.BaseTerminalTabComponent{constructor(e,t,s){super(e),this.mcp=t,this.localNotifications=s,this.asRoot=!1,this.cwd=".",this.setTitle("Bianbu Cloud Shell"),this.icon="terminal",this.enableToolbar=!0,this.profile=this.profile||{id:"bianbu-cloud-shell",type:"bianbu-cloud",name:"Bianbu Cloud Shell",group:"Bianbu Cloud",options:{kind:"shell"},icon:"terminal",color:"#2b6cb0",disableDynamicTitle:!1,behaviorOnSessionEnd:"keep",weight:0,isBuiltin:!0,isTemplate:!1}}async onFrontendReady(){var e,t,s;let i;const n=await this.mcp.getHealth().catch(()=>null);if(null===(e=null==n?void 0:n.supports)||void 0===e?void 0:e.ptySession)try{const e=new c.BianbuPtySession(this.logger,this.mcp);i=e,this.setSession(i,!0),await e.start({cwd:this.cwd,asRoot:this.asRoot,cols:(null===(t=this.size)||void 0===t?void 0:t.columns)||80,rows:(null===(s=this.size)||void 0===s?void 0:s.rows)||24})}catch(e){this.logger.warn("PTY session failed, falling back to shell session",e);const t=new d.BianbuShellSession(this.logger,this.mcp);i=t,this.setSession(i,!0),await t.start({cwd:this.cwd,asRoot:this.asRoot})}else{const e=new d.BianbuShellSession(this.logger,this.mcp);i=e,this.setSession(i,!0),await e.start({cwd:this.cwd,asRoot:this.asRoot})}i.releaseInitialDataBuffer(),this.localNotifications.notice("Bianbu Cloud shell ready"),await super.onFrontendReady()}};i([(0,o.Input)(),n("design:type",Object)],u.prototype,"profile",void 0),i([(0,o.Input)(),n("design:type",Object)],u.prototype,"asRoot",void 0),i([(0,o.Input)(),n("design:type",Object)],u.prototype,"cwd",void 0),u=i([(0,o.Component)({template:r.BaseTerminalTabComponent.template,styles:r.BaseTerminalTabComponent.styles,animations:r.BaseTerminalTabComponent.animations}),n("design:paramtypes",[o.Injector,l.BianbuMcpService,a.NotificationsService])],u),t.BianbuCloudShellTabComponent=u},982(e){"use strict";e.exports=require("crypto")},928(e){"use strict";e.exports=require("path")},358(t){"use strict";t.exports=e},860(e){"use strict";e.exports=t},182(e){"use strict";e.exports=s},947(e){"use strict";e.exports=i},650(e){"use strict";e.exports=n},700(e){"use strict";e.exports=o},349(e){"use strict";e.exports=r}},l={},function e(t){var s=l[t];if(void 0!==s)return s.exports;var i=l[t]={exports:{}};return a[t].call(i.exports,i,i.exports,e),i.exports}(440);var a,l});
2
2
  //# sourceMappingURL=index.js.map