1135
};
1136
}
1138
>
1139
>
// ---- Chat surface --------------------------------------------------
1140
>
1141
>
/**
1142
>
* The chat-addressed operation surface an agent exposes for the chats
1143
>
* within a session.
1144
>
*
1145
>
* Every operation method addresses a chat by a concrete chat channel URI:
1146
>
* the default chat channel for a session's DEFAULT chat, or an additional
1147
>
* chat's own channel URI. The orchestrator ({@link IAgentService}) owns the
1148
>
* feature-level `(session, chat)` to chat-channel mapping and only ever calls
1149
>
* these operations with a concrete chat URI. This replaces the legacy
1150
>
* `(session, chat?)` parameter pairs and the per-agent default-chat handling on
1151
>
* {@link IAgent}.
1152
>
*
1153
>
* Optional on {@link IAgent}: agents implement this incrementally (waves
1154
>
* C2/C3/C4). Until an agent exposes it, {@link IAgentService} falls back to the
1155
>
* agent's legacy `(session, chat?)` methods via a thin adapter.
1156
>
*/
1157
>
export interface IAgentChats {
1158
>
/**
1159
>
* Create a fresh additional chat within the session the `chat` URI belongs
1160
>
* to, sharing the session's working directory, model, agent, and
1161
>
* customizations. `chat` is the client-chosen channel URI the new chat is
1162
>
* addressed by; its parent session is derived from it.
1163
>
* Returns the opaque {@link IAgentCreateChatResult} blob to persist for
1164
>
* restore (or `void` when the agent keeps no resumable backing).
1165
>
*/
1166
>
createChat(chat: URI, options?: IAgentCreateChatOptions): Promise<IAgentCreateChatResult | void>;
1167
>
1168
>
/**
1169
>
* Fork a new chat from an existing one. The new `chat`
1170
>
* inherits `source`'s backing up to and including
1171
>
* {@link IAgentCreateChatForkSource.turnId} and then continues
1172
>
* independently. The new chat's parent session is derived from its URI.
1173
>
*/
1174
>
fork(chat: URI, source: IAgentCreateChatForkSource, options?: IAgentCreateChatOptions): Promise<IAgentCreateChatResult | void>;
1175
>
1176
>
/**
1177
>
* Dispose an additional chat created via
1178
>
* {@link createChat}/{@link fork}, freeing its backing. A session's
1179
>
* default chat cannot be disposed in isolation; it lives and dies
1180
>
* with the session.
1181
>
*/
1182
>
disposeChat(chat: URI): Promise<void>;
1183
>
1184
>
/**
1185
>
* Send a user message into `chat`; on first send, the host passes the resolved
1186
>
* working directory (or `undefined` for workspace-less sessions).
1187
>
*/
1188
>
sendMessage(chat: URI, prompt: string, workingDirectory: URI | undefined, attachments?: readonly MessageAttachment[], turnId?: string, senderClientId?: string): Promise<void>;
1189
>
1190
>
/** Abort the in-flight turn for `chat`. */
1191
>
abort(chat: URI): Promise<void>;
1192
>
1193
>
/** Change the model for `chat`. */
1194
>
changeModel(chat: URI, model: ModelSelection): Promise<void>;
1195
>
1196
>
/**
1197
>
* Change (or clear) the selected custom agent for `chat`. Passing
1198
>
* `undefined` clears the selection (provider default behavior).
1199
>
*/
1200
>
changeAgent(chat: URI, agent: AgentSelection | undefined): Promise<void>;
1201
>
1202
>
/** Reconstruct the turns for `chat` (used on restore). */
1203
>
getMessages(chat: URI): Promise<readonly Turn[]>;
1204
>
}
1205
>
1206
>
export interface IAgentResolveSessionConfigParams {
1207
>
readonly provider?: AgentProvider;
1208
>
readonly workingDirectory?: URI;
1209
>
readonly config?: Record<string, unknown>;
1210
>
}
1211
>
1212
>
export interface IAgentSessionConfigCompletionsParams extends IAgentResolveSessionConfigParams {
1213
>
readonly property: string;
1214
>
readonly query?: string;
1215
>
}
1216
>
1217
>
/** Serializable model information from the agent host. */
1218
>
export interface IAgentModelInfo {
1219
>
readonly provider: AgentProvider;
1220
>
readonly id: string;
1221
>
readonly name: string;
1222
>
readonly maxContextWindow?: number;
1223
>
readonly maxOutputTokens?: number;
1224
>
readonly maxPromptTokens?: number;
1225
>
readonly supportsVision: boolean;
1226
>
readonly configSchema?: ConfigSchema;
1227
>
readonly policyState?: PolicyState;
1228
>
readonly _meta?: Record<string, unknown>;
1229
>
}
1230
>
1231
>
// ---- Agent signals (sent via IAgent.onDidSessionProgress) -------------------
1232
>
1233
>
/**
1234
>
* A signal emitted by an agent during session execution.
1235
>
*
1236
>
* Most signals carry a protocol {@link SessionAction} directly via the
1237
>
* `kind: 'action'` shape, eliminating a parallel event ontology. A small
1238
>
* number of cases that have no clean protocol action (permission
1239
>
* auto-approval, subagent session creation, steering message
1240
>
* acknowledgment) remain as discriminated non-action signals so the host
1241
>
* can perform side effects before — or instead of — dispatching an action.
1242
>
*/
1243
>
export type AgentSignal =
1244
>
| IAgentActionSignal
1245
>
| IAgentToolPendingConfirmationSignal
1246
>
| IAgentSubagentStartedSignal
1247
>
| IAgentSubagentCompletedSignal
1248
>
| IAgentSteeringConsumedSignal;
1249
>
1250
>
/**
1251
>
* Carries a protocol {@link SessionAction} produced by an agent. The host
1252
>
* dispatches the action through the state manager after routing via
1253
>
* {@link IAgentActionSignal.parentToolCallId} (if set).
1254
>
*
1255
>
* Agents are responsible for populating the target channel and any `turnId` /
1256
>
* `partId` fields on the action.
1257
>
*/
1258
>
export interface IAgentActionSignal {
1259
>
readonly kind: 'action';
1260
>
/** Target session or chat channel URI. For inner subagent events this is the parent session — see {@link parentToolCallId}. */
1261
>
readonly resource: URI;
1262
>
/** Protocol action to dispatch. */
1263
>
readonly action: SessionAction | ChatAction;
1264
>
/** If set, route the action to the subagent session belonging to this tool call. */
1265
>
readonly parentToolCallId?: string;
1266
>
}
1267
>
1268
>
/**
1269
>
* A tool has finished collecting parameters and needs the host to decide
1270
>
* whether it should run (or, mid-execution, re-confirm). The host applies
1271
>
* auto-approval logic over {@link permissionKind} / {@link permissionPath}
1272
>
* (see `SessionPermissionManager.getAutoApproval`) and then dispatches the
1273
>
* appropriate `ChatToolCallReady` action — with confirmation options
1274
>
* baked in when the user must approve, or with `confirmed: NotNeeded` when
1275
>
* the host auto-approved.
1276
>
*
1277
>
* Kept as a non-action signal because the host owns this approval policy;
1278
>
* the agent only describes the tool call and the kind of permission being
1279
>
* requested. The {@link state} field carries the protocol-shaped tool-call
1280
>
* state and is dispatched verbatim into the action.
1281
>
*/
1282
>
export interface IAgentToolPendingConfirmationSignal {
1283
>
readonly kind: 'pending_confirmation';
1284
>
/** Target chat channel URI containing the tool call. */
1285
>
readonly chat: URI;
1286
>
/** Protocol-shaped pending-confirmation state, dispatched verbatim into `ChatToolCallReady`. */
1287
>
readonly state: ToolCallPendingConfirmationState;
1288
>
/** Host-only auto-approval kind (not part of the dispatched action). */
1289
>
readonly permissionKind?: 'shell' | 'write' | 'mcp' | 'read' | 'url' | 'skill' | 'custom-tool' | 'hook' | 'memory' | 'extension-management' | 'extension-permission-access';
1290
>
/** Host-only auto-approval path target (not part of the dispatched action). */
1291
>
readonly permissionPath?: string;
1292
>
/**
1293
>
* Host-only flag (not part of the dispatched action): the model requested
1294
>
* this shell command run OUTSIDE the sandbox (and the host opted in via
1295
>
* `sandbox.allowBypass`).
1296
>
*/
1297
>
readonly requestSandboxBypass?: boolean;
1298
>
/**
1299
>
* If set, the tool call belongs to the subagent rooted at this
1300
>
* parent tool call. Used by the host to route the resulting
1301
>
* `ChatToolCallReady` to the subagent session — otherwise the
1302
>
* action would land on the parent session, where there is no
1303
>
* matching `ChatToolCallStart`.
1304
>
*/
1305
>
readonly parentToolCallId?: string;
1306
>
}
1307
>
1308
>
/**
1309
>
* A subagent was spawned by a tool call. The host creates a child session
1310
>
* silently and routes subsequent inner-tool events to it.
1311
>
*
1312
>
* Kept as a non-action signal because subagent session creation has no
1313
>
* protocol action — it's a host-side composition primitive.
1314
>
*/
1315
>
export interface IAgentSubagentStartedSignal {
1316
>
readonly kind: 'subagent_started';
1317
>
readonly chat: URI;
1318
>
readonly toolCallId: string;
1319
>
readonly agentName: string;
1320
>
readonly agentDisplayName: string;
1321
>
readonly agentDescription?: string;
1322
>
/**
1323
>
* The spawning Task tool's short (typically 3-5 word) `description`
1324
>
* input, e.g. "Review package.json structure". Distinct from
1325
>
* {@link agentDescription} (the agent *type*'s long role blurb) and
1326
>
* {@link agentDisplayName} (the agent type's name). Preferred as the
1327
>
* peer chat's tab title because it is concise and per-task, so two
1328
>
* subagents of the same type still get distinct, meaningful names.
1329
>
* Absent when the harness does not surface a task description.
1330
>
*/
1331
>
readonly taskDescription?: string;
1332
>
/**
1333
>
* The full delegated instruction the parent handed the subagent (the
1334
>
* spawning tool's `prompt` input). Populated by each provider at emit
1335
>
* time from its own native source, so the shared orchestrator never
1336
>
* parses a provider-specific tool-input shape. Seeds the subagent peer
1337
>
* chat's opening request. Distinct from {@link taskDescription} (a short
1338
>
* tab-title label). Absent when the harness does not surface a prompt.
1339
>
*/
1340
>
readonly taskPrompt?: string;
1341
>
/**
1342
>
* If set, the spawning tool call ({@link toolCallId}) itself lives
1343
>
* inside another subagent's chat — this is the tool call **one level up**
1344
>
* from the spawning tool (its parent), i.e. the tool that spawned the
1345
>
* immediate parent chat. The host uses it to route the
1346
>
* subagent-discovery side effect (the `ChatToolCallContentChanged`
1347
>
* block that lets clients find the child chat) to that immediate parent
1348
>
* chat rather than the top-level {@link chat}. Because subagent chats
1349
>
* are flat (all keyed off the root session + the spawning tool id),
1350
>
* this single one-hop reference resolves the correct parent chat at
1351
>
* ANY nesting depth — no per-level chain is needed. Absent for a
1352
>
* top-level subagent, whose spawning tool call lives directly in
1353
>
* {@link chat}.
1354
>
*/
1355
>
readonly parentToolCallId?: string;
1356
>
}
1357
>
1358
>
/**
1359
>
* A subagent has finished — either successfully or with an error. The host
1360
>
* uses this to tear down the child session after all of its events have been
1361
>
* routed. The parent tool call completing is not a reliable signal for this
1362
>
* because background subagents (e.g. Copilot's `mode: background` task) keep
1363
>
* emitting events after their parent tool call returns immediately.
1364
>
*/
1365
>
export interface IAgentSubagentCompletedSignal {
1366
>
readonly kind: 'subagent_completed';
1367
>
readonly chat: URI;
1368
>
readonly toolCallId: string;
1369
>
}
1370
>
1371
>
/** A steering message was consumed (sent to the model). */
1372
>
export interface IAgentSteeringConsumedSignal {
1373
>
readonly kind: 'steering_consumed';
1374
>
readonly chat: URI;
1375
>
readonly id: string;
1376
>
}
1377
>
1378
>
// ---- Session URI helpers ----------------------------------------------------
1379
>
1380
>
export namespace AgentSession {
1381
>
1382
>
/**
1383
>
* Creates a session URI from a provider name and raw session ID.
1384
>
* The URI scheme is the provider name (e.g., `copilot:/<rawId>`).
1385
>
*/
1386
>
export function uri(provider: AgentProvider, rawSessionId: string): URI {
1387
return URI.from({ scheme: provider, path: `/${rawSessionId}` });
1388
}
1390
>
/**
1391
>
* Extracts the raw session ID from a session URI (the path without leading slash).
1392
>
* Accepts both a URI object and a URI string.
1393
>
*/
1394
>
export function id(session: URI | string): string {
1395
const parsed = typeof session === 'string' ? URI.parse(session) : session;
1396
return parsed.path.substring(1);
1397
}
1399
>
/**
1400
>
* Extracts the provider name from a session URI scheme.
1401
>
* Accepts both a URI object and a URI string.
1402
>
*/
1403
>
export function provider(session: URI | string): AgentProvider | undefined {
1404
const parsed = typeof session === 'string' ? URI.parse(session) : session;
1405
return parsed.scheme || undefined;
1406
}
1408
>
1409
>
// ---- Agent provider interface -----------------------------------------------
1410
>
1411
>
/**
1412
>
* A notification originating from an MCP server, routed back to the AHP
1413
>
* client through the `mcp://` side channel. `channel` is the channel
1414
>
* URI advertised on the owning
1415
>
* {@link McpServerCustomization.channel | McpServerCustomization}; the
1416
>
* client uses it to fan the notification out to the appropriate App.
1417
>
* `method` and `params` follow the underlying MCP notification spec
1418
>
* (e.g. `notifications/tools/list_changed`).
1419
>
*/
1420
>
export interface IMcpNotification {
1421
>
readonly channel: string;
1422
>
readonly method: string;
1423
>
readonly params?: Record<string, unknown>;
1424
>
}
1425
>
1426
>
/**
1427
>
* A subagent child session discovered in a parent session's event log,
1428
>
* returned by {@link IAgent.getSubagentSessions} so a parent restore can
1429
>
* register the child's state up-front.
1430
>
*/
1431
>
export interface IRestoredSubagentSession {
1432
>
/** Child subagent session URI (subscribable by clients). */
1433
>
readonly resource: URI;
1434
>
/** Parent tool call id that spawned the subagent. */
1435
>
readonly toolCallId: string;
1436
>
/** Display title for the subagent session. */
1437
>
readonly title: string;
1438
>
/** Reconstructed turns for the subagent's transcript. */
1439
>
readonly turns: readonly Turn[];
1440
>
}
1441
>
1442
>
/**
1443
>
* A per-session handle for one active client's contributions (tools and
1444
>
* plugin customizations) to an agent session, obtained via
1445
>
* {@link IAgent.getOrCreateActiveClient}.
1446
>
*
1447
>
* `tools` and `customizations` are mutable accessor properties: assigning a
1448
>
* new array replaces this client's contribution wholesale and triggers the
1449
>
* agent's internal reaction (refreshing the merged tool set exposed to the
1450
>
* model, or kicking off an asynchronous customization sync). The arrays are
1451
>
* `readonly` so callers cannot mutate them in place and silently bypass the
1452
>
* setter. The agent merges the contributions of all active clients on a
1453
>
* session, deduplicating as needed.
1454
>
*/
1455
>
export interface IActiveClient {
1456
>
/** Client identifier (matches `clientId` from `initialize`). */
1457
>
readonly clientId: string;
1458
>
/** Human-readable client name (e.g. `"VS Code"`), if provided. */
1459
>
readonly displayName: string | undefined;
1460
>
/** This client's tools. Assigning replaces the set (full replacement). */
1461
>
tools: readonly ToolDefinition[];
1462
>
/** This client's plugin customizations. Assigning replaces the set and starts an internal sync. */
1463
>
customizations: readonly ClientPluginCustomization[];
1464
>
}
1465
>
1466
>
/**
1467
>
* Implemented by each agent backend (e.g. Copilot SDK).
1468
>
* The {@link IAgentService} dispatches to the appropriate agent based on
1469
>
* the agent id.
1470
>
*/
1471
>
export interface IAgent {
1472
>
/** Unique identifier for this provider (e.g. `'copilot'`). */
1473
>
readonly id: AgentProvider;
1474
>
1475
>
/** Fires when the provider streams progress for a session. */
1476
>
readonly onDidSessionProgress: Event<AgentSignal>;
1477
>
1478
>
/**
1479
>
* Fires once when a previously
1480
>
* {@link IAgentCreateSessionResult.provisional} session has been
1481
>
* materialized — i.e. its SDK session, worktree (if any), and on-disk
1482
>
* metadata are all in place. The {@link IAgentService} uses this event
1483
>
* to fire the deferred `sessionAdded` notification with the now-final
1484
>
* summary.
1485
>
*/
1486
>
readonly onDidMaterializeSession?: Event<IAgentMaterializeSessionEvent>;
1487
>
1488
>
/**
1489
>
* Provides the agent host's server-tool host so the provider can advertise
1490
>
* and execute the agent host's server tools (feedback "comments" today, more
1491
>
* in the future) against a session's state. Optional: providers that do not
1492
>
* support server-side tools simply omit it. Called once during registration
1493
>
* with the {@link IAgentService}.
1494
>
*/
1495
>
setServerToolHost?(host: IAgentServerToolHost): void;
1496
>
1497
>
// ---- Chat surface ------------------------------------------------------
1498
>
//
1499
>
// `chats` is the chat-addressed operation surface. Its chats are addressed
1500
>
// by concrete chat channel URIs. The orchestrator ({@link IAgentService})
1501
>
// owns the feature-level `(session, chat)` to chat-channel mapping.
1502
>
1503
>
/**
1504
>
* Chat-addressed surface for the chats within a session (send/abort/
1505
>
* change model/agent, create/fork/dispose chats, read history).
1506
>
*/
1507
>
readonly chats: IAgentChats;
1508
>
1509
>
// ---- Session lifecycle / configuration ---------------------------------
1510
>
1511
>
/** Create a new session. Host-owned worktree fields are omitted from `config.config`. */
1512
>
createSession(config?: IAgentCreateSessionConfig): Promise<IAgentCreateSessionResult>;
1513
>
1514
>
/** Resolve provider-owned session configuration; host-owned worktree fields are omitted. */
1515
>
resolveSessionConfig(params: IAgentResolveSessionConfigParams): Promise<ResolveSessionConfigResult>;
1516
>
1517
>
/** Return dynamic completions for a provider-owned session configuration property. */
1518
>
sessionConfigCompletions(params: IAgentSessionConfigCompletionsParams): Promise<SessionConfigCompletionsResult>;
1519
>
1520
>
/**
1521
>
* Re-attach an agent's in-memory backing for a peer chat on session
1522
>
* restore, decoding the opaque `providerData` produced earlier by
1523
>
* {@link IAgentChats.createChat} (or the latest
1524
>
* {@link onDidChangeChatData}). After this resolves the agent MUST
1525
>
* be able to serve {@link getSessionMessages}/
1526
>
* {@link IAgentChats.sendMessage} for `chat`.
1527
>
* Best-effort: implementations SHOULD NOT throw on a corrupt/unknown blob —
1528
>
* log and no-op so the orchestrator restores the chat with history but no
1529
>
* live backing. `providerData` is `undefined` only for legacy entries with
1530
>
* no stored blob, in which case the agent MAY consult its own legacy
1531
>
* persistence once to recover the backing.
1532
>
*/
1533
>
materializeChat?(chat: URI, providerData: string | undefined): Promise<void>;
1534
>
1535
>
/**
1536
>
* Migration-only enumeration of a session's peer chats persisted in the
1537
>
* agent's OWN legacy format (predating the orchestrator-owned catalog). The
1538
>
* orchestrator calls this once, when its own catalog is absent, to drain the
1539
>
* legacy chats into {@link PEER_CHATS_METADATA_KEY}; subsequent restores read
1540
>
* the orchestrator catalog and never consult this again. Each entry's
1541
>
* `providerData` uses the same encoding {@link IAgentChats.createChat}
1542
>
* produces and {@link materializeChat} decodes. Agents with no legacy
1543
>
* format (e.g. Codex) omit this method.
1544
>
*/
1545
>
listLegacyChats?(session: URI): Promise<readonly IAgentLegacyChat[]>;
1546
>
1547
>
/**
1548
>
* Fires when a peer chat's opaque `providerData` changes after creation
1549
>
* (e.g. per-chat model switch, fork remap). The orchestrator re-persists the
1550
>
* blob. Agents whose blob is immutable never fire this.
1551
>
*/
1552
>
readonly onDidChangeChatData?: Event<IAgentChatDataChange>;
1553
>
1554
>
// ---- Spawned chat (membership) channel -------------------------
1555
>
//
1556
>
// First-class membership channel for chats the agent spawns itself
1557
>
// (e.g. sub-agent / "team" member chats delegated by a tool call),
1558
>
// as opposed to user-driven chats created via
1559
>
// {@link IAgentChats.createChat}. The orchestrator
1560
>
// ({@link IAgentService}) routes these straight into the chat catalog
1561
>
// (addChat/removeChat) so harness-spawned and user-driven chats share ONE
1562
>
// membership path. Agents that never spawn chats omit both events.
1563
>
1564
>
/**
1565
>
* Fires when the agent spawns a new chat within a session (e.g. a
1566
>
* sub-agent delegated by a tool call). The orchestrator records it in the
1567
>
* chat catalog, preserving the {@link IAgentSpawnChatEvent.parent}
1568
>
* spawn edge as the chat's {@link ChatOriginKind.Tool} origin.
1569
>
*/
1570
>
readonly onDidSpawnChat?: Event<IAgentSpawnChatEvent>;
1571
>
1572
>
/**
1573
>
* Called when a chat's pending (steering) message changes.
1574
>
* The agent harness decides how to react — e.g. inject steering
1575
>
* mid-turn via `mode: 'immediate'`. Steering is always addressed by a
1576
>
* concrete chat channel URI — the session's default chat or an additional
1577
>
* peer chat — so it never leaks into a sibling chat of the same session.
1578
>
*
1579
>
* Queued messages are consumed on the server side and are not
1580
>
* forwarded to the agent; `queuedMessages` will always be empty.
1581
>
*/
1582
>
setPendingMessages?(chat: URI, steeringMessage: PendingMessage | undefined, queuedMessages: readonly PendingMessage[]): void;
1583
>
1584
>
/**
1585
>
* Retrieve the reconstructed turns for a session, used when restoring
1586
>
* sessions from persistent storage. Each agent owns the conversion from
1587
>
* its SDK-specific event log to protocol {@link Turn}s, including
1588
>
* subagent sessions (callers pass the subagent URI to retrieve the
1589
>
* child session's turns).
1590
>
*/
1591
>
getSessionMessages(session: URI): Promise<readonly Turn[]>;
1592
>
1593
>
/**
1594
>
* Returns the subagent child sessions discoverable in a session's event
1595
>
* log so a parent restore can eagerly register them in a single pass.
1596
>
* Without this, every child is restored separately by re-fetching and
1597
>
* re-reconstructing the full parent event log (one pass per subagent).
1598
>
* Agents that serve this from the same reconstruction they already
1599
>
* produced for the parent turns avoid that redundant work entirely.
1600
>
* Optional; agents without subagents omit it.
1601
>
*/
1602
>
getSubagentSessions?(session: URI): Promise<readonly IRestoredSubagentSession[]>;
1603
>
1604
>
/** Dispose a session, freeing resources. */
1605
>
disposeSession(session: URI): Promise<void>;
1606
>
1607
>
/**
1608
>
* Release a session's in-memory resources (SDK session/connection, cached
1609
>
* per-session state) without deleting any durable data. Unlike
1610
>
* {@link disposeSession}, this is non-destructive: the on-disk session log,
1611
>
* session database, and worktree are all preserved so the session can be
1612
>
* transparently resumed later. Used by idle-session eviction to bound
1613
>
* memory in long-lived host processes. Optional; providers that hold no
1614
>
* releasable in-memory state simply omit it.
1615
>
*/
1616
>
releaseSession?(session: URI): Promise<void>;
1617
>
1618
>
/** Respond to a pending permission request from the SDK. */
1619
>
respondToPermissionRequest(requestId: string, approved: boolean): void;
1620
>
1621
>
/** Respond to a pending user input request from the SDK's ask_user tool. */
1622
>
respondToUserInputRequest(requestId: string, response: ChatInputResponseKind, answers?: Record<string, ChatInputAnswer>): void;
1623
>
1624
>
/** Return the descriptor for this agent. */
1625
>
getDescriptor(): IAgentDescriptor;
1626
>
1627
>
/** Available models from this provider. */
1628
>
readonly models: IObservable<readonly IAgentModelInfo[]>;
1629
>
1630
>
/**
1631
>
* Re-enumerate this provider's model list and publish the result to
1632
>
* {@link models}. Called both on provider-owned triggers (authentication,
1633
>
* transport changes) and periodically by the host's model-refresh
1634
>
* scheduler, so implementations MUST coalesce concurrent calls into a
1635
>
* single backend request and MUST NOT reject: a failed refresh is logged
1636
>
* and leaves the last known-good list in place.
1637
>
*
1638
>
* Optional so providers without a dynamic model catalog (mocks, test
1639
>
* agents) need not implement it.
1640
>
*/
1641
>
refreshModels?(): Promise<void>;
1642
>
1643
>
/** List persisted sessions from this provider. */
1644
>
listSessions(): Promise<IAgentSessionMetadata[]>;
1645
>
1646
>
/** Retrieve metadata for a single persisted session, without enumerating the provider catalog. */
1647
>
getSessionMetadata?(session: URI): Promise<IAgentSessionMetadata | undefined>;
1648
>
1649
>
/** Declare protected resources this agent requires auth for (RFC 9728). */
1650
>
getProtectedResources(): ProtectedResourceMetadata[];
1651
>
1652
>
/**
1653
>
* Endpoints this provider uses and recommends probing in network
1654
>
* diagnostics. Optional.
1655
>
*/
1656
>
getNetworkDiagnosticsEndpoints?(): Promise<readonly IAgentHostNetworkEndpoint[]>;
1657
>
1658
>
/** Authenticated account name to display in network diagnostics, when known. */
1659
>
getNetworkDiagnosticsAccount?(): Promise<string | undefined>;
1660
>
1661
>
/** Resolve the provider's own effective enterprise managed-settings snapshot. */
1662
>
getManagedSettingsDiagnostics?(): Promise<IAgentHostManagedSettingsSnapshot>;
1663
>
1664
>
/**
1665
>
* Fires when the agent's host-owned customizations change
1666
>
* (loading state, resolution results, etc.), so infrastructure
1667
>
* can republish {@link AgentInfo} and session customization state.
1668
>
*/
1669
>
readonly onDidCustomizationsChange?: Event<void>;
1670
>
1671
>
/**
1672
>
* Fires when this agent needs the client to (re-)authenticate a
1673
>
* protected resource — for example after a runtime transport-mode flip
1674
>
* makes a previously-unneeded credential required. The host stamps the
1675
>
* root channel and forwards it verbatim as an `auth/required`
1676
>
* notification; clients respond via {@link authenticate}.
1677
>
*/
1678
>
readonly onDidRequireAuth?: Event<Omit<AuthRequiredParams, 'channel'>>;
1679
>
1680
>
/**
1681
>
* Returns the host-owned customizations this agent currently exposes.
1682
>
*
1683
>
* Used to publish baseline customization metadata on {@link AgentInfo}.
1684
>
* Always container customizations ({@link PluginCustomization} or
1685
>
* {@link DirectoryCustomization}).
1686
>
*/
1687
>
getCustomizations?(): readonly Customization[];
1688
>
1689
>
/**
1690
>
* Returns the effective customization list for a session, including
1691
>
* source, enablement, and loading/error status.
1692
>
*/
1693
>
getSessionCustomizations?(session: URI): Promise<readonly Customization[]>;
1694
>
1695
>
/**
1696
>
* Authenticate for a specific resource. Returns true if accepted.
1697
>
* The `resource` matches {@link IAuthorizationProtectedResourceMetadata.resource}.
1698
>
*/
1699
>
authenticate(resource: string, token: string): Promise<boolean>;
1700
>
1701
>
/**
1702
>
* Optional hook for provider-owned session resources that are not advertised
1703
>
* as root agent protected resources, such as MCP server OAuth challenges.
1704
>
*/
1705
>
handleAuthenticationToken?(params: AuthenticateParams): Promise<boolean>;
1706
>
1707
>
/**
1708
>
* Truncate a chat's history. If `turnId` is provided, keeps turns up to
1709
>
* and including that turn. If omitted, all turns are removed.
1710
>
*
1711
>
* `chat` identifies which chat to truncate: the session's default chat
1712
>
* (addressed by the session's default chat URI) or a peer (non-default)
1713
>
* chat, which has its own backing.
1714
>
*
1715
>
* Optional — not all providers support truncation.
1716
>
*/
1717
>
truncateSession?(session: URI, turnId: string | undefined, chat: URI): Promise<void>;
1718
>
1719
>
/**
1720
>
* Notifies the provider that a session's archived state has changed.
1721
>
* Providers may use this to clean up or restore per-session resources
1722
>
* (for example, removing a session-owned worktree on archive and
1723
>
* recreating it on unarchive). Optional.
1724
>
*/
1725
>
onArchivedChanged?(session: URI, isArchived: boolean): Promise<void>;
1726
>
1727
>
/**
1728
>
* Notifies the provider that a **client** (user) changed this session's
1729
>
* config — e.g. via an approvals/model picker. `values` is the post-reducer
1730
>
* merged config. Lets the provider propagate a session-mutable change (such
1731
>
* as Claude's `permissionMode`) to a running SDK mid-turn. Fires only for
1732
>
* client-originated changes; internal server-side config writes (e.g. a tool
1733
>
* persisting a mode) do NOT trigger it, so a provider can forward freely
1734
>
* without re-entering its own SDK callbacks. Optional.
1735
>
*/
1736
>
onSessionConfigChanged?(session: URI, values: Record<string, unknown>): void;
1737
>
1738
>
/**
1739
>
* Get (or lazily create) the per-session handle for an active client,
1740
>
* identified by `clientId`. Mutating the returned {@link IActiveClient}'s
1741
>
* `tools` / `customizations` updates only that client's contribution; the
1742
>
* agent merges the contributions of all active clients when exposing them
1743
>
* to the model. A session MAY have several active clients at once.
1744
>
*
1745
>
* @param session The session URI this client contributes to.
1746
>
* @param client The client's `clientId` and optional human-readable name.
1747
>
*/
1748
>
getOrCreateActiveClient(session: URI, client: { readonly clientId: string; readonly displayName?: string }): IActiveClient;
1749
>
1750
>
/**
1751
>
* Remove an active client from a session, clearing its tool and
1752
>
* customization contributions. No-op when no active client matches
1753
>
* `clientId`.
1754
>
*
1755
>
* @param session The session the client is leaving.
1756
>
* @param clientId The client to remove.
1757
>
*/
1758
>
removeActiveClient(session: URI, clientId: string): void;
1759
>
1760
>
/**
1761
>
* Called when a client completes a client-provided tool call.
1762
>
* Resolves the tool handler's deferred promise so the SDK can continue.
1763
>
*
1764
>
* @param session The session the tool call belongs to.
1765
>
* @param chat The chat channel the tool call was issued on, when known.
1766
>
* Agents that track peer chats separately from the default chat (e.g.
1767
>
* copilot) use this to route the completion to the right chat;
1768
>
* agents without peer chats ignore it and resolve by `session`.
1769
>
* @param toolCallId The id of the tool call being completed.
1770
>
* @param result The result of the tool call.
1771
>
*/
1772
>
onClientToolCallComplete(session: URI, chat: URI, toolCallId: string, result: ToolCallResult): void;
1773
>
1774
>
/** Request a session MCP server start/restart by customization id. */
1775
>
startMcpServer?(session: URI, id: string): Promise<void>;
1776
>
1777
>
/** Request a session MCP server stop by customization id. */
1778
>
stopMcpServer?(session: URI, id: string): Promise<void>;
1779
>
1780
>
/** Gracefully shut down all sessions. */
1781
>
shutdown(): Promise<void>;
1782
>
1783
>
/**
1784
>
* Routes a request received on an `mcp://` side channel to the agent's
1785
>
* MCP server implementation. The channel carries raw MCP JSON-RPC
1786
>
* methods (e.g. `tools/list`, `tools/call`, `resources/read`) tagged
1787
>
* with the routing envelope; the protocol server decodes the envelope
1788
>
* and forwards `(session, serverName, method, params)` here.
1789
>
*
1790
>
* The agent MUST reject unknown methods with an error whose message
1791
>
* begins with `Method not found` so the protocol server can map it to
1792
>
* a JSON-RPC `-32601`.
1793
>
*
1794
>
* Optional — agents that don't surface any MCP servers (or don't
1795
>
* advertise `mcpApp` capabilities) can omit this.
1796
>
*/
1797
>
handleMcpRequest?(session: URI, serverName: string, method: string, params: Record<string, unknown> | undefined): Promise<unknown>;
1798
>
1799
>
/**
1800
>
* Fires when an MCP server owned by this agent emits a notification
1801
>
* that should be forwarded to AHP clients over the `mcp://` side
1802
>
* channel. Today this is exclusively
1803
>
* `notifications/tools/list_changed` and
1804
>
* `notifications/resources/list_changed`. The protocol server
1805
>
* fans the notification out to every connected client.
1806
>
*
1807
>
* Optional — agents that don't expose MCP servers can omit this.
1808
>
*/
1809
>
readonly onMcpNotification?: Event<IMcpNotification>;
1810
>
1811
>
/** Dispose this provider and all its resources. */
1812
>
dispose(): void;
1813
>
}
1814
>
1815
>
// ---- Service interfaces -----------------------------------------------------
1816
>
1817
>
export const IAgentService = createDecorator<IAgentService>('agentService');
1818
>
1819
>
/**
1820
>
* Service contract for communicating with the agent host process. Methods here
1821
>
* are proxied across MessagePort via `ProxyChannel`.
1822
>
*
1823
>
* State is synchronized via the subscribe/unsubscribe/dispatchAction protocol.
1824
>
* Clients observe root state (agents, models) and session state via subscriptions,
1825
>
* and mutate state by dispatching actions (e.g. session/turnStarted, session/turnCancelled).
1826
>
*/
1827
>
export interface IAgentService {
1828
>
readonly _serviceBrand: undefined;
1829
>
1830
>
/**
1831
>
* Authenticate for a protected resource on the server.
1832
>
* The {@link AuthenticateParams.resource} must match a resource from
1833
>
* the agent's protectedResources in root state. Analogous to RFC 6750
1834
>
* bearer token delivery.
1835
>
*/
1836
>
authenticate(params: AuthenticateParams): Promise<AuthenticateResult>;
1837
>
1838
>
/** Return a bearer token previously supplied via {@link authenticate}. */
1839
>
getAuthToken(request: IAgentHostAuthTokenRequest): string | undefined;
1840
>
1841
>
/** List all available sessions from the Copilot CLI. */
1842
>
listSessions(): Promise<IAgentSessionMetadata[]>;
1843
>
1844
>
/** Create a new session. Returns the session URI. */
1845
>
createSession(config?: IAgentCreateSessionConfig): Promise<URI>;
1846
>
1847
>
/**
1848
>
* Create an additional chat within an existing session. Spins up the
1849
>
* backing chat in the harness (sharing the session's session) and
1850
>
* registers the chat in the session's catalog so subscribers observe a
1851
>
* `session/chatAdded` action. The `chat` URI is the client-chosen channel.
1852
>
*/
1853
>
createChat(session: URI, chat: URI, options?: IAgentCreateChatOptions): Promise<void>;
1854
>
1855
>
/** Dispose an additional chat created via {@link createChat}. */
1856
>
disposeChat(session: URI, chat: URI): Promise<void>;
1857
>
1858
>
/** Resolve the dynamic configuration schema for creating a session. */
1859
>
resolveSessionConfig(params: IAgentResolveSessionConfigParams): Promise<ResolveSessionConfigResult>;
1860
>
1861
>
/** Return dynamic completions for a session configuration property. */
1862
>
sessionConfigCompletions(params: IAgentSessionConfigCompletionsParams): Promise<SessionConfigCompletionsResult>;
1863
>
1864
>
/**
1865
>
* Return completion items for a partially-typed input (e.g. an `@`-mention
1866
>
* inside a user message the user is composing). Delegates to a pluggable
1867
>
* set of {@link IAgentHostCompletionItemProvider}s registered with the
1868
>
* agent host.
1869
>
*
1870
>
* Note: this method does not accept a {@link CancellationToken} because
1871
>
* `CancellationToken`s do not round-trip through the IPC boundary today
1872
>
* (the deserialised value lacks the prototype methods used by
1873
>
* subscribers). Callers that need cancellation should race the returned
1874
>
* promise on their own side.
1875
>
*/
1876
>
completions(params: CompletionsParams): Promise<CompletionsResult>;
1877
>
1878
>
/**
1879
>
* Returns the set of characters that, when typed in a {@link UserMessage}
1880
>
* input, SHOULD cause the client to issue a `completions` request.
1881
>
* Aggregated from every registered {@link IAgentHostCompletionItemProvider}.
1882
>
*/
1883
>
getCompletionTriggerCharacters(): Promise<readonly string[]>;
1884
>
1885
>
/** Dispose a session in the agent host, freeing SDK resources. */
1886
>
disposeSession(session: URI): Promise<void>;
1887
>
1888
>
/** Create a new terminal on the agent host. */
1889
>
createTerminal(params: CreateTerminalParams): Promise<void>;
1890
>
1891
>
/** Dispose a terminal and kill its process if still running. */
1892
>
disposeTerminal(terminal: URI): Promise<void>;
1893
>
1894
>
/** Invoke a server-defined changeset operation. */
1895
>
invokeChangesetOperation(params: InvokeChangesetOperationParams): Promise<InvokeChangesetOperationResult>;
1896
>
1897
>
/**
1898
>
* Routes a request received on an `mcp://` AHP side channel to the
1899
>
* MCP server implementation owned by the appropriate agent. The
1900
>
* channel URI shape is `mcp://<providerId>/<sessionId>/<serverName>`
1901
>
* (the latter two segments URL-encoded), matching the
1902
>
* {@link McpServerCustomization.channel | channel} the agent host
1903
>
* advertises while the server is in
1904
>
* {@link McpServerStatus.Ready | `Ready`}.
1905
>
*
1906
>
* `method` is the raw MCP JSON-RPC method (e.g. `tools/list`,
1907
>
* `tools/call`, `resources/read`); `params` are the JSON-RPC params
1908
>
* (still carrying the routing envelope's `channel` field, which the
1909
>
* agent may ignore). Rejects with an `Error` whose message begins
1910
>
* with `Method not found` when the channel is unknown or the agent
1911
>
* doesn't recognise the method — the protocol server translates that
1912
>
* into a JSON-RPC `-32601`.
1913
>
*/
1914
>
handleMcpRequest(channel: string, method: string, params: Record<string, unknown> | undefined): Promise<unknown>;
1915
>
1916
>
/**
1917
>
* Aggregated stream of MCP notifications across every agent. The
1918
>
* protocol server subscribes once and broadcasts each notification as
1919
>
* a JSON-RPC notification to all connected clients (the routing
1920
>
* envelope's `channel` field is sufficient for client-side dispatch,
1921
>
* so no per-subscription fanout is required).
1922
>
*/
1923
>
readonly onMcpNotification: Event<IMcpNotification>;
1924
>
1925
>
/** Gracefully shut down all sessions and the underlying client. */
1926
>
shutdown(): Promise<void>;
1927
>
1928
>
/**
1929
>
* Host-level network context for diagnostics — agent host version, OS/arch,
1930
>
* account, proxy settings/env, and the endpoints worth probing (which
1931
>
* callers probe via {@link diagnosticsFetch}, plus any additional URLs).
1932
>
*/
1933
>
getNetworkDiagnosticsInfo(): Promise<IAgentHostNetworkDiagnosticsInfo>;
1934
>
1935
>
/** Resolve managed settings through each provider's native SDK/runtime implementation. */
1936
>
getManagedSettingsDiagnostics(): Promise<readonly IAgentHostManagedSettingsDiagnostics[]>;
1937
>
1938
>
/**
1939
>
* Probe connectivity from the agent host process to a single `url`,
1940
>
* resolving the proxy and timing DNS + reachability. Used by the "Network
1941
>
* Diagnostics" developer command.
1942
>
*/
1943
>
diagnosticsFetch(url: string): Promise<IAgentHostNetworkFetchResult>;
1944
>
1945
>
// ---- Protocol methods (sessions process protocol) ----------------------
1946
>
1947
>
/**
1948
>
* Subscribe to state at the given URI. Returns a snapshot of the current
1949
>
* state and the serverSeq at snapshot time. Subsequent actions for this
1950
>
* resource arrive via {@link onDidAction}. Registers `clientId` against
1951
>
* the resource so the server-side refcount knows who is watching, so the
1952
>
* caller does not need to invoke {@link addSubscriber} separately. Pair
1953
>
* with {@link unsubscribe} when the subscription is released.
1954
>
*/
1955
>
subscribe(resource: URI, clientId: string): Promise<IStateSnapshot>;
1956
>
1957
>
/**
1958
>
* Counterpart to {@link subscribe}. Drops `clientId` from the refcount
1959
>
* for `resource`; when the last subscriber is removed, idle session state
1960
>
* for `resource` may be evicted from the server.
1961
>
*/
1962
>
unsubscribe(resource: URI, clientId: string): void;
1963
>
1964
>
/**
1965
>
* Register `clientId` against `resource` without going through
1966
>
* {@link subscribe}. Only needed by callers that hand out snapshots
1967
>
* synchronously (e.g. the JSON-RPC handshake serving `initialSubscriptions`
1968
>
* out of the in-memory state cache); regular subscribers should call
1969
>
* {@link subscribe} instead. Counterpart cleanup is {@link unsubscribe}.
1970
>
*/
1971
>
addSubscriber(resource: URI, clientId: string): void;
1972
>
1973
>
/**
1974
>
* Fires when the server applies an action to subscribable state.
1975
>
* Clients use this alongside {@link subscribe} to keep their local
1976
>
* state in sync.
1977
>
*/
1978
>
readonly onDidAction: Event<ActionEnvelope>;
1979
>
1980
>
/**
1981
>
* Fires when the server broadcasts an ephemeral notification
1982
>
* (e.g. sessionAdded, sessionRemoved).
1983
>
*/
1984
>
readonly onDidNotification: Event<INotification>;
1985
>
1986
>
/**
1987
>
* Dispatch a client-originated action to the server. The server applies
1988
>
* it to state, triggers side effects, and echoes it back via
1989
>
* {@link onDidAction} with the client's origin for reconciliation.
1990
>
*
1991
>
* `channel` is the protocol URI string identifying the channel the action
1992
>
* targets (a session URI for session actions, terminal URI for terminal
1993
>
* actions, or {@link ROOT_STATE_URI} for root actions). Strings are used
1994
>
* rather than {@link URI} objects so that authority-less scheme URIs
1995
>
* like `ahp-root://` survive the wire format without normalization.
1996
>
*/
1997
>
dispatchAction(channel: string, action: SessionAction | ChatAction | TerminalAction | ClientChangesetAction | ClientAnnotationsAction | IRootConfigChangedAction, clientId: string, clientSeq: number): void;
1998
>
1999
>
/**
2000
>
* List the contents of a directory on the agent host's filesystem.
2001
>
* Used by the client to drive a remote folder picker before session creation.
2002
>
*/
2003
>
resourceList(uri: URI): Promise<ResourceListResult>;
2004
>
2005
>
/**
2006
>
* Read stored content by URI from the agent host (e.g. file edit snapshots,
2007
>
* or reading files from the remote filesystem).
2008
>
*/
2009
>
resourceRead(uri: URI): Promise<ResourceReadResult>;
2010
>
2011
>
/**
2012
>
* Write content to a file on the agent host's filesystem.
2013
>
* Used for undo/redo operations on file edits.
2014
>
*/
2015
>
resourceWrite(params: ResourceWriteParams): Promise<ResourceWriteResult>;
2016
>
2017
>
/**
2018
>
* Copy a resource from one URI to another on the agent host's filesystem.
2019
>
*/
2020
>
resourceCopy(params: ResourceCopyParams): Promise<ResourceCopyResult>;
2021
>
2022
>
/**
2023
>
* Delete a resource at a URI on the agent host's filesystem.
2024
>
*/
2025
>
resourceDelete(params: ResourceDeleteParams): Promise<ResourceDeleteResult>;
2026
>
2027
>
/**
2028
>
* Move (rename) a resource from one URI to another on the agent host's filesystem.
2029
>
*/
2030
>
resourceMove(params: ResourceMoveParams): Promise<ResourceMoveResult>;
2031
>
2032
>
/**
2033
>
* Resolve a resource (stat + realpath) on the agent host's filesystem.
2034
>
*/
2035
>
resourceResolve(params: ResourceResolveParams): Promise<ResourceResolveResult>;
2036
>
2037
>
/**
2038
>
* Create a directory (mkdir -p semantics) on the agent host's filesystem.
2039
>
*/
2040
>
resourceMkdir(params: ResourceMkdirParams): Promise<ResourceMkdirResult>;
2041
>
2042
>
/**
2043
>
* Create a resource watcher on the agent host's filesystem. Returns the
2044
>
* `ahp-resource-watch:/<id>` channel URI the caller subscribes to in
2045
>
* order to receive `resourceWatch/changed` events. The watcher is
2046
>
* tied to the subscriber refcount on that channel — the implementation
2047
>
* MUST hold the underlying file-system watcher for a short grace
2048
>
* period after the last unsubscribe so reconnects don't drop events.
2049
>
*/
2050
>
createResourceWatch(params: CreateResourceWatchParams): Promise<CreateResourceWatchResult>;
2051
>
2052
>
/**
2053
>
* Notify the agent service that a client subscribed to the given
2054
>
* `ahp-resource-watch:` channel so the per-watch refcount is bumped
2055
>
* (and the underlying {@link IFileService} watcher attached on the
2056
>
* first subscriber). Returns the decoded watch descriptor when the
2057
>
* channel parses successfully and the watcher is live; returns
2058
>
* `undefined` for unknown channels so the caller can surface a
2059
>
* not-found error.
2060
>
*/
2061
>
onResourceWatchSubscribed(channel: string): ResourceWatchState | undefined;
2062
>
2063
>
/**
2064
>
* Counterpart to {@link onResourceWatchSubscribed}. Decrements the
2065
>
* per-watch refcount; on the last drop the watcher is held for a
2066
>
* short grace period before disposal.
2067
>
*/
2068
>
onResourceWatchUnsubscribed(channel: string): boolean;
2069
>
}
2070
>
2071
>
/**
2072
>
* Consumer-facing connection to an agent host. Session handlers, terminal
2073
>
* contributions, and other features program against this interface.
2074
>
*
2075
>
* Implementations wrap an {@link IAgentService} and layer subscription
2076
>
* management and optimistic write-ahead on top.
2077
>
*/
2078
>
export interface IAgentConnection {
2079
>
2080
>
readonly clientId: string;
2081
>
2082
>
// ---- State subscriptions ------------------------------------------------
2083
>
readonly rootState: IAgentSubscription<RootState>;
2084
>
/**
2085
>
* Acquire a refcounted subscription to `resource`. `owner` names the
2086
>
* caller holding the reference so inspection surfaces can attribute who
2087
>
* is retaining a subscription; use a stable identifier such as the
2088
>
* acquiring class name.
2089
>
*/
2090
>
getSubscription<T extends StateComponents>(kind: T, resource: URI, owner: string): IReference<IAgentSubscription<ComponentToState[T]>>;
2091
>
getSubscriptionUnmanaged<T extends StateComponents>(kind: T, resource: URI): IAgentSubscription<ComponentToState[T]> | undefined;
2092
>
2093
>
/**
2094
>
* Returns the in-flight `createSession` Promise for `resource`, or `undefined` if no create is pending. Callers
2095
>
* that need to gate work on a racing eager `createSession` (e.g. before deciding whether to fall through to a
2096
>
* duplicate create) should await this first.
2097
>
*/
2098
>
getInflightSessionCreate(resource: URI): Promise<unknown> | undefined;
2099
>
2100
>
/**
2101
>
* Read-only descriptors of every active resource subscription on this
2102
>
* connection, for inspection/debug surfaces. Excludes the always-live
2103
>
* {@link rootState}.
2104
>
*/
2105
>
getActiveSubscriptions(): readonly IActiveSubscriptionInfo[];
2106
>
2107
>
// ---- Action dispatch ----------------------------------------------------
2108
>
/**
2109
>
* Dispatch a client-originated action. `channel` is the protocol URI
2110
>
* string identifying the channel the action targets (a session URI for
2111
>
* session actions, terminal URI for terminal actions, or
2112
>
* `ROOT_STATE_URI` for root-config actions). Strings are used rather
2113
>
* than {@link URI} objects so authority-less scheme URIs like
2114
>
* `ahp-root://` survive the wire format without normalization.
2115
>
*/
2116
>
dispatch(channel: string, action: SessionAction | ChatAction | TerminalAction | ClientChangesetAction | ClientAnnotationsAction | IRootConfigChangedAction): void;
2117
>
2118
>
// ---- Events (connection-level) ------------------------------------------
2119
>
readonly onDidNotification: Event<INotification>;
2120
>
readonly onDidAction: Event<ActionEnvelope>;
2121
>
/**
2122
>
* Fires when the host forwards an MCP server notification (e.g.
2123
>
* `notifications/tools/list_changed`) over the `mcp://` side channel.
2124
>
* The `channel` field on the notification routes the payload to the
2125
>
* matching {@link McpServerCustomization}.
2126
>
*/
2127
>
readonly onMcpNotification: Event<IMcpNotification>;
2128
>
2129
>
// ---- MCP side-channel ---------------------------------------------------
2130
>
/**
2131
>
* Send a request on an `mcp://` AHP side channel. `channel` is the
2132
>
* `mcp://` URI advertised by the matching {@link McpServerCustomization}
2133
>
* (only available while the server is `ready`). `method` is the raw MCP
2134
>
* JSON-RPC method (e.g. `tools/call`, `resources/read`,
2135
>
* `sampling/createMessage`); `params` are the JSON-RPC params (the
2136
>
* connection adds the routing envelope's `channel` field automatically).
2137
>
*
2138
>
* Rejects with an `Error` whose message begins with `Method not found`
2139
>
* when the channel is unknown or the host doesn't recognise the method.
2140
>
*/
2141
>
handleMcpRequest(channel: string, method: string, params: Record<string, unknown> | undefined): Promise<unknown>;
2142
>
2143
>
// ---- Session lifecycle --------------------------------------------------
2144
>
authenticate(params: AuthenticateParams): Promise<AuthenticateResult>;
2145
>
listSessions(): Promise<IAgentSessionMetadata[]>;
2146
>
createSession(config?: IAgentCreateSessionConfig): Promise<URI>;
2147
>
resolveSessionConfig(params: IAgentResolveSessionConfigParams): Promise<ResolveSessionConfigResult>;
2148
>
sessionConfigCompletions(params: IAgentSessionConfigCompletionsParams): Promise<SessionConfigCompletionsResult>;
2149
>
completions(params: CompletionsParams): Promise<CompletionsResult>;
2150
>
2151
>
/**
2152
>
* Trigger characters announced by the connected agent host that should
2153
>
* cause the client to issue a `completions` request when typed in a
2154
>
* user-message input. Resolves once on first request and is cached.
2155
>
*/
2156
>
getCompletionTriggerCharacters(): Promise<readonly string[]>;
2157
>
2158
>
/**
2159
>
* The host's `initialize` handshake result, exposed observably so callers
2160
>
* can derive advertised capabilities (e.g. {@link InitializeResult.terminalCommandPrefix},
2161
>
* {@link InitializeResult.completionTriggerCharacters}). `undefined` until
2162
>
* the handshake completes.
2163
>
*/
2164
>
readonly initializeResult: IObservable<InitializeResult | undefined>;
2165
>
disposeSession(session: URI): Promise<void>;
2166
>
2167
>
/**
2168
>
* Host-level network context for diagnostics (version, OS/arch, account,
2169
>
* proxy settings/env, endpoints). Runs on the agent host process (local or
2170
>
* remote), so the result reflects the environment the Copilot SDK actually
2171
>
* runs in.
2172
>
*/
2173
>
getNetworkDiagnosticsInfo(): Promise<IAgentHostNetworkDiagnosticsInfo>;
2174
>
2175
>
/** Resolve managed settings through each provider's native SDK/runtime implementation. */
2176
>
getManagedSettingsDiagnostics(): Promise<readonly IAgentHostManagedSettingsDiagnostics[]>;
2177
>
2178
>
/**
2179
>
* Probe connectivity from the agent host to a single `url`. Runs on the
2180
>
* agent host process (local or remote), so the result reflects the
2181
>
* environment the Copilot SDK actually runs in.
2182
>
*/
2183
>
diagnosticsFetch(url: string): Promise<IAgentHostNetworkFetchResult>;
2184
>
2185
>
/**
2186
>
* Create an additional peer chat inside an existing session. `chat` is a
2187
>
* client-chosen chat URI (see {@link buildChatUri}). The host adds the
2188
>
* chat to the session's catalog and publishes `session/chatAdded`.
2189
>
*/
2190
>
createChat(session: URI, chat: URI, options?: IAgentCreateChatOptions): Promise<void>;
2191
>
/** Dispose an additional chat created via {@link createChat}. */
2192
>
disposeChat(chat: URI): Promise<void>;
2193
>
2194
>
// ---- Terminal lifecycle -------------------------------------------------
2195
>
createTerminal(params: CreateTerminalParams): Promise<void>;
2196
>
disposeTerminal(terminal: URI): Promise<void>;
2197
>
2198
>
// ---- Changeset operations -----------------------------------------------
2199
>
invokeChangesetOperation(params: InvokeChangesetOperationParams): Promise<InvokeChangesetOperationResult>;
2200
>
2201
>
// ---- Filesystem operations ----------------------------------------------
2202
>
resourceList(uri: URI): Promise<ResourceListResult>;
2203
>
resourceRead(uri: URI): Promise<ResourceReadResult>;
2204
>
resourceWrite(params: ResourceWriteParams): Promise<ResourceWriteResult>;
2205
>
resourceCopy(params: ResourceCopyParams): Promise<ResourceCopyResult>;
2206
>
resourceDelete(params: ResourceDeleteParams): Promise<ResourceDeleteResult>;
2207
>
resourceMove(params: ResourceMoveParams): Promise<ResourceMoveResult>;
2208
>
resourceResolve(params: ResourceResolveParams): Promise<ResourceResolveResult>;
2209
>
resourceMkdir(params: ResourceMkdirParams): Promise<ResourceMkdirResult>;
2210
>
createResourceWatch(params: CreateResourceWatchParams): Promise<CreateResourceWatchResult>;
2211
>
/**
2212
>
* Convenience method that bundles
2213
>
* {@link createResourceWatch} + {@link subscribe} + a typed
2214
>
* {@link IFileChange}[] event stream, so consumers (notably
2215
>
* `AHPFileSystemProvider.watch`) can drive a watcher without
2216
>
* understanding the underlying channel protocol. Disposing the
2217
>
* returned handle unsubscribes.
2218
>
*/
2219
>
watchResource(params: CreateResourceWatchParams): Promise<IRemoteWatchHandle>;
2220
>
}
2221
>
2222
>
export const IAgentHostService = createDecorator<IAgentHostService>('agentHostService');
2223
>
2224
>
/**
2225
>
* The local wrapper around the agent host process (manages lifecycle, restart,
2226
>
* exposes the proxied service). Consumed by the main process and workbench.
2227
>
*/
2228
>
export interface IAgentHostService extends IAgentConnection {
2229
>
2230
>
readonly _serviceBrand: undefined;
2231
>
2232
>
readonly onAgentHostExit: Event<number>;
2233
>
readonly onAgentHostStart: Event<void>;
2234
>
2235
>
/**
2236
>
* `true` while we are in the middle of authenticating against the local
2237
>
* agent host (resolving tokens for any advertised `protectedResources` and
2238
>
* pushing them via {@link authenticate}). Defaults to `true` at startup so
2239
>
* that the period before the first auth pass is also covered.
2240
>
*
2241
>
* Producers (the workbench `AgentHostContribution`) flip this around their
2242
>
* auth pass; consumers (e.g. the local sessions provider) read it to mark
2243
>
* sessions as still loading.
2244
>
*/
2245
>
readonly authenticationPending: IObservable<boolean>;
2246
>
2247
>
/** Update {@link authenticationPending}. Internal — only the auth driver should call this. */
2248
>
setAuthenticationPending(pending: boolean): void;
2249
>
2250
>
restartAgentHost(): Promise<void>;
2251
>
2252
>
startWebSocketServer(): Promise<IAgentHostSocketInfo>;
2253
>
2254
>
/**
2255
>
* Get inspector listener info for the agent host process. If the inspector
2256
>
* is not currently active and `tryEnable` is true, opens the inspector on
2257
>
* a random local port. Returns `undefined` if the inspector cannot be
2258
>
* enabled.
2259
>
*/
2260
>
getInspectInfo(tryEnable: boolean): Promise<IAgentHostInspectInfo | undefined>;
2261
>
}