agentHostResourceService.ts ×28

Frontier kind: Code frontier

unlabeled · c_2b0ced33dc30

33 tests · 21097 LOC · 106 files · introduces 0 tests · 436 LOC · 3 files

Introduces — evidence that enters the hierarchy at this concept

Code
31 ranges436 lines · 3 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
2227 ranges21097 lines · 106 files · Browse complete extent
All tests (intent)
33 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

3 files ranked by introduced lines: 436 introduced LOC across 31 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/services/agentHost/common/agentHostResourceService.ts 187 introduced LOC · 28 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- agentHostResourceService.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { DeferredPromise } from '../../../../base/common/async.js';
7 > import { VSBuffer, decodeBase64 } from '../../../../base/common/buffer.js';
8 > import { CancellationError } from '../../../../base/common/errors.js';
9 > import { Disposable, IDisposable, toDisposable } from '../../../../base/common/lifecycle.js';
10 > import { IObservable, derived, observableValue } from '../../../../base/common/observable.js';
11 > import { extUri } from '../../../../base/common/resources.js';
12 > import { URI } from '../../../../base/common/uri.js';
13 > import { generateUuid } from '../../../../base/common/uuid.js';
14 > import { ITextModelService } from '../../../../editor/common/services/resolverService.js';
15 > import {
16 > AgentHostAccessMode,
17 > AgentHostLocalFilePermissionsSettingId,
18 > AgentHostPermissionMode,
19 > AgentHostPermissionsSetting,
20 > AgentHostResourcePermissionError,
21 > IAgentHostResourceService,
22 > IPendingResourceRequest,
23 > IResourceListResult,
24 > IResourceReadResult,
25 > LOCAL_AGENT_HOST_ADDRESS,
26 > } from '../../../../platform/agentHost/common/agentHostResourceService.js';
27 > import { normalizeRemoteAgentHostAddress } from '../../../../platform/agentHost/common/agentHostUri.js';
28 > import {
29 > ContentEncoding,
30 > ResourceCopyParams, ResourceDeleteParams, ResourceMkdirParams, ResourceMoveParams,
31 > ResourceRequestParams, ResourceResolveParams, ResourceResolveResult, ResourceType, ResourceWriteParams,
32 > } from '../../../../platform/agentHost/common/state/protocol/commands.js';
33 > import { ROOT_STATE_URI } from '../../../../platform/agentHost/common/state/sessionState.js';
34 > import { ConfigurationTarget, IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
35 > import { IFileService } from '../../../../platform/files/common/files.js';
36 > import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
37 > import { ILogService } from '../../../../platform/log/common/log.js';
38 >
39 > interface IInternalPendingRequest extends IPendingResourceRequest {
40 > readonly deferred: DeferredPromise<void>;
41 > }
42 >
43 > interface IInMemoryGrant {
44 > readonly address: string;
45 > /**
46 > * Resolves to the realpath'd URI for the grant. Stored as a promise so
47 > * `grantImplicitRead` can return synchronously while the realpath lookup
48 > * is in flight; consumers in `_isCovered` await the resolved URI before
49 > * comparing, so a check that happens before the lookup completes still
50 > * compares against the canonical path. Always resolves (never rejects).
51 > */
52 > readonly realpath: Promise<URI>;
53 > readonly mode: AgentHostAccessMode;
54 > }
55 >
56 > /**
57 > * Default implementation of {@link IAgentHostResourceService} — the unified
58 > * owner of agent-host-facing filesystem operations and the permission
59 > * policy that gates them. Reads transparently fall back to
60 > * {@link ITextModelService} so virtual resources (untitled documents,
61 > * notebook cells, ...) work without the host having to know about them.
62 > *
63 > * Permission storage shape (in user settings):
64 > *
65 > * ```jsonc
66 > * "chat.agentHost.localFilePermissions": {
67 > * "localhost:3000": {
68 > * "file:///Users/me/.gitconfig": "r",
69 > * "file:///Users/me/.agentConfig": "rw"
70 > * },
71 > * "local": { ... }
72 > * }
73 > * ```
74 > *
75 > * - Keys are addresses normalized via {@link normalizeRemoteAgentHostAddress},
76 > * with the in-process local agent host keyed under `'local'`.
77 > * - Values are URI strings → `r` | `rw`. Descendant URIs are covered by a
78 > * parent grant.
79 > */
80 > export class AgentHostResourceService extends Disposable implements IAgentHostResourceService {
81 > declare readonly _serviceBrand: undefined;
82 >
83 > private readonly _inMemoryGrants = new Map<string, IInMemoryGrant>();
84 > private readonly _pending = observableValue<readonly IInternalPendingRequest[]>('agentHostResources.pending', []);
85 >
86 > readonly allPending: IObservable<readonly IPendingResourceRequest[]> = this._pending;
87 >
88 > constructor(
89 > @IConfigurationService private readonly _configurationService: IConfigurationService,
90 > @IFileService private readonly _fileService: IFileService,
91 > @ITextModelService private readonly _textModelService: ITextModelService,
92 > @ILogService private readonly _logService: ILogService,
93 > ) {
94 > super();
95 > }
96 >
97 > // ---- Gated FS operations ------------------------------------------------
98 >
99 > async list(address: string, uri: URI): Promise<IResourceListResult> {
100 await this._gate(address, uri, AgentHostPermissionMode.Read, { channel: ROOT_STATE_URI, uri: uri.toString(), read: true });
101 const stat = await this._fileService.resolve(uri);
110 };
111 }
113 > async read(address: string, uri: URI): Promise<IResourceReadResult> {
114 await this._gate(address, uri, AgentHostPermissionMode.Read, { channel: ROOT_STATE_URI, uri: uri.toString(), read: true });
115 try {
124 }
125 }
127 > async write(address: string, params: ResourceWriteParams): Promise<void> {
128 const uri = URI.parse(params.uri);
129 await this._gate(address, uri, AgentHostPermissionMode.Write, { channel: ROOT_STATE_URI, uri: uri.toString(), write: true });
144 }
145 }
147 > async del(address: string, params: ResourceDeleteParams): Promise<void> {
148 const uri = URI.parse(params.uri);
149 await this._gate(address, uri, AgentHostPermissionMode.Write, { channel: ROOT_STATE_URI, uri: uri.toString(), write: true });
150 await this._fileService.del(uri, { recursive: !!params.recursive });
151 }
153 > async move(address: string, params: ResourceMoveParams): Promise<void> {
154 const source = URI.parse(params.source);
155 const destination = URI.parse(params.destination);
158 await this._fileService.move(source, destination, !params.failIfExists);
159 }
161 > async copy(address: string, params: ResourceCopyParams): Promise<void> {
162 const source = URI.parse(params.source);
163 const destination = URI.parse(params.destination);
166 await this._fileService.copy(source, destination, !params.failIfExists);
167 }
169 > async resolve(address: string, params: ResourceResolveParams): Promise<ResourceResolveResult> {
170 const uri = URI.parse(params.uri);
171 await this._gate(address, uri, AgentHostPermissionMode.Read, { channel: ROOT_STATE_URI, uri: uri.toString(), read: true });
197 };
198 }
200 > async mkdir(address: string, params: ResourceMkdirParams): Promise<void> {
201 const uri = URI.parse(params.uri);
202 await this._gate(address, uri, AgentHostPermissionMode.Write, { channel: ROOT_STATE_URI, uri: uri.toString(), write: true });
207 await this._fileService.createFolder(uri);
208 }
210 > // ---- Permission requests / observables ---------------------------------
211 >
212 > async check(address: string, uri: URI, mode: AgentHostPermissionMode): Promise<boolean> {
213 const normalized = normalizeRemoteAgentHostAddress(address);
214 const canonical = await this._canonicalize(uri);
215 return this._isCovered(normalized, canonical, mode);
216 }
218 > async request(address: string, params: ResourceRequestParams): Promise<void> {
219 const normalized = normalizeRemoteAgentHostAddress(address);
220 const canonical = await this._canonicalize(URI.parse(params.uri));
229 }
230 }
232 > pendingFor(address: string): IObservable<readonly IPendingResourceRequest[]> {
233 const normalized = normalizeRemoteAgentHostAddress(address);
234 return derived(reader => this._pending.read(reader).filter(r => r.address === normalized));
235 }
237 > findPending(id: string): IPendingResourceRequest | undefined {
238 return this._pending.get().find(r => r.id === id);
239 }
241 > grantImplicitRead(address: string, uri: URI): IDisposable {
242 const handle = generateUuid();
243 const lexical = extUri.normalizePath(uri);
253 return toDisposable(() => this._inMemoryGrants.delete(handle));
254 }
256 > connectionClosed(address: string): void {
257 const normalized = normalizeRemoteAgentHostAddress(address);
258
276 }
277 }
279 > // ---- internals ---------------------------------------------------------
280 >
281 > private async _gate(
282 address: string,
283 uri: URI,
289 }
290 }
292 > private async _readVirtual(uri: URI): Promise<VSBuffer | undefined> {
293 try {
294 const ref = await this._textModelService.createModelReference(uri);
302 }
303 }
305 > /**
306 > * Write {@link bytes} as text into the resolved text model for {@link uri},
307 > * if one can be resolved and is writable. Returns `true` when the model was
308 > * updated, `false` otherwise (no provider, readonly, decode failure).
309 > */
310 > private async _writeVirtual(uri: URI, bytes: VSBuffer): Promise<boolean> {
311 try {
312 const ref = await this._textModelService.createModelReference(uri);
324 }
325 }
327 > /**
328 > * Resolve {@link uri} via {@link ITextModelService} and synthesize a
329 > * {@link ResourceResolveResult} so virtual resources stat as `File` with
330 > * a size matching their text content. Returns `undefined` if no model
331 > * can be resolved.
332 > */
333 > private async _statVirtual(uri: URI): Promise<ResourceResolveResult | undefined> {
334 try {
335 const ref = await this._textModelService.createModelReference(uri);
348 }
349 }
351 > /**
352 > * Resolve {@link uri} against the local filesystem, collapsing `..`
353 > * segments and following symlinks so the policy check sees the same
354 > * path the OS will actually open. For URIs that don't exist (e.g. a
355 > * `resourceWrite` for a new file), realpath the deepest existing
356 > * ancestor and re-append the leaf.
357 > */
358 > private async _canonicalize(uri: URI): Promise<URI> {
359 > const normalized = extUri.normalizePath(uri);
360 > const real = await this._fileService.realpath(normalized).catch(() => undefined);
361 > if (real) {
362 return real;
363 }
370 ? extUri.joinPath(realParent, extUri.basename(normalized))
371 : normalized;
373 >
374 > private async _isCovered(address: string, canonicalUri: URI, mode: AgentHostPermissionMode): Promise<boolean> {
375 > if (address === LOCAL_AGENT_HOST_ADDRESS) {
376 return true;
377 }
378 > const requireWrite = mode === AgentHostPermissionMode.Write; agentHostResourceService.ts
379 >
380 > for (const grant of this._readPersistedGrants(address)) {
381 if (requireWrite && grant.mode !== AgentHostAccessMode.ReadWrite) {
382 continue;
399 const realpaths = await Promise.all(candidates);
400 return realpaths.some(uri => extUri.isEqualOrParent(canonicalUri, uri));
402 >
403 > private _enqueue(address: string, canonicalUri: URI, mode: AgentHostPermissionMode): Promise<void> {
404 const existing = this._pending.get().find(r =>
405 r.address === address && r.mode === mode && extUri.isEqual(r.uri, canonicalUri));
425 return deferred.p;
426 }
428 > private _resolve(request: IInternalPendingRequest, scope: 'memory' | 'persist'): void {
429 const accessMode = request.mode === AgentHostPermissionMode.Write
430 ? AgentHostAccessMode.ReadWrite
446 request.deferred.complete();
447 }
449 > private _dropPending(request: IInternalPendingRequest): void {
450 const next = this._pending.get().filter(r => r !== request);
451 if (next.length !== this._pending.get().length) {
453 }
454 }
456 > private *_readPersistedGrants(address: string): Iterable<{ uri: URI; mode: AgentHostAccessMode }> {
457 > const forAddress = this._configurationService
458 > .getValue<AgentHostPermissionsSetting>(AgentHostLocalFilePermissionsSettingId)?.[address];
459 > if (!forAddress) {
460 return;
461 }
470 }
471 }
473 >
474 > private async _persistGrant(address: string, uri: URI, mode: AgentHostPermissionMode): Promise<void> {
475 const requested: AgentHostAccessMode = mode === AgentHostPermissionMode.Write
476 ? AgentHostAccessMode.ReadWrite
498 );
499 }
501 > private _inspectScopedSetting(): { target: ConfigurationTarget; value: AgentHostPermissionsSetting } {
502 const inspected = this._configurationService.inspect<AgentHostPermissionsSetting>(AgentHostLocalFilePermissionsSettingId);
503 if (inspected.applicationValue !== undefined) {
515 return { target: ConfigurationTarget.APPLICATION, value: {} };
516 }
518 >
519 > registerSingleton(IAgentHostResourceService, AgentHostResourceService, InstantiationType.Delayed);
src/vs/platform/agentHost/common/agentHostResourceService.ts 163 introduced LOC · 2 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- agentHostResourceService.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { VSBuffer } from '../../../base/common/buffer.js';
7 > import { IDisposable } from '../../../base/common/lifecycle.js';
8 > import { IObservable } from '../../../base/common/observable.js';
9 > import { URI } from '../../../base/common/uri.js';
10 > import { createDecorator } from '../../instantiation/common/instantiation.js';
11 > import {
12 > DirectoryEntry,
13 > ResourceCopyParams, ResourceDeleteParams, ResourceMkdirParams, ResourceMoveParams,
14 > ResourceRequestParams, ResourceResolveParams, ResourceResolveResult, ResourceWriteParams,
15 > } from './state/protocol/commands.js';
16 >
17 > /**
18 > * Stable sentinel address used for the in-process local agent host. Keyed
19 > * persisted grants in user settings live under this name so that "Always
20 > * allow" survives window reloads.
21 > */
22 > export const LOCAL_AGENT_HOST_ADDRESS = 'local';
23 >
24 > /** Configuration key for persisted per-host filesystem grants. */
25 > export const AgentHostLocalFilePermissionsSettingId = 'chat.agentHost.localFilePermissions';
26 >
27 > /** Persisted access mode for a granted URI. */
28 > export const enum AgentHostAccessMode {
29 > Read = 'r',
30 > ReadWrite = 'rw',
31 > }
32 >
33 > /**
34 > * Persisted shape of {@link AgentHostLocalFilePermissionsSettingId}:
35 > * `{ [normalizedAddress]: { [uriString]: 'r' | 'rw' } }`.
36 > */
37 > export type AgentHostPermissionsSetting = Record<string, Record<string, AgentHostAccessMode>>;
38 >
39 > /**
40 > * Capability a request needs from the user. The protocol-level `read` and
41 > * `write` flags are split into one or two of these requests.
42 > */
43 > export const enum AgentHostPermissionMode {
44 > Read = 'read',
45 > Write = 'write',
46 > }
47 >
48 > /** A single pending permission request awaiting user input. */
49 > export interface IPendingResourceRequest {
50 > readonly id: string;
51 > readonly address: string;
52 > readonly uri: URI;
53 > readonly mode: AgentHostPermissionMode;
54 > /** Approve and remember the grant in user settings. */
55 > allowAlways(): void;
56 > /**
57 > * Approve the request and remember it in memory for the lifetime of the
58 > * connection (cleared on connection close or window reload).
59 > */
60 > allow(): void;
61 > /** Reject this request. */
62 > deny(): void;
63 > }
64 >
65 > /**
66 > * Thrown by gated FS operations on {@link IAgentHostResourceService} when
67 > * the calling address lacks the required permission. Carries the
68 > * {@link ResourceRequestParams} that, if approved, would unlock the
69 > * operation, so wire adapters can echo it back to the agent host inside a
70 > * `PermissionDenied` frame and let the host run the standard
71 > * `resourceRequest` → retry loop.
72 > */
73 > export class AgentHostResourcePermissionError extends Error {
74 > constructor(public readonly request: ResourceRequestParams | undefined) {
75 super(request
76 ? `Access to ${request.uri} is not granted.`
78 this.name = 'AgentHostResourcePermissionError';
79 }
81 >
82 > export interface IResourceReadResult {
83 > readonly bytes: VSBuffer;
84 > }
85 >
86 > export interface IResourceListResult {
87 > readonly entries: readonly DirectoryEntry[];
88 > }
89 >
90 > export const IAgentHostResourceService = createDecorator<IAgentHostResourceService>('agentHostResourceService');
91 >
92 > /**
93 > * Single owner of agent-host-facing filesystem operations and the
94 > * permission policy that gates them. Combines what were previously two
95 > * services (`IAgentHostPermissionService` + `IAgentHostVirtualResourceProvider`)
96 > * into one consistent interface used by both the in-process local channel
97 > * and the remote protocol client.
98 > *
99 > * Each FS method is gated by a permission check keyed on `address`: a
100 > * normalized network host for remote agent hosts, or
101 > * {@link LOCAL_AGENT_HOST_ADDRESS} for the local utility-process host.
102 > * Denied operations throw {@link AgentHostResourcePermissionError} carrying
103 > * the {@link ResourceRequestParams} that, if granted, would unlock the
104 > * operation.
105 > *
106 > * Read operations transparently fall back to virtual content (untitled
107 > * documents, notebook cells, ...) when the local file service cannot
108 > * resolve the URI.
109 > */
110 > export interface IAgentHostResourceService {
111 > readonly _serviceBrand: undefined;
112 >
113 > // ---- Gated filesystem operations ---------------------------------------
114 >
115 > list(address: string, uri: URI): Promise<IResourceListResult>;
116 > read(address: string, uri: URI): Promise<IResourceReadResult>;
117 > write(address: string, params: ResourceWriteParams): Promise<void>;
118 > del(address: string, params: ResourceDeleteParams): Promise<void>;
119 > move(address: string, params: ResourceMoveParams): Promise<void>;
120 > copy(address: string, params: ResourceCopyParams): Promise<void>;
121 > resolve(address: string, params: ResourceResolveParams): Promise<ResourceResolveResult>;
122 > mkdir(address: string, params: ResourceMkdirParams): Promise<void>;
123 >
124 > // ---- Permission requests / observables (UI) ----------------------------
125 >
126 > /**
127 > * Returns whether {@link uri} is already granted for {@link mode} on
128 > * {@link address}. Useful as a pre-check before sending data to a host
129 > * that will read it back. The same gating runs implicitly inside every
130 > * FS method on this service.
131 > */
132 > check(address: string, uri: URI, mode: AgentHostPermissionMode): Promise<boolean>;
133 >
134 > /**
135 > * Handle an inbound `resourceRequest` from a host. Resolves once access
136 > * is granted (immediately, if already covered); rejects with a
137 > * `CancellationError` if the user denies or the connection closes.
138 > */
139 > request(address: string, params: ResourceRequestParams): Promise<void>;
140 >
141 > /** Per-address observable of pending requests for UI surfaces. */
142 > pendingFor(address: string): IObservable<readonly IPendingResourceRequest[]>;
143 >
144 > /** Observable of all pending requests across every address. */
145 > readonly allPending: IObservable<readonly IPendingResourceRequest[]>;
146 >
147 > /**
148 > * Find a pending request by id, across all addresses. Returns
149 > * `undefined` once the request has been resolved or rejected.
150 > */
151 > findPending(id: string): IPendingResourceRequest | undefined;
152 >
153 > // ---- Implicit grants and lifecycle -------------------------------------
154 >
155 > /**
156 > * Register an implicit read grant for {@link uri} (and descendants) on
157 > * {@link address}. Used by call sites that are about to send a URI to a
158 > * host and therefore expect that host to read it back. The returned
159 > * disposable revokes the grant.
160 > */
161 > grantImplicitRead(address: string, uri: URI): IDisposable;
162 >
163 > /**
164 > * Notify that the connection at {@link address} has closed. Drops all
165 > * implicit grants and rejects any outstanding pending requests.
166 > */
167 > connectionClosed(address: string): void;
168 > }
src/vs/editor/common/services/resolverService.ts 86 introduced LOC · 1 range

Open complete file

1 > /*--------------------------------------------------------------------------------------------- resolverService.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { Event } from '../../../base/common/event.js';
7 > import { IMarkdownString } from '../../../base/common/htmlContent.js';
8 > import { IDisposable, IReference } from '../../../base/common/lifecycle.js';
9 > import { URI } from '../../../base/common/uri.js';
10 > import { ITextModel, ITextSnapshot } from '../model.js';
11 > import { IResolvableEditorModel } from '../../../platform/editor/common/editor.js';
12 > import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
13 >
14 > export const ITextModelService = createDecorator<ITextModelService>('textModelService');
15 >
16 > export interface ITextModelService {
17 > readonly _serviceBrand: undefined;
18 >
19 > /**
20 > * Provided a resource URI, it will return a model reference
21 > * which should be disposed once not needed anymore.
22 > */
23 > createModelReference(resource: URI): Promise<IReference<IResolvedTextEditorModel>>;
24 >
25 > /**
26 > * Registers a specific `scheme` content provider.
27 > */
28 > registerTextModelContentProvider(scheme: string, provider: ITextModelContentProvider): IDisposable;
29 >
30 > /**
31 > * Check if the given resource can be resolved to a text model.
32 > */
33 > canHandleResource(resource: URI): boolean;
34 > }
35 >
36 > export interface ITextModelContentProvider {
37 >
38 > /**
39 > * Given a resource, return the content of the resource as `ITextModel`.
40 > */
41 > provideTextContent(resource: URI): Promise<ITextModel | null> | null;
42 > }
43 >
44 > export interface ITextEditorModel extends IResolvableEditorModel {
45 >
46 > /**
47 > * Emitted when the text model is about to be disposed.
48 > */
49 > readonly onWillDispose: Event<void>;
50 >
51 > /**
52 > * Provides access to the underlying `ITextModel`.
53 > */
54 > readonly textEditorModel: ITextModel | null;
55 >
56 > /**
57 > * Creates a snapshot of the model's contents.
58 > */
59 > createSnapshot(this: IResolvedTextEditorModel): ITextSnapshot;
60 > createSnapshot(this: ITextEditorModel): ITextSnapshot | null;
61 >
62 > /**
63 > * Signals if this model is readonly or not.
64 > */
65 > isReadonly(): boolean | IMarkdownString;
66 >
67 > /**
68 > * The language id of the text model if known.
69 > */
70 > getLanguageId(): string | undefined;
71 >
72 > /**
73 > * Find out if this text model has been disposed.
74 > */
75 > isDisposed(): boolean;
76 > }
77 >
78 > export interface IResolvedTextEditorModel extends ITextEditorModel {
79 >
80 > /**
81 > * Same as ITextEditorModel#textEditorModel, but never null.
82 > */
83 > readonly textEditorModel: ITextModel;
84 > }
85 >
86 > export function isResolvedTextEditorModel(model: ITextEditorModel): model is IResolvedTextEditorModel {
87 const candidate = model as IResolvedTextEditorModel;
88