@codingame/monaco-vscode-xterm-common 31.0.1 → 32.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/vscode/src/vs/platform/agentHost/common/state/protocol/actions.d.ts +154 -90
- package/vscode/src/vs/platform/agentHost/common/state/protocol/actions.js +4 -1
- package/vscode/src/vs/platform/agentHost/common/state/protocol/notifications.d.ts +9 -9
- package/vscode/src/vs/platform/agentHost/common/state/sessionState.d.ts +82 -19
- package/vscode/src/vs/platform/agentHost/common/state/sessionState.js +5 -1
- package/vscode/src/vs/workbench/contrib/terminal/browser/agentHostPty.d.ts +12 -1
- package/vscode/src/vs/workbench/contrib/terminal/browser/agentHostPty.js +52 -1
- package/vscode/src/vs/workbench/contrib/terminal/browser/agentHostTerminalService.d.ts +11 -0
- package/vscode/src/vs/workbench/contrib/terminal/browser/agentHostTerminalService.js +55 -10
- 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 +0 -2
- package/vscode/src/vs/workbench/contrib/terminal/browser/terminalInstance.js +42 -38
- package/vscode/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.js +2 -2
- package/vscode/src/vs/workbench/contrib/terminal/browser/terminalResizeDebouncer.js +15 -0
- package/vscode/src/vs/workbench/contrib/terminal/browser/terminalTabsList.js +14 -14
- 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/state.d.ts +0 -1418
- package/vscode/src/vs/platform/agentHost/common/state/protocol/state.js +0 -118
|
@@ -36,10 +36,13 @@ var ActionType;
|
|
|
36
36
|
ActionType["SessionCustomizationToggled"] = "session/customizationToggled";
|
|
37
37
|
ActionType["SessionTruncated"] = "session/truncated";
|
|
38
38
|
ActionType["SessionIsReadChanged"] = "session/isReadChanged";
|
|
39
|
-
ActionType["
|
|
39
|
+
ActionType["SessionIsArchivedChanged"] = "session/isArchivedChanged";
|
|
40
|
+
ActionType["SessionActivityChanged"] = "session/activityChanged";
|
|
40
41
|
ActionType["SessionDiffsChanged"] = "session/diffsChanged";
|
|
41
42
|
ActionType["SessionConfigChanged"] = "session/configChanged";
|
|
43
|
+
ActionType["SessionMetaChanged"] = "session/metaChanged";
|
|
42
44
|
ActionType["RootTerminalsChanged"] = "root/terminalsChanged";
|
|
45
|
+
ActionType["RootConfigChanged"] = "root/configChanged";
|
|
43
46
|
ActionType["TerminalData"] = "terminal/data";
|
|
44
47
|
ActionType["TerminalInput"] = "terminal/input";
|
|
45
48
|
ActionType["TerminalResized"] = "terminal/resized";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { URI,
|
|
1
|
+
import type { URI, SessionSummary } from "@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/state";
|
|
2
2
|
/**
|
|
3
3
|
* Reason why authentication is required.
|
|
4
4
|
*
|
|
@@ -47,10 +47,10 @@ export declare enum NotificationType {
|
|
|
47
47
|
* }
|
|
48
48
|
* ```
|
|
49
49
|
*/
|
|
50
|
-
export interface
|
|
50
|
+
export interface SessionAddedNotification {
|
|
51
51
|
type: NotificationType.SessionAdded;
|
|
52
52
|
/** Summary of the new session */
|
|
53
|
-
summary:
|
|
53
|
+
summary: SessionSummary;
|
|
54
54
|
}
|
|
55
55
|
/**
|
|
56
56
|
* Broadcast to all connected clients when a session is disposed.
|
|
@@ -71,7 +71,7 @@ export interface ISessionAddedNotification {
|
|
|
71
71
|
* }
|
|
72
72
|
* ```
|
|
73
73
|
*/
|
|
74
|
-
export interface
|
|
74
|
+
export interface SessionRemovedNotification {
|
|
75
75
|
type: NotificationType.SessionRemoved;
|
|
76
76
|
/** URI of the removed session */
|
|
77
77
|
session: URI;
|
|
@@ -99,7 +99,7 @@ export interface ISessionRemovedNotification {
|
|
|
99
99
|
* replayed on reconnect. On reconnect, clients should re-fetch the full
|
|
100
100
|
* catalog via `listSessions()` as usual.
|
|
101
101
|
* - The server SHOULD emit this notification whenever any mutable field on
|
|
102
|
-
* {@link
|
|
102
|
+
* {@link SessionSummary | `SessionSummary`} changes for a session the
|
|
103
103
|
* server has surfaced via `listSessions()` or `notify/sessionAdded`.
|
|
104
104
|
* Servers MAY coalesce or debounce updates for noisy fields (for example,
|
|
105
105
|
* `modifiedAt` bumps while a turn is streaming, or rapidly changing
|
|
@@ -128,7 +128,7 @@ export interface ISessionRemovedNotification {
|
|
|
128
128
|
* }
|
|
129
129
|
* ```
|
|
130
130
|
*/
|
|
131
|
-
export interface
|
|
131
|
+
export interface SessionSummaryChangedNotification {
|
|
132
132
|
type: NotificationType.SessionSummaryChanged;
|
|
133
133
|
/** URI of the session whose summary changed */
|
|
134
134
|
session: URI;
|
|
@@ -138,7 +138,7 @@ export interface ISessionSummaryChangedNotification {
|
|
|
138
138
|
* Identity fields (`resource`, `provider`, `createdAt`) never change and
|
|
139
139
|
* MUST be omitted by senders; receivers SHOULD ignore them if present.
|
|
140
140
|
*/
|
|
141
|
-
changes: Partial<
|
|
141
|
+
changes: Partial<SessionSummary>;
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
144
|
* Sent by the server when a protected resource requires (re-)authentication.
|
|
@@ -166,7 +166,7 @@ export interface ISessionSummaryChangedNotification {
|
|
|
166
166
|
* }
|
|
167
167
|
* ```
|
|
168
168
|
*/
|
|
169
|
-
export interface
|
|
169
|
+
export interface AuthRequiredNotification {
|
|
170
170
|
type: NotificationType.AuthRequired;
|
|
171
171
|
/** The protected resource identifier that requires authentication */
|
|
172
172
|
resource: string;
|
|
@@ -176,4 +176,4 @@ export interface IAuthRequiredNotification {
|
|
|
176
176
|
/**
|
|
177
177
|
* Discriminated union of all protocol notifications.
|
|
178
178
|
*/
|
|
179
|
-
export type
|
|
179
|
+
export type ProtocolNotification = SessionAddedNotification | SessionRemovedNotification | SessionSummaryChangedNotification | AuthRequiredNotification;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { URI as ResourceURI } from "@codingame/monaco-vscode-api/vscode/vs/base/common/uri";
|
|
2
|
+
import { ToolResultFileEditContent, type ActiveTurn, type RootState, type SessionState, type SessionSummary, type ToolCallCancelledState, type ToolCallCompletedState, type ToolCallResult, type ToolCallState, type ToolResultContent, type ToolResultSubagentContent, type URI as ProtocolURI, type UserMessage, TerminalState } from "@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/state";
|
|
3
|
+
export { type ActiveTurn, type AgentInfo, type ConfigPropertySchema, type ConfigSchema, type ContentRef, type ErrorInfo, type ProjectInfo, type MarkdownResponsePart, type MessageAttachment, type MessageResourceAttachment, type ReasoningResponsePart, type ResponsePart, type RootState, type SessionActiveClient, type SessionConfigState, type FileEdit as ISessionFileDiff, type ModelSelection, type SessionModelInfo, type SessionState, type SessionSummary, type Snapshot, type TerminalState, type ToolAnnotations, type ToolCallCancelledState, type ToolCallCompletedState, type ToolCallPendingConfirmationState, type ToolCallPendingResultConfirmationState, type ToolCallResponsePart, type ToolCallResult, type ToolCallRunningState, type ToolCallState, type ToolCallStreamingState, type ToolDefinition, type CustomizationRef, type SessionCustomization, type ToolResultEmbeddedResourceContent as IToolResultBinaryContent, type ToolResultContent, type ToolResultFileEditContent, type ToolResultSubagentContent, type ToolResultTextContent, type Turn, type UsageInfo, type UserMessage, type PendingMessage, type StringOrMarkdown, type URI, type SessionInputRequest, type SessionInputQuestion, type SessionInputAnswer, type SessionInputOption, CustomizationStatus, MessageAttachmentKind, PendingMessageKind, PolicyState, ResponsePartKind, SessionInputAnswerState, SessionInputAnswerValueKind, SessionInputQuestionKind, SessionInputResponseKind, SessionLifecycle, SessionStatus, ToolCallConfirmationReason, ToolCallCancellationReason, ToolCallStatus, ToolResultContentType, TurnState, } from "@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/state";
|
|
3
4
|
/**
|
|
4
5
|
* The kind of file edit operation. Derived from the presence/absence of
|
|
5
|
-
* `before`/`after` in {@link
|
|
6
|
+
* `before`/`after` in {@link ToolResultFileEditContent}.
|
|
6
7
|
*/
|
|
7
8
|
export declare enum FileEditKind {
|
|
8
9
|
/** Content edit (same file URI, different content). */
|
|
@@ -19,58 +20,120 @@ export declare const ROOT_STATE_URI = "agenthost:/root";
|
|
|
19
20
|
/**
|
|
20
21
|
* A tool call in a terminal state, stored in completed turns.
|
|
21
22
|
*/
|
|
22
|
-
export type ICompletedToolCall =
|
|
23
|
+
export type ICompletedToolCall = ToolCallCompletedState | ToolCallCancelledState;
|
|
23
24
|
/**
|
|
24
25
|
* Derived status type for the tool call lifecycle.
|
|
25
26
|
*/
|
|
26
|
-
export type ToolCallStatusString =
|
|
27
|
+
export type ToolCallStatusString = ToolCallState["status"];
|
|
27
28
|
/**
|
|
28
29
|
* Extracts a plain-text tool output string from a tool call result's `content`
|
|
29
30
|
* array. Joins all text-type content parts into a single string.
|
|
30
31
|
*
|
|
31
32
|
* Returns `undefined` if there are no text content parts.
|
|
32
33
|
*/
|
|
33
|
-
export declare function getToolOutputText(result:
|
|
34
|
+
export declare function getToolOutputText(result: ToolCallResult): string | undefined;
|
|
34
35
|
/**
|
|
35
36
|
* Extracts file edit content entries from a tool call result's `content` array.
|
|
36
37
|
* Returns an empty array if there are no file edit content parts.
|
|
37
38
|
*/
|
|
38
|
-
export declare function getToolFileEdits(result:
|
|
39
|
+
export declare function getToolFileEdits(result: ToolCallResult): ToolResultFileEditContent[];
|
|
39
40
|
/**
|
|
40
41
|
* Extracts the first subagent content entry from a tool call's `content` array.
|
|
41
42
|
* Works with both completed tool call results and running tool call states.
|
|
42
43
|
* Returns `undefined` if there are no subagent content parts.
|
|
43
44
|
*/
|
|
44
45
|
export declare function getToolSubagentContent(result: {
|
|
45
|
-
content?: readonly
|
|
46
|
-
}):
|
|
46
|
+
content?: readonly ToolResultContent[];
|
|
47
|
+
}): ToolResultSubagentContent | undefined;
|
|
47
48
|
/**
|
|
48
49
|
* Builds a subagent session URI from a parent session URI and tool call ID.
|
|
49
50
|
* Convention: `{parentSessionUri}/subagent/{toolCallId}`
|
|
50
51
|
*/
|
|
51
|
-
export declare function buildSubagentSessionUri(parentSession:
|
|
52
|
+
export declare function buildSubagentSessionUri(parentSession: ProtocolURI | ResourceURI, toolCallId: string): string;
|
|
52
53
|
/**
|
|
53
54
|
* Parses a subagent session URI into its parent session URI and tool call ID.
|
|
54
55
|
* Returns `undefined` if the URI does not follow the subagent convention.
|
|
55
56
|
*/
|
|
56
|
-
export declare function parseSubagentSessionUri(uri:
|
|
57
|
-
parentSession:
|
|
57
|
+
export declare function parseSubagentSessionUri(uri: ProtocolURI | ResourceURI): {
|
|
58
|
+
parentSession: ResourceURI;
|
|
58
59
|
toolCallId: string;
|
|
59
60
|
} | undefined;
|
|
60
61
|
/**
|
|
61
62
|
* Returns whether a session URI represents a subagent session.
|
|
62
63
|
*/
|
|
63
|
-
export declare function isSubagentSession(uri:
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
export declare function isSubagentSession(uri: ProtocolURI | ResourceURI): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Builds the string prefix used by the state manager for cached subagent sessions.
|
|
67
|
+
*/
|
|
68
|
+
export declare function buildSubagentSessionUriPrefix(parentSession: ProtocolURI | ResourceURI): string;
|
|
69
|
+
export declare function createRootState(): RootState;
|
|
70
|
+
export declare function createSessionState(summary: SessionSummary): SessionState;
|
|
71
|
+
export declare function createActiveTurn(id: string, userMessage: UserMessage): ActiveTurn;
|
|
67
72
|
export declare enum StateComponents {
|
|
68
73
|
Root = 0,
|
|
69
74
|
Session = 1,
|
|
70
75
|
Terminal = 2
|
|
71
76
|
}
|
|
72
77
|
export type ComponentToState = {
|
|
73
|
-
[StateComponents.Root]:
|
|
74
|
-
[StateComponents.Session]:
|
|
75
|
-
[StateComponents.Terminal]:
|
|
78
|
+
[StateComponents.Root]: RootState;
|
|
79
|
+
[StateComponents.Session]: SessionState;
|
|
80
|
+
[StateComponents.Terminal]: TerminalState;
|
|
76
81
|
};
|
|
82
|
+
/**
|
|
83
|
+
* VS Code-side alias for the protocol's open `_meta` property bag on
|
|
84
|
+
* {@link SessionState}. Keys SHOULD be namespaced (e.g. `git`, `vscode.foo`)
|
|
85
|
+
* to avoid collisions; values MUST be JSON-serializable.
|
|
86
|
+
*/
|
|
87
|
+
export type SessionMeta = Record<string, unknown>;
|
|
88
|
+
/**
|
|
89
|
+
* Reserved key under {@link SessionMeta} for the well-known git-state
|
|
90
|
+
* payload. Value at this key, when present, MUST be shaped like
|
|
91
|
+
* {@link ISessionGitState}. This is a VS Code-specific convention layered
|
|
92
|
+
* on top of the protocol's generic `_meta` bag — the protocol itself does
|
|
93
|
+
* not know about git state.
|
|
94
|
+
*/
|
|
95
|
+
export declare const SESSION_META_GIT_KEY = "git";
|
|
96
|
+
/**
|
|
97
|
+
* Git state of a session's working directory, carried under
|
|
98
|
+
* {@link SessionMeta} at {@link SESSION_META_GIT_KEY}. Used by clients to
|
|
99
|
+
* drive source-control affordances (e.g. PR/merge buttons in the Agents
|
|
100
|
+
* app).
|
|
101
|
+
*
|
|
102
|
+
* All fields are optional — agents that do not track a particular field
|
|
103
|
+
* should omit it rather than send a placeholder, so clients can distinguish
|
|
104
|
+
* "unknown" from "known to be zero".
|
|
105
|
+
*/
|
|
106
|
+
export interface ISessionGitState {
|
|
107
|
+
/** Whether the working directory has a `github.com` git remote. */
|
|
108
|
+
readonly hasGitHubRemote?: boolean;
|
|
109
|
+
/** Current branch name. */
|
|
110
|
+
readonly branchName?: string;
|
|
111
|
+
/** Base branch the work targets (e.g. `main`). */
|
|
112
|
+
readonly baseBranchName?: string;
|
|
113
|
+
/** Upstream tracking branch (e.g. `origin/feature`). */
|
|
114
|
+
readonly upstreamBranchName?: string;
|
|
115
|
+
/** Number of commits the upstream branch has ahead of the local branch. */
|
|
116
|
+
readonly incomingChanges?: number;
|
|
117
|
+
/** Number of commits the local branch has ahead of the upstream branch. */
|
|
118
|
+
readonly outgoingChanges?: number;
|
|
119
|
+
/** Number of files with uncommitted changes. */
|
|
120
|
+
readonly uncommittedChanges?: number;
|
|
121
|
+
/** GitHub repository owner parsed from the working copy's GitHub remote (preferring `origin`, falling back to the first GitHub remote). */
|
|
122
|
+
readonly githubOwner?: string;
|
|
123
|
+
/** GitHub repository name parsed from the working copy's GitHub remote (preferring `origin`, falling back to the first GitHub remote). */
|
|
124
|
+
readonly githubRepo?: string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Reads the well-known git-state payload from {@link SessionMeta}, if
|
|
128
|
+
* present. Returns `undefined` when the meta bag is absent or the value at
|
|
129
|
+
* the git key is not a plain object (e.g. an array or a primitive).
|
|
130
|
+
* Individual fields with wrong types are silently dropped so partial state
|
|
131
|
+
* still propagates.
|
|
132
|
+
*/
|
|
133
|
+
export declare function readSessionGitState(meta: SessionMeta | undefined): ISessionGitState | undefined;
|
|
134
|
+
/**
|
|
135
|
+
* Returns a new {@link SessionMeta} with the git-state payload set to
|
|
136
|
+
* `gitState`, or with the git slot removed if `gitState` is `undefined`.
|
|
137
|
+
* Returns `undefined` if the result would be empty.
|
|
138
|
+
*/
|
|
139
|
+
export declare function withSessionGitState(meta: SessionMeta | undefined, gitState: ISessionGitState | undefined): SessionMeta | undefined;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
|
|
2
2
|
import '@codingame/monaco-vscode-api/vscode/vs/base/common/errors';
|
|
3
|
-
|
|
3
|
+
import '@codingame/monaco-vscode-api/vscode/vs/base/common/charCode';
|
|
4
|
+
import '@codingame/monaco-vscode-api/vscode/vs/base/common/marshallingIds';
|
|
5
|
+
import '@codingame/monaco-vscode-api/vscode/vs/base/common/path';
|
|
6
|
+
import '@codingame/monaco-vscode-api/vscode/vs/base/common/platform';
|
|
7
|
+
export { CustomizationStatus, MessageAttachmentKind, PendingMessageKind, PolicyState, ResponsePartKind, SessionInputAnswerState, SessionInputAnswerValueKind, SessionInputQuestionKind, SessionInputResponseKind, SessionLifecycle, SessionStatus, ToolCallCancellationReason, ToolCallConfirmationReason, ToolCallStatus, ToolResultContentType, TurnState } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/state';
|
|
4
8
|
|
|
5
9
|
var FileEditKind;
|
|
6
10
|
(function(FileEditKind) {
|
|
@@ -54,7 +54,7 @@ export declare function getAhpCommandMarkId(commandId: string, kind: AhpCommandM
|
|
|
54
54
|
* shutdown() → disposeTerminal command
|
|
55
55
|
*/
|
|
56
56
|
export declare class AgentHostPty extends BasePty implements ITerminalChildProcess {
|
|
57
|
-
private
|
|
57
|
+
private _connection;
|
|
58
58
|
private readonly _terminalUri;
|
|
59
59
|
private readonly _options?;
|
|
60
60
|
private readonly _startBarrier;
|
|
@@ -102,5 +102,16 @@ export declare class AgentHostPty extends BasePty implements ITerminalChildProce
|
|
|
102
102
|
sendSignal(_signal: string): void;
|
|
103
103
|
refreshProperty<T extends ProcessPropertyType>(type: T): Promise<IProcessPropertyMap[T]>;
|
|
104
104
|
updateProperty<T extends ProcessPropertyType>(_type: T, _value: IProcessPropertyMap[T]): Promise<void>;
|
|
105
|
+
/**
|
|
106
|
+
* Reconnect this pty to a new agent host connection. Tears down the
|
|
107
|
+
* old subscription and re-subscribes with the new connection, replaying
|
|
108
|
+
* content from the server-side snapshot. Terminal output during the
|
|
109
|
+
* disconnect gap is a stream (not state), so some loss is expected.
|
|
110
|
+
*
|
|
111
|
+
* @returns `true` if reconnection succeeded, `false` otherwise.
|
|
112
|
+
*/
|
|
113
|
+
reconnect(newConnection: IAgentConnection): Promise<boolean>;
|
|
114
|
+
/** The terminal URI this pty is subscribed to. */
|
|
115
|
+
get terminalUri(): URI;
|
|
105
116
|
dispose(): void;
|
|
106
117
|
}
|
|
@@ -6,7 +6,7 @@ import { ProcessPropertyType } from '@codingame/monaco-vscode-api/vscode/vs/plat
|
|
|
6
6
|
import { AGENT_HOST_SCHEME, fromAgentHostUri } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/agentHostUri';
|
|
7
7
|
import { ActionType } from '../../../../platform/agentHost/common/state/protocol/actions.js';
|
|
8
8
|
import '../../../../platform/agentHost/common/state/protocol/notifications.js';
|
|
9
|
-
import { TerminalClaimKind } from '
|
|
9
|
+
import { TerminalClaimKind } from '@codingame/monaco-vscode-api/vscode/vs/platform/agentHost/common/state/protocol/state';
|
|
10
10
|
import { StateComponents } from '../../../../platform/agentHost/common/state/sessionState.js';
|
|
11
11
|
import { BasePty } from '../common/basePty.js';
|
|
12
12
|
|
|
@@ -266,6 +266,57 @@ class AgentHostPty extends BasePty {
|
|
|
266
266
|
return this._properties[type];
|
|
267
267
|
}
|
|
268
268
|
async updateProperty(_type, _value) {}
|
|
269
|
+
async reconnect(newConnection) {
|
|
270
|
+
this._subscriptionDisposables.clear();
|
|
271
|
+
this._subscriptionRef?.dispose();
|
|
272
|
+
this._subscriptionRef = undefined;
|
|
273
|
+
this._connection = newConnection;
|
|
274
|
+
try {
|
|
275
|
+
this._subscriptionRef = this._connection.getSubscription(StateComponents.Terminal, this._terminalUri);
|
|
276
|
+
const subscription = this._subscriptionRef.object;
|
|
277
|
+
if (subscription.value === undefined) {
|
|
278
|
+
const RECONNECT_HYDRATE_TIMEOUT_MS = 10_000;
|
|
279
|
+
await ( new Promise((resolve, reject) => {
|
|
280
|
+
const timer = setTimeout(() => {
|
|
281
|
+
listener.dispose();
|
|
282
|
+
reject(( new Error("Reconnect hydration timed out")));
|
|
283
|
+
}, RECONNECT_HYDRATE_TIMEOUT_MS);
|
|
284
|
+
const listener = subscription.onDidChange(() => {
|
|
285
|
+
clearTimeout(timer);
|
|
286
|
+
listener.dispose();
|
|
287
|
+
resolve();
|
|
288
|
+
});
|
|
289
|
+
this._subscriptionDisposables.add(listener);
|
|
290
|
+
}));
|
|
291
|
+
}
|
|
292
|
+
const state = subscription.value;
|
|
293
|
+
if (state.supportsCommandDetection && !this._supportsCommandDetection) {
|
|
294
|
+
this._supportsCommandDetection = true;
|
|
295
|
+
this._onSupportsCommandDetection.fire();
|
|
296
|
+
}
|
|
297
|
+
this.handleData("\u001b[2J\u001b[3J\u001b[H");
|
|
298
|
+
this._replayContent(state.content);
|
|
299
|
+
if (state.cwd) {
|
|
300
|
+
this._properties.cwd = ( state.cwd.toString());
|
|
301
|
+
}
|
|
302
|
+
if (state.title) {
|
|
303
|
+
this._properties.title = state.title;
|
|
304
|
+
}
|
|
305
|
+
this._subscriptionDisposables.add(subscription.onDidApplyAction(envelope => {
|
|
306
|
+
this._handleAction(envelope);
|
|
307
|
+
}));
|
|
308
|
+
return true;
|
|
309
|
+
} catch (err) {
|
|
310
|
+
console.warn(
|
|
311
|
+
"[AgentHostPty] Reconnection failed:",
|
|
312
|
+
err instanceof Error ? err.message : String(err)
|
|
313
|
+
);
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
get terminalUri() {
|
|
318
|
+
return this._terminalUri;
|
|
319
|
+
}
|
|
269
320
|
dispose() {
|
|
270
321
|
this._subscriptionRef?.dispose();
|
|
271
322
|
this._subscriptionRef = undefined;
|
|
@@ -44,6 +44,12 @@ export declare class AgentHostTerminalService extends Disposable implements IAge
|
|
|
44
44
|
private _defaultCwd;
|
|
45
45
|
/** Revived terminal instances, keyed by terminal URI string. */
|
|
46
46
|
private readonly _revivedInstances;
|
|
47
|
+
/**
|
|
48
|
+
* Active AgentHostPty instances with their owning connection clientId,
|
|
49
|
+
* keyed by terminal URI string. Used for reconnection scoping.
|
|
50
|
+
*/
|
|
51
|
+
private readonly _activePtys;
|
|
52
|
+
private readonly _reviveSequencer;
|
|
47
53
|
constructor(_terminalService: ITerminalService, _terminalChatService: ITerminalChatService, _terminalProfileService: ITerminalProfileService, _quickInputService: IQuickInputService);
|
|
48
54
|
registerEntry(entry: IAgentHostEntry): IDisposable;
|
|
49
55
|
getProfileForConnection(address: string): IAgentHostTerminalProfileInfo | undefined;
|
|
@@ -53,4 +59,9 @@ export declare class AgentHostTerminalService extends Disposable implements IAge
|
|
|
53
59
|
createTerminalForEntry(address: string, options?: IAgentHostTerminalCreateOptions): Promise<ITerminalInstance | undefined>;
|
|
54
60
|
createTerminal(connection: IAgentConnection, options?: IAgentHostTerminalCreateOptions): Promise<ITerminalInstance>;
|
|
55
61
|
reviveTerminal(connection: IAgentConnection, terminalUri: URI, terminalToolSessionId: string): Promise<ITerminalInstance>;
|
|
62
|
+
private _doReviveTerminal;
|
|
63
|
+
reconnectTerminals(newConnection: IAgentConnection, oldClientId: string): Promise<{
|
|
64
|
+
recovered: number;
|
|
65
|
+
total: number;
|
|
66
|
+
}>;
|
|
56
67
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
|
3
|
+
import { SequencerByKey } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
|
|
3
4
|
import { Disposable, DisposableMap, toDisposable, DisposableStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
4
5
|
import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
|
|
5
6
|
import { URI } from '@codingame/monaco-vscode-api/vscode/vs/base/common/uri';
|
|
@@ -32,6 +33,8 @@ let AgentHostTerminalService = class AgentHostTerminalService extends Disposable
|
|
|
32
33
|
this._profiles = observableValue("agentHostTerminalProfiles", []);
|
|
33
34
|
this.profiles = this._profiles;
|
|
34
35
|
this._revivedInstances = ( new Map());
|
|
36
|
+
this._activePtys = ( new Map());
|
|
37
|
+
this._reviveSequencer = ( new SequencerByKey());
|
|
35
38
|
}
|
|
36
39
|
registerEntry(entry) {
|
|
37
40
|
this._entries.push(entry);
|
|
@@ -80,7 +83,7 @@ let AgentHostTerminalService = class AgentHostTerminalService extends Disposable
|
|
|
80
83
|
}
|
|
81
84
|
} else if (displaying < entries.length) {
|
|
82
85
|
desiredProfiles.set("__quickpick__", {
|
|
83
|
-
name: ( localize(
|
|
86
|
+
name: ( localize(13777, "Agent Host…")),
|
|
84
87
|
address: "__quickpick__",
|
|
85
88
|
getConnection: () => undefined
|
|
86
89
|
});
|
|
@@ -101,7 +104,7 @@ let AgentHostTerminalService = class AgentHostTerminalService extends Disposable
|
|
|
101
104
|
infos.push({
|
|
102
105
|
extensionIdentifier: AGENT_HOST_PROFILE_EXT_ID,
|
|
103
106
|
profileId: key,
|
|
104
|
-
title: key === "__quickpick__" ? ( localize(
|
|
107
|
+
title: key === "__quickpick__" ? ( localize(13777, "Agent Host…")) : ( localize(13778, "Agent Host ({0})", desiredProfiles.get(key).name)),
|
|
105
108
|
address: key
|
|
106
109
|
});
|
|
107
110
|
}
|
|
@@ -116,12 +119,12 @@ let AgentHostTerminalService = class AgentHostTerminalService extends Disposable
|
|
|
116
119
|
let displayName = entry.name;
|
|
117
120
|
if (key === "__quickpick__") {
|
|
118
121
|
const picks = ( allEntries.map(e => ({
|
|
119
|
-
label: ( localize(
|
|
122
|
+
label: ( localize(13778, "Agent Host ({0})", e.name)),
|
|
120
123
|
address: e.address,
|
|
121
124
|
hostName: e.name
|
|
122
125
|
})));
|
|
123
126
|
const pick = await this._quickInputService.pick(picks, {
|
|
124
|
-
placeHolder: ( localize(
|
|
127
|
+
placeHolder: ( localize(13779, "Select an agent host to open a terminal on"))
|
|
125
128
|
});
|
|
126
129
|
if (!pick) {
|
|
127
130
|
return;
|
|
@@ -137,13 +140,13 @@ let AgentHostTerminalService = class AgentHostTerminalService extends Disposable
|
|
|
137
140
|
return;
|
|
138
141
|
}
|
|
139
142
|
await this.createTerminal(connection, {
|
|
140
|
-
name: ( localize(
|
|
143
|
+
name: ( localize(13778, "Agent Host ({0})", displayName)),
|
|
141
144
|
cwd: options.cwd ? (typeof options.cwd === "string" ? URI.file(options.cwd) : options.cwd) : this._defaultCwd,
|
|
142
145
|
location: options.location
|
|
143
146
|
});
|
|
144
147
|
}
|
|
145
148
|
};
|
|
146
|
-
const title = key === "__quickpick__" ? ( localize(
|
|
149
|
+
const title = key === "__quickpick__" ? ( localize(13777, "Agent Host…")) : ( localize(13778, "Agent Host ({0})", entry.name));
|
|
147
150
|
const store = ( new DisposableStore());
|
|
148
151
|
store.add(
|
|
149
152
|
this._terminalProfileService.registerTerminalProfileProvider(AGENT_HOST_PROFILE_EXT_ID, key, provider)
|
|
@@ -172,8 +175,9 @@ let AgentHostTerminalService = class AgentHostTerminalService extends Disposable
|
|
|
172
175
|
scheme: "agenthost-terminal",
|
|
173
176
|
path: `/${generateUuid()}`
|
|
174
177
|
}));
|
|
175
|
-
const name = options?.name ?? ( localize(
|
|
176
|
-
|
|
178
|
+
const name = options?.name ?? ( localize(13780, "Agent Host Terminal"));
|
|
179
|
+
const key = ( terminalUri.toString());
|
|
180
|
+
const instance = await this._terminalService.createTerminal({
|
|
177
181
|
config: {
|
|
178
182
|
customPtyImplementation: (id, cols, rows) => {
|
|
179
183
|
const pty = ( new AgentHostPty(id, connection, terminalUri, {
|
|
@@ -183,6 +187,10 @@ let AgentHostTerminalService = class AgentHostTerminalService extends Disposable
|
|
|
183
187
|
if (cols > 0 && rows > 0) {
|
|
184
188
|
pty.resize(cols, rows);
|
|
185
189
|
}
|
|
190
|
+
this._activePtys.set(key, {
|
|
191
|
+
pty,
|
|
192
|
+
clientId: connection.clientId
|
|
193
|
+
});
|
|
186
194
|
return pty;
|
|
187
195
|
},
|
|
188
196
|
name,
|
|
@@ -193,9 +201,19 @@ let AgentHostTerminalService = class AgentHostTerminalService extends Disposable
|
|
|
193
201
|
},
|
|
194
202
|
location: options?.location
|
|
195
203
|
});
|
|
204
|
+
this._register(instance.onDisposed(() => {
|
|
205
|
+
this._activePtys.delete(key);
|
|
206
|
+
}));
|
|
207
|
+
return instance;
|
|
196
208
|
}
|
|
197
209
|
async reviveTerminal(connection, terminalUri, terminalToolSessionId) {
|
|
198
210
|
const key = ( terminalUri.toString());
|
|
211
|
+
return this._reviveSequencer.queue(
|
|
212
|
+
key,
|
|
213
|
+
() => this._doReviveTerminal(connection, terminalUri, terminalToolSessionId, key)
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
async _doReviveTerminal(connection, terminalUri, terminalToolSessionId, key) {
|
|
199
217
|
const existing = this._revivedInstances.get(key);
|
|
200
218
|
if (existing) {
|
|
201
219
|
return existing;
|
|
@@ -217,10 +235,15 @@ let AgentHostTerminalService = class AgentHostTerminalService extends Disposable
|
|
|
217
235
|
if (!store.isDisposed) {
|
|
218
236
|
commandSource.connect(instance, pty);
|
|
219
237
|
}
|
|
238
|
+
this._activePtys.set(key, {
|
|
239
|
+
pty,
|
|
240
|
+
clientId: connection.clientId
|
|
241
|
+
});
|
|
220
242
|
return pty;
|
|
221
243
|
},
|
|
222
|
-
name: ( localize(
|
|
223
|
-
isFeatureTerminal: true
|
|
244
|
+
name: ( localize(13781, "Agent Host Terminal")),
|
|
245
|
+
isFeatureTerminal: true,
|
|
246
|
+
hideFromUser: true
|
|
224
247
|
}
|
|
225
248
|
});
|
|
226
249
|
this._terminalChatService.registerTerminalInstanceWithToolSession(terminalToolSessionId, instance);
|
|
@@ -228,9 +251,31 @@ let AgentHostTerminalService = class AgentHostTerminalService extends Disposable
|
|
|
228
251
|
instance.store.add(store);
|
|
229
252
|
this._register(instance.onDisposed(() => {
|
|
230
253
|
this._revivedInstances.delete(key);
|
|
254
|
+
this._activePtys.delete(key);
|
|
231
255
|
}));
|
|
232
256
|
return instance;
|
|
233
257
|
}
|
|
258
|
+
async reconnectTerminals(newConnection, oldClientId) {
|
|
259
|
+
const entries = [...this._activePtys.entries()].filter(([, entry]) => entry.clientId === oldClientId);
|
|
260
|
+
const total = entries.length;
|
|
261
|
+
let recovered = 0;
|
|
262
|
+
const promises = [];
|
|
263
|
+
for (const [key, entry] of entries) {
|
|
264
|
+
promises.push(entry.pty.reconnect(newConnection).then(success => {
|
|
265
|
+
if (success) {
|
|
266
|
+
recovered++;
|
|
267
|
+
entry.clientId = newConnection.clientId;
|
|
268
|
+
} else {
|
|
269
|
+
console.warn(`[AgentHostTerminalService] Failed to reconnect terminal: ${key}`);
|
|
270
|
+
}
|
|
271
|
+
}));
|
|
272
|
+
}
|
|
273
|
+
await Promise.all(promises);
|
|
274
|
+
return {
|
|
275
|
+
recovered,
|
|
276
|
+
total
|
|
277
|
+
};
|
|
278
|
+
}
|
|
234
279
|
};
|
|
235
280
|
AgentHostTerminalService = ( __decorate([( __param(0, ITerminalService)), ( __param(1, ITerminalChatService)), ( __param(2, ITerminalProfileService)), ( __param(3, IQuickInputService))], AgentHostTerminalService));
|
|
236
281
|
|
|
@@ -24,7 +24,7 @@ let EnvironmentVariableInfoStale = class EnvironmentVariableInfoStale {
|
|
|
24
24
|
addExtensionIdentifiers(extSet, ( this._diff.removed.values()));
|
|
25
25
|
addExtensionIdentifiers(extSet, ( this._diff.changed.values()));
|
|
26
26
|
let message = ( localize(
|
|
27
|
-
|
|
27
|
+
13786,
|
|
28
28
|
"The following extensions want to relaunch the terminal to contribute to its environment:"
|
|
29
29
|
));
|
|
30
30
|
message += getMergedDescription(this._collection, scope, this._extensionService, extSet);
|
|
@@ -32,7 +32,7 @@ let EnvironmentVariableInfoStale = class EnvironmentVariableInfoStale {
|
|
|
32
32
|
}
|
|
33
33
|
_getActions() {
|
|
34
34
|
return [{
|
|
35
|
-
label: ( localize(
|
|
35
|
+
label: ( localize(13787, "Relaunch Terminal")),
|
|
36
36
|
run: () => this._terminalService.getInstanceFromId(this._terminalId)?.relaunch(),
|
|
37
37
|
commandId: TerminalCommandId.Relaunch
|
|
38
38
|
}];
|
|
@@ -59,7 +59,7 @@ let EnvironmentVariableInfoChangesActive = class EnvironmentVariableInfoChangesA
|
|
|
59
59
|
const extSet = ( new Set());
|
|
60
60
|
addExtensionIdentifiers(extSet, ( this._collection.getVariableMap(scope).values()));
|
|
61
61
|
let message = ( localize(
|
|
62
|
-
|
|
62
|
+
13788,
|
|
63
63
|
"The following extensions have contributed to this terminal's environment:"
|
|
64
64
|
));
|
|
65
65
|
message += getMergedDescription(this._collection, scope, this._extensionService, extSet);
|
|
@@ -67,7 +67,7 @@ let EnvironmentVariableInfoChangesActive = class EnvironmentVariableInfoChangesA
|
|
|
67
67
|
}
|
|
68
68
|
_getActions(scope) {
|
|
69
69
|
return [{
|
|
70
|
-
label: ( localize(
|
|
70
|
+
label: ( localize(13789, "Show Environment Contributions")),
|
|
71
71
|
run: () => this._commandService.executeCommand(TerminalCommandId.ShowEnvironmentContributions, scope),
|
|
72
72
|
commandId: TerminalCommandId.ShowEnvironmentContributions
|
|
73
73
|
}];
|
|
@@ -95,7 +95,7 @@ function getMergedDescription(collection, scope, extensionService, extSet) {
|
|
|
95
95
|
}
|
|
96
96
|
const workspaceDescription = workspaceDescriptions.get(ext);
|
|
97
97
|
if (workspaceDescription) {
|
|
98
|
-
const workspaceSuffix = globalDescription ? ` (${( localize(
|
|
98
|
+
const workspaceSuffix = globalDescription ? ` (${( localize(13790, "workspace"))})` : "";
|
|
99
99
|
message.push(`\n- \`${getExtensionName(ext, extensionService)}${workspaceSuffix}\``);
|
|
100
100
|
message.push(`: ${workspaceDescription}`);
|
|
101
101
|
}
|