tabby-mcp-server 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
**A Comprehensive MCP Server Plugin for Tabby Terminal**
|
|
14
14
|
|
|
15
|
-
*Connect AI assistants to your terminal with full control capabilities —
|
|
15
|
+
*Connect AI assistants to your terminal with full control capabilities — 21 MCP tools included*
|
|
16
16
|
|
|
17
17
|
[English](README.md) | [中文](README_CN.md)
|
|
18
18
|
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
|
|
29
29
|
### 🖥️ Terminal Control
|
|
30
30
|
- Execute commands with output capture
|
|
31
|
+
- Send interactive input (vim, less, top)
|
|
31
32
|
- Read terminal buffer content
|
|
32
|
-
- Abort running commands
|
|
33
|
-
- List all terminal sessions
|
|
33
|
+
- Abort/monitor running commands
|
|
34
34
|
|
|
35
35
|
</td>
|
|
36
36
|
<td width="50%">
|
|
@@ -211,14 +211,16 @@ For clients that don't support SSE, use the STDIO bridge:
|
|
|
211
211
|
|
|
212
212
|
## 🛠️ Available Tools
|
|
213
213
|
|
|
214
|
-
### Terminal Control (
|
|
214
|
+
### Terminal Control (6)
|
|
215
215
|
|
|
216
216
|
| Tool | Description |
|
|
217
217
|
|------|-------------|
|
|
218
218
|
| `get_session_list` | List all terminal sessions |
|
|
219
219
|
| `exec_command` | Execute command with output |
|
|
220
|
+
| `send_input` | Send interactive input (Ctrl+C, etc) |
|
|
220
221
|
| `get_terminal_buffer` | Read terminal buffer |
|
|
221
222
|
| `abort_command` | Abort running command |
|
|
223
|
+
| `get_command_status` | Monitor active commands |
|
|
222
224
|
|
|
223
225
|
### Tab Management (10)
|
|
224
226
|
|
package/dist/index.js
CHANGED
|
@@ -17453,6 +17453,8 @@ const core_1 = __webpack_require__(9430);
|
|
|
17453
17453
|
const tabby_core_1 = __webpack_require__(1368);
|
|
17454
17454
|
const mcpService_1 = __webpack_require__(7554);
|
|
17455
17455
|
const mcpLogger_service_1 = __webpack_require__(9924);
|
|
17456
|
+
// Version from package.json - update on each release
|
|
17457
|
+
const PLUGIN_VERSION = '1.0.4';
|
|
17456
17458
|
/**
|
|
17457
17459
|
* MCP Settings Tab Component
|
|
17458
17460
|
*/
|
|
@@ -17461,6 +17463,19 @@ let McpSettingsTabComponent = class McpSettingsTabComponent {
|
|
|
17461
17463
|
this.config = config;
|
|
17462
17464
|
this.mcpService = mcpService;
|
|
17463
17465
|
this.logger = logger;
|
|
17466
|
+
this.version = PLUGIN_VERSION;
|
|
17467
|
+
this.saveMessage = '';
|
|
17468
|
+
}
|
|
17469
|
+
ngOnInit() {
|
|
17470
|
+
// Ensure timing config exists
|
|
17471
|
+
if (!this.config.store.mcp.timing) {
|
|
17472
|
+
this.config.store.mcp.timing = {
|
|
17473
|
+
pollInterval: 100,
|
|
17474
|
+
initialDelay: 0,
|
|
17475
|
+
sessionStableChecks: 5,
|
|
17476
|
+
sessionPollInterval: 200
|
|
17477
|
+
};
|
|
17478
|
+
}
|
|
17464
17479
|
}
|
|
17465
17480
|
get isRunning() {
|
|
17466
17481
|
return this.mcpService.isServerRunning();
|
|
@@ -17484,9 +17499,28 @@ let McpSettingsTabComponent = class McpSettingsTabComponent {
|
|
|
17484
17499
|
console.log('MCP Logs:', logs);
|
|
17485
17500
|
alert('Logs have been printed to the console (Cmd+Option+I)');
|
|
17486
17501
|
}
|
|
17502
|
+
exportLogsToFile() {
|
|
17503
|
+
const logs = this.logger.exportLogs();
|
|
17504
|
+
const json = JSON.stringify(logs, null, 2);
|
|
17505
|
+
const blob = new Blob([json], { type: 'application/json' });
|
|
17506
|
+
const url = URL.createObjectURL(blob);
|
|
17507
|
+
const a = document.createElement('a');
|
|
17508
|
+
a.href = url;
|
|
17509
|
+
a.download = `mcp-logs-${new Date().toISOString().slice(0, 10)}.json`;
|
|
17510
|
+
document.body.appendChild(a);
|
|
17511
|
+
a.click();
|
|
17512
|
+
document.body.removeChild(a);
|
|
17513
|
+
URL.revokeObjectURL(url);
|
|
17514
|
+
this.logger.info('Logs exported to JSON file');
|
|
17515
|
+
}
|
|
17487
17516
|
clearLogs() {
|
|
17488
17517
|
this.logger.clearLogs();
|
|
17489
17518
|
}
|
|
17519
|
+
saveConfig() {
|
|
17520
|
+
this.config.save();
|
|
17521
|
+
this.saveMessage = '✓ Settings saved';
|
|
17522
|
+
setTimeout(() => { this.saveMessage = ''; }, 2000);
|
|
17523
|
+
}
|
|
17490
17524
|
getConfigExample() {
|
|
17491
17525
|
return JSON.stringify({
|
|
17492
17526
|
mcpServers: {
|
|
@@ -17508,7 +17542,10 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
|
|
|
17508
17542
|
selector: 'mcp-settings-tab',
|
|
17509
17543
|
template: `
|
|
17510
17544
|
<div class="mcp-settings">
|
|
17511
|
-
<
|
|
17545
|
+
<div class="header-row">
|
|
17546
|
+
<h3>🔌 MCP Server Settings</h3>
|
|
17547
|
+
<span class="version-badge">v{{ version }}</span>
|
|
17548
|
+
</div>
|
|
17512
17549
|
|
|
17513
17550
|
<div class="form-group">
|
|
17514
17551
|
<label>Server Status</label>
|
|
@@ -17534,14 +17571,14 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
|
|
|
17534
17571
|
<div class="form-group">
|
|
17535
17572
|
<label>Port</label>
|
|
17536
17573
|
<input type="number" class="form-control" [(ngModel)]="config.store.mcp.port"
|
|
17537
|
-
placeholder="3001" min="1024" max="65535">
|
|
17574
|
+
placeholder="3001" min="1024" max="65535" (change)="saveConfig()">
|
|
17538
17575
|
<small class="form-text text-muted">MCP server port (default: 3001)</small>
|
|
17539
17576
|
</div>
|
|
17540
17577
|
|
|
17541
17578
|
<div class="form-group">
|
|
17542
17579
|
<div class="checkbox">
|
|
17543
17580
|
<label>
|
|
17544
|
-
<input type="checkbox" [(ngModel)]="config.store.mcp.startOnBoot">
|
|
17581
|
+
<input type="checkbox" [(ngModel)]="config.store.mcp.startOnBoot" (change)="saveConfig()">
|
|
17545
17582
|
Start server on Tabby launch
|
|
17546
17583
|
</label>
|
|
17547
17584
|
</div>
|
|
@@ -17554,7 +17591,7 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
|
|
|
17554
17591
|
<div class="form-group">
|
|
17555
17592
|
<div class="checkbox">
|
|
17556
17593
|
<label>
|
|
17557
|
-
<input type="checkbox" [(ngModel)]="config.store.mcp.enableLogging">
|
|
17594
|
+
<input type="checkbox" [(ngModel)]="config.store.mcp.enableLogging" (change)="saveConfig()">
|
|
17558
17595
|
Enable logging
|
|
17559
17596
|
</label>
|
|
17560
17597
|
</div>
|
|
@@ -17562,7 +17599,7 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
|
|
|
17562
17599
|
|
|
17563
17600
|
<div class="form-group" *ngIf="config.store.mcp.enableLogging">
|
|
17564
17601
|
<label>Log Level</label>
|
|
17565
|
-
<select class="form-control" [(ngModel)]="config.store.mcp.logLevel">
|
|
17602
|
+
<select class="form-control" [(ngModel)]="config.store.mcp.logLevel" (change)="saveConfig()">
|
|
17566
17603
|
<option value="debug">Debug</option>
|
|
17567
17604
|
<option value="info">Info</option>
|
|
17568
17605
|
<option value="warn">Warning</option>
|
|
@@ -17572,6 +17609,7 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
|
|
|
17572
17609
|
|
|
17573
17610
|
<div class="form-group" *ngIf="config.store.mcp.enableLogging">
|
|
17574
17611
|
<button class="btn btn-sm btn-secondary" (click)="viewLogs()">View Logs</button>
|
|
17612
|
+
<button class="btn btn-sm btn-outline-secondary ml-2" (click)="exportLogsToFile()">Export JSON</button>
|
|
17575
17613
|
<button class="btn btn-sm btn-outline-secondary ml-2" (click)="clearLogs()">Clear Logs</button>
|
|
17576
17614
|
</div>
|
|
17577
17615
|
|
|
@@ -17582,7 +17620,7 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
|
|
|
17582
17620
|
<div class="form-group">
|
|
17583
17621
|
<div class="checkbox">
|
|
17584
17622
|
<label>
|
|
17585
|
-
<input type="checkbox" [(ngModel)]="config.store.mcp.pairProgrammingMode.enabled">
|
|
17623
|
+
<input type="checkbox" [(ngModel)]="config.store.mcp.pairProgrammingMode.enabled" (change)="saveConfig()">
|
|
17586
17624
|
Enable Pair Programming Mode
|
|
17587
17625
|
</label>
|
|
17588
17626
|
</div>
|
|
@@ -17594,7 +17632,7 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
|
|
|
17594
17632
|
<div class="form-group" *ngIf="config.store.mcp.pairProgrammingMode.enabled">
|
|
17595
17633
|
<div class="checkbox">
|
|
17596
17634
|
<label>
|
|
17597
|
-
<input type="checkbox" [(ngModel)]="config.store.mcp.pairProgrammingMode.showConfirmationDialog">
|
|
17635
|
+
<input type="checkbox" [(ngModel)]="config.store.mcp.pairProgrammingMode.showConfirmationDialog" (change)="saveConfig()">
|
|
17598
17636
|
Show confirmation dialog
|
|
17599
17637
|
</label>
|
|
17600
17638
|
</div>
|
|
@@ -17603,7 +17641,7 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
|
|
|
17603
17641
|
<div class="form-group" *ngIf="config.store.mcp.pairProgrammingMode.enabled">
|
|
17604
17642
|
<div class="checkbox">
|
|
17605
17643
|
<label>
|
|
17606
|
-
<input type="checkbox" [(ngModel)]="config.store.mcp.pairProgrammingMode.autoFocusTerminal">
|
|
17644
|
+
<input type="checkbox" [(ngModel)]="config.store.mcp.pairProgrammingMode.autoFocusTerminal" (change)="saveConfig()">
|
|
17607
17645
|
Auto-focus terminal on command execution
|
|
17608
17646
|
</label>
|
|
17609
17647
|
</div>
|
|
@@ -17611,6 +17649,41 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
|
|
|
17611
17649
|
|
|
17612
17650
|
<hr />
|
|
17613
17651
|
|
|
17652
|
+
<h4>⏱️ Timing Settings</h4>
|
|
17653
|
+
<small class="form-text text-muted mb-2">
|
|
17654
|
+
Advanced timing configuration for command execution and session detection
|
|
17655
|
+
</small>
|
|
17656
|
+
|
|
17657
|
+
<div class="form-group">
|
|
17658
|
+
<label>Poll Interval (ms)</label>
|
|
17659
|
+
<input type="number" class="form-control" [(ngModel)]="config.store.mcp.timing.pollInterval"
|
|
17660
|
+
placeholder="100" min="50" max="1000" (change)="saveConfig()">
|
|
17661
|
+
<small class="form-text text-muted">How often to check for command output (default: 100)</small>
|
|
17662
|
+
</div>
|
|
17663
|
+
|
|
17664
|
+
<div class="form-group">
|
|
17665
|
+
<label>Initial Delay (ms)</label>
|
|
17666
|
+
<input type="number" class="form-control" [(ngModel)]="config.store.mcp.timing.initialDelay"
|
|
17667
|
+
placeholder="0" min="0" max="5000" (change)="saveConfig()">
|
|
17668
|
+
<small class="form-text text-muted">Delay before polling starts (default: 0)</small>
|
|
17669
|
+
</div>
|
|
17670
|
+
|
|
17671
|
+
<div class="form-group">
|
|
17672
|
+
<label>Session Stable Checks</label>
|
|
17673
|
+
<input type="number" class="form-control" [(ngModel)]="config.store.mcp.timing.sessionStableChecks"
|
|
17674
|
+
placeholder="5" min="1" max="20" (change)="saveConfig()">
|
|
17675
|
+
<small class="form-text text-muted">Number of stable checks for session ready detection (default: 5)</small>
|
|
17676
|
+
</div>
|
|
17677
|
+
|
|
17678
|
+
<div class="form-group">
|
|
17679
|
+
<label>Session Poll Interval (ms)</label>
|
|
17680
|
+
<input type="number" class="form-control" [(ngModel)]="config.store.mcp.timing.sessionPollInterval"
|
|
17681
|
+
placeholder="200" min="100" max="2000" (change)="saveConfig()">
|
|
17682
|
+
<small class="form-text text-muted">Interval for session ready polling (default: 200)</small>
|
|
17683
|
+
</div>
|
|
17684
|
+
|
|
17685
|
+
<hr />
|
|
17686
|
+
|
|
17614
17687
|
<h4>🔗 Connection Info</h4>
|
|
17615
17688
|
<div class="connection-info">
|
|
17616
17689
|
<p><strong>SSE Endpoint:</strong> <code>http://localhost:{{ config.store.mcp.port }}/sse</code></p>
|
|
@@ -17622,12 +17695,29 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
|
|
|
17622
17695
|
<button class="btn btn-sm btn-outline-primary" (click)="copyConfig()">Copy Config</button>
|
|
17623
17696
|
</div>
|
|
17624
17697
|
</div>
|
|
17698
|
+
|
|
17699
|
+
<div class="save-status mt-3" *ngIf="saveMessage">
|
|
17700
|
+
<span class="text-success">{{ saveMessage }}</span>
|
|
17701
|
+
</div>
|
|
17625
17702
|
</div>
|
|
17626
17703
|
`,
|
|
17627
17704
|
styles: [`
|
|
17628
17705
|
.mcp-settings {
|
|
17629
17706
|
padding: 1rem;
|
|
17630
17707
|
}
|
|
17708
|
+
.header-row {
|
|
17709
|
+
display: flex;
|
|
17710
|
+
align-items: center;
|
|
17711
|
+
justify-content: space-between;
|
|
17712
|
+
}
|
|
17713
|
+
.version-badge {
|
|
17714
|
+
background: rgba(0, 123, 255, 0.2);
|
|
17715
|
+
color: #007bff;
|
|
17716
|
+
padding: 0.25rem 0.5rem;
|
|
17717
|
+
border-radius: 4px;
|
|
17718
|
+
font-size: 0.85em;
|
|
17719
|
+
font-weight: bold;
|
|
17720
|
+
}
|
|
17631
17721
|
.status-container {
|
|
17632
17722
|
display: flex;
|
|
17633
17723
|
align-items: center;
|
|
@@ -17662,6 +17752,18 @@ exports.McpSettingsTabComponent = McpSettingsTabComponent = __decorate([
|
|
|
17662
17752
|
font-size: 0.85em;
|
|
17663
17753
|
overflow-x: auto;
|
|
17664
17754
|
}
|
|
17755
|
+
.ml-2 {
|
|
17756
|
+
margin-left: 0.5rem;
|
|
17757
|
+
}
|
|
17758
|
+
.mb-2 {
|
|
17759
|
+
margin-bottom: 0.5rem;
|
|
17760
|
+
display: block;
|
|
17761
|
+
}
|
|
17762
|
+
.save-status {
|
|
17763
|
+
padding: 0.5rem;
|
|
17764
|
+
background: rgba(40, 167, 69, 0.1);
|
|
17765
|
+
border-radius: 4px;
|
|
17766
|
+
}
|
|
17665
17767
|
`]
|
|
17666
17768
|
}),
|
|
17667
17769
|
__metadata("design:paramtypes", [tabby_core_1.ConfigService,
|
|
@@ -24861,45 +24963,73 @@ Special keys: \\x03 (Ctrl+C), \\x04 (Ctrl+D), \\x1b (Escape), \\r (Enter)`,
|
|
|
24861
24963
|
}
|
|
24862
24964
|
/**
|
|
24863
24965
|
* Wait for command output between markers
|
|
24966
|
+
* Timing is configurable via Settings → MCP → Timing
|
|
24864
24967
|
*/
|
|
24865
24968
|
async waitForCommandOutput(session, startMarker, endMarker, timeout, isAborted) {
|
|
24866
24969
|
const startTime = Date.now();
|
|
24867
24970
|
let lastBufferLength = 0;
|
|
24868
|
-
let
|
|
24971
|
+
let stableCount = 0;
|
|
24972
|
+
// Get timing config (with fallback defaults)
|
|
24973
|
+
const timing = this.config.store.mcp?.timing || {};
|
|
24974
|
+
const pollInterval = timing.pollInterval ?? 100;
|
|
24975
|
+
const initialDelay = timing.initialDelay ?? 0;
|
|
24976
|
+
// Optional initial delay (configurable, default 0)
|
|
24977
|
+
if (initialDelay > 0) {
|
|
24978
|
+
await new Promise(resolve => setTimeout(resolve, initialDelay));
|
|
24979
|
+
}
|
|
24869
24980
|
while (Date.now() - startTime < timeout) {
|
|
24870
24981
|
if (isAborted()) {
|
|
24871
24982
|
return { success: false, output: '', error: 'Command aborted' };
|
|
24872
24983
|
}
|
|
24873
24984
|
const buffer = this.getTerminalBufferText(session);
|
|
24874
|
-
//
|
|
24875
|
-
|
|
24876
|
-
const
|
|
24877
|
-
|
|
24878
|
-
|
|
24879
|
-
//
|
|
24880
|
-
const
|
|
24881
|
-
const
|
|
24882
|
-
|
|
24883
|
-
|
|
24884
|
-
output,
|
|
24885
|
-
|
|
24886
|
-
|
|
24985
|
+
// Look for end marker with exit code pattern (complete marker)
|
|
24986
|
+
// End marker format: __MCP_END_<timestamp>__ <exit_code>
|
|
24987
|
+
const endPattern = new RegExp(`${endMarker}\\s+(\\d+)`, 'm');
|
|
24988
|
+
const endMatch = buffer.match(endPattern);
|
|
24989
|
+
if (endMatch) {
|
|
24990
|
+
// Found complete end marker with exit code
|
|
24991
|
+
const endIndex = buffer.indexOf(endMatch[0]);
|
|
24992
|
+
const startIndex = buffer.lastIndexOf(startMarker, endIndex);
|
|
24993
|
+
if (startIndex !== -1 && startIndex < endIndex) {
|
|
24994
|
+
// Extract output between markers
|
|
24995
|
+
let output = buffer.substring(startIndex + startMarker.length, endIndex).trim();
|
|
24996
|
+
// Remove command echo (first line often contains the wrapped command)
|
|
24997
|
+
// Look for the start marker echo line and skip it
|
|
24998
|
+
const lines = output.split('\n');
|
|
24999
|
+
if (lines.length > 0 && lines[0].includes(startMarker.slice(0, 10))) {
|
|
25000
|
+
lines.shift();
|
|
25001
|
+
output = lines.join('\n').trim();
|
|
25002
|
+
}
|
|
25003
|
+
const exitCode = parseInt(endMatch[1], 10);
|
|
25004
|
+
return {
|
|
25005
|
+
success: exitCode === 0,
|
|
25006
|
+
output,
|
|
25007
|
+
exitCode
|
|
25008
|
+
};
|
|
25009
|
+
}
|
|
24887
25010
|
}
|
|
24888
|
-
// Track
|
|
25011
|
+
// Track buffer stability (helps detect when output is complete)
|
|
24889
25012
|
if (buffer.length === lastBufferLength) {
|
|
24890
|
-
|
|
25013
|
+
stableCount++;
|
|
24891
25014
|
}
|
|
24892
25015
|
else {
|
|
24893
|
-
|
|
25016
|
+
stableCount = 0;
|
|
24894
25017
|
lastBufferLength = buffer.length;
|
|
24895
25018
|
}
|
|
24896
|
-
|
|
25019
|
+
// Wait between checks (configurable via Settings → MCP → Timing)
|
|
25020
|
+
await new Promise(resolve => setTimeout(resolve, pollInterval));
|
|
24897
25021
|
}
|
|
24898
25022
|
// On timeout, return partial output if start marker found
|
|
24899
25023
|
const buffer = this.getTerminalBufferText(session);
|
|
24900
25024
|
const startIndex = buffer.lastIndexOf(startMarker);
|
|
24901
25025
|
if (startIndex !== -1) {
|
|
24902
|
-
|
|
25026
|
+
let partialOutput = buffer.substring(startIndex + startMarker.length).trim();
|
|
25027
|
+
// Clean up command echo
|
|
25028
|
+
const lines = partialOutput.split('\n');
|
|
25029
|
+
if (lines.length > 0 && lines[0].includes('&&')) {
|
|
25030
|
+
lines.shift();
|
|
25031
|
+
partialOutput = lines.join('\n').trim();
|
|
25032
|
+
}
|
|
24903
25033
|
return {
|
|
24904
25034
|
success: false,
|
|
24905
25035
|
output: partialOutput,
|
|
@@ -27665,16 +27795,58 @@ Set waitForReady=false (default) for immediate return - use get_session_list to
|
|
|
27665
27795
|
if (tab) {
|
|
27666
27796
|
const tabIndex = this.app.tabs.indexOf(tab);
|
|
27667
27797
|
if (waitForReady) {
|
|
27668
|
-
// Wait for the terminal to be
|
|
27798
|
+
// Wait for the terminal session to be fully connected
|
|
27799
|
+
// Timing is configurable via Settings → MCP → Timing
|
|
27800
|
+
const timing = this.config.store.mcp?.timing || {};
|
|
27801
|
+
const sessionPollInterval = timing.sessionPollInterval ?? 200;
|
|
27802
|
+
const sessionStableChecks = timing.sessionStableChecks ?? 5;
|
|
27669
27803
|
const startTime = Date.now();
|
|
27670
27804
|
let ready = false;
|
|
27805
|
+
let lastBufferLength = 0;
|
|
27806
|
+
let stableCount = 0;
|
|
27671
27807
|
while (Date.now() - startTime < timeout) {
|
|
27672
|
-
|
|
27673
|
-
|
|
27808
|
+
const tabAny = tab;
|
|
27809
|
+
// Check multiple indicators of connection readiness:
|
|
27810
|
+
// 1. frontend exists (terminal rendered)
|
|
27811
|
+
// 2. session exists and is open
|
|
27812
|
+
// 3. sessionReady is explicitly true
|
|
27813
|
+
// 4. buffer has content (indicates activity)
|
|
27814
|
+
const hasSession = tabAny.session !== undefined;
|
|
27815
|
+
const sessionOpen = tabAny.session?.open === true;
|
|
27816
|
+
const frontendReady = tabAny.frontend !== undefined;
|
|
27817
|
+
const sessionReady = tabAny.sessionReady === true;
|
|
27818
|
+
// Also check if terminal buffer has content (indicates connection activity)
|
|
27819
|
+
let bufferLength = 0;
|
|
27820
|
+
try {
|
|
27821
|
+
const xterm = tabAny.frontend?.xterm;
|
|
27822
|
+
if (xterm?.buffer?.active) {
|
|
27823
|
+
bufferLength = xterm.buffer.active.length;
|
|
27824
|
+
}
|
|
27825
|
+
}
|
|
27826
|
+
catch (e) {
|
|
27827
|
+
// Ignore buffer access errors
|
|
27828
|
+
}
|
|
27829
|
+
// Consider ready if:
|
|
27830
|
+
// - Session is open, OR
|
|
27831
|
+
// - Frontend is ready AND sessionReady is true, OR
|
|
27832
|
+
// - Terminal buffer has stabilized with content
|
|
27833
|
+
if (sessionOpen || (frontendReady && sessionReady)) {
|
|
27674
27834
|
ready = true;
|
|
27675
27835
|
break;
|
|
27676
27836
|
}
|
|
27677
|
-
|
|
27837
|
+
// Check for buffer stability (activity settled)
|
|
27838
|
+
if (bufferLength > 0 && bufferLength === lastBufferLength) {
|
|
27839
|
+
stableCount++;
|
|
27840
|
+
if (stableCount >= sessionStableChecks) {
|
|
27841
|
+
ready = true;
|
|
27842
|
+
break;
|
|
27843
|
+
}
|
|
27844
|
+
}
|
|
27845
|
+
else {
|
|
27846
|
+
stableCount = 0;
|
|
27847
|
+
lastBufferLength = bufferLength;
|
|
27848
|
+
}
|
|
27849
|
+
await new Promise(resolve => setTimeout(resolve, sessionPollInterval));
|
|
27678
27850
|
}
|
|
27679
27851
|
this.logger.info(`Opened profile: ${profile.name} (ready: ${ready})`);
|
|
27680
27852
|
return {
|
|
@@ -59734,6 +59906,13 @@ let McpConfigProvider = class McpConfigProvider extends tabby_core_1.ConfigProvi
|
|
|
59734
59906
|
enabled: true,
|
|
59735
59907
|
showConfirmationDialog: true,
|
|
59736
59908
|
autoFocusTerminal: true
|
|
59909
|
+
},
|
|
59910
|
+
// Timing configuration (in milliseconds)
|
|
59911
|
+
timing: {
|
|
59912
|
+
pollInterval: 100, // How often to check for command output
|
|
59913
|
+
initialDelay: 0, // Delay before starting to poll (0 = no delay)
|
|
59914
|
+
sessionStableChecks: 5, // Number of stable checks for session ready detection
|
|
59915
|
+
sessionPollInterval: 200 // Interval for session ready polling
|
|
59737
59916
|
}
|
|
59738
59917
|
}
|
|
59739
59918
|
};
|