@codingame/monaco-vscode-xterm-common 36.2.7 → 37.2.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/package.json +4 -4
- package/vscode/src/vs/workbench/contrib/terminal/browser/agentHostOutputChannel.d.ts +22 -0
- package/vscode/src/vs/workbench/contrib/terminal/browser/agentHostOutputChannel.js +48 -0
- package/vscode/src/vs/workbench/contrib/terminal/browser/agentHostPty.d.ts +17 -5
- package/vscode/src/vs/workbench/contrib/terminal/browser/agentHostPty.js +173 -63
- package/vscode/src/vs/workbench/contrib/terminal/browser/agentHostTerminalService.d.ts +13 -3
- package/vscode/src/vs/workbench/contrib/terminal/browser/agentHostTerminalService.js +119 -56
- package/vscode/src/vs/workbench/contrib/terminal/browser/environmentVariableInfo.js +5 -5
- package/vscode/src/vs/workbench/contrib/terminal/browser/terminalActions.js +61 -61
- package/vscode/src/vs/workbench/contrib/terminal/browser/terminalInstance.d.ts +6 -2
- package/vscode/src/vs/workbench/contrib/terminal/browser/terminalInstance.js +71 -49
- package/vscode/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.d.ts +1 -0
- package/vscode/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.js +9 -7
- package/vscode/src/vs/workbench/contrib/terminal/browser/terminalTabsList.js +5 -5
- package/vscode/src/vs/workbench/contrib/terminal/browser/terminalTooltip.js +3 -3
- package/vscode/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollColorRegistry.js +3 -3
- package/vscode/src/vs/workbench/contrib/terminalContrib/stickyScroll/browser/terminalStickyScrollOverlay.js +3 -3
- package/vscode/src/vs/platform/agentHost/common/state/protocol/common/notifications.d.ts +0 -51
- package/vscode/src/vs/platform/agentHost/common/state/protocol/common/notifications.js +0 -9
- package/vscode/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChat.d.ts +0 -78
- package/vscode/src/vs/workbench/contrib/terminalContrib/chat/browser/terminalChat.js +0 -83
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codingame/monaco-vscode-xterm-common",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "37.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "VSCode public API plugged on the monaco editor - common package depending on xterm",
|
|
6
6
|
"keywords": [],
|
|
@@ -15,9 +15,9 @@
|
|
|
15
15
|
},
|
|
16
16
|
"type": "module",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@codingame/monaco-vscode-api": "
|
|
19
|
-
"@codingame/monaco-vscode-xterm-addons-common": "
|
|
20
|
-
"@xterm/xterm": "6.1.0-beta.
|
|
18
|
+
"@codingame/monaco-vscode-api": "37.2.0",
|
|
19
|
+
"@codingame/monaco-vscode-xterm-addons-common": "37.2.0",
|
|
20
|
+
"@xterm/xterm": "6.1.0-beta.304"
|
|
21
21
|
},
|
|
22
22
|
"exports": {
|
|
23
23
|
".": {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Event } from "@codingame/monaco-vscode-api/vscode/vs/base/common/event";
|
|
2
|
+
import { Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
|
|
3
|
+
import { URI } from "@codingame/monaco-vscode-api/vscode/vs/base/common/uri";
|
|
4
|
+
import { IAgentConnection } from "@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/agentService";
|
|
5
|
+
import type { IChatTerminalOutputSource } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/terminal/browser/terminal";
|
|
6
|
+
/**
|
|
7
|
+
* Read-only view of an AHP output channel. Unlike {@link AgentHostPty}, this
|
|
8
|
+
* does not create a terminal process or an {@code ITerminalInstance}; chat
|
|
9
|
+
* renders the accumulated plain-text state in its own detached xterm.
|
|
10
|
+
*/
|
|
11
|
+
export declare class AgentHostOutputChannel extends Disposable implements IChatTerminalOutputSource {
|
|
12
|
+
private readonly _onDidChange;
|
|
13
|
+
readonly onDidChange: Event<void>;
|
|
14
|
+
private _output;
|
|
15
|
+
get output(): string;
|
|
16
|
+
private _hasExited;
|
|
17
|
+
get hasExited(): boolean;
|
|
18
|
+
private _exitCode;
|
|
19
|
+
get exitCode(): number | undefined;
|
|
20
|
+
constructor(connection: IAgentConnection, terminalUri: URI);
|
|
21
|
+
private _acceptState;
|
|
22
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
|
|
2
|
+
import { Emitter } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
|
|
3
|
+
import { Disposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
4
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-root/state';
|
|
5
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-session/state';
|
|
6
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-chat/state';
|
|
7
|
+
import { TerminalLifecycleStatus } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-terminal/state';
|
|
8
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-changeset/state';
|
|
9
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-resource-watch/state';
|
|
10
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-automation/state';
|
|
11
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-automation-run/state';
|
|
12
|
+
import { StateComponents } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/sessionState';
|
|
13
|
+
|
|
14
|
+
class AgentHostOutputChannel extends Disposable {
|
|
15
|
+
get output() {
|
|
16
|
+
return this._output;
|
|
17
|
+
}
|
|
18
|
+
get hasExited() {
|
|
19
|
+
return this._hasExited;
|
|
20
|
+
}
|
|
21
|
+
get exitCode() {
|
|
22
|
+
return this._exitCode;
|
|
23
|
+
}
|
|
24
|
+
constructor(connection, terminalUri) {
|
|
25
|
+
super();
|
|
26
|
+
this._onDidChange = this._register(( new Emitter()));
|
|
27
|
+
this.onDidChange = this._onDidChange.event;
|
|
28
|
+
this._output = "";
|
|
29
|
+
this._hasExited = false;
|
|
30
|
+
const subscriptionRef = this._register(
|
|
31
|
+
connection.getSubscription(StateComponents.Terminal, terminalUri, "AgentHostOutputChannel")
|
|
32
|
+
);
|
|
33
|
+
const subscription = subscriptionRef.object;
|
|
34
|
+
if (subscription.value && !(subscription.value instanceof Error)) {
|
|
35
|
+
this._acceptState(subscription.value);
|
|
36
|
+
}
|
|
37
|
+
this._register(subscription.onDidChange(state => this._acceptState(state)));
|
|
38
|
+
}
|
|
39
|
+
_acceptState(state) {
|
|
40
|
+
this._output = ( state.content.map(part => part.type === "command" ? part.output : part.value)).join("").replace(/\r?\n/g, "\r\n");
|
|
41
|
+
const lifecycle = state.lifecycle;
|
|
42
|
+
this._hasExited = lifecycle.status === TerminalLifecycleStatus.Exited;
|
|
43
|
+
this._exitCode = lifecycle.status === TerminalLifecycleStatus.Exited ? lifecycle.exitCode : undefined;
|
|
44
|
+
this._onDidChange.fire();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { AgentHostOutputChannel };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Event } from "@codingame/monaco-vscode-api/vscode/vs/base/common/event";
|
|
2
2
|
import { URI } from "@codingame/monaco-vscode-api/vscode/vs/base/common/uri";
|
|
3
3
|
import { IProcessPropertyMap, ITerminalChildProcess, ITerminalLaunchError, ITerminalLaunchResult, ProcessPropertyType } from "@codingame/monaco-vscode-api/vscode/vs/platform/terminal/common/terminal";
|
|
4
|
-
import {
|
|
4
|
+
import { ITerminalLogService } from "@codingame/monaco-vscode-api/vscode/vs/platform/terminal/common/terminal.service";
|
|
5
|
+
import { IAgentConnection } from "@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/agentService";
|
|
5
6
|
import { BasePty } from "../common/basePty.js";
|
|
6
7
|
/**
|
|
7
8
|
* Options for creating a new terminal on an agent host.
|
|
@@ -56,11 +57,14 @@ export declare function getAhpCommandMarkId(commandId: string, kind: AhpCommandM
|
|
|
56
57
|
export declare class AgentHostPty extends BasePty implements ITerminalChildProcess {
|
|
57
58
|
private _connection;
|
|
58
59
|
private readonly _terminalUri;
|
|
59
|
-
private readonly _options
|
|
60
|
+
private readonly _options;
|
|
61
|
+
private readonly _logService;
|
|
60
62
|
private readonly _startBarrier;
|
|
61
|
-
private readonly
|
|
62
|
-
private
|
|
63
|
+
private readonly _lifetime;
|
|
64
|
+
private readonly _subscription;
|
|
65
|
+
private _terminalCreation;
|
|
63
66
|
private _initialCwd;
|
|
67
|
+
private _didSignalReady;
|
|
64
68
|
private readonly _onCommandExecuted;
|
|
65
69
|
readonly onCommandExecuted: Event<IAgentHostPtyCommandExecutedEvent>;
|
|
66
70
|
private readonly _onCommandFinished;
|
|
@@ -76,8 +80,10 @@ export declare class AgentHostPty extends BasePty implements ITerminalChildProce
|
|
|
76
80
|
* echo as a real command — we filter those out here.
|
|
77
81
|
*/
|
|
78
82
|
private readonly _suppressedCommandIds;
|
|
79
|
-
constructor(id: number, _connection: IAgentConnection, _terminalUri: URI, _options
|
|
83
|
+
constructor(id: number, _connection: IAgentConnection, _terminalUri: URI, _options: IAgentHostPtyOptions | undefined, _logService: ITerminalLogService);
|
|
80
84
|
start(): Promise<ITerminalLaunchError | ITerminalLaunchResult | undefined>;
|
|
85
|
+
private _clearTerminalCreation;
|
|
86
|
+
private _signalReady;
|
|
81
87
|
private _handleAction;
|
|
82
88
|
/**
|
|
83
89
|
* Replays structured terminal content parts from the initial state snapshot.
|
|
@@ -90,9 +96,15 @@ export declare class AgentHostPty extends BasePty implements ITerminalChildProce
|
|
|
90
96
|
* are unwrapped to their original URI via {@link fromAgentHostUri}.
|
|
91
97
|
*/
|
|
92
98
|
private _resolveCwdForProtocol;
|
|
99
|
+
private _createSubscription;
|
|
100
|
+
private _waitForHydration;
|
|
93
101
|
input(data: string): void;
|
|
94
102
|
resize(cols: number, rows: number): void;
|
|
95
103
|
shutdown(_immediate: boolean): void;
|
|
104
|
+
private _requestHostTerminalDisposal;
|
|
105
|
+
private _disposeHostTerminal;
|
|
106
|
+
private _logHostDisposalError;
|
|
107
|
+
private _exitAndDispose;
|
|
96
108
|
getInitialCwd(): Promise<string>;
|
|
97
109
|
getCwd(): Promise<string>;
|
|
98
110
|
clearBuffer(): Promise<void>;
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
|
|
2
|
-
import { Barrier } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { Barrier, raceCancellation, DeferredPromise, disposableTimeout } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
|
|
3
|
+
import { CancellationTokenSource } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
|
|
4
|
+
import { Emitter, Event } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
|
|
5
|
+
import { MutableDisposable, DisposableStore, toDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
5
6
|
import { ProcessPropertyType } from '@codingame/monaco-vscode-api/vscode/vs/platform/terminal/common/terminal';
|
|
6
7
|
import { AGENT_HOST_SCHEME, fromAgentHostUri } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/agentHostUri';
|
|
7
8
|
import { ActionType } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/common/actions';
|
|
8
|
-
import '
|
|
9
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/common/notifications';
|
|
9
10
|
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-root/state';
|
|
10
11
|
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-session/state';
|
|
11
12
|
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-chat/state';
|
|
12
13
|
import { TerminalClaimKind } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-terminal/state';
|
|
13
14
|
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-changeset/state';
|
|
14
15
|
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-resource-watch/state';
|
|
16
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-automation/state';
|
|
17
|
+
import '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/channels-automation-run/state';
|
|
15
18
|
import { StateComponents } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/sessionState';
|
|
16
19
|
import { BasePty } from '../common/basePty.js';
|
|
17
20
|
|
|
@@ -34,14 +37,17 @@ class AgentHostPty extends BasePty {
|
|
|
34
37
|
get supportsCommandDetection() {
|
|
35
38
|
return this._supportsCommandDetection;
|
|
36
39
|
}
|
|
37
|
-
constructor(id, _connection, _terminalUri, _options) {
|
|
40
|
+
constructor(id, _connection, _terminalUri, _options, _logService) {
|
|
38
41
|
super(id, false);
|
|
39
42
|
this._connection = _connection;
|
|
40
43
|
this._terminalUri = _terminalUri;
|
|
41
44
|
this._options = _options;
|
|
45
|
+
this._logService = _logService;
|
|
42
46
|
this._startBarrier = ( new Barrier());
|
|
43
|
-
this.
|
|
47
|
+
this._lifetime = this._register(( new CancellationTokenSource()));
|
|
48
|
+
this._subscription = this._register(( new MutableDisposable()));
|
|
44
49
|
this._initialCwd = "";
|
|
50
|
+
this._didSignalReady = false;
|
|
45
51
|
this._onCommandExecuted = this._register(( new Emitter()));
|
|
46
52
|
this.onCommandExecuted = this._onCommandExecuted.event;
|
|
47
53
|
this._onCommandFinished = this._register(( new Emitter()));
|
|
@@ -52,30 +58,45 @@ class AgentHostPty extends BasePty {
|
|
|
52
58
|
this._suppressedCommandIds = ( new Set());
|
|
53
59
|
}
|
|
54
60
|
async start() {
|
|
61
|
+
const connection = this._connection;
|
|
55
62
|
try {
|
|
63
|
+
if (this._lifetime.token.isCancellationRequested) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
56
66
|
if (!this._options?.attachOnly) {
|
|
57
|
-
|
|
67
|
+
const terminalCreation = connection.createTerminal({
|
|
58
68
|
channel: ( this._terminalUri.toString()),
|
|
59
69
|
claim: {
|
|
60
70
|
kind: TerminalClaimKind.Client,
|
|
61
|
-
clientId:
|
|
71
|
+
clientId: connection.clientId
|
|
62
72
|
},
|
|
63
73
|
name: this._options?.name,
|
|
64
74
|
cwd: this._resolveCwdForProtocol(this._options?.cwd),
|
|
65
75
|
cols: this._lastDimensions.cols > 0 ? this._lastDimensions.cols : undefined,
|
|
66
76
|
rows: this._lastDimensions.rows > 0 ? this._lastDimensions.rows : undefined
|
|
67
77
|
});
|
|
78
|
+
this._terminalCreation = terminalCreation;
|
|
79
|
+
terminalCreation.then(
|
|
80
|
+
() => this._clearTerminalCreation(terminalCreation),
|
|
81
|
+
() => this._clearTerminalCreation(terminalCreation)
|
|
82
|
+
);
|
|
83
|
+
const created = await raceCancellation(terminalCreation.then(() => true), this._lifetime.token, false);
|
|
84
|
+
if (!created) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
68
87
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
88
|
+
if (this._lifetime.token.isCancellationRequested || this._connection !== connection) {
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
const {
|
|
92
|
+
subscription,
|
|
93
|
+
store
|
|
94
|
+
} = this._createSubscription(this._connection);
|
|
95
|
+
if (!(await this._waitForHydration(subscription, store))) {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
if (this._lifetime.token.isCancellationRequested || this._subscription.value !== store) {
|
|
99
|
+
return undefined;
|
|
79
100
|
}
|
|
80
101
|
const state = subscription.value;
|
|
81
102
|
if (state.supportsCommandDetection) {
|
|
@@ -89,31 +110,49 @@ class AgentHostPty extends BasePty {
|
|
|
89
110
|
if (state.title) {
|
|
90
111
|
this._properties.title = state.title;
|
|
91
112
|
}
|
|
92
|
-
this.
|
|
113
|
+
this._signalReady();
|
|
114
|
+
store.add(subscription.onDidApplyAction(envelope => {
|
|
93
115
|
this._handleAction(envelope);
|
|
94
116
|
}));
|
|
95
|
-
this._startBarrier.open();
|
|
96
|
-
this.handleReady({
|
|
97
|
-
pid: -1,
|
|
98
|
-
cwd: this._initialCwd,
|
|
99
|
-
windowsPty: undefined
|
|
100
|
-
});
|
|
101
117
|
return undefined;
|
|
102
118
|
} catch (err) {
|
|
103
|
-
this.
|
|
119
|
+
if (this._lifetime.token.isCancellationRequested || this._connection !== connection) {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
104
122
|
return {
|
|
105
123
|
message: err instanceof Error ? err.message : String(err)
|
|
106
124
|
};
|
|
125
|
+
} finally {
|
|
126
|
+
this._startBarrier.open();
|
|
107
127
|
}
|
|
108
128
|
}
|
|
129
|
+
_clearTerminalCreation(terminalCreation) {
|
|
130
|
+
if (this._terminalCreation === terminalCreation) {
|
|
131
|
+
this._terminalCreation = undefined;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
_signalReady() {
|
|
135
|
+
if (this._didSignalReady || this._lifetime.token.isCancellationRequested) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
this._didSignalReady = true;
|
|
139
|
+
this.handleReady({
|
|
140
|
+
pid: -1,
|
|
141
|
+
cwd: this._initialCwd,
|
|
142
|
+
windowsPty: undefined
|
|
143
|
+
});
|
|
144
|
+
}
|
|
109
145
|
_handleAction(envelope) {
|
|
146
|
+
if (this._lifetime.token.isCancellationRequested) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
110
149
|
const action = envelope.action;
|
|
111
150
|
switch (action.type) {
|
|
112
151
|
case ActionType.TerminalData:
|
|
113
152
|
this.handleData(action.data);
|
|
114
153
|
break;
|
|
115
154
|
case ActionType.TerminalExited:
|
|
116
|
-
this.
|
|
155
|
+
this._exitAndDispose(action.exitCode);
|
|
117
156
|
break;
|
|
118
157
|
case ActionType.TerminalCwdChanged:
|
|
119
158
|
this._properties.cwd = ( action.cwd.toString());
|
|
@@ -211,11 +250,43 @@ class AgentHostPty extends BasePty {
|
|
|
211
250
|
}
|
|
212
251
|
return ( cwd.toString());
|
|
213
252
|
}
|
|
253
|
+
_createSubscription(connection) {
|
|
254
|
+
const store = ( new DisposableStore());
|
|
255
|
+
try {
|
|
256
|
+
const subscription = store.add(
|
|
257
|
+
connection.getSubscription(StateComponents.Terminal, this._terminalUri, "AgentHostPty")
|
|
258
|
+
).object;
|
|
259
|
+
this._subscription.value = store;
|
|
260
|
+
return {
|
|
261
|
+
subscription,
|
|
262
|
+
store
|
|
263
|
+
};
|
|
264
|
+
} catch (error) {
|
|
265
|
+
store.dispose();
|
|
266
|
+
throw error;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async _waitForHydration(subscription, store, timeoutMs) {
|
|
270
|
+
if (subscription.value !== undefined) {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
const hydration = ( new DeferredPromise());
|
|
274
|
+
const timeout = timeoutMs === undefined ? undefined : disposableTimeout(() => hydration.error(( new Error("Reconnect hydration timed out"))), timeoutMs, store);
|
|
275
|
+
store.add(toDisposable(() => hydration.complete(false)));
|
|
276
|
+
store.add(Event.once(subscription.onDidChange)(() => {
|
|
277
|
+
timeout?.dispose();
|
|
278
|
+
hydration.complete(true);
|
|
279
|
+
}));
|
|
280
|
+
return raceCancellation(hydration.p, this._lifetime.token, false);
|
|
281
|
+
}
|
|
214
282
|
input(data) {
|
|
215
|
-
if (this._inReplay) {
|
|
283
|
+
if (this._inReplay || this._lifetime.token.isCancellationRequested) {
|
|
216
284
|
return;
|
|
217
285
|
}
|
|
218
286
|
this._startBarrier.wait().then(() => {
|
|
287
|
+
if (this._lifetime.token.isCancellationRequested) {
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
219
290
|
this._connection.dispatch(( this._terminalUri.toString()), {
|
|
220
291
|
type: ActionType.TerminalInput,
|
|
221
292
|
data
|
|
@@ -223,12 +294,15 @@ class AgentHostPty extends BasePty {
|
|
|
223
294
|
});
|
|
224
295
|
}
|
|
225
296
|
resize(cols, rows) {
|
|
226
|
-
if (this._inReplay || (this._lastDimensions.cols === cols && this._lastDimensions.rows === rows)) {
|
|
297
|
+
if (this._lifetime.token.isCancellationRequested || this._inReplay || (this._lastDimensions.cols === cols && this._lastDimensions.rows === rows)) {
|
|
227
298
|
return;
|
|
228
299
|
}
|
|
229
300
|
this._lastDimensions.cols = cols;
|
|
230
301
|
this._lastDimensions.rows = rows;
|
|
231
302
|
this._startBarrier.wait().then(() => {
|
|
303
|
+
if (this._lifetime.token.isCancellationRequested) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
232
306
|
this._connection.dispatch(( this._terminalUri.toString()), {
|
|
233
307
|
type: ActionType.TerminalResized,
|
|
234
308
|
cols,
|
|
@@ -237,14 +311,43 @@ class AgentHostPty extends BasePty {
|
|
|
237
311
|
});
|
|
238
312
|
}
|
|
239
313
|
shutdown(_immediate) {
|
|
240
|
-
this.
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
314
|
+
if (this._lifetime.token.isCancellationRequested) {
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
this._requestHostTerminalDisposal();
|
|
318
|
+
this._exitAndDispose(undefined);
|
|
319
|
+
}
|
|
320
|
+
_requestHostTerminalDisposal() {
|
|
321
|
+
if (this._options?.attachOnly) {
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
this._disposeHostTerminal();
|
|
325
|
+
if (this._terminalCreation) {
|
|
326
|
+
void this._terminalCreation.then(() => this._disposeHostTerminal(), () => this._disposeHostTerminal());
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
_disposeHostTerminal() {
|
|
330
|
+
try {
|
|
331
|
+
void this._connection.disposeTerminal(this._terminalUri).catch(err => this._logHostDisposalError(err));
|
|
332
|
+
} catch (err) {
|
|
333
|
+
this._logHostDisposalError(err);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
_logHostDisposalError(err) {
|
|
337
|
+
this._logService.warn(
|
|
338
|
+
`[AgentHostPty] Failed to dispose host terminal: ${err instanceof Error ? err.message : String(err)}`
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
_exitAndDispose(exitCode) {
|
|
342
|
+
if (this._lifetime.token.isCancellationRequested) {
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
this._lifetime.cancel();
|
|
346
|
+
this._subscription.clear();
|
|
347
|
+
this._startBarrier.open();
|
|
348
|
+
queueMicrotask(() => {
|
|
349
|
+
this.handleExit(exitCode);
|
|
350
|
+
this.dispose();
|
|
248
351
|
});
|
|
249
352
|
}
|
|
250
353
|
async getInitialCwd() {
|
|
@@ -254,6 +357,9 @@ class AgentHostPty extends BasePty {
|
|
|
254
357
|
return this._properties.cwd || this._initialCwd;
|
|
255
358
|
}
|
|
256
359
|
async clearBuffer() {
|
|
360
|
+
if (this._lifetime.token.isCancellationRequested) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
257
363
|
this._connection.dispatch(( this._terminalUri.toString()), {
|
|
258
364
|
type: ActionType.TerminalCleared
|
|
259
365
|
});
|
|
@@ -269,27 +375,22 @@ class AgentHostPty extends BasePty {
|
|
|
269
375
|
}
|
|
270
376
|
async updateProperty(_type, _value) {}
|
|
271
377
|
async reconnect(newConnection) {
|
|
272
|
-
this.
|
|
273
|
-
|
|
274
|
-
|
|
378
|
+
if (this._lifetime.token.isCancellationRequested) {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
this._subscription.clear();
|
|
275
382
|
this._connection = newConnection;
|
|
383
|
+
let subscriptionStore;
|
|
276
384
|
try {
|
|
277
|
-
|
|
278
|
-
const subscription =
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const listener = subscription.onDidChange(() => {
|
|
287
|
-
clearTimeout(timer);
|
|
288
|
-
listener.dispose();
|
|
289
|
-
resolve();
|
|
290
|
-
});
|
|
291
|
-
this._subscriptionDisposables.add(listener);
|
|
292
|
-
}));
|
|
385
|
+
const result = this._createSubscription(this._connection);
|
|
386
|
+
const subscription = result.subscription;
|
|
387
|
+
subscriptionStore = result.store;
|
|
388
|
+
const RECONNECT_HYDRATE_TIMEOUT_MS = 10_000;
|
|
389
|
+
if (!(await this._waitForHydration(subscription, subscriptionStore, RECONNECT_HYDRATE_TIMEOUT_MS))) {
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
if (this._lifetime.token.isCancellationRequested || this._subscription.value !== subscriptionStore) {
|
|
393
|
+
return false;
|
|
293
394
|
}
|
|
294
395
|
const state = subscription.value;
|
|
295
396
|
if (state.supportsCommandDetection && !this._supportsCommandDetection) {
|
|
@@ -304,15 +405,24 @@ class AgentHostPty extends BasePty {
|
|
|
304
405
|
if (state.title) {
|
|
305
406
|
this._properties.title = state.title;
|
|
306
407
|
}
|
|
307
|
-
this.
|
|
408
|
+
this._signalReady();
|
|
409
|
+
subscriptionStore.add(subscription.onDidApplyAction(envelope => {
|
|
308
410
|
this._handleAction(envelope);
|
|
309
411
|
}));
|
|
310
412
|
return true;
|
|
311
413
|
} catch (err) {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
414
|
+
if (!this._lifetime.token.isCancellationRequested) {
|
|
415
|
+
this._logService.warn(
|
|
416
|
+
`[AgentHostPty] Reconnection failed: ${err instanceof Error ? err.message : String(err)}`
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
if (subscriptionStore && this._subscription.value === subscriptionStore) {
|
|
420
|
+
this._subscription.clear();
|
|
421
|
+
}
|
|
422
|
+
if (!this._didSignalReady && !this._lifetime.token.isCancellationRequested) {
|
|
423
|
+
this._requestHostTerminalDisposal();
|
|
424
|
+
this._exitAndDispose(undefined);
|
|
425
|
+
}
|
|
316
426
|
return false;
|
|
317
427
|
}
|
|
318
428
|
}
|
|
@@ -320,8 +430,8 @@ class AgentHostPty extends BasePty {
|
|
|
320
430
|
return this._terminalUri;
|
|
321
431
|
}
|
|
322
432
|
dispose() {
|
|
323
|
-
this.
|
|
324
|
-
this.
|
|
433
|
+
this._lifetime.cancel();
|
|
434
|
+
this._subscription.clear();
|
|
325
435
|
super.dispose();
|
|
326
436
|
}
|
|
327
437
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { Disposable, IDisposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
|
|
2
2
|
import { IObservable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/observable";
|
|
3
3
|
import { URI } from "@codingame/monaco-vscode-api/vscode/vs/base/common/uri";
|
|
4
|
-
import { IAgentConnection } from "@codingame/monaco-vscode-
|
|
4
|
+
import { IAgentConnection } from "@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/agentService";
|
|
5
5
|
import { IQuickInputService } from "@codingame/monaco-vscode-api/vscode/vs/platform/quickinput/common/quickInput.service";
|
|
6
|
+
import { ITerminalLogService } from "@codingame/monaco-vscode-api/vscode/vs/platform/terminal/common/terminal.service";
|
|
6
7
|
import { ITerminalInstance, ITerminalLocationOptions } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/terminal/browser/terminal";
|
|
7
8
|
import { ITerminalChatService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/terminal/browser/terminal.service";
|
|
8
9
|
import { ITerminalService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/terminal/browser/terminal.service";
|
|
@@ -35,6 +36,7 @@ export declare class AgentHostTerminalService extends Disposable implements IAge
|
|
|
35
36
|
private readonly _terminalChatService;
|
|
36
37
|
private readonly _terminalProfileService;
|
|
37
38
|
private readonly _quickInputService;
|
|
39
|
+
private readonly _logService;
|
|
38
40
|
readonly _serviceBrand: undefined;
|
|
39
41
|
private readonly _entries;
|
|
40
42
|
private readonly _usedHosts;
|
|
@@ -49,8 +51,8 @@ export declare class AgentHostTerminalService extends Disposable implements IAge
|
|
|
49
51
|
* keyed by terminal URI string. Used for reconnection scoping.
|
|
50
52
|
*/
|
|
51
53
|
private readonly _activePtys;
|
|
52
|
-
private readonly
|
|
53
|
-
constructor(_terminalService: ITerminalService, _terminalChatService: ITerminalChatService, _terminalProfileService: ITerminalProfileService, _quickInputService: IQuickInputService);
|
|
54
|
+
private readonly _pendingRevives;
|
|
55
|
+
constructor(_terminalService: ITerminalService, _terminalChatService: ITerminalChatService, _terminalProfileService: ITerminalProfileService, _quickInputService: IQuickInputService, _logService: ITerminalLogService);
|
|
54
56
|
registerEntry(entry: IAgentHostEntry): IDisposable;
|
|
55
57
|
getProfileForConnection(address: string): IAgentHostTerminalProfileInfo | undefined;
|
|
56
58
|
setDefaultCwd(cwd: URI | undefined): void;
|
|
@@ -59,7 +61,15 @@ export declare class AgentHostTerminalService extends Disposable implements IAge
|
|
|
59
61
|
createTerminalForEntry(address: string, options?: IAgentHostTerminalCreateOptions): Promise<ITerminalInstance | undefined>;
|
|
60
62
|
createTerminal(connection: IAgentConnection, options?: IAgentHostTerminalCreateOptions): Promise<ITerminalInstance>;
|
|
61
63
|
reviveTerminal(connection: IAgentConnection, terminalUri: URI, terminalToolSessionId: string): Promise<ITerminalInstance>;
|
|
64
|
+
attachOutputTerminal(connection: IAgentConnection, terminalUri: URI, terminalToolSessionId: string): IDisposable;
|
|
62
65
|
private _doReviveTerminal;
|
|
66
|
+
/** Creates the registration that owns the pty produced for {@link key}. */
|
|
67
|
+
private _createPtyRegistration;
|
|
68
|
+
/**
|
|
69
|
+
* Ties the registration's lifetime to the terminal instance so the local
|
|
70
|
+
* pty is disposed even on paths that never call `shutdown()`.
|
|
71
|
+
*/
|
|
72
|
+
private _registerInstancePtyCleanup;
|
|
63
73
|
reconnectTerminals(newConnection: IAgentConnection, oldClientId: string): Promise<{
|
|
64
74
|
recovered: number;
|
|
65
75
|
total: number;
|