@ai-sdk/harness-acp 1.0.1 → 1.0.2

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/dist/index.d.ts CHANGED
@@ -1,6 +1,104 @@
1
1
  import { HarnessV1PermissionMode, HarnessV1 } from '@ai-sdk/harness';
2
2
  import { ToolSet } from '@ai-sdk/provider-utils';
3
3
 
4
+ type ACPMetadata = Record<string, unknown>;
5
+ type ACPRole = 'assistant' | 'user';
6
+ type ACPAnnotations = {
7
+ audience?: Array<ACPRole> | null;
8
+ lastModified?: string | null;
9
+ priority?: number | null;
10
+ _meta?: ACPMetadata | null;
11
+ };
12
+ type ACPTextContent = {
13
+ annotations?: ACPAnnotations | null;
14
+ text: string;
15
+ _meta?: ACPMetadata | null;
16
+ };
17
+ type ACPImageContent = {
18
+ annotations?: ACPAnnotations | null;
19
+ data: string;
20
+ mimeType: string;
21
+ uri?: string | null;
22
+ _meta?: ACPMetadata | null;
23
+ };
24
+ type ACPAudioContent = {
25
+ annotations?: ACPAnnotations | null;
26
+ data: string;
27
+ mimeType: string;
28
+ _meta?: ACPMetadata | null;
29
+ };
30
+ type ACPResourceLink = {
31
+ annotations?: ACPAnnotations | null;
32
+ description?: string | null;
33
+ mimeType?: string | null;
34
+ name: string;
35
+ size?: number | null;
36
+ title?: string | null;
37
+ uri: string;
38
+ _meta?: ACPMetadata | null;
39
+ };
40
+ type ACPTextResourceContents = {
41
+ mimeType?: string | null;
42
+ text: string;
43
+ uri: string;
44
+ _meta?: ACPMetadata | null;
45
+ };
46
+ type ACPBlobResourceContents = {
47
+ blob: string;
48
+ mimeType?: string | null;
49
+ uri: string;
50
+ _meta?: ACPMetadata | null;
51
+ };
52
+ type ACPEmbeddedResource = {
53
+ annotations?: ACPAnnotations | null;
54
+ resource: ACPTextResourceContents | ACPBlobResourceContents;
55
+ _meta?: ACPMetadata | null;
56
+ };
57
+ type ACPContentBlock = (ACPTextContent & {
58
+ type: 'text';
59
+ }) | (ACPImageContent & {
60
+ type: 'image';
61
+ }) | (ACPAudioContent & {
62
+ type: 'audio';
63
+ }) | (ACPResourceLink & {
64
+ type: 'resource_link';
65
+ }) | (ACPEmbeddedResource & {
66
+ type: 'resource';
67
+ });
68
+ type ACPToolCallContent = {
69
+ type: 'content';
70
+ content: ACPContentBlock;
71
+ _meta?: ACPMetadata | null;
72
+ } | {
73
+ type: 'diff';
74
+ path: string;
75
+ oldText?: string | null;
76
+ newText: string;
77
+ _meta?: ACPMetadata | null;
78
+ } | {
79
+ type: 'terminal';
80
+ terminalId: string;
81
+ _meta?: ACPMetadata | null;
82
+ };
83
+ type ACPToolKind = 'read' | 'edit' | 'delete' | 'move' | 'search' | 'execute' | 'think' | 'fetch' | 'switch_mode' | 'other';
84
+ type ACPToolCallStatus = 'pending' | 'in_progress' | 'completed' | 'failed';
85
+ type ACPToolCallLocation = {
86
+ path: string;
87
+ line?: number | null;
88
+ _meta?: ACPMetadata | null;
89
+ };
90
+ type ACPToolCall = {
91
+ toolCallId: string;
92
+ title: string;
93
+ kind?: ACPToolKind;
94
+ status?: ACPToolCallStatus;
95
+ content?: Array<ACPToolCallContent>;
96
+ locations?: Array<ACPToolCallLocation>;
97
+ rawInput?: unknown;
98
+ rawOutput?: unknown;
99
+ _meta?: ACPMetadata | null;
100
+ };
101
+
4
102
  type ACPSerializablePrimitive = string | number | boolean | null;
5
103
  type ACPSerializableValue = ACPSerializablePrimitive | ReadonlyArray<ACPSerializableValue> | {
6
104
  readonly [key: string]: ACPSerializableValue;
@@ -53,6 +151,8 @@ type ACPPermissionModeMapping = Readonly<Record<HarnessV1PermissionMode, ACPPerm
53
151
  type ACPV1Settings = {
54
152
  readonly version?: 'v1';
55
153
  readonly harnessId: string;
154
+ readonly mcpServers?: Record<string, unknown>;
155
+ readonly isMcpToolCall?: (toolCall: ACPToolCall) => boolean;
56
156
  readonly auth?: ACPProviderAuthenticationMode;
57
157
  readonly source: ACPSource;
58
158
  readonly executable: string;
@@ -70,6 +170,11 @@ type ACPV1Settings = {
70
170
  readonly session?: {
71
171
  readonly meta?: Readonly<Record<string, ACPSerializableValue>>;
72
172
  };
173
+ /**
174
+ * Creates the authentication token used by the sandbox bridge. Defaults to
175
+ * a random 32-byte hexadecimal token.
176
+ */
177
+ readonly mintBridgeToken?: (sandboxId: string) => string;
73
178
  };
74
179
 
75
180
  type ACPAuthOptions = ACPProviderAuthenticationMode;
@@ -80,6 +185,12 @@ type ACPClientApp = {
80
185
 
81
186
  type ACPHarnessSettings<TBuiltinTools extends ToolSet = {}> = {
82
187
  readonly builtinTools?: TBuiltinTools;
188
+ /**
189
+ * MCP server definitions keyed by server name. Each definition uses the
190
+ * underlying runtime's native MCP server configuration format.
191
+ */
192
+ readonly mcpServers?: Record<string, unknown>;
193
+ readonly isMcpToolCall?: (toolCall: ACPToolCall) => boolean;
83
194
  readonly port?: number;
84
195
  readonly startupTimeoutMs?: number;
85
196
  readonly clientApp?: ACPClientApp;
@@ -96,9 +207,10 @@ type ACPHarnessSettings<TBuiltinTools extends ToolSet = {}> = {
96
207
  readonly modelId?: ACPV1Settings['modelId'];
97
208
  readonly permissionModeMapping?: ACPV1Settings['permissionModeMapping'];
98
209
  readonly session?: ACPV1Settings['session'];
210
+ readonly mintBridgeToken?: ACPV1Settings['mintBridgeToken'];
99
211
  };
100
212
  declare function createACP<TBuiltinTools extends ToolSet = {}>(settings: ACPHarnessSettings<TBuiltinTools>): HarnessV1<TBuiltinTools>;
101
213
 
102
214
  declare const VERSION: string;
103
215
 
104
- export { type ACPAuthOptions, type ACPAuthentication, type ACPClientApp, type ACPHarnessSettings, type ACPNpmLockedSource, type ACPNpmSimpleSource, type ACPPermissionModeMapping, type ACPPermissionModeTarget, type ACPProfileValue, type ACPProviderAuthentication, type ACPProviderAuthenticationMode, type ACPSerializablePrimitive, type ACPSerializableValue, type ACPSource, type ACPV1Settings, type ACPValueSource, VERSION, createACP };
216
+ export { type ACPAnnotations, type ACPAudioContent, type ACPAuthOptions, type ACPAuthentication, type ACPBlobResourceContents, type ACPClientApp, type ACPContentBlock, type ACPEmbeddedResource, type ACPHarnessSettings, type ACPImageContent, type ACPMetadata, type ACPNpmLockedSource, type ACPNpmSimpleSource, type ACPPermissionModeMapping, type ACPPermissionModeTarget, type ACPProfileValue, type ACPProviderAuthentication, type ACPProviderAuthenticationMode, type ACPResourceLink, type ACPRole, type ACPSerializablePrimitive, type ACPSerializableValue, type ACPSource, type ACPTextContent, type ACPTextResourceContents, type ACPToolCall, type ACPToolCallContent, type ACPToolCallLocation, type ACPToolCallStatus, type ACPToolKind, type ACPV1Settings, type ACPValueSource, VERSION, createACP };
package/dist/index.js CHANGED
@@ -540,9 +540,19 @@ var coldRestoreSchema = z2.object({
540
540
  type: z2.literal("cold-restore"),
541
541
  acpSessionId: z2.string()
542
542
  });
543
- var outboundMessageSchema = harnessV1BridgeOutboundMessageSchema;
543
+ var acpToolCallCandidateSchema = z2.object({
544
+ type: z2.literal("acp-tool-call-candidate"),
545
+ toolCall: z2.custom(
546
+ (value) => value != null && typeof value === "object" && typeof value.toolCallId === "string" && typeof value.title === "string"
547
+ )
548
+ });
549
+ var outboundMessageSchema = z2.union([
550
+ harnessV1BridgeOutboundMessageSchema,
551
+ acpToolCallCandidateSchema
552
+ ]);
544
553
  var startMessageSchema = harnessV1BridgeStartBaseSchema.extend({
545
554
  prompt: z2.array(acpTextContentBlockSchema),
555
+ mcpServers: z2.record(z2.string(), z2.unknown()).optional(),
546
556
  tools: z2.array(acpSerializableToolSpecSchema).optional(),
547
557
  builtinTools: z2.array(builtinToolSchema).readonly().default([]),
548
558
  permissionModeMapping: permissionModeMappingSchema.optional(),
@@ -622,6 +632,7 @@ function createACPTurnStartConfig({
622
632
  builtinTools,
623
633
  permissionMode,
624
634
  permissionModeMapping,
635
+ mcpServers,
625
636
  debug,
626
637
  authenticationProfile,
627
638
  sessionMeta
@@ -633,7 +644,8 @@ function createACPTurnStartConfig({
633
644
  authenticationProfile,
634
645
  sessionMeta: sessionMeta ?? null,
635
646
  builtinTools,
636
- permissionModeMapping: permissionModeMapping ?? null
647
+ permissionModeMapping: permissionModeMapping ?? null,
648
+ mcpServers: mcpServers ?? null
637
649
  })
638
650
  ).digest("hex"),
639
651
  prompt: [...prompt],
@@ -897,6 +909,14 @@ function createACPV1({
897
909
  clientApp,
898
910
  lifecycleStateSchema
899
911
  }) {
912
+ if (settings.mcpServers != null && Object.prototype.hasOwnProperty.call(
913
+ settings.mcpServers,
914
+ "ai-sdk-harness-tools"
915
+ )) {
916
+ throw new Error(
917
+ 'ACP MCP server name "ai-sdk-harness-tools" is reserved for HarnessAgent tools.'
918
+ );
919
+ }
900
920
  if (!HARNESS_ID_REGEXP.test(settings.harnessId)) {
901
921
  throw new Error(
902
922
  `ACP harnessId must be a stable kebab-case identifier; received ${JSON.stringify(settings.harnessId)}.`
@@ -1118,6 +1138,8 @@ function createACPV1({
1118
1138
  builtinTools: builtinToolCatalog,
1119
1139
  permissionMode,
1120
1140
  permissionModeMapping,
1141
+ mcpServers: settings.mcpServers,
1142
+ isMcpToolCall: settings.isMcpToolCall,
1121
1143
  initialGuidanceApplied: resolveACPInitialGuidanceApplied({
1122
1144
  isResume: true,
1123
1145
  lifecycleState: lifecycleData
@@ -1167,7 +1189,8 @@ function createACPV1({
1167
1189
  authenticationProfile,
1168
1190
  sessionMeta: settings.session?.meta,
1169
1191
  builtinTools: builtinToolCatalog,
1170
- permissionModeMapping
1192
+ permissionModeMapping,
1193
+ mcpServers: settings.mcpServers
1171
1194
  });
1172
1195
  respawnStrategy = {
1173
1196
  mode: "lossy-rerun",
@@ -1196,6 +1219,7 @@ function createACPV1({
1196
1219
  sessionMeta: settings.session?.meta,
1197
1220
  builtinTools: builtinToolCatalog,
1198
1221
  permissionModeMapping,
1222
+ mcpServers: settings.mcpServers,
1199
1223
  debug: startOptions.observability?.debug
1200
1224
  });
1201
1225
  respawnStrategy = {
@@ -1210,7 +1234,7 @@ function createACPV1({
1210
1234
  override: portOverride,
1211
1235
  harnessId: settings.harnessId
1212
1236
  });
1213
- const token = randomBytes(32).toString("hex");
1237
+ const token = settings.mintBridgeToken == null ? randomBytes(32).toString("hex") : settings.mintBridgeToken(sandboxSession.id);
1214
1238
  await sandbox.run({
1215
1239
  command: `mkdir -p ${shellQuote(workDir)} ${shellQuote(bridgeStateDir)}`,
1216
1240
  abortSignal: startOptions.abortSignal
@@ -1300,6 +1324,7 @@ function createACPV1({
1300
1324
  builtinTools: builtinToolCatalog,
1301
1325
  permissionMode,
1302
1326
  permissionModeMapping,
1327
+ ...settings.mcpServers == null ? {} : { mcpServers: settings.mcpServers },
1303
1328
  tools: respawnStrategy.turnStartConfig.tools,
1304
1329
  turnStartConfig: respawnStrategy.turnStartConfig,
1305
1330
  recoveryMode: {
@@ -1337,6 +1362,8 @@ function createACPV1({
1337
1362
  builtinTools: builtinToolCatalog,
1338
1363
  permissionMode,
1339
1364
  permissionModeMapping,
1365
+ mcpServers: settings.mcpServers,
1366
+ isMcpToolCall: settings.isMcpToolCall,
1340
1367
  initialGuidanceApplied: resolveACPInitialGuidanceApplied({
1341
1368
  isResume,
1342
1369
  lifecycleState: lifecycleData
@@ -1496,6 +1523,8 @@ function createSession({
1496
1523
  builtinTools,
1497
1524
  permissionMode,
1498
1525
  permissionModeMapping,
1526
+ mcpServers,
1527
+ isMcpToolCall,
1499
1528
  initialGuidanceApplied: initialGuidanceAppliedAtStart,
1500
1529
  skillCatalog,
1501
1530
  skillsFingerprint,
@@ -1542,6 +1571,8 @@ function createSession({
1542
1571
  let abortError;
1543
1572
  let abortListenerAttached = false;
1544
1573
  let openBlock;
1574
+ const dynamicToolCalls = /* @__PURE__ */ new Map();
1575
+ const toolCallClassificationErrors = /* @__PURE__ */ new Map();
1545
1576
  const subscriptions = [];
1546
1577
  const forward = (event) => {
1547
1578
  if (event.type === "text-start" || event.type === "reasoning-start") {
@@ -1574,9 +1605,7 @@ function createSession({
1574
1605
  "reasoning-start",
1575
1606
  "reasoning-delta",
1576
1607
  "reasoning-end",
1577
- "tool-call",
1578
1608
  "tool-approval-request",
1579
- "tool-result",
1580
1609
  "file-change",
1581
1610
  "finish-step",
1582
1611
  "raw"
@@ -1604,6 +1633,44 @@ function createSession({
1604
1633
  settle({ error: abortError });
1605
1634
  }
1606
1635
  };
1636
+ subscriptions.push(
1637
+ channel.on("acp-tool-call-candidate", (event) => {
1638
+ try {
1639
+ dynamicToolCalls.set(
1640
+ event.toolCall.toolCallId,
1641
+ isMcpToolCall?.(event.toolCall) === true
1642
+ );
1643
+ } catch (error) {
1644
+ toolCallClassificationErrors.set(event.toolCall.toolCallId, error);
1645
+ }
1646
+ })
1647
+ );
1648
+ subscriptions.push(
1649
+ channel.on("tool-call", (event) => {
1650
+ if (toolCallClassificationErrors.has(event.toolCallId)) {
1651
+ const error = toolCallClassificationErrors.get(event.toolCallId);
1652
+ closeForwardedBlock();
1653
+ forward({ type: "error", error });
1654
+ try {
1655
+ channel.send({ type: "abort" });
1656
+ } catch {
1657
+ }
1658
+ settle({ error });
1659
+ return;
1660
+ }
1661
+ forward(
1662
+ dynamicToolCalls.get(event.toolCallId) === true ? { ...event, dynamic: true } : event
1663
+ );
1664
+ })
1665
+ );
1666
+ subscriptions.push(
1667
+ channel.on("tool-result", (event) => {
1668
+ const dynamic = dynamicToolCalls.get(event.toolCallId) === true;
1669
+ dynamicToolCalls.delete(event.toolCallId);
1670
+ toolCallClassificationErrors.delete(event.toolCallId);
1671
+ forward(dynamic ? { ...event, dynamic: true } : event);
1672
+ })
1673
+ );
1607
1674
  for (const type of eventTypes) {
1608
1675
  subscriptions.push(channel.on(type, (event) => forward(event)));
1609
1676
  }
@@ -1744,6 +1811,7 @@ function createSession({
1744
1811
  builtinTools,
1745
1812
  permissionMode,
1746
1813
  permissionModeMapping,
1814
+ mcpServers,
1747
1815
  debug,
1748
1816
  authenticationProfile,
1749
1817
  sessionMeta
@@ -1769,6 +1837,7 @@ function createSession({
1769
1837
  builtinTools,
1770
1838
  permissionMode,
1771
1839
  permissionModeMapping,
1840
+ ...mcpServers == null ? {} : { mcpServers },
1772
1841
  tools: options.tools == null ? void 0 : turnStartConfig.tools,
1773
1842
  turnStartConfig
1774
1843
  });
@@ -1806,6 +1875,7 @@ function createSession({
1806
1875
  builtinTools: turnStartConfig.builtinTools,
1807
1876
  permissionMode: turnStartConfig.permissionMode,
1808
1877
  permissionModeMapping: turnStartConfig.permissionModeMapping,
1878
+ ...mcpServers == null ? {} : { mcpServers },
1809
1879
  tools: turnStartConfig.tools,
1810
1880
  turnStartConfig,
1811
1881
  recoveryMode: {
@@ -1938,7 +2008,8 @@ function validateACPTurnStartConfig({
1938
2008
  authenticationProfile,
1939
2009
  sessionMeta,
1940
2010
  builtinTools,
1941
- permissionModeMapping
2011
+ permissionModeMapping,
2012
+ mcpServers
1942
2013
  }) {
1943
2014
  const current = createACPTurnStartConfig({
1944
2015
  prompt: turnStartConfig.prompt,
@@ -1946,6 +2017,7 @@ function validateACPTurnStartConfig({
1946
2017
  builtinTools,
1947
2018
  permissionMode: turnStartConfig.permissionMode,
1948
2019
  permissionModeMapping,
2020
+ mcpServers,
1949
2021
  debug: turnStartConfig.debug,
1950
2022
  authenticationProfile,
1951
2023
  sessionMeta
@@ -1964,6 +2036,7 @@ function validateACPColdSessionConfiguration({
1964
2036
  sessionMeta,
1965
2037
  builtinTools,
1966
2038
  permissionModeMapping,
2039
+ mcpServers,
1967
2040
  debug
1968
2041
  }) {
1969
2042
  const current = createACPTurnStartConfig({
@@ -1972,6 +2045,7 @@ function validateACPColdSessionConfiguration({
1972
2045
  builtinTools,
1973
2046
  permissionMode,
1974
2047
  permissionModeMapping,
2048
+ mcpServers,
1975
2049
  debug,
1976
2050
  authenticationProfile,
1977
2051
  sessionMeta
@@ -2021,7 +2095,7 @@ function deserializeBridgeError({
2021
2095
  }
2022
2096
 
2023
2097
  // src/version.ts
2024
- var VERSION = true ? "1.0.1" : "0.0.0-test";
2098
+ var VERSION = true ? "1.0.2" : "0.0.0-test";
2025
2099
 
2026
2100
  // src/acp-harness.ts
2027
2101
  var ACP_CLIENT_APP = {
@@ -2063,6 +2137,14 @@ var acpResumeStateSchema = z4.object({
2063
2137
  skillsFingerprint: z4.string().optional()
2064
2138
  });
2065
2139
  function createACP(settings) {
2140
+ if (settings.mcpServers != null && Object.prototype.hasOwnProperty.call(
2141
+ settings.mcpServers,
2142
+ "ai-sdk-harness-tools"
2143
+ )) {
2144
+ throw new Error(
2145
+ 'ACP MCP server name "ai-sdk-harness-tools" is reserved for HarnessAgent tools.'
2146
+ );
2147
+ }
2066
2148
  const version = settings.version ?? "v1";
2067
2149
  switch (version) {
2068
2150
  case "v1": {