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
@@ -0,0 +1,98 @@
1
+ import type { CliType } from "./provider-types.js";
2
+ import { type AdminSafetyClass, type AdminSurfaceKind, type ProviderDefinition } from "./provider-definitions.js";
3
+ export declare function modelsResourceUri(id: CliType): string;
4
+ export declare function sessionsResourceUri(id: CliType): string;
5
+ export declare function providerAcpResourceUri(id: CliType): string;
6
+ export interface RequestToolDescriptor {
7
+ readonly provider: CliType;
8
+ readonly displayName: string;
9
+ readonly syncToolName: string;
10
+ readonly asyncToolName: string;
11
+ readonly transport: string;
12
+ readonly acpCapable: boolean;
13
+ }
14
+ export interface ResourceDescriptor {
15
+ readonly provider: CliType;
16
+ readonly displayName: string;
17
+ readonly sessionLabel: string;
18
+ readonly icon: string;
19
+ readonly modelsUri: string;
20
+ readonly sessionsUri: string;
21
+ readonly exposesModelsResource: boolean;
22
+ readonly exposesSessionsResource: boolean;
23
+ }
24
+ export interface ModelListingRow {
25
+ readonly provider: CliType;
26
+ readonly displayName: string;
27
+ readonly strategy: string;
28
+ readonly discoveryArgv: readonly string[];
29
+ readonly evidence: string;
30
+ }
31
+ export interface SessionListingRow {
32
+ readonly provider: CliType;
33
+ readonly sessionLabel: string;
34
+ readonly resourceUri: string;
35
+ readonly continue: boolean;
36
+ readonly resume: boolean;
37
+ readonly fork: boolean;
38
+ readonly sessionIdSelection: boolean;
39
+ }
40
+ export interface ProviderCapabilityRow {
41
+ readonly provider: CliType;
42
+ readonly displayName: string;
43
+ readonly executables: readonly string[];
44
+ readonly transport: string;
45
+ readonly acpClassification: string;
46
+ readonly sandbox: boolean;
47
+ readonly permissionMode: boolean;
48
+ readonly approvalMode: boolean;
49
+ readonly trust: boolean;
50
+ readonly outputFormats: readonly string[];
51
+ readonly streamingFormats: readonly string[];
52
+ readonly capabilityScope: string;
53
+ }
54
+ export interface AdminToolDescriptor {
55
+ readonly provider: CliType;
56
+ readonly displayName: string;
57
+ readonly families: readonly {
58
+ readonly family: string;
59
+ readonly safety: AdminSafetyClass;
60
+ readonly kind: AdminSurfaceKind;
61
+ readonly readOnly: boolean;
62
+ readonly invokableSubcommand: boolean;
63
+ readonly evidence: string;
64
+ }[];
65
+ }
66
+ export interface UpstreamContractRow {
67
+ readonly provider: CliType;
68
+ readonly targetVersion: string;
69
+ readonly helpChecksumRef: string | null;
70
+ readonly acpClassification: string;
71
+ readonly nativeEntrypoint: string | null;
72
+ }
73
+ export interface DocsSummaryRow {
74
+ readonly provider: CliType;
75
+ readonly displayName: string;
76
+ readonly primaryDocs: readonly string[];
77
+ readonly capabilityScope: string;
78
+ }
79
+ export declare function generateProviderIdListing(defs?: readonly ProviderDefinition[]): readonly CliType[];
80
+ export declare function generateRequestToolDescriptors(defs?: readonly ProviderDefinition[]): readonly RequestToolDescriptor[];
81
+ export declare function generateResourceDescriptors(defs?: readonly ProviderDefinition[]): readonly ResourceDescriptor[];
82
+ export declare function parseModelsResourceUri(uri: string, defs?: readonly ProviderDefinition[]): CliType | null;
83
+ export declare function parseSessionsResourceUri(uri: string, defs?: readonly ProviderDefinition[]): CliType | null;
84
+ export interface ProviderAcpDescriptor {
85
+ readonly provider: CliType;
86
+ readonly displayName: string;
87
+ readonly icon: string;
88
+ readonly acpUri: string;
89
+ readonly nativeAcp: boolean;
90
+ }
91
+ export declare function generateProviderAcpDescriptors(defs?: readonly ProviderDefinition[]): readonly ProviderAcpDescriptor[];
92
+ export declare function parseProviderAcpResourceUri(uri: string, defs?: readonly ProviderDefinition[]): CliType | null;
93
+ export declare function generateModelListingRows(defs?: readonly ProviderDefinition[]): readonly ModelListingRow[];
94
+ export declare function generateSessionListingRows(defs?: readonly ProviderDefinition[]): readonly SessionListingRow[];
95
+ export declare function generateProviderCapabilityRows(defs?: readonly ProviderDefinition[]): readonly ProviderCapabilityRow[];
96
+ export declare function generateAdminToolDescriptors(defs?: readonly ProviderDefinition[]): readonly AdminToolDescriptor[];
97
+ export declare function generateUpstreamContractRows(defs?: readonly ProviderDefinition[]): readonly UpstreamContractRow[];
98
+ export declare function generateDocsSummaryRows(defs?: readonly ProviderDefinition[]): readonly DocsSummaryRow[];
@@ -0,0 +1,140 @@
1
+ import { adminSurfaceKind, getAllProviderDefinitions, } from "./provider-definitions.js";
2
+ export function modelsResourceUri(id) {
3
+ return `models://${id}`;
4
+ }
5
+ export function sessionsResourceUri(id) {
6
+ return `sessions://${id}`;
7
+ }
8
+ export function providerAcpResourceUri(id) {
9
+ return `provider-acp://${id}`;
10
+ }
11
+ export function generateProviderIdListing(defs = getAllProviderDefinitions()) {
12
+ return defs.map(def => def.id);
13
+ }
14
+ export function generateRequestToolDescriptors(defs = getAllProviderDefinitions()) {
15
+ return defs.map(def => ({
16
+ provider: def.id,
17
+ displayName: def.displayName,
18
+ syncToolName: def.requestSurface.syncToolName,
19
+ asyncToolName: def.requestSurface.asyncToolName,
20
+ transport: def.requestSurface.transport,
21
+ acpCapable: def.requestSurface.acpCapable,
22
+ }));
23
+ }
24
+ export function generateResourceDescriptors(defs = getAllProviderDefinitions()) {
25
+ return defs.map(def => ({
26
+ provider: def.id,
27
+ displayName: def.displayName,
28
+ sessionLabel: def.sessionLabel,
29
+ icon: def.icon,
30
+ modelsUri: modelsResourceUri(def.id),
31
+ sessionsUri: sessionsResourceUri(def.id),
32
+ exposesModelsResource: def.resourcePolicy.exposesModelsResource,
33
+ exposesSessionsResource: def.resourcePolicy.exposesSessionsResource,
34
+ }));
35
+ }
36
+ export function parseModelsResourceUri(uri, defs = getAllProviderDefinitions()) {
37
+ for (const def of defs) {
38
+ if (def.resourcePolicy.exposesModelsResource && modelsResourceUri(def.id) === uri) {
39
+ return def.id;
40
+ }
41
+ }
42
+ return null;
43
+ }
44
+ export function parseSessionsResourceUri(uri, defs = getAllProviderDefinitions()) {
45
+ for (const def of defs) {
46
+ if (def.resourcePolicy.exposesSessionsResource && sessionsResourceUri(def.id) === uri) {
47
+ return def.id;
48
+ }
49
+ }
50
+ return null;
51
+ }
52
+ export function generateProviderAcpDescriptors(defs = getAllProviderDefinitions()) {
53
+ return defs
54
+ .filter(def => def.acp.classification === "native")
55
+ .map(def => ({
56
+ provider: def.id,
57
+ displayName: def.displayName,
58
+ icon: def.icon,
59
+ acpUri: providerAcpResourceUri(def.id),
60
+ nativeAcp: true,
61
+ }));
62
+ }
63
+ export function parseProviderAcpResourceUri(uri, defs = getAllProviderDefinitions()) {
64
+ for (const def of defs) {
65
+ if (providerAcpResourceUri(def.id) === uri) {
66
+ return def.id;
67
+ }
68
+ }
69
+ return null;
70
+ }
71
+ export function generateModelListingRows(defs = getAllProviderDefinitions()) {
72
+ return defs.map(def => ({
73
+ provider: def.id,
74
+ displayName: def.displayName,
75
+ strategy: def.discovery.modelDiscovery.strategy,
76
+ discoveryArgv: def.discovery.modelDiscovery.argv,
77
+ evidence: def.discovery.modelDiscovery.evidence,
78
+ }));
79
+ }
80
+ export function generateSessionListingRows(defs = getAllProviderDefinitions()) {
81
+ return defs.map(def => ({
82
+ provider: def.id,
83
+ sessionLabel: def.sessionLabel,
84
+ resourceUri: sessionsResourceUri(def.id),
85
+ continue: def.discovery.sessionContinuity.continue,
86
+ resume: def.discovery.sessionContinuity.resume,
87
+ fork: def.discovery.sessionContinuity.fork,
88
+ sessionIdSelection: def.discovery.sessionContinuity.sessionIdSelection,
89
+ }));
90
+ }
91
+ export function generateProviderCapabilityRows(defs = getAllProviderDefinitions()) {
92
+ return defs.map(def => ({
93
+ provider: def.id,
94
+ displayName: def.displayName,
95
+ executables: def.executables,
96
+ transport: def.requestSurface.transport,
97
+ acpClassification: def.acp.classification,
98
+ sandbox: def.safetyModes.sandbox,
99
+ permissionMode: def.safetyModes.permissionMode,
100
+ approvalMode: def.safetyModes.approvalMode,
101
+ trust: def.safetyModes.trust,
102
+ outputFormats: def.outputFormats,
103
+ streamingFormats: def.streamingFormats,
104
+ capabilityScope: def.capabilityScope,
105
+ }));
106
+ }
107
+ export function generateAdminToolDescriptors(defs = getAllProviderDefinitions()) {
108
+ return defs.map(def => ({
109
+ provider: def.id,
110
+ displayName: def.displayName,
111
+ families: def.adminSubcommands.map(family => {
112
+ const kind = adminSurfaceKind(family);
113
+ return {
114
+ family: family.family,
115
+ safety: family.safety,
116
+ kind,
117
+ readOnly: family.safety === "read-only",
118
+ invokableSubcommand: kind === "cli-subcommand",
119
+ evidence: family.evidence,
120
+ };
121
+ }),
122
+ }));
123
+ }
124
+ export function generateUpstreamContractRows(defs = getAllProviderDefinitions()) {
125
+ return defs.map(def => ({
126
+ provider: def.id,
127
+ targetVersion: def.upstreamContract.targetVersion,
128
+ helpChecksumRef: def.upstreamContract.helpChecksumRef,
129
+ acpClassification: def.acp.classification,
130
+ nativeEntrypoint: def.acp.nativeEntrypoint,
131
+ }));
132
+ }
133
+ export function generateDocsSummaryRows(defs = getAllProviderDefinitions()) {
134
+ return defs.map(def => ({
135
+ provider: def.id,
136
+ displayName: def.displayName,
137
+ primaryDocs: def.docs.primary,
138
+ capabilityScope: def.capabilityScope,
139
+ }));
140
+ }
@@ -1,6 +1,6 @@
1
1
  import { type CliInfo } from "./model-registry.js";
2
- import { type CliType } from "./session-manager.js";
3
- import { type ProvidersConfig } from "./config.js";
2
+ import { type CliType } from "./provider-definitions.js";
3
+ import { type AcpConfig, type ProvidersConfig } from "./config.js";
4
4
  export interface ProviderToolControl {
5
5
  name?: string;
6
6
  supported: boolean;
@@ -130,6 +130,7 @@ export interface ProviderCapabilityQuery {
130
130
  includePaths?: boolean;
131
131
  refresh?: boolean;
132
132
  providersConfig?: ProvidersConfig;
133
+ acpConfig?: AcpConfig;
133
134
  }
134
135
  export type ProviderToolCapabilitiesMap = Partial<Record<ProviderCapabilityId, ProviderToolCapabilities>>;
135
136
  export declare function getProviderToolCapabilities(queryOrCli?: ProviderCapabilityQuery | ProviderCapabilityId): ProviderToolCapabilitiesMap;
@@ -4,7 +4,7 @@ import path from "path";
4
4
  import { parse as parseToml } from "smol-toml";
5
5
  import { CLAUDE_MCP_SERVER_NAMES } from "./claude-mcp-config.js";
6
6
  import { getAvailableCliInfo } from "./model-registry.js";
7
- import { CLI_TYPES } from "./session-manager.js";
7
+ import { CLI_TYPES, getProviderDefinition } from "./provider-definitions.js";
8
8
  import { enabledApiProviders, isXaiProviderEnabled, loadProvidersConfig, } from "./config.js";
9
9
  import { apiContinuityForKind } from "./api-provider.js";
10
10
  const MAX_SKILLS_PER_DIR = 100;
@@ -34,11 +34,11 @@ export const ACP_CONTRACT = {
34
34
  providers: {
35
35
  mistral: {
36
36
  classification: "native_candidate",
37
- summary: "Mistral Vibe exposes native ACP via vibe-acp; first runtime pilot candidate.",
37
+ summary: "Mistral Vibe exposes native ACP via vibe-acp; runtime routing is live but config-gated.",
38
38
  },
39
39
  grok: {
40
40
  classification: "native_candidate",
41
- summary: "xAI Grok CLI exposes native ACP via grok agent stdio; second runtime pilot candidate.",
41
+ summary: "xAI Grok CLI exposes native ACP via grok agent stdio; runtime routing is live but config-gated.",
42
42
  },
43
43
  codex: {
44
44
  classification: "adapter_mediated_deferred",
@@ -50,7 +50,7 @@ export const ACP_CONTRACT = {
50
50
  },
51
51
  gemini: {
52
52
  classification: "absent_watchlist",
53
- summary: "Google Antigravity agy 1.0.13 has no ACP surface; watchlist item only.",
53
+ summary: "Google Antigravity agy 1.0.14 has no ACP surface; watchlist item only.",
54
54
  },
55
55
  grok_api: {
56
56
  classification: "absent_watchlist",
@@ -58,7 +58,7 @@ export const ACP_CONTRACT = {
58
58
  },
59
59
  devin: {
60
60
  classification: "native_candidate",
61
- summary: "Cognition Devin CLI exposes a native ACP server via `devin acp` (stdio); Slice D1 initialize + session/new smoke passed (protocolVersion 1, third runtime pilot). Runtime routing stays config-gated.",
61
+ summary: "Cognition Devin CLI exposes a native ACP server via `devin acp` (stdio); Slice D1 initialize + session/new smoke passed (protocolVersion 1). Runtime routing is live but config-gated.",
62
62
  },
63
63
  cursor: {
64
64
  classification: "native_candidate",
@@ -67,126 +67,128 @@ export const ACP_CONTRACT = {
67
67
  },
68
68
  };
69
69
  const ACP_DOCS_REFERENCE = "docs/plans/first-class-acp-gateway-extension.dag.toml";
70
- const ACP_CAPABILITIES = {
70
+ const ACP_RUNTIME_GATE_CAVEAT = "Native ACP runtime routing is config-gated: it is live only when `[acp].enabled` " +
71
+ "plus this provider's `enabled` and `runtime_enabled` are all set; otherwise " +
72
+ 'transport:"acp" requests fail closed and default requests use the CLI transport.';
73
+ const ACP_RESIDUAL = {
71
74
  mistral: {
72
75
  status: "native_smoke_passed",
73
- mediation: "native",
74
- targetVersion: "vibe 2.17.1",
75
- entrypoint: { command: "vibe-acp", args: [] },
76
- runtimeEnabled: false,
77
76
  smokeSupported: true,
78
77
  smokeStatus: "passed",
79
- caveats: [
80
- "Native ACP via the provider-scoped vibe-acp executable; first runtime pilot.",
81
- "Runtime routing stays disabled until ACP is enabled in gateway config.",
82
- ],
83
- docs: ACP_DOCS_REFERENCE,
78
+ caveats: ["Native ACP via the provider-scoped vibe-acp executable.", ACP_RUNTIME_GATE_CAVEAT],
84
79
  },
85
80
  grok: {
86
81
  status: "native_smoke_passed",
87
- mediation: "native",
88
- targetVersion: "grok 0.2.73 (9ff14c43bb)",
89
- entrypoint: { command: "grok", args: ["agent", "stdio"] },
90
- runtimeEnabled: false,
91
82
  smokeSupported: true,
92
83
  smokeStatus: "passed",
93
84
  caveats: [
94
- "Native ACP via grok agent stdio; second runtime pilot.",
85
+ "Native ACP via grok agent stdio.",
95
86
  "Credential lookup is owned by the installed CLI; empty-env smoke is not expected to pass.",
96
- "Runtime routing stays disabled until ACP is enabled in gateway config.",
87
+ ACP_RUNTIME_GATE_CAVEAT,
97
88
  ],
98
- docs: ACP_DOCS_REFERENCE,
99
89
  },
100
90
  codex: {
101
91
  status: "adapter_mediated_deferred",
102
- mediation: "adapter_mediated",
103
- targetVersion: "codex-cli 0.142.4",
104
- entrypoint: null,
105
- runtimeEnabled: false,
106
92
  smokeSupported: false,
107
93
  smokeStatus: "unsupported",
108
94
  caveats: [
109
95
  "No native ACP entrypoint at the target version; ACP would be adapter-mediated.",
110
96
  "Adapter support requires a separate threat model and is never labelled native gateway ACP support.",
111
97
  ],
112
- docs: ACP_DOCS_REFERENCE,
113
98
  },
114
99
  claude: {
115
100
  status: "adapter_mediated_deferred",
116
- mediation: "adapter_mediated",
117
- targetVersion: "claude 2.1.195",
118
- entrypoint: null,
119
- runtimeEnabled: false,
120
101
  smokeSupported: false,
121
102
  smokeStatus: "unsupported",
122
103
  caveats: [
123
104
  "No native Claude Code CLI ACP entrypoint at the target version; ACP would be adapter-mediated.",
124
105
  "Adapter ownership, permission bridging, and install story must be specified before runtime support.",
125
106
  ],
126
- docs: ACP_DOCS_REFERENCE,
127
107
  },
128
108
  gemini: {
129
109
  status: "absent_watchlist",
130
- mediation: "none",
131
- targetVersion: "agy 1.0.13",
132
- entrypoint: null,
133
- runtimeEnabled: false,
134
110
  smokeSupported: false,
135
111
  smokeStatus: "unsupported",
136
112
  caveats: [
137
- "Antigravity agy 1.0.13 has no ACP flag or subcommand.",
113
+ "Antigravity agy 1.0.14 has no ACP flag or subcommand.",
138
114
  "Legacy Gemini CLI ACP evidence does not transfer to agy; kept on the upstream drift watchlist.",
139
115
  ],
140
- docs: ACP_DOCS_REFERENCE,
141
116
  },
142
117
  grok_api: {
143
118
  status: "not_applicable",
144
- mediation: "none",
145
- targetVersion: "xAI Responses API",
146
- entrypoint: null,
147
- runtimeEnabled: false,
148
119
  smokeSupported: false,
149
120
  smokeStatus: "unsupported",
150
121
  caveats: ["ACP is a CLI-stdio transport; the HTTP API provider has no ACP surface."],
151
- docs: ACP_DOCS_REFERENCE,
152
122
  },
153
123
  devin: {
154
124
  status: "native_smoke_passed",
155
- mediation: "native",
156
- targetVersion: "devin 2026.8.18 (16737566)",
157
- entrypoint: { command: "devin", args: ["acp"] },
158
- runtimeEnabled: false,
159
125
  smokeSupported: true,
160
126
  smokeStatus: "passed",
161
127
  caveats: [
162
128
  'Native ACP via `devin acp` (stdio JSON-RPC); Slice D1 initialize + session/new smoke passed (protocolVersion 1, agent "Affogato").',
163
129
  "Credentials come from `devin auth login` or WINDSURF_API_KEY; empty-env smoke is not expected to pass.",
164
- "Runtime routing stays disabled until ACP is enabled in gateway config.",
130
+ ACP_RUNTIME_GATE_CAVEAT,
165
131
  ],
166
- docs: ACP_DOCS_REFERENCE,
167
132
  },
168
133
  cursor: {
169
134
  status: "native_smoke_passed",
170
- mediation: "native",
171
- targetVersion: "cursor-agent 2026.06.29-2ad2186",
172
- entrypoint: { command: "cursor-agent", args: ["acp"] },
173
- runtimeEnabled: false,
174
135
  smokeSupported: true,
175
136
  smokeStatus: "passed",
176
137
  caveats: [
177
- "Native ACP via hidden `cursor-agent acp` stdio JSON-RPC entrypoint; manual initialize + session/new smoke passed locally (protocolVersion 1, session created; no agentInfo returned).",
178
- "Runtime routing stays disabled until ACP is enabled in gateway config.",
138
+ "Native ACP via the companion-owned hidden `cursor-agent acp` stdio JSON-RPC entrypoint; manual initialize + session/new smoke passed locally (protocolVersion 1, session created; no agentInfo returned).",
139
+ ACP_RUNTIME_GATE_CAVEAT,
179
140
  ],
180
- docs: ACP_DOCS_REFERENCE,
181
141
  },
182
142
  };
183
- function cloneAcpCapability(acp) {
143
+ function acpMediationFor(cli) {
144
+ switch (ACP_CONTRACT.providers[cli].classification) {
145
+ case "native_candidate":
146
+ return "native";
147
+ case "adapter_mediated_deferred":
148
+ return "adapter_mediated";
149
+ case "absent_watchlist":
150
+ return "none";
151
+ }
152
+ }
153
+ function acpRegistryFacts(cli) {
154
+ if (cli === "grok_api") {
155
+ return { entrypoint: null, targetVersion: "xAI Responses API" };
156
+ }
157
+ const def = getProviderDefinition(cli);
184
158
  return {
185
- ...acp,
186
- entrypoint: acp.entrypoint
187
- ? { command: acp.entrypoint.command, args: [...acp.entrypoint.args] }
159
+ entrypoint: def.acp.entrypoint
160
+ ? { command: def.acp.entrypoint.command, args: [...def.acp.entrypoint.args] }
188
161
  : null,
189
- caveats: [...acp.caveats],
162
+ targetVersion: def.upstreamContract.targetVersion,
163
+ };
164
+ }
165
+ function resolveAcpRuntimeEnabled(cli, mediation, acpConfig) {
166
+ if (mediation !== "native")
167
+ return false;
168
+ if (!acpConfig?.enabled)
169
+ return false;
170
+ const providerConfig = acpConfig.providers[cli];
171
+ return providerConfig?.enabled === true && providerConfig.runtimeEnabled === true;
172
+ }
173
+ function buildAcpCapability(cli, acpConfig) {
174
+ const residual = ACP_RESIDUAL[cli];
175
+ const mediation = acpMediationFor(cli);
176
+ const { entrypoint, targetVersion } = acpRegistryFacts(cli);
177
+ const runtimeEnabled = resolveAcpRuntimeEnabled(cli, mediation, acpConfig);
178
+ const caveats = [...residual.caveats];
179
+ if (mediation === "native" && (acpConfig === null || acpConfig === undefined)) {
180
+ caveats.push("runtimeEnabled shows the safe default (off): the resolved gateway [acp] config was not available to this capability read.");
181
+ }
182
+ return {
183
+ status: residual.status,
184
+ mediation,
185
+ targetVersion,
186
+ entrypoint,
187
+ runtimeEnabled,
188
+ smokeSupported: residual.smokeSupported,
189
+ smokeStatus: residual.smokeStatus,
190
+ caveats,
191
+ docs: ACP_DOCS_REFERENCE,
190
192
  };
191
193
  }
192
194
  const PROVIDER_CAPABILITY_IDS = [
@@ -972,7 +974,7 @@ function buildOneProviderToolCapabilities(cli, query) {
972
974
  modelInfo: getModelInfo(cli, query),
973
975
  summary: definition.summary,
974
976
  acpContract: { ...ACP_CONTRACT.providers[cli] },
975
- acp: cloneAcpCapability(ACP_CAPABILITIES[cli]),
977
+ acp: buildAcpCapability(cli, query.acpConfig),
976
978
  controls: cloneControls(definition.controls),
977
979
  features,
978
980
  discoveredSkills,
@@ -1234,6 +1236,7 @@ function normalizeQuery(queryOrCli) {
1234
1236
  includePaths: query.includePaths ?? false,
1235
1237
  refresh: query.refresh ?? false,
1236
1238
  providersConfig: query.providersConfig,
1239
+ acpConfig: query.acpConfig,
1237
1240
  };
1238
1241
  }
1239
1242
  function capabilityCacheKey(cli, query) {
@@ -1244,8 +1247,20 @@ function capabilityCacheKey(cli, query) {
1244
1247
  includeUnsupported: query.includeUnsupported,
1245
1248
  includePaths: query.includePaths,
1246
1249
  providersConfig: query.providersConfig ? providerConfigCacheKey(query.providersConfig) : null,
1250
+ acpConfig: query.acpConfig ? acpConfigCacheKey(query.acpConfig) : null,
1247
1251
  });
1248
1252
  }
1253
+ function acpConfigCacheKey(config) {
1254
+ return {
1255
+ enabled: config.enabled,
1256
+ providers: Object.fromEntries(Object.entries(config.providers)
1257
+ .sort(([a], [b]) => a.localeCompare(b))
1258
+ .map(([name, provider]) => [
1259
+ name,
1260
+ { enabled: provider.enabled, runtimeEnabled: provider.runtimeEnabled },
1261
+ ])),
1262
+ };
1263
+ }
1249
1264
  function providerConfigCacheKey(config) {
1250
1265
  return {
1251
1266
  xai: config.xai
@@ -0,0 +1,28 @@
1
+ export declare const OAUTH_AUTHORIZE_PATH = "/oauth/authorize";
2
+ export declare const OAUTH_TOKEN_PATH = "/oauth/token";
3
+ export declare const OAUTH_REGISTER_PATH = "/oauth/register";
4
+ export declare const OAUTH_PROTECTED_RESOURCE_METADATA_PATH = "/.well-known/oauth-protected-resource";
5
+ export declare const OAUTH_AUTHORIZATION_SERVER_METADATA_PATH = "/.well-known/oauth-authorization-server";
6
+ export declare const OPENID_CONFIGURATION_PATH = "/.well-known/openid-configuration";
7
+ export declare const DEFAULT_MCP_PATH = "/mcp";
8
+ export declare function joinBaseAndPath(baseOrigin: string, path: string): string;
9
+ export declare function toOrigin(rawUrl: string | null | undefined): string | null;
10
+ export declare function resolveConfiguredRemoteOrigin(opts: {
11
+ issuer?: string | null;
12
+ publicUrl?: string | null;
13
+ }): string | null;
14
+ export interface RemoteConnectorUrls {
15
+ baseOrigin: string | null;
16
+ mcpUrl: string | null;
17
+ issuer: string | null;
18
+ authorizationUrl: string | null;
19
+ tokenUrl: string | null;
20
+ registrationUrl: string | null;
21
+ protectedResourceMetadataUrl: string | null;
22
+ authorizationServerMetadataUrl: string | null;
23
+ }
24
+ export declare function buildRemoteConnectorUrls(opts: {
25
+ baseOrigin: string | null;
26
+ mcpPath?: string;
27
+ oauthEnabled: boolean;
28
+ }): RemoteConnectorUrls;
@@ -0,0 +1,61 @@
1
+ export const OAUTH_AUTHORIZE_PATH = "/oauth/authorize";
2
+ export const OAUTH_TOKEN_PATH = "/oauth/token";
3
+ export const OAUTH_REGISTER_PATH = "/oauth/register";
4
+ export const OAUTH_PROTECTED_RESOURCE_METADATA_PATH = "/.well-known/oauth-protected-resource";
5
+ export const OAUTH_AUTHORIZATION_SERVER_METADATA_PATH = "/.well-known/oauth-authorization-server";
6
+ export const OPENID_CONFIGURATION_PATH = "/.well-known/openid-configuration";
7
+ export const DEFAULT_MCP_PATH = "/mcp";
8
+ export function joinBaseAndPath(baseOrigin, path) {
9
+ const trimmedBase = baseOrigin.replace(/\/+$/, "");
10
+ const suffix = path.startsWith("/") ? path : `/${path}`;
11
+ return `${trimmedBase}${suffix}`;
12
+ }
13
+ export function toOrigin(rawUrl) {
14
+ if (!rawUrl)
15
+ return null;
16
+ try {
17
+ return new URL(rawUrl).origin;
18
+ }
19
+ catch {
20
+ return null;
21
+ }
22
+ }
23
+ export function resolveConfiguredRemoteOrigin(opts) {
24
+ if (opts.issuer && opts.issuer !== "auto") {
25
+ const fromIssuer = toOrigin(opts.issuer);
26
+ if (fromIssuer)
27
+ return fromIssuer;
28
+ }
29
+ return toOrigin(opts.publicUrl ?? null);
30
+ }
31
+ export function buildRemoteConnectorUrls(opts) {
32
+ const base = opts.baseOrigin;
33
+ const mcpPath = opts.mcpPath && opts.mcpPath.length > 0 ? opts.mcpPath : DEFAULT_MCP_PATH;
34
+ if (!base) {
35
+ return {
36
+ baseOrigin: null,
37
+ mcpUrl: null,
38
+ issuer: null,
39
+ authorizationUrl: null,
40
+ tokenUrl: null,
41
+ registrationUrl: null,
42
+ protectedResourceMetadataUrl: null,
43
+ authorizationServerMetadataUrl: null,
44
+ };
45
+ }
46
+ const oauth = opts.oauthEnabled;
47
+ return {
48
+ baseOrigin: base,
49
+ mcpUrl: joinBaseAndPath(base, mcpPath),
50
+ issuer: oauth ? base : null,
51
+ authorizationUrl: oauth ? joinBaseAndPath(base, OAUTH_AUTHORIZE_PATH) : null,
52
+ tokenUrl: oauth ? joinBaseAndPath(base, OAUTH_TOKEN_PATH) : null,
53
+ registrationUrl: oauth ? joinBaseAndPath(base, OAUTH_REGISTER_PATH) : null,
54
+ protectedResourceMetadataUrl: oauth
55
+ ? joinBaseAndPath(base, OAUTH_PROTECTED_RESOURCE_METADATA_PATH)
56
+ : null,
57
+ authorizationServerMetadataUrl: oauth
58
+ ? joinBaseAndPath(base, OAUTH_AUTHORIZATION_SERVER_METADATA_PATH)
59
+ : null,
60
+ };
61
+ }