@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/CHANGELOG.md +10 -0
- package/README.md +10 -9
- package/dist/bridge/host-tool-mcp.mjs +1 -1
- package/dist/bridge/index.mjs +59 -24
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.d.ts +13 -17
- package/dist/index.js +69 -44
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/acp-harness.ts +3 -2
- package/src/index.ts +1 -2
- package/src/v1/acp-v1-bridge-protocol.ts +27 -6
- package/src/v1/acp-v1-harness.ts +36 -34
- package/src/v1/acp-v1-settings.ts +12 -16
- package/src/v1/acp-v1-turn-start-config.ts +7 -3
- package/src/v1/bridge/acp-v1-bridge-environment.ts +4 -8
- package/src/v1/bridge/index.ts +10 -2
- package/src/v1/bridge/model-mapping.ts +35 -0
- package/src/v1/bridge/protocol-configuration.ts +6 -2
- package/src/v1/implementation.ts +8 -0
- package/src/v1/index.ts +1 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/harness-acp",
|
|
3
|
-
"version": "1.0.
|
|
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.
|
|
30
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
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": {
|
package/src/acp-harness.ts
CHANGED
|
@@ -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
|
|
54
|
+
* Maps the HarnessAgent model identifier to an ACP session operation.
|
|
54
55
|
*/
|
|
55
|
-
readonly
|
|
56
|
+
readonly modelMapping: ACPV1Settings['modelMapping'];
|
|
56
57
|
/**
|
|
57
58
|
* @deprecated Use `model` on `HarnessAgent` instead.
|
|
58
59
|
*/
|
package/src/index.ts
CHANGED
|
@@ -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({
|
|
166
|
-
|
|
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])
|
package/src/v1/acp-v1-harness.ts
CHANGED
|
@@ -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
|
|
162
|
-
validateACPV1Implementation(
|
|
162
|
+
const implementation = createACPV1Implementation({ settings });
|
|
163
|
+
validateACPV1Implementation(implementation);
|
|
163
164
|
const bootstrap = createACPBootstrap({
|
|
164
165
|
harnessId: settings.harnessId,
|
|
165
|
-
implementation
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
|
159
|
+
* Maps the HarnessAgent model identifier to an ACP session operation.
|
|
164
160
|
*/
|
|
165
|
-
readonly
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
...(
|
|
90
|
-
...(implementationEnv == null ? {} : { implementationEnv }),
|
|
86
|
+
...(clientCapabilities == null ? {} : { clientCapabilities }),
|
|
91
87
|
}),
|
|
92
88
|
};
|
|
93
89
|
}
|
package/src/v1/bridge/index.ts
CHANGED
|
@@ -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
|
-
[...
|
|
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
|
|
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,
|
package/src/v1/implementation.ts
CHANGED
|
@@ -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,
|