llm-cli-gateway 2.13.1 → 2.14.0-rc.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +140 -0
  2. package/README.md +53 -26
  3. package/dist/acp/client.d.ts +29 -1
  4. package/dist/acp/client.js +78 -4
  5. package/dist/acp/errors.d.ts +9 -1
  6. package/dist/acp/errors.js +19 -0
  7. package/dist/acp/event-normalizer.d.ts +12 -0
  8. package/dist/acp/event-normalizer.js +16 -0
  9. package/dist/acp/flight-redaction.d.ts +3 -0
  10. package/dist/acp/flight-redaction.js +3 -0
  11. package/dist/acp/permission-bridge.js +11 -5
  12. package/dist/acp/process-manager.d.ts +2 -1
  13. package/dist/acp/process-manager.js +43 -4
  14. package/dist/acp/provider-registry.js +19 -11
  15. package/dist/acp/runtime.d.ts +8 -0
  16. package/dist/acp/runtime.js +47 -4
  17. package/dist/acp/types.d.ts +3083 -55
  18. package/dist/acp/types.js +242 -5
  19. package/dist/async-job-manager.d.ts +2 -0
  20. package/dist/async-job-manager.js +11 -0
  21. package/dist/codex-json-parser.d.ts +1 -0
  22. package/dist/codex-json-parser.js +6 -0
  23. package/dist/config.d.ts +16 -0
  24. package/dist/config.js +105 -19
  25. package/dist/connector-setup.d.ts +39 -0
  26. package/dist/connector-setup.js +86 -0
  27. package/dist/doctor.d.ts +39 -1
  28. package/dist/doctor.js +182 -3
  29. package/dist/flight-recorder.d.ts +2 -0
  30. package/dist/flight-recorder.js +20 -0
  31. package/dist/gemini-json-parser.d.ts +2 -0
  32. package/dist/gemini-json-parser.js +45 -8
  33. package/dist/grok-json-parser.d.ts +14 -0
  34. package/dist/grok-json-parser.js +156 -0
  35. package/dist/http-transport.js +27 -3
  36. package/dist/index.d.ts +48 -2
  37. package/dist/index.js +633 -144
  38. package/dist/job-store.d.ts +45 -7
  39. package/dist/job-store.js +138 -17
  40. package/dist/model-registry.d.ts +1 -0
  41. package/dist/model-registry.js +46 -0
  42. package/dist/oauth.js +17 -16
  43. package/dist/postgres-job-store-worker.d.ts +1 -0
  44. package/dist/postgres-job-store-worker.js +327 -0
  45. package/dist/pricing.d.ts +3 -2
  46. package/dist/provider-acp-capabilities.d.ts +52 -0
  47. package/dist/provider-acp-capabilities.js +101 -0
  48. package/dist/provider-admin-tools.d.ts +100 -0
  49. package/dist/provider-admin-tools.js +572 -0
  50. package/dist/provider-capability-cache.d.ts +46 -0
  51. package/dist/provider-capability-cache.js +248 -0
  52. package/dist/provider-capability-discovery.d.ts +85 -0
  53. package/dist/provider-capability-discovery.js +461 -0
  54. package/dist/provider-capability-resolver.d.ts +29 -0
  55. package/dist/provider-capability-resolver.js +92 -0
  56. package/dist/provider-definition-assertions.d.ts +9 -0
  57. package/dist/provider-definition-assertions.js +147 -0
  58. package/dist/provider-definitions.d.ts +127 -0
  59. package/dist/provider-definitions.js +758 -0
  60. package/dist/provider-help-parser.d.ts +34 -0
  61. package/dist/provider-help-parser.js +203 -0
  62. package/dist/provider-model-discovery.d.ts +30 -0
  63. package/dist/provider-model-discovery.js +229 -0
  64. package/dist/provider-output-metadata.d.ts +7 -0
  65. package/dist/provider-output-metadata.js +68 -0
  66. package/dist/provider-schema-builder.d.ts +22 -0
  67. package/dist/provider-schema-builder.js +55 -0
  68. package/dist/provider-surface-generator.d.ts +98 -0
  69. package/dist/provider-surface-generator.js +140 -0
  70. package/dist/provider-tool-capabilities.d.ts +3 -2
  71. package/dist/provider-tool-capabilities.js +77 -62
  72. package/dist/remote-url.d.ts +28 -0
  73. package/dist/remote-url.js +61 -0
  74. package/dist/request-helpers.d.ts +37 -4
  75. package/dist/request-helpers.js +134 -0
  76. package/dist/resources.d.ts +6 -1
  77. package/dist/resources.js +67 -193
  78. package/dist/session-manager.d.ts +2 -0
  79. package/dist/session-manager.js +34 -8
  80. package/dist/stream-json-parser.d.ts +1 -0
  81. package/dist/stream-json-parser.js +3 -0
  82. package/dist/upstream-contracts.d.ts +17 -1
  83. package/dist/upstream-contracts.js +209 -36
  84. package/dist/workspace-registry.d.ts +9 -0
  85. package/dist/workspace-registry.js +24 -4
  86. package/npm-shrinkwrap.json +2 -2
  87. package/package.json +8 -3
  88. package/setup/status.schema.json +75 -0
@@ -72,6 +72,20 @@ export declare const CODEX_SANDBOX_MODES: readonly ["read-only", "workspace-writ
72
72
  export type CodexSandboxMode = (typeof CODEX_SANDBOX_MODES)[number];
73
73
  export declare const CODEX_ASK_FOR_APPROVAL_MODES: readonly ["untrusted", "on-request", "never"];
74
74
  export type CodexAskForApproval = (typeof CODEX_ASK_FOR_APPROVAL_MODES)[number];
75
+ export declare const CODEX_LOCAL_PROVIDERS: readonly ["lmstudio", "ollama"];
76
+ export type CodexLocalProvider = (typeof CODEX_LOCAL_PROVIDERS)[number];
77
+ export declare const CODEX_COLOR_MODES: readonly ["always", "never", "auto"];
78
+ export type CodexColorMode = (typeof CODEX_COLOR_MODES)[number];
79
+ export type UnexposedFlagReason = "interactive-only" | "gateway-managed" | "admin-deferred";
80
+ export interface UnexposedCliFlag {
81
+ flag: string;
82
+ reason: UnexposedFlagReason;
83
+ detail: string;
84
+ }
85
+ export declare const CLAUDE_UNEXPOSED_CLI_FLAGS: readonly UnexposedCliFlag[];
86
+ export declare const CODEX_UNEXPOSED_CLI_FLAGS: readonly UnexposedCliFlag[];
87
+ export declare const GEMINI_UNEXPOSED_CLI_FLAGS: readonly UnexposedCliFlag[];
88
+ export declare const MISTRAL_UNEXPOSED_CLI_FLAGS: readonly UnexposedCliFlag[];
75
89
  export interface CodexSandboxFlagsInput {
76
90
  sandboxMode?: CodexSandboxMode;
77
91
  askForApproval?: CodexAskForApproval;
@@ -98,8 +112,8 @@ export declare const CLAUDE_HIGH_IMPACT_PARAMS_SCHEMA: z.ZodEffects<z.ZodObject<
98
112
  effort: z.ZodOptional<z.ZodEnum<["low", "medium", "high", "xhigh", "max"]>>;
99
113
  excludeDynamicSystemPromptSections: z.ZodOptional<z.ZodBoolean>;
100
114
  }, "strip", z.ZodTypeAny, {
101
- agent?: string | undefined;
102
115
  agents?: Record<string, Record<string, unknown>> | undefined;
116
+ agent?: string | undefined;
103
117
  forkSession?: boolean | undefined;
104
118
  systemPrompt?: string | undefined;
105
119
  appendSystemPrompt?: string | undefined;
@@ -108,8 +122,8 @@ export declare const CLAUDE_HIGH_IMPACT_PARAMS_SCHEMA: z.ZodEffects<z.ZodObject<
108
122
  effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
109
123
  excludeDynamicSystemPromptSections?: boolean | undefined;
110
124
  }, {
111
- agent?: string | undefined;
112
125
  agents?: Record<string, Record<string, unknown>> | undefined;
126
+ agent?: string | undefined;
113
127
  forkSession?: boolean | undefined;
114
128
  systemPrompt?: string | undefined;
115
129
  appendSystemPrompt?: string | undefined;
@@ -118,8 +132,8 @@ export declare const CLAUDE_HIGH_IMPACT_PARAMS_SCHEMA: z.ZodEffects<z.ZodObject<
118
132
  effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
119
133
  excludeDynamicSystemPromptSections?: boolean | undefined;
120
134
  }>, {
121
- agent?: string | undefined;
122
135
  agents?: Record<string, Record<string, unknown>> | undefined;
136
+ agent?: string | undefined;
123
137
  forkSession?: boolean | undefined;
124
138
  systemPrompt?: string | undefined;
125
139
  appendSystemPrompt?: string | undefined;
@@ -128,8 +142,8 @@ export declare const CLAUDE_HIGH_IMPACT_PARAMS_SCHEMA: z.ZodEffects<z.ZodObject<
128
142
  effort?: "low" | "medium" | "high" | "xhigh" | "max" | undefined;
129
143
  excludeDynamicSystemPromptSections?: boolean | undefined;
130
144
  }, {
131
- agent?: string | undefined;
132
145
  agents?: Record<string, Record<string, unknown>> | undefined;
146
+ agent?: string | undefined;
133
147
  forkSession?: boolean | undefined;
134
148
  systemPrompt?: string | undefined;
135
149
  appendSystemPrompt?: string | undefined;
@@ -180,6 +194,17 @@ export interface ClaudeHighImpactFlagsInput {
180
194
  settingSources?: string;
181
195
  settings?: string;
182
196
  tools?: string[];
197
+ includeHookEvents?: boolean;
198
+ replayUserMessages?: boolean;
199
+ systemPromptFile?: string;
200
+ appendSystemPromptFile?: string;
201
+ name?: string;
202
+ pluginDir?: string[];
203
+ pluginUrl?: string[];
204
+ safeMode?: boolean;
205
+ bare?: boolean;
206
+ debug?: string | boolean;
207
+ debugFile?: string;
183
208
  }
184
209
  export declare function prepareClaudeHighImpactFlags(input: ClaudeHighImpactFlagsInput): string[];
185
210
  export declare const CODEX_CONFIG_OVERRIDES_SCHEMA: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodEffects<z.ZodString, string, string>>>;
@@ -200,6 +225,8 @@ export declare const CODEX_HIGH_IMPACT_PARAMS_SCHEMA: z.ZodObject<{
200
225
  images: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
201
226
  ignoreUserConfig: z.ZodOptional<z.ZodBoolean>;
202
227
  ignoreRules: z.ZodOptional<z.ZodBoolean>;
228
+ enable: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
229
+ disable: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
203
230
  }, "strip", z.ZodTypeAny, {
204
231
  search?: boolean | undefined;
205
232
  outputSchema?: string | Record<string, unknown> | undefined;
@@ -209,6 +236,8 @@ export declare const CODEX_HIGH_IMPACT_PARAMS_SCHEMA: z.ZodObject<{
209
236
  images?: string[] | undefined;
210
237
  ignoreUserConfig?: boolean | undefined;
211
238
  ignoreRules?: boolean | undefined;
239
+ enable?: string[] | undefined;
240
+ disable?: string[] | undefined;
212
241
  }, {
213
242
  search?: boolean | undefined;
214
243
  outputSchema?: string | Record<string, unknown> | undefined;
@@ -218,6 +247,8 @@ export declare const CODEX_HIGH_IMPACT_PARAMS_SCHEMA: z.ZodObject<{
218
247
  images?: string[] | undefined;
219
248
  ignoreUserConfig?: boolean | undefined;
220
249
  ignoreRules?: boolean | undefined;
250
+ enable?: string[] | undefined;
251
+ disable?: string[] | undefined;
221
252
  }>;
222
253
  export interface CodexHighImpactFlagsInput {
223
254
  outputSchema?: string | Record<string, unknown>;
@@ -228,6 +259,8 @@ export interface CodexHighImpactFlagsInput {
228
259
  images?: string[];
229
260
  ignoreUserConfig?: boolean;
230
261
  ignoreRules?: boolean;
262
+ enable?: string[];
263
+ disable?: string[];
231
264
  }
232
265
  export interface CodexHighImpactFlagsResult {
233
266
  args: string[];
@@ -176,6 +176,86 @@ export function resolveClaudePermissionFlags(input) {
176
176
  export const GEMINI_APPROVAL_MODES = ["default", "auto_edit", "yolo", "plan"];
177
177
  export const CODEX_SANDBOX_MODES = ["read-only", "workspace-write", "danger-full-access"];
178
178
  export const CODEX_ASK_FOR_APPROVAL_MODES = ["untrusted", "on-request", "never"];
179
+ export const CODEX_LOCAL_PROVIDERS = ["lmstudio", "ollama"];
180
+ export const CODEX_COLOR_MODES = ["always", "never", "auto"];
181
+ export const CLAUDE_UNEXPOSED_CLI_FLAGS = [
182
+ {
183
+ flag: "--tmux",
184
+ reason: "interactive-only",
185
+ detail: "Creates an attached tmux/iTerm2 session for a worktree (requires --worktree); incompatible with headless --print.",
186
+ },
187
+ {
188
+ flag: "--background",
189
+ reason: "gateway-managed",
190
+ detail: "Starts a detached background agent (managed via `claude agents`); conflicts with the gateway's own async-job model.",
191
+ },
192
+ {
193
+ flag: "--remote-control",
194
+ reason: "gateway-managed",
195
+ detail: "Starts an interactive Remote Control session; a stateful/remote surface deferred to the gateway-managed transport.",
196
+ },
197
+ {
198
+ flag: "--remote",
199
+ reason: "admin-deferred",
200
+ detail: "No bare --remote exists in installed Claude help; the only remote surface is --remote-control (gateway-managed).",
201
+ },
202
+ {
203
+ flag: "--worktree",
204
+ reason: "gateway-managed",
205
+ detail: "claude --help advertises -w, --worktree [name], but gateway worktrees are owned by slice λ (worktree-manager); the native --worktree is intentionally never emitted so the gateway owns the checkout lifecycle.",
206
+ },
207
+ {
208
+ flag: "--resume",
209
+ reason: "gateway-managed",
210
+ detail: "claude --help advertises -r, --resume [value] for interactive resume; the gateway session model maps continuity onto --continue (continueSession) and --session-id (sessionId), so the raw --resume passthrough is intentionally not wired.",
211
+ },
212
+ ];
213
+ export const CODEX_UNEXPOSED_CLI_FLAGS = [
214
+ {
215
+ flag: "--remote",
216
+ reason: "admin-deferred",
217
+ detail: "TUI-only (top-level `codex` help, not `codex exec`): connects the TUI to a remote app-server endpoint; not a headless exec flag.",
218
+ },
219
+ {
220
+ flag: "--remote-auth-token-env",
221
+ reason: "admin-deferred",
222
+ detail: "TUI-only companion to --remote (bearer-token env var for the remote app-server websocket); not a headless exec flag.",
223
+ },
224
+ {
225
+ flag: "--ask-for-approval",
226
+ reason: "admin-deferred",
227
+ detail: "Removed from the installed `codex exec` upstream: current codex exec no longer accepts --ask-for-approval. The askForApproval MCP input is retained for back-compat but warns and emits no argv (accepted-but-ignored); classified here because the flag is not present in the installed headless help.",
228
+ },
229
+ {
230
+ flag: "--search",
231
+ reason: "admin-deferred",
232
+ detail: "Removed from the installed `codex exec` upstream: current codex exec no longer accepts --search. The search MCP input is retained for back-compat but warns and emits no argv (accepted-but-ignored); classified here because the flag is not present in the installed headless help.",
233
+ },
234
+ ];
235
+ export const GEMINI_UNEXPOSED_CLI_FLAGS = [
236
+ {
237
+ flag: "--prompt-interactive",
238
+ reason: "interactive-only",
239
+ detail: "Runs an initial prompt then continues in an attached interactive session (short alias -i); incompatible with the headless --print run mode the gateway drives.",
240
+ },
241
+ {
242
+ flag: "--log-file",
243
+ reason: "admin-deferred",
244
+ detail: "Overrides agy's internal CLI log file path (a diagnostic/maintenance surface); the gateway flight recorder is the request-logging surface, so this is deferred to a later admin phase.",
245
+ },
246
+ ];
247
+ export const MISTRAL_UNEXPOSED_CLI_FLAGS = [
248
+ {
249
+ flag: "--setup",
250
+ reason: "admin-deferred",
251
+ detail: "Vibe `--setup` configures the API key and exits; a credential/setup maintenance op, not a headless run flag. Deferred to the phase-6 admin surface.",
252
+ },
253
+ {
254
+ flag: "--check-upgrade",
255
+ reason: "admin-deferred",
256
+ detail: "Vibe `--check-upgrade` checks for a Vibe update, prompts to install, and exits; a maintenance op, not a headless run flag. Deferred to the phase-6 admin surface.",
257
+ },
258
+ ];
179
259
  export function resolveCodexSandboxFlags(input) {
180
260
  const { sandboxMode, askForApproval, fullAuto, useLegacyFullAutoFlag } = input;
181
261
  const args = [];
@@ -324,6 +404,48 @@ export function prepareClaudeHighImpactFlags(input) {
324
404
  if (input.tools && input.tools.length > 0) {
325
405
  args.push("--tools", ...input.tools);
326
406
  }
407
+ if (input.includeHookEvents) {
408
+ args.push("--include-hook-events");
409
+ }
410
+ if (input.replayUserMessages) {
411
+ args.push("--replay-user-messages");
412
+ }
413
+ if (input.systemPromptFile !== undefined) {
414
+ args.push("--system-prompt-file", input.systemPromptFile);
415
+ }
416
+ if (input.appendSystemPromptFile !== undefined) {
417
+ args.push("--append-system-prompt-file", input.appendSystemPromptFile);
418
+ }
419
+ if (input.name !== undefined) {
420
+ args.push("--name", input.name);
421
+ }
422
+ if (input.pluginDir && input.pluginDir.length > 0) {
423
+ for (const dir of input.pluginDir) {
424
+ args.push("--plugin-dir", dir);
425
+ }
426
+ }
427
+ if (input.pluginUrl && input.pluginUrl.length > 0) {
428
+ for (const url of input.pluginUrl) {
429
+ args.push("--plugin-url", url);
430
+ }
431
+ }
432
+ if (input.safeMode) {
433
+ args.push("--safe-mode");
434
+ }
435
+ if (input.bare) {
436
+ args.push("--bare");
437
+ }
438
+ if (input.debug !== undefined && input.debug !== false) {
439
+ if (typeof input.debug === "string") {
440
+ args.push("--debug", input.debug);
441
+ }
442
+ else {
443
+ args.push("--debug");
444
+ }
445
+ }
446
+ if (input.debugFile !== undefined) {
447
+ args.push("--debug-file", input.debugFile);
448
+ }
327
449
  return args;
328
450
  }
329
451
  export const CODEX_CONFIG_OVERRIDES_SCHEMA = z
@@ -382,6 +504,8 @@ export const CODEX_HIGH_IMPACT_PARAMS_SCHEMA = z.object({
382
504
  images: z.array(z.string()).optional(),
383
505
  ignoreUserConfig: z.boolean().optional(),
384
506
  ignoreRules: z.boolean().optional(),
507
+ enable: z.array(z.string()).optional(),
508
+ disable: z.array(z.string()).optional(),
385
509
  });
386
510
  export function prepareCodexHighImpactFlags(input) {
387
511
  const missingImagePath = findMissingImagePath(input.images);
@@ -417,6 +541,16 @@ export function prepareCodexHighImpactFlags(input) {
417
541
  if (input.ignoreRules) {
418
542
  args.push("--ignore-rules");
419
543
  }
544
+ if (input.enable && input.enable.length > 0) {
545
+ for (const feature of input.enable) {
546
+ args.push("--enable", feature);
547
+ }
548
+ }
549
+ if (input.disable && input.disable.length > 0) {
550
+ for (const feature of input.disable) {
551
+ args.push("--disable", feature);
552
+ }
553
+ }
420
554
  return {
421
555
  args,
422
556
  cleanup,
@@ -1,8 +1,11 @@
1
1
  import { ISessionManager } from "./session-manager.js";
2
+ import { type CliType } from "./session-manager.js";
2
3
  import { PerformanceMetrics } from "./metrics.js";
3
4
  import { FlightRecorderQuery } from "./flight-recorder.js";
4
5
  import { type GlobalCacheStats, type PrefixCacheStats, type SessionCacheStats } from "./cache-stats.js";
5
6
  import { type CacheAwarenessConfig, type ProvidersConfig } from "./config.js";
7
+ import type { AcpConfig } from "./config.js";
8
+ import { type ResolvedProviderCapability } from "./provider-capability-resolver.js";
6
9
  export interface ResourceDefinition {
7
10
  uri: string;
8
11
  name: string;
@@ -26,7 +29,9 @@ export declare class ResourceProvider {
26
29
  private flightRecorder;
27
30
  private cacheAwareness;
28
31
  private providers;
29
- constructor(sessionManager: ISessionManager, performanceMetrics: PerformanceMetrics, flightRecorder?: FlightRecorderQuery, cacheAwareness?: CacheAwarenessConfig | null, providers?: ProvidersConfig | null);
32
+ private capabilityPeek;
33
+ private acpConfig;
34
+ constructor(sessionManager: ISessionManager, performanceMetrics: PerformanceMetrics, flightRecorder?: FlightRecorderQuery, cacheAwareness?: CacheAwarenessConfig | null, providers?: ProvidersConfig | null, capabilityPeek?: (id: CliType) => ResolvedProviderCapability | null, acpConfig?: AcpConfig | null);
30
35
  getFlightRecorderQuery(): FlightRecorderQuery;
31
36
  private apiRuntimes;
32
37
  private continuityTrackedApiRuntimes;
package/dist/resources.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { callerIsRemote, remoteSafeSession, } from "./session-manager.js";
1
2
  import { CLI_TYPES, PROVIDER_TYPES } from "./session-manager.js";
2
3
  import { getRequestContext, principalCanAccess, resolveOwnerPrincipal } from "./request-context.js";
3
4
  import { getAvailableCliInfo } from "./model-registry.js";
@@ -7,18 +8,26 @@ import { apiContinuityForKind } from "./api-provider.js";
7
8
  import { apiProviderCatalogEntry } from "./api-request.js";
8
9
  import { buildProviderSubcommandsCompactCatalog, getCliSubcommandContract, serializeCliSubcommandContract, } from "./upstream-contracts.js";
9
10
  import { getOneProviderToolCapabilities, getProviderToolCapabilities, knownProviderCapabilityIds, providerCapabilityIds, } from "./provider-tool-capabilities.js";
11
+ import { generateProviderAcpDescriptors, generateResourceDescriptors, parseModelsResourceUri, parseProviderAcpResourceUri, parseSessionsResourceUri, } from "./provider-surface-generator.js";
12
+ import { getProviderDefinition } from "./provider-definitions.js";
13
+ import { buildProviderAcpCapabilityRecord } from "./provider-acp-capabilities.js";
14
+ import { buildProviderDiscoveredView, peekProviderCapabilitySet, } from "./provider-capability-resolver.js";
10
15
  export class ResourceProvider {
11
16
  sessionManager;
12
17
  performanceMetrics;
13
18
  flightRecorder;
14
19
  cacheAwareness;
15
20
  providers;
16
- constructor(sessionManager, performanceMetrics, flightRecorder = { queryRequests: () => [] }, cacheAwareness = null, providers = null) {
21
+ capabilityPeek;
22
+ acpConfig;
23
+ constructor(sessionManager, performanceMetrics, flightRecorder = { queryRequests: () => [] }, cacheAwareness = null, providers = null, capabilityPeek = peekProviderCapabilitySet, acpConfig = null) {
17
24
  this.sessionManager = sessionManager;
18
25
  this.performanceMetrics = performanceMetrics;
19
26
  this.flightRecorder = flightRecorder;
20
27
  this.cacheAwareness = cacheAwareness;
21
28
  this.providers = providers;
29
+ this.capabilityPeek = capabilityPeek;
30
+ this.acpConfig = acpConfig;
22
31
  }
23
32
  getFlightRecorderQuery() {
24
33
  return this.flightRecorder;
@@ -60,61 +69,19 @@ export class ResourceProvider {
60
69
  lastModified: new Date().toISOString(),
61
70
  },
62
71
  },
63
- {
64
- uri: "sessions://claude",
65
- name: "Claude Sessions",
66
- title: "🤖 Claude Sessions",
67
- description: "List of Claude conversation sessions",
68
- mimeType: "application/json",
69
- annotations: {
70
- audience: ["user", "assistant"],
71
- priority: 0.6,
72
- },
73
- },
74
- {
75
- uri: "sessions://codex",
76
- name: "Codex Sessions",
77
- title: "💻 Codex Sessions",
78
- description: "List of Codex conversation sessions",
79
- mimeType: "application/json",
80
- annotations: {
81
- audience: ["user", "assistant"],
82
- priority: 0.6,
83
- },
84
- },
85
- {
86
- uri: "sessions://gemini",
87
- name: "Gemini Sessions",
88
- title: "✨ Gemini Sessions",
89
- description: "List of Gemini conversation sessions",
90
- mimeType: "application/json",
91
- annotations: {
92
- audience: ["user", "assistant"],
93
- priority: 0.6,
94
- },
95
- },
96
- {
97
- uri: "sessions://grok",
98
- name: "Grok Sessions",
99
- title: "⚡ Grok Sessions",
100
- description: "List of Grok conversation sessions",
72
+ ...generateResourceDescriptors()
73
+ .filter(descriptor => descriptor.exposesSessionsResource)
74
+ .map(descriptor => ({
75
+ uri: descriptor.sessionsUri,
76
+ name: `${descriptor.sessionLabel}s`,
77
+ title: `${descriptor.icon} ${descriptor.sessionLabel}s`,
78
+ description: `List of ${descriptor.displayName} conversation sessions`,
101
79
  mimeType: "application/json",
102
80
  annotations: {
103
81
  audience: ["user", "assistant"],
104
82
  priority: 0.6,
105
83
  },
106
- },
107
- {
108
- uri: "sessions://mistral",
109
- name: "Mistral Sessions",
110
- title: "🌬 Mistral Sessions",
111
- description: "List of Mistral Vibe conversation sessions",
112
- mimeType: "application/json",
113
- annotations: {
114
- audience: ["user", "assistant"],
115
- priority: 0.6,
116
- },
117
- },
84
+ })),
118
85
  ...this.continuityTrackedApiRuntimes().map(rt => ({
119
86
  uri: `sessions://${rt.name}`,
120
87
  name: `${rt.name} Sessions`,
@@ -126,61 +93,19 @@ export class ResourceProvider {
126
93
  priority: 0.6,
127
94
  },
128
95
  })),
129
- {
130
- uri: "models://claude",
131
- name: "Claude Models",
132
- title: "🧠 Claude Models & Capabilities",
133
- description: "Available Claude models and their capabilities",
134
- mimeType: "application/json",
135
- annotations: {
136
- audience: ["user", "assistant"],
137
- priority: 0.8,
138
- },
139
- },
140
- {
141
- uri: "models://codex",
142
- name: "Codex Models",
143
- title: "🔧 Codex Models & Capabilities",
144
- description: "Available Codex models and their capabilities",
145
- mimeType: "application/json",
146
- annotations: {
147
- audience: ["user", "assistant"],
148
- priority: 0.8,
149
- },
150
- },
151
- {
152
- uri: "models://gemini",
153
- name: "Gemini Models",
154
- title: "🌟 Gemini Models & Capabilities",
155
- description: "Available Gemini models and their capabilities",
156
- mimeType: "application/json",
157
- annotations: {
158
- audience: ["user", "assistant"],
159
- priority: 0.8,
160
- },
161
- },
162
- {
163
- uri: "models://grok",
164
- name: "Grok Models",
165
- title: "⚡ Grok Models & Capabilities",
166
- description: "Available Grok models and their capabilities",
167
- mimeType: "application/json",
168
- annotations: {
169
- audience: ["user", "assistant"],
170
- priority: 0.8,
171
- },
172
- },
173
- {
174
- uri: "models://mistral",
175
- name: "Mistral Models",
176
- title: "🌬 Mistral Models & Capabilities",
177
- description: "Available Mistral Vibe models and their capabilities",
96
+ ...generateResourceDescriptors()
97
+ .filter(descriptor => descriptor.exposesModelsResource)
98
+ .map(descriptor => ({
99
+ uri: descriptor.modelsUri,
100
+ name: `${descriptor.displayName} Models`,
101
+ title: `${descriptor.icon} ${descriptor.displayName} Models & Capabilities`,
102
+ description: `Available ${descriptor.displayName} models and their capabilities`,
178
103
  mimeType: "application/json",
179
104
  annotations: {
180
105
  audience: ["user", "assistant"],
181
106
  priority: 0.8,
182
107
  },
183
- },
108
+ })),
184
109
  ...this.apiRuntimes().map(rt => ({
185
110
  uri: `models://${rt.name}`,
186
111
  name: `${rt.name} Models`,
@@ -236,11 +161,23 @@ export class ResourceProvider {
236
161
  priority: 0.8,
237
162
  },
238
163
  })),
164
+ ...generateProviderAcpDescriptors().map(descriptor => ({
165
+ uri: descriptor.acpUri,
166
+ name: `${descriptor.displayName} ACP Capabilities`,
167
+ title: `${descriptor.icon} ${descriptor.displayName} ACP Capabilities`,
168
+ description: `Native ACP entrypoint, negotiated capabilities, supported session methods, and host-service policy for ${descriptor.displayName}`,
169
+ mimeType: "application/json",
170
+ annotations: {
171
+ audience: ["user", "assistant"],
172
+ priority: 0.7,
173
+ },
174
+ })),
239
175
  ];
240
176
  }
241
177
  ownedSessions(sessions) {
242
178
  const caller = resolveOwnerPrincipal(getRequestContext());
243
- return sessions.filter(s => principalCanAccess(s.ownerPrincipal, caller));
179
+ const owned = sessions.filter(s => principalCanAccess(s.ownerPrincipal, caller));
180
+ return callerIsRemote() ? owned.map(remoteSafeSession) : owned;
244
181
  }
245
182
  async ownedActiveId(provider) {
246
183
  const active = await Promise.resolve(this.sessionManager.getActiveSession(provider));
@@ -269,109 +206,28 @@ export class ResourceProvider {
269
206
  }, null, 2),
270
207
  };
271
208
  }
272
- if (uri === "sessions://claude") {
273
- const sessions = this.ownedSessions(await this.sessionManager.listSessions("claude"));
209
+ const sessionProvider = parseSessionsResourceUri(uri);
210
+ if (sessionProvider) {
211
+ const sessions = this.ownedSessions(await this.sessionManager.listSessions(sessionProvider));
274
212
  return {
275
213
  uri,
276
214
  mimeType: "application/json",
277
215
  text: JSON.stringify({
278
- cli: "claude",
216
+ cli: sessionProvider,
279
217
  total: sessions.length,
280
218
  sessions,
281
- activeSession: await this.ownedActiveId("claude"),
219
+ activeSession: await this.ownedActiveId(sessionProvider),
282
220
  }, null, 2),
283
221
  };
284
222
  }
285
- if (uri === "sessions://codex") {
286
- const sessions = this.ownedSessions(await this.sessionManager.listSessions("codex"));
287
- return {
288
- uri,
289
- mimeType: "application/json",
290
- text: JSON.stringify({
291
- cli: "codex",
292
- total: sessions.length,
293
- sessions,
294
- activeSession: await this.ownedActiveId("codex"),
295
- }, null, 2),
296
- };
297
- }
298
- if (uri === "sessions://gemini") {
299
- const sessions = this.ownedSessions(await this.sessionManager.listSessions("gemini"));
300
- return {
301
- uri,
302
- mimeType: "application/json",
303
- text: JSON.stringify({
304
- cli: "gemini",
305
- total: sessions.length,
306
- sessions,
307
- activeSession: await this.ownedActiveId("gemini"),
308
- }, null, 2),
309
- };
310
- }
311
- if (uri === "sessions://grok") {
312
- const sessions = this.ownedSessions(await this.sessionManager.listSessions("grok"));
313
- return {
314
- uri,
315
- mimeType: "application/json",
316
- text: JSON.stringify({
317
- cli: "grok",
318
- total: sessions.length,
319
- sessions,
320
- activeSession: await this.ownedActiveId("grok"),
321
- }, null, 2),
322
- };
323
- }
324
- if (uri === "sessions://mistral") {
325
- const sessions = this.ownedSessions(await this.sessionManager.listSessions("mistral"));
326
- return {
327
- uri,
328
- mimeType: "application/json",
329
- text: JSON.stringify({
330
- cli: "mistral",
331
- total: sessions.length,
332
- sessions,
333
- activeSession: await this.ownedActiveId("mistral"),
334
- }, null, 2),
335
- };
336
- }
337
- if (uri === "models://claude") {
223
+ const modelProvider = parseModelsResourceUri(uri);
224
+ if (modelProvider) {
338
225
  const cliInfo = getAvailableCliInfo();
226
+ const discovered = buildProviderDiscoveredView(getProviderDefinition(modelProvider), cliInfo[modelProvider], this.capabilityPeek);
339
227
  return {
340
228
  uri,
341
229
  mimeType: "application/json",
342
- text: JSON.stringify(cliInfo.claude, null, 2),
343
- };
344
- }
345
- if (uri === "models://codex") {
346
- const cliInfo = getAvailableCliInfo();
347
- return {
348
- uri,
349
- mimeType: "application/json",
350
- text: JSON.stringify(cliInfo.codex, null, 2),
351
- };
352
- }
353
- if (uri === "models://gemini") {
354
- const cliInfo = getAvailableCliInfo();
355
- return {
356
- uri,
357
- mimeType: "application/json",
358
- text: JSON.stringify(cliInfo.gemini, null, 2),
359
- };
360
- }
361
- if (uri === "models://grok") {
362
- const cliInfo = getAvailableCliInfo();
363
- return {
364
- uri,
365
- mimeType: "application/json",
366
- text: JSON.stringify(cliInfo.grok, null, 2),
367
- };
368
- }
369
- if (uri === "models://mistral") {
370
- const cliInfo = getAvailableCliInfo();
371
- return {
372
- uri,
373
- mimeType: "application/json",
374
- text: JSON.stringify(cliInfo.mistral, null, 2),
230
+ text: JSON.stringify({ ...cliInfo[modelProvider], discovered }, null, 2),
375
231
  };
376
232
  }
377
233
  if (uri.startsWith("models://")) {
@@ -418,7 +274,10 @@ export class ResourceProvider {
418
274
  return {
419
275
  uri,
420
276
  mimeType: "application/json",
421
- text: JSON.stringify(getProviderToolCapabilities({ providersConfig: this.providers ?? undefined }), null, 2),
277
+ text: JSON.stringify(getProviderToolCapabilities({
278
+ providersConfig: this.providers ?? undefined,
279
+ acpConfig: this.acpConfig ?? undefined,
280
+ }), null, 2),
422
281
  };
423
282
  }
424
283
  const providerToolsResource = parseProviderToolsUri(uri, this.providerCapabilityIds());
@@ -428,9 +287,24 @@ export class ResourceProvider {
428
287
  mimeType: "application/json",
429
288
  text: JSON.stringify(getOneProviderToolCapabilities(providerToolsResource.provider, {
430
289
  providersConfig: this.providers ?? undefined,
290
+ acpConfig: this.acpConfig ?? undefined,
431
291
  }), null, 2),
432
292
  };
433
293
  }
294
+ const acpProvider = parseProviderAcpResourceUri(uri);
295
+ if (acpProvider) {
296
+ const resolved = this.capabilityPeek(acpProvider);
297
+ const record = buildProviderAcpCapabilityRecord(acpProvider, {
298
+ discovered: resolved?.set.acpInitialize ?? null,
299
+ discoveredDegraded: resolved?.degraded ?? false,
300
+ acpConfig: this.acpConfig,
301
+ });
302
+ return {
303
+ uri,
304
+ mimeType: "application/json",
305
+ text: JSON.stringify(record, null, 2),
306
+ };
307
+ }
434
308
  const subcommandResource = parseProviderSubcommandUri(uri);
435
309
  if (subcommandResource) {
436
310
  const contract = getCliSubcommandContract(subcommandResource.provider, subcommandResource.commandPath);
@@ -23,6 +23,8 @@ export interface SessionStorage {
23
23
  sessions: Record<string, Session>;
24
24
  activeSession: Record<ProviderType, string | null>;
25
25
  }
26
+ export declare function remoteSafeSession(session: Session): Session;
27
+ export declare function callerIsRemote(): boolean;
26
28
  export type SessionCleanupHook = (session: Session) => void | Promise<void>;
27
29
  export declare class FileSessionManager {
28
30
  private storagePath;