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);