@ai-sdk/harness-acp 1.0.31 → 1.0.32

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/harness-acp",
3
- "version": "1.0.31",
3
+ "version": "1.0.32",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -26,8 +26,8 @@
26
26
  }
27
27
  },
28
28
  "dependencies": {
29
- "@ai-sdk/harness": "1.0.93",
30
- "@ai-sdk/provider-utils": "5.0.33",
29
+ "@ai-sdk/harness": "1.0.94",
30
+ "@ai-sdk/provider-utils": "5.0.34",
31
31
  "ws": "^8.21.0"
32
32
  },
33
33
  "peerDependencies": {
@@ -48,11 +48,12 @@ export type ACPHarnessSettings<TBuiltinTools extends ToolSet = {}> = {
48
48
  readonly credentialForwarding?: ACPV1Settings['credentialForwarding'];
49
49
  readonly env?: ACPV1Settings['env'];
50
50
  readonly authentication?: ACPV1Settings['authentication'];
51
+ readonly clientCapabilities?: ACPV1Settings['clientCapabilities'];
51
52
  readonly providerAuthentication?: ACPV1Settings['providerAuthentication'];
52
53
  /**
53
- * Maps a HarnessAgent model identifier to implementation launch settings.
54
+ * Maps the HarnessAgent model identifier to an ACP session operation.
54
55
  */
55
- readonly resolveModel: ACPV1Settings['resolveModel'];
56
+ readonly modelMapping: ACPV1Settings['modelMapping'];
56
57
  /**
57
58
  * @deprecated Use `model` on `HarnessAgent` instead.
58
59
  */
package/src/index.ts CHANGED
@@ -24,8 +24,7 @@ export type {
24
24
  ACPAuthentication,
25
25
  ACPInstallCommandSource,
26
26
  ACPInstructionMapping,
27
- ACPModelResolution,
28
- ACPModelResolver,
27
+ ACPModelMapping,
29
28
  ACPNpmLockedSource,
30
29
  ACPNpmSimpleSource,
31
30
  ACPOutputSchemaMapping,
@@ -14,6 +14,7 @@ import { z } from 'zod/v4';
14
14
  import type { ACPToolCall } from '../acp-tool-call';
15
15
  import type {
16
16
  ACPInstructionMapping,
17
+ ACPModelMapping,
17
18
  ACPPermissionModeMapping,
18
19
  } from './acp-v1-settings';
19
20
  import { acpTextContentBlockSchema } from './acp-v1-prompt';
@@ -125,6 +126,20 @@ const outputSchemaMappingSchema: z.ZodType<ACPSerializableOutputSchemaMapping> =
125
126
  path: z.array(z.string().min(1)).min(1),
126
127
  });
127
128
 
129
+ const modelMappingSchema: z.ZodType<ACPModelMapping> = z.discriminatedUnion(
130
+ 'type',
131
+ [
132
+ z.object({
133
+ type: z.literal('session-config-option'),
134
+ path: z.string().min(1),
135
+ }),
136
+ z.object({
137
+ type: z.literal('session-model'),
138
+ path: z.string().min(1),
139
+ }),
140
+ ],
141
+ );
142
+
128
143
  export type ACPTurnStartConfig = {
129
144
  readonly version: 1;
130
145
  readonly configurationFingerprint: string;
@@ -133,6 +148,8 @@ export type ACPTurnStartConfig = {
133
148
  readonly builtinTools: Array<ACPBuiltinToolMapping>;
134
149
  readonly permissionMode: HarnessV1PermissionMode;
135
150
  readonly permissionModeMapping?: ACPPermissionModeMapping;
151
+ readonly model?: string;
152
+ readonly modelMapping?: ACPModelMapping;
136
153
  readonly debug?: HarnessV1DebugConfig;
137
154
  readonly responseFormat?: z.infer<
138
155
  typeof harnessV1BridgeStartBaseSchema
@@ -148,6 +165,8 @@ export const acpTurnStartConfigSchema = z.object({
148
165
  builtinTools: z.array(builtinToolSchema).default([]),
149
166
  permissionMode: harnessV1BridgeStartBaseSchema.shape.permissionMode.unwrap(),
150
167
  permissionModeMapping: permissionModeMappingSchema.optional(),
168
+ model: harnessV1BridgeStartBaseSchema.shape.model.optional(),
169
+ modelMapping: modelMappingSchema.optional(),
151
170
  debug: harnessV1BridgeStartBaseSchema.shape.debug.optional(),
152
171
  responseFormat:
153
172
  harnessV1BridgeStartBaseSchema.shape.responseFormat.optional(),
@@ -156,14 +175,15 @@ export const acpTurnStartConfigSchema = z.object({
156
175
 
157
176
  export type ACPColdSessionState = Omit<
158
177
  ACPTurnStartConfig,
159
- 'prompt' | 'debug'
160
- > & {
161
- readonly modelId?: string;
162
- };
178
+ 'prompt' | 'debug' | 'model' | 'modelMapping'
179
+ >;
163
180
 
164
181
  export const acpColdSessionStateSchema: z.ZodType<ACPColdSessionState> =
165
- acpTurnStartConfigSchema.omit({ prompt: true, debug: true }).extend({
166
- modelId: z.string().optional(),
182
+ acpTurnStartConfigSchema.omit({
183
+ prompt: true,
184
+ debug: true,
185
+ model: true,
186
+ modelMapping: true,
167
187
  });
168
188
 
169
189
  const lossyRecoverySchema = z.object({
@@ -203,6 +223,7 @@ export const startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
203
223
  tools: z.array(acpSerializableToolSpecSchema).optional(),
204
224
  builtinTools: z.array(builtinToolSchema).readonly().default([]),
205
225
  permissionModeMapping: permissionModeMappingSchema.optional(),
226
+ modelMapping: modelMappingSchema.optional(),
206
227
  turnStartConfig: acpTurnStartConfigSchema,
207
228
  recoveryMode: z
208
229
  .discriminatedUnion('type', [lossyRecoverySchema, coldRestoreSchema])
@@ -80,6 +80,7 @@ import {
80
80
  } from './acp-v1-prompt';
81
81
  import type {
82
82
  ACPInstructionMapping,
83
+ ACPModelMapping,
83
84
  ACPOutputSchemaMapping,
84
85
  ACPPermissionModeMapping,
85
86
  ACPPermissionModeTarget,
@@ -158,11 +159,11 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
158
159
  `ACP harnessId must be a stable kebab-case identifier; received ${JSON.stringify(settings.harnessId)}.`,
159
160
  );
160
161
  }
161
- const baseImplementation = createACPV1Implementation({ settings });
162
- validateACPV1Implementation(baseImplementation);
162
+ const implementation = createACPV1Implementation({ settings });
163
+ validateACPV1Implementation(implementation);
163
164
  const bootstrap = createACPBootstrap({
164
165
  harnessId: settings.harnessId,
165
- implementation: baseImplementation,
166
+ implementation,
166
167
  });
167
168
  const permissionModeMapping = isCompletePermissionModeMapping({
168
169
  value: settings.permissionModeMapping,
@@ -186,24 +187,6 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
186
187
  'ACP built-in tool filtering is not available in this initial ACP v1 implementation.',
187
188
  });
188
189
  }
189
- const modelId = startOptions.model ?? settings.modelId;
190
- const modelConfiguration =
191
- modelId == null ? undefined : settings.resolveModel({ model: modelId });
192
- const implementation = {
193
- ...baseImplementation,
194
- ...(modelConfiguration?.args == null
195
- ? {}
196
- : { args: modelConfiguration.args }),
197
- ...(modelConfiguration?.env == null
198
- ? {}
199
- : {
200
- env: {
201
- ...baseImplementation.env,
202
- ...modelConfiguration.env,
203
- },
204
- }),
205
- };
206
- validateACPV1Implementation(implementation);
207
190
  const permissionMode = startOptions.permissionMode ?? 'allow-all';
208
191
  const env = { ...process.env };
209
192
  const authenticationEnvironment = resolveACPAuthenticationEnvironment({
@@ -221,6 +204,8 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
221
204
  acpVersion: 'v1',
222
205
  implementation,
223
206
  clientApp,
207
+ clientCapabilities: settings.clientCapabilities,
208
+ modelMapping: settings.modelMapping,
224
209
  providerAuthentication: providerAuthenticationCompatibility,
225
210
  permissionModeMapping: settings.permissionModeMapping,
226
211
  });
@@ -452,7 +437,8 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
452
437
  harnessId: settings.harnessId,
453
438
  channel: attachChannel,
454
439
  proc: undefined,
455
- modelId,
440
+ modelMapping: settings.modelMapping,
441
+ defaultModelId: settings.modelId,
456
442
  sessionMeta: settings.session?.meta,
457
443
  instructionMapping: settings.instructionMapping,
458
444
  outputSchemaMapping: settings.outputSchemaMapping,
@@ -518,6 +504,7 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
518
504
  sessionMeta: settings.session?.meta,
519
505
  instructionMapping: settings.instructionMapping,
520
506
  outputSchemaMapping: settings.outputSchemaMapping,
507
+ modelMapping: settings.modelMapping,
521
508
  builtinTools: builtinToolCatalog,
522
509
  permissionModeMapping,
523
510
  mcpServers: settings.mcpServers,
@@ -544,12 +531,12 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
544
531
  }
545
532
  const turnStartConfig = validateACPColdSessionConfiguration({
546
533
  coldSession,
547
- modelId,
548
534
  permissionMode,
549
535
  authenticationProfile,
550
536
  sessionMeta: settings.session?.meta,
551
537
  instructionMapping: settings.instructionMapping,
552
538
  outputSchemaMapping: settings.outputSchemaMapping,
539
+ modelMapping: settings.modelMapping,
553
540
  builtinTools: builtinToolCatalog,
554
541
  permissionModeMapping,
555
542
  mcpServers: settings.mcpServers,
@@ -608,8 +595,7 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
608
595
  providerEnvironment:
609
596
  sandboxProviderEnvironment == null ? undefined : {},
610
597
  sessionMeta: settings.session?.meta,
611
- implementationArgs: modelConfiguration?.args,
612
- implementationEnv: modelConfiguration?.env,
598
+ clientCapabilities: settings.clientCapabilities,
613
599
  }),
614
600
  ...sandboxProviderAuthenticationEnvironment,
615
601
  BRIDGE_CHANNEL_TOKEN: token,
@@ -722,7 +708,8 @@ export function createACPV1<TBuiltinTools extends ToolSet = {}>({
722
708
  harnessId: settings.harnessId,
723
709
  channel,
724
710
  proc,
725
- modelId,
711
+ modelMapping: settings.modelMapping,
712
+ defaultModelId: settings.modelId,
726
713
  sessionMeta: settings.session?.meta,
727
714
  instructionMapping: settings.instructionMapping,
728
715
  outputSchemaMapping: settings.outputSchemaMapping,
@@ -1046,7 +1033,8 @@ function createSession({
1046
1033
  harnessId,
1047
1034
  channel,
1048
1035
  proc,
1049
- modelId,
1036
+ modelMapping,
1037
+ defaultModelId,
1050
1038
  sessionMeta,
1051
1039
  instructionMapping,
1052
1040
  outputSchemaMapping,
@@ -1081,7 +1069,8 @@ function createSession({
1081
1069
  harnessId: string;
1082
1070
  channel: ACPChannel;
1083
1071
  proc: Experimental_SandboxProcess | undefined;
1084
- modelId: string | undefined;
1072
+ modelMapping: ACPModelMapping;
1073
+ defaultModelId: string | undefined;
1085
1074
  sessionMeta: Readonly<Record<string, ACPSerializableValue>> | undefined;
1086
1075
  instructionMapping: ACPInstructionMapping | undefined;
1087
1076
  outputSchemaMapping: ACPOutputSchemaMapping | undefined;
@@ -1375,7 +1364,6 @@ function createSession({
1375
1364
  : {
1376
1365
  coldSession: createACPColdSessionState({
1377
1366
  turnStartConfig: latestTurnStartConfig,
1378
- modelId,
1379
1367
  }),
1380
1368
  }),
1381
1369
  ...(!includeTurnStartConfig || latestTurnStartConfig == null
@@ -1407,7 +1395,6 @@ function createSession({
1407
1395
  return {
1408
1396
  sessionId,
1409
1397
  isResume,
1410
- ...(modelId == null ? {} : { modelId }),
1411
1398
  doPromptTurn: async options => {
1412
1399
  await synchronizeSkills({
1413
1400
  skills: options.skills,
@@ -1442,6 +1429,7 @@ function createSession({
1442
1429
  prompt: options.prompt,
1443
1430
  harnessId,
1444
1431
  });
1432
+ const model = options.model ?? defaultModelId;
1445
1433
  const turnStartConfig = createACPTurnStartConfig({
1446
1434
  prompt,
1447
1435
  tools: options.tools ?? [],
@@ -1455,6 +1443,8 @@ function createSession({
1455
1443
  instructionMapping,
1456
1444
  responseFormat: options.responseFormat,
1457
1445
  outputSchemaMapping,
1446
+ model,
1447
+ modelMapping,
1458
1448
  });
1459
1449
  const nextInstructionsFingerprint = fingerprintValue({
1460
1450
  value: options.instructions ?? null,
@@ -1491,6 +1481,7 @@ function createSession({
1491
1481
  builtinTools,
1492
1482
  permissionMode,
1493
1483
  permissionModeMapping,
1484
+ ...(model == null ? {} : { model, modelMapping }),
1494
1485
  ...(options.responseFormat == null
1495
1486
  ? {}
1496
1487
  : { responseFormat: options.responseFormat }),
@@ -1554,6 +1545,12 @@ function createSession({
1554
1545
  builtinTools: turnStartConfig.builtinTools,
1555
1546
  permissionMode: turnStartConfig.permissionMode,
1556
1547
  permissionModeMapping: turnStartConfig.permissionModeMapping,
1548
+ ...(turnStartConfig.model == null
1549
+ ? {}
1550
+ : {
1551
+ model: turnStartConfig.model,
1552
+ modelMapping: turnStartConfig.modelMapping,
1553
+ }),
1557
1554
  ...(turnStartConfig.responseFormat == null
1558
1555
  ? {}
1559
1556
  : { responseFormat: turnStartConfig.responseFormat }),
@@ -1751,6 +1748,7 @@ function validateACPTurnStartConfig({
1751
1748
  sessionMeta,
1752
1749
  instructionMapping,
1753
1750
  outputSchemaMapping,
1751
+ modelMapping,
1754
1752
  builtinTools,
1755
1753
  permissionModeMapping,
1756
1754
  mcpServers,
@@ -1760,6 +1758,7 @@ function validateACPTurnStartConfig({
1760
1758
  sessionMeta: Readonly<Record<string, ACPSerializableValue>> | undefined;
1761
1759
  instructionMapping: ACPInstructionMapping | undefined;
1762
1760
  outputSchemaMapping: ACPOutputSchemaMapping | undefined;
1761
+ modelMapping: ACPModelMapping;
1763
1762
  builtinTools: ReadonlyArray<ACPBuiltinToolMapping>;
1764
1763
  permissionModeMapping: ACPPermissionModeMapping | undefined;
1765
1764
  mcpServers: Record<string, unknown> | undefined;
@@ -1777,6 +1776,8 @@ function validateACPTurnStartConfig({
1777
1776
  instructionMapping,
1778
1777
  responseFormat: turnStartConfig.responseFormat,
1779
1778
  outputSchemaMapping,
1779
+ model: turnStartConfig.model,
1780
+ modelMapping,
1780
1781
  });
1781
1782
  if (
1782
1783
  current.configurationFingerprint !==
@@ -1790,24 +1791,24 @@ function validateACPTurnStartConfig({
1790
1791
 
1791
1792
  function validateACPColdSessionConfiguration({
1792
1793
  coldSession,
1793
- modelId,
1794
1794
  permissionMode,
1795
1795
  authenticationProfile,
1796
1796
  sessionMeta,
1797
1797
  instructionMapping,
1798
1798
  outputSchemaMapping,
1799
+ modelMapping,
1799
1800
  builtinTools,
1800
1801
  permissionModeMapping,
1801
1802
  mcpServers,
1802
1803
  debug,
1803
1804
  }: {
1804
1805
  coldSession: ACPColdSessionState;
1805
- modelId: string | undefined;
1806
1806
  permissionMode: NonNullable<StartMessage['permissionMode']>;
1807
1807
  authenticationProfile: ACPAuthenticationProfileIdentity;
1808
1808
  sessionMeta: Readonly<Record<string, ACPSerializableValue>> | undefined;
1809
1809
  instructionMapping: ACPInstructionMapping | undefined;
1810
1810
  outputSchemaMapping: ACPOutputSchemaMapping | undefined;
1811
+ modelMapping: ACPModelMapping;
1811
1812
  builtinTools: ReadonlyArray<ACPBuiltinToolMapping>;
1812
1813
  permissionModeMapping: ACPPermissionModeMapping | undefined;
1813
1814
  mcpServers: Record<string, unknown> | undefined;
@@ -1826,11 +1827,12 @@ function validateACPColdSessionConfiguration({
1826
1827
  instructionMapping,
1827
1828
  responseFormat: coldSession.responseFormat,
1828
1829
  outputSchemaMapping,
1830
+ model: undefined,
1831
+ modelMapping,
1829
1832
  });
1830
1833
  if (
1831
1834
  current.configurationFingerprint !== coldSession.configurationFingerprint ||
1832
- coldSession.permissionMode !== permissionMode ||
1833
- coldSession.modelId !== modelId
1835
+ coldSession.permissionMode !== permissionMode
1834
1836
  ) {
1835
1837
  throw new Error(
1836
1838
  'ACP cold-session state is incompatible with the current non-secret session configuration.',
@@ -75,20 +75,15 @@ export type ACPProviderAuthentication = {
75
75
  };
76
76
  };
77
77
 
78
- export type ACPModelResolution = {
79
- /**
80
- * Replaces the implementation's static launch arguments.
81
- */
82
- readonly args?: ReadonlyArray<string>;
83
- /**
84
- * Overlays the implementation's static launch environment.
85
- */
86
- readonly env?: Readonly<Record<string, string>>;
87
- };
88
-
89
- export type ACPModelResolver = (options: {
90
- readonly model: string;
91
- }) => ACPModelResolution;
78
+ export type ACPModelMapping =
79
+ | {
80
+ readonly type: 'session-config-option';
81
+ readonly path: string;
82
+ }
83
+ | {
84
+ readonly type: 'session-model';
85
+ readonly path: string;
86
+ };
92
87
 
93
88
  export type ACPCredentialBrokering = ({
94
89
  env,
@@ -158,11 +153,12 @@ export type ACPV1Settings = {
158
153
  */
159
154
  readonly env?: Readonly<Record<string, string>>;
160
155
  readonly authentication?: ACPAuthentication;
156
+ readonly clientCapabilities?: Readonly<Record<string, ACPSerializableValue>>;
161
157
  readonly providerAuthentication?: ACPProviderAuthentication;
162
158
  /**
163
- * Maps a HarnessAgent model identifier to implementation launch settings.
159
+ * Maps the HarnessAgent model identifier to an ACP session operation.
164
160
  */
165
- readonly resolveModel: ACPModelResolver;
161
+ readonly modelMapping: ACPModelMapping;
166
162
  /**
167
163
  * @deprecated Use `model` on `HarnessAgent` instead.
168
164
  */
@@ -11,6 +11,7 @@ import {
11
11
  import type { ACPTextContentBlock } from './acp-v1-prompt';
12
12
  import type {
13
13
  ACPInstructionMapping,
14
+ ACPModelMapping,
14
15
  ACPOutputSchemaMapping,
15
16
  ACPPermissionModeMapping,
16
17
  ACPSerializableValue,
@@ -29,6 +30,8 @@ export function createACPTurnStartConfig({
29
30
  instructionMapping,
30
31
  responseFormat,
31
32
  outputSchemaMapping,
33
+ model,
34
+ modelMapping,
32
35
  }: {
33
36
  prompt: ReadonlyArray<ACPTextContentBlock>;
34
37
  tools: ReadonlyArray<HarnessV1ToolSpec>;
@@ -42,6 +45,8 @@ export function createACPTurnStartConfig({
42
45
  instructionMapping: ACPInstructionMapping | undefined;
43
46
  responseFormat: StartMessage['responseFormat'];
44
47
  outputSchemaMapping: ACPOutputSchemaMapping | undefined;
48
+ model: string | undefined;
49
+ modelMapping: ACPModelMapping;
45
50
  }): ACPTurnStartConfig {
46
51
  return {
47
52
  version: 1,
@@ -52,6 +57,7 @@ export function createACPTurnStartConfig({
52
57
  sessionMeta: sessionMeta ?? null,
53
58
  ...(instructionMapping == null ? {} : { instructionMapping }),
54
59
  ...(outputSchemaMapping == null ? {} : { outputSchemaMapping }),
60
+ modelMapping,
55
61
  builtinTools,
56
62
  permissionModeMapping: permissionModeMapping ?? null,
57
63
  mcpServers: mcpServers ?? null,
@@ -62,6 +68,7 @@ export function createACPTurnStartConfig({
62
68
  tools: tools.map(tool => acpSerializableToolSpecSchema.parse(tool)),
63
69
  builtinTools: [...builtinTools],
64
70
  permissionMode,
71
+ ...(model == null ? {} : { model, modelMapping }),
65
72
  ...(responseFormat == null ? {} : { responseFormat }),
66
73
  ...(outputSchemaMapping == null
67
74
  ? {}
@@ -78,10 +85,8 @@ export function createACPTurnStartConfig({
78
85
 
79
86
  export function createACPColdSessionState({
80
87
  turnStartConfig,
81
- modelId,
82
88
  }: {
83
89
  turnStartConfig: ACPTurnStartConfig;
84
- modelId: string | undefined;
85
90
  }): ACPColdSessionState {
86
91
  return {
87
92
  version: turnStartConfig.version,
@@ -98,7 +103,6 @@ export function createACPColdSessionState({
98
103
  ...(turnStartConfig.permissionModeMapping == null
99
104
  ? {}
100
105
  : { permissionModeMapping: turnStartConfig.permissionModeMapping }),
101
- ...(modelId == null ? {} : { modelId }),
102
106
  };
103
107
  }
104
108
 
@@ -59,8 +59,7 @@ export type ACPBridgeConfiguration = {
59
59
  readonly providerAuthentication?: ACPResolvedProviderAuthentication;
60
60
  readonly providerEnvironment?: Readonly<Record<string, string>>;
61
61
  readonly sessionMeta?: Readonly<Record<string, ACPSerializableValue>>;
62
- readonly implementationArgs?: ReadonlyArray<string>;
63
- readonly implementationEnv?: Readonly<Record<string, string>>;
62
+ readonly clientCapabilities?: Readonly<Record<string, ACPSerializableValue>>;
64
63
  };
65
64
 
66
65
  const bridgeConfigurationSchema: z.ZodType<ACPBridgeConfiguration> = z.object({
@@ -68,8 +67,7 @@ const bridgeConfigurationSchema: z.ZodType<ACPBridgeConfiguration> = z.object({
68
67
  providerAuthentication: providerAuthenticationSchema.optional(),
69
68
  providerEnvironment: z.record(z.string(), z.string()).optional(),
70
69
  sessionMeta: serializableRecordSchema.optional(),
71
- implementationArgs: z.array(z.string()).optional(),
72
- implementationEnv: z.record(z.string(), z.string()).optional(),
70
+ clientCapabilities: serializableRecordSchema.optional(),
73
71
  });
74
72
 
75
73
  export function createACPBridgeEnvironment({
@@ -77,8 +75,7 @@ export function createACPBridgeEnvironment({
77
75
  providerAuthentication,
78
76
  providerEnvironment,
79
77
  sessionMeta,
80
- implementationArgs,
81
- implementationEnv,
78
+ clientCapabilities,
82
79
  }: ACPBridgeConfiguration): Record<string, string> {
83
80
  return {
84
81
  [ACP_BRIDGE_CONFIGURATION_ENV]: JSON.stringify({
@@ -86,8 +83,7 @@ export function createACPBridgeEnvironment({
86
83
  ...(providerAuthentication == null ? {} : { providerAuthentication }),
87
84
  ...(providerEnvironment == null ? {} : { providerEnvironment }),
88
85
  ...(sessionMeta == null ? {} : { sessionMeta }),
89
- ...(implementationArgs == null ? {} : { implementationArgs }),
90
- ...(implementationEnv == null ? {} : { implementationEnv }),
86
+ ...(clientCapabilities == null ? {} : { clientCapabilities }),
91
87
  }),
92
88
  };
93
89
  }
@@ -44,6 +44,7 @@ import {
44
44
  } from './refresh-host-tool-catalog';
45
45
  import { createACPPermissionController } from './permission-controller';
46
46
  import { configureACPPermissionMode } from './permission-mode';
47
+ import { configureACPModel } from './model-mapping';
47
48
  import {
48
49
  assertACPResumeCapability,
49
50
  createACPRecoveredSession,
@@ -214,6 +215,13 @@ async function runTurn(start: StartMessage, turn: BridgeTurn): Promise<void> {
214
215
  return;
215
216
  }
216
217
 
218
+ await configureACPModel({
219
+ agent: connection!.agent,
220
+ sessionId: activeSession.sessionId,
221
+ model: start.model,
222
+ mapping: start.modelMapping,
223
+ });
224
+
217
225
  let rejectCancellationFailure!: (error: unknown) => void;
218
226
  const cancellationFailure = new Promise<never>((_, reject) => {
219
227
  rejectCancellationFailure = reject;
@@ -419,12 +427,11 @@ async function ensureSession({
419
427
  implementationDir,
420
428
  privateHome: implementation.privateHome,
421
429
  }),
422
- ...bridgeConfiguration.implementationEnv,
423
430
  },
424
431
  });
425
432
  child = spawn(
426
433
  `${implementationDir}/${implementation.executablePath}`,
427
- [...(bridgeConfiguration.implementationArgs ?? implementation.args)],
434
+ [...implementation.args],
428
435
  {
429
436
  cwd: workDir,
430
437
  env: instructionConfiguration.environment,
@@ -475,6 +482,7 @@ async function ensureSession({
475
482
  protocolVersion: acp.PROTOCOL_VERSION,
476
483
  clientApp,
477
484
  authentication,
485
+ clientCapabilities: bridgeConfiguration.clientCapabilities,
478
486
  supportsBooleanSessionConfigOptions: Object.values(
479
487
  start.permissionModeMapping ?? {},
480
488
  ).some(
@@ -0,0 +1,35 @@
1
+ import * as acp from '@agentclientprotocol/sdk';
2
+ import type { ACPModelMapping } from '../acp-v1-settings';
3
+
4
+ export async function configureACPModel({
5
+ agent,
6
+ sessionId,
7
+ model,
8
+ mapping,
9
+ }: {
10
+ agent: acp.ClientContext;
11
+ sessionId: string;
12
+ model: string | undefined;
13
+ mapping: ACPModelMapping | undefined;
14
+ }): Promise<void> {
15
+ if (model == null) return;
16
+ if (mapping == null) {
17
+ throw new Error('ACP model mapping is required when a model is set.');
18
+ }
19
+ /*
20
+ * Some ACP harnesses, including Grok Build, use the non-standard
21
+ * `session/set_model` convention.
22
+ */
23
+ if (mapping.type === 'session-model') {
24
+ await agent.request('session/set_model', {
25
+ sessionId,
26
+ [mapping.path]: model,
27
+ });
28
+ return;
29
+ }
30
+ await agent.request(acp.methods.agent.session.setConfigOption, {
31
+ sessionId,
32
+ configId: mapping.path,
33
+ value: model,
34
+ });
35
+ }
@@ -16,11 +16,13 @@ export function createACPInitializeRequest({
16
16
  protocolVersion,
17
17
  clientApp,
18
18
  authentication,
19
+ clientCapabilities: configuredClientCapabilities,
19
20
  supportsBooleanSessionConfigOptions = false,
20
21
  }: {
21
22
  protocolVersion: number;
22
23
  clientApp: ACPClientApp;
23
24
  authentication: ACPAuthentication | undefined;
25
+ clientCapabilities?: Readonly<Record<string, unknown>>;
24
26
  supportsBooleanSessionConfigOptions?: boolean;
25
27
  }): {
26
28
  readonly protocolVersion: number;
@@ -30,8 +32,10 @@ export function createACPInitializeRequest({
30
32
  };
31
33
  readonly clientCapabilities: Readonly<Record<string, unknown>>;
32
34
  } {
33
- let clientCapabilities: Readonly<Record<string, unknown>> =
34
- authentication?.clientCapabilities ?? {};
35
+ let clientCapabilities = mergeRecords({
36
+ left: authentication?.clientCapabilities ?? {},
37
+ right: configuredClientCapabilities ?? {},
38
+ });
35
39
  if (supportsBooleanSessionConfigOptions) {
36
40
  clientCapabilities = mergeRecords({
37
41
  left: clientCapabilities,
@@ -4,8 +4,10 @@ import type {
4
4
  ACPProviderAuthenticationCompatibility,
5
5
  } from '../acp-auth';
6
6
  import type {
7
+ ACPModelMapping,
7
8
  ACPNpmSimpleSource,
8
9
  ACPPermissionModeMapping,
10
+ ACPSerializableValue,
9
11
  ACPSource,
10
12
  ACPV1Settings,
11
13
  } from './acp-v1-settings';
@@ -172,6 +174,8 @@ export function createImplementationIdentity({
172
174
  acpVersion,
173
175
  implementation,
174
176
  clientApp,
177
+ clientCapabilities,
178
+ modelMapping,
175
179
  providerAuthentication,
176
180
  permissionModeMapping,
177
181
  }: {
@@ -179,6 +183,8 @@ export function createImplementationIdentity({
179
183
  acpVersion: 'v1';
180
184
  implementation: ACPImplementation;
181
185
  clientApp: ACPClientApp;
186
+ clientCapabilities?: Readonly<Record<string, ACPSerializableValue>>;
187
+ modelMapping: ACPModelMapping;
182
188
  providerAuthentication: ACPProviderAuthenticationCompatibility | undefined;
183
189
  permissionModeMapping?: ACPPermissionModeMapping;
184
190
  }): string {
@@ -221,6 +227,8 @@ export function createImplementationIdentity({
221
227
  executable: implementation.executable,
222
228
  args: implementation.args ?? [],
223
229
  clientApp,
230
+ clientCapabilities: clientCapabilities ?? null,
231
+ modelMapping,
224
232
  environment: {
225
233
  forwarded: forwardedEnvironment,
226
234
  credential: credentialEnvironment,
package/src/v1/index.ts CHANGED
@@ -5,8 +5,7 @@ export type {
5
5
  ACPAuthenticationMode,
6
6
  ACPInstallCommandSource,
7
7
  ACPInstructionMapping,
8
- ACPModelResolution,
9
- ACPModelResolver,
8
+ ACPModelMapping,
10
9
  ACPNpmLockedSource,
11
10
  ACPNpmSimpleSource,
12
11
  ACPOutputSchemaMapping,