@ai-sdk/harness-acp 1.0.0 → 1.0.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.
package/dist/index.d.ts CHANGED
@@ -14,28 +14,22 @@ type ACPValueSource = {
14
14
  type ACPProfileValue = ACPSerializablePrimitive | ACPValueSource | ReadonlyArray<ACPProfileValue> | {
15
15
  readonly [key: string]: ACPProfileValue;
16
16
  };
17
- type ACPNpmLaunchSettings = {
18
- readonly type: 'npm';
19
- readonly executable: string;
20
- readonly args?: ReadonlyArray<string>;
21
- readonly forwardEnv?: ReadonlyArray<string>;
17
+ type ACPNpmSimpleSource = {
18
+ readonly type: 'npm-simple';
19
+ readonly packageName: string;
22
20
  /**
23
- * Runtime environment values that are safe to persist in bootstrap and
24
- * lifecycle compatibility identity.
21
+ * Exact version to install. When omitted, the package's `latest` dist-tag is
22
+ * installed and no version takes part in the implementation identity, so a
23
+ * new upstream release does not invalidate existing lifecycle state.
25
24
  */
26
- readonly env?: Readonly<Record<string, string>>;
27
- };
28
- type ACPSimpleNpmImplementation = ACPNpmLaunchSettings & {
29
- readonly mode: 'simple';
30
- readonly packageName: string;
31
- readonly version: string;
25
+ readonly packageVersion?: string;
32
26
  };
33
- type ACPLockedNpmImplementation = ACPNpmLaunchSettings & {
34
- readonly mode: 'locked';
27
+ type ACPNpmLockedSource = {
28
+ readonly type: 'npm-locked';
35
29
  readonly packageJson: string;
36
30
  readonly pnpmLockYaml: string;
37
31
  };
38
- type ACPNpmImplementation = ACPSimpleNpmImplementation | ACPLockedNpmImplementation;
32
+ type ACPSource = ACPNpmSimpleSource | ACPNpmLockedSource;
39
33
  type ACPAuthentication = {
40
34
  readonly methodId: string;
41
35
  readonly meta?: Readonly<Record<string, ACPSerializableValue>>;
@@ -60,7 +54,15 @@ type ACPV1Settings = {
60
54
  readonly version?: 'v1';
61
55
  readonly harnessId: string;
62
56
  readonly auth?: ACPProviderAuthenticationMode;
63
- readonly implementation: ACPNpmImplementation;
57
+ readonly source: ACPSource;
58
+ readonly executable: string;
59
+ readonly args?: ReadonlyArray<string>;
60
+ readonly forwardEnv?: ReadonlyArray<string>;
61
+ /**
62
+ * Runtime environment values that are safe to persist in bootstrap and
63
+ * lifecycle compatibility identity.
64
+ */
65
+ readonly env?: Readonly<Record<string, string>>;
64
66
  readonly authentication?: ACPAuthentication;
65
67
  readonly providerAuthentication?: ACPProviderAuthentication;
66
68
  readonly modelId?: string;
@@ -84,7 +86,11 @@ type ACPHarnessSettings<TBuiltinTools extends ToolSet = {}> = {
84
86
  readonly version?: ACPV1Settings['version'];
85
87
  readonly harnessId: ACPV1Settings['harnessId'];
86
88
  readonly auth?: ACPV1Settings['auth'];
87
- readonly implementation: ACPV1Settings['implementation'];
89
+ readonly source: ACPV1Settings['source'];
90
+ readonly executable: ACPV1Settings['executable'];
91
+ readonly args?: ACPV1Settings['args'];
92
+ readonly forwardEnv?: ACPV1Settings['forwardEnv'];
93
+ readonly env?: ACPV1Settings['env'];
88
94
  readonly authentication?: ACPV1Settings['authentication'];
89
95
  readonly providerAuthentication?: ACPV1Settings['providerAuthentication'];
90
96
  readonly modelId?: ACPV1Settings['modelId'];
@@ -95,4 +101,4 @@ declare function createACP<TBuiltinTools extends ToolSet = {}>(settings: ACPHarn
95
101
 
96
102
  declare const VERSION: string;
97
103
 
98
- export { type ACPAuthOptions, type ACPAuthentication, type ACPClientApp, type ACPHarnessSettings, type ACPLockedNpmImplementation, type ACPNpmImplementation, type ACPPermissionModeMapping, type ACPPermissionModeTarget, type ACPProfileValue, type ACPProviderAuthentication, type ACPProviderAuthenticationMode, type ACPSerializablePrimitive, type ACPSerializableValue, type ACPSimpleNpmImplementation, type ACPV1Settings, type ACPValueSource, VERSION, createACP };
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 };
package/dist/index.js CHANGED
@@ -1,6 +1,33 @@
1
1
  // src/acp-harness.ts
2
2
  import { z as z4 } from "zod/v4";
3
3
 
4
+ // src/v1/acp-v1-harness.ts
5
+ import { createHash as createHash5, randomBytes } from "crypto";
6
+ import { readFile } from "fs/promises";
7
+ import { posix } from "path";
8
+ import { fileURLToPath } from "url";
9
+ import {
10
+ HarnessCapabilityUnsupportedError as HarnessCapabilityUnsupportedError2,
11
+ harnessV1DiagnosticFromBridgeFrame
12
+ } from "@ai-sdk/harness";
13
+ import { HarnessBridgeCapabilityUnsupportedError } from "@ai-sdk/harness/bridge";
14
+ import {
15
+ createBridgeErrorHandler,
16
+ createBridgeStartupError,
17
+ classifyDiskLog,
18
+ drainBridgeProcessStream,
19
+ forwardBridgeProcessStream,
20
+ markBridgeStarting,
21
+ resolveSandboxHomeDir,
22
+ SandboxChannel,
23
+ shellQuote,
24
+ waitForBridgeReady
25
+ } from "@ai-sdk/harness/utils";
26
+ import {
27
+ asSchema
28
+ } from "@ai-sdk/provider-utils";
29
+ import { WebSocket } from "ws";
30
+
4
31
  // src/acp-auth.ts
5
32
  import { createHash } from "crypto";
6
33
  import { getAiGatewayAuthFromEnv } from "@ai-sdk/harness/utils";
@@ -145,53 +172,34 @@ function sortIdentityValue({ value }) {
145
172
  return value;
146
173
  }
147
174
 
148
- // src/v1/acp-v1-harness.ts
149
- import { createHash as createHash5, randomBytes } from "crypto";
150
- import { readFile } from "fs/promises";
151
- import { posix } from "path";
152
- import { fileURLToPath } from "url";
153
- import {
154
- HarnessCapabilityUnsupportedError as HarnessCapabilityUnsupportedError2,
155
- harnessV1DiagnosticFromBridgeFrame
156
- } from "@ai-sdk/harness";
157
- import { HarnessBridgeCapabilityUnsupportedError } from "@ai-sdk/harness/bridge";
158
- import {
159
- createBridgeErrorHandler,
160
- createBridgeStartupError,
161
- classifyDiskLog,
162
- drainBridgeProcessStream,
163
- forwardBridgeProcessStream,
164
- markBridgeStarting,
165
- resolveSandboxHomeDir,
166
- SandboxChannel,
167
- shellQuote,
168
- waitForBridgeReady
169
- } from "@ai-sdk/harness/utils";
170
- import {
171
- asSchema
172
- } from "@ai-sdk/provider-utils";
173
- import { WebSocket } from "ws";
174
-
175
175
  // src/v1/implementation.ts
176
176
  import { createHash as createHash2 } from "crypto";
177
+ function createACPV1Implementation({
178
+ settings
179
+ }) {
180
+ return {
181
+ source: settings.source,
182
+ executable: settings.executable,
183
+ args: settings.args,
184
+ forwardEnv: settings.forwardEnv,
185
+ env: settings.env
186
+ };
187
+ }
177
188
  var EXACT_SEMVER_REGEXP = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
178
189
  var PACKAGE_NAME_REGEXP = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
179
190
  var EXECUTABLE_NAME_REGEXP = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
180
191
  var ENVIRONMENT_VARIABLE_NAME_REGEXP = /^[A-Za-z_][A-Za-z0-9_]*$/;
181
192
  function validateACPV1Implementation(implementation) {
182
- if (isLockedImplementation(implementation)) {
183
- if (implementation.packageJson.length === 0) {
184
- throw new Error(
185
- "ACP locked npm implementation packageJson must not be empty."
186
- );
193
+ const { source } = implementation;
194
+ if (source.type === "npm-locked") {
195
+ if (source.packageJson.length === 0) {
196
+ throw new Error("ACP source.packageJson must not be empty.");
187
197
  }
188
- if (implementation.pnpmLockYaml.length === 0) {
189
- throw new Error(
190
- "ACP locked npm implementation pnpmLockYaml must not be empty."
191
- );
198
+ if (source.pnpmLockYaml.length === 0) {
199
+ throw new Error("ACP source.pnpmLockYaml must not be empty.");
192
200
  }
193
201
  } else {
194
- validateSimpleImplementation({ implementation });
202
+ validateNpmSimpleSource({ source });
195
203
  }
196
204
  if (!EXECUTABLE_NAME_REGEXP.test(implementation.executable)) {
197
205
  throw new Error(
@@ -212,8 +220,9 @@ function validateACPV1Implementation(implementation) {
212
220
  function createImplementationManifest({
213
221
  implementation
214
222
  }) {
215
- if (isLockedImplementation(implementation)) {
216
- return implementation.packageJson;
223
+ const { source } = implementation;
224
+ if (source.type === "npm-locked") {
225
+ return source.packageJson;
217
226
  }
218
227
  return JSON.stringify(
219
228
  {
@@ -222,7 +231,7 @@ function createImplementationManifest({
222
231
  private: true,
223
232
  type: "module",
224
233
  dependencies: {
225
- [implementation.packageName]: implementation.version
234
+ [source.packageName]: source.packageVersion ?? "latest"
226
235
  }
227
236
  },
228
237
  null,
@@ -232,18 +241,17 @@ function createImplementationManifest({
232
241
  function getImplementationLockfile({
233
242
  implementation
234
243
  }) {
235
- return isLockedImplementation(implementation) ? implementation.pnpmLockYaml : void 0;
244
+ const { source } = implementation;
245
+ return source.type === "npm-locked" ? source.pnpmLockYaml : void 0;
236
246
  }
237
247
  function createImplementationDescriptor({
238
- implementation,
239
- implementationIdentity
248
+ implementation
240
249
  }) {
241
250
  return JSON.stringify(
242
251
  {
243
252
  executable: implementation.executable,
244
253
  args: implementation.args ?? [],
245
- envKeys: getImplementationEnvironmentKeys({ implementation }),
246
- implementationIdentity
254
+ envKeys: getImplementationEnvironmentKeys({ implementation })
247
255
  },
248
256
  null,
249
257
  2
@@ -257,14 +265,15 @@ function createImplementationIdentity({
257
265
  providerAuthentication,
258
266
  permissionModeMapping
259
267
  }) {
260
- const acquisition = isLockedImplementation(implementation) ? {
261
- mode: "locked",
262
- packageJson: implementation.packageJson,
263
- pnpmLockYaml: implementation.pnpmLockYaml
268
+ const { source } = implementation;
269
+ const sourceIdentity = source.type === "npm-locked" ? {
270
+ type: source.type,
271
+ packageJson: source.packageJson,
272
+ pnpmLockYaml: source.pnpmLockYaml
264
273
  } : {
265
- mode: "simple",
266
- packageName: implementation.packageName,
267
- version: implementation.version
274
+ type: source.type,
275
+ packageName: source.packageName,
276
+ ...source.packageVersion == null ? {} : { packageVersion: source.packageVersion }
268
277
  };
269
278
  const forwardedEnvironment = [
270
279
  ...new Set(implementation.forwardEnv ?? [])
@@ -275,7 +284,7 @@ function createImplementationIdentity({
275
284
  const payload = {
276
285
  harnessId,
277
286
  acpVersion,
278
- acquisition,
287
+ source: sourceIdentity,
279
288
  executable: implementation.executable,
280
289
  args: implementation.args ?? [],
281
290
  clientApp,
@@ -293,7 +302,7 @@ function createImplementationInstallCommand({
293
302
  storeDir,
294
303
  implementation
295
304
  }) {
296
- return `pnpm --dir ${implementationDir} install` + (isLockedImplementation(implementation) ? " --frozen-lockfile" : "") + ` --prod --store-dir ${storeDir}`;
305
+ return `pnpm --dir ${implementationDir} install` + (implementation.source.type === "npm-locked" ? " --frozen-lockfile" : "") + ` --prod --store-dir ${storeDir}`;
297
306
  }
298
307
  function resolveImplementationEnvironment({
299
308
  implementation,
@@ -311,17 +320,17 @@ function resolveImplementationEnvironment({
311
320
  ...implementation.env
312
321
  };
313
322
  }
314
- function validateSimpleImplementation({
315
- implementation
323
+ function validateNpmSimpleSource({
324
+ source
316
325
  }) {
317
- if (!PACKAGE_NAME_REGEXP.test(implementation.packageName)) {
326
+ if (!PACKAGE_NAME_REGEXP.test(source.packageName)) {
318
327
  throw new Error(
319
- `ACP npm package name is invalid: ${JSON.stringify(implementation.packageName)}.`
328
+ `ACP npm package name is invalid: ${JSON.stringify(source.packageName)}.`
320
329
  );
321
330
  }
322
- if (!EXACT_SEMVER_REGEXP.test(implementation.version)) {
331
+ if (source.packageVersion != null && !EXACT_SEMVER_REGEXP.test(source.packageVersion)) {
323
332
  throw new Error(
324
- `ACP npm implementation version must be an exact semantic version; received ${JSON.stringify(implementation.version)}.`
333
+ `ACP npm package version must be an exact semantic version; received ${JSON.stringify(source.packageVersion)}.`
325
334
  );
326
335
  }
327
336
  }
@@ -360,9 +369,6 @@ function getImplementationEnvironmentKeys({
360
369
  ])
361
370
  ].sort();
362
371
  }
363
- function isLockedImplementation(implementation) {
364
- return implementation.mode === "locked";
365
- }
366
372
  function stableStringify2({ value }) {
367
373
  return JSON.stringify(sortValue({ value }));
368
374
  }
@@ -889,9 +895,6 @@ function createACPV1({
889
895
  port: portOverride,
890
896
  startupTimeoutMs,
891
897
  clientApp,
892
- implementationIdentity,
893
- authenticationProfile,
894
- providerAuthenticationCompatibility,
895
898
  lifecycleStateSchema
896
899
  }) {
897
900
  if (!HARNESS_ID_REGEXP.test(settings.harnessId)) {
@@ -899,7 +902,8 @@ function createACPV1({
899
902
  `ACP harnessId must be a stable kebab-case identifier; received ${JSON.stringify(settings.harnessId)}.`
900
903
  );
901
904
  }
902
- validateACPV1Implementation(settings.implementation);
905
+ const implementation = createACPV1Implementation({ settings });
906
+ validateACPV1Implementation(implementation);
903
907
  const BOOTSTRAP_DIR = `.harness-bootstrap/${settings.harnessId}`;
904
908
  let cachedBootstrap;
905
909
  const permissionModeMapping = isCompletePermissionModeMapping({
@@ -921,7 +925,7 @@ function createACPV1({
921
925
  readBridgeAsset({ name: "host-tool-mcp.mjs" })
922
926
  ]);
923
927
  const implementationLock = getImplementationLockfile({
924
- implementation: settings.implementation
928
+ implementation
925
929
  });
926
930
  cachedBootstrap = {
927
931
  harnessId: settings.harnessId,
@@ -943,14 +947,13 @@ function createACPV1({
943
947
  {
944
948
  path: `${BOOTSTRAP_DIR}/implementation/package.json`,
945
949
  content: createImplementationManifest({
946
- implementation: settings.implementation
950
+ implementation
947
951
  })
948
952
  },
949
953
  {
950
954
  path: `${BOOTSTRAP_DIR}/implementation/implementation.json`,
951
955
  content: createImplementationDescriptor({
952
- implementation: settings.implementation,
953
- implementationIdentity
956
+ implementation
954
957
  })
955
958
  },
956
959
  ...implementationLock == null ? [] : [
@@ -968,7 +971,7 @@ function createACPV1({
968
971
  command: createImplementationInstallCommand({
969
972
  implementationDir: "implementation",
970
973
  storeDir: "../.pnpm-store",
971
- implementation: settings.implementation
974
+ implementation
972
975
  })
973
976
  }
974
977
  ]
@@ -983,13 +986,31 @@ function createACPV1({
983
986
  });
984
987
  }
985
988
  const permissionMode = startOptions.permissionMode ?? "allow-all";
989
+ const env = { ...process.env };
990
+ const providerAuthenticationCompatibility = resolveACPProviderAuthenticationCompatibility({
991
+ auth: settings.auth,
992
+ providerAuthentication: settings.providerAuthentication,
993
+ env
994
+ });
995
+ const implementationIdentity = createImplementationIdentity({
996
+ harnessId: settings.harnessId,
997
+ acpVersion: "v1",
998
+ implementation,
999
+ clientApp,
1000
+ providerAuthentication: providerAuthenticationCompatibility,
1001
+ permissionModeMapping: settings.permissionModeMapping
1002
+ });
1003
+ const authenticationProfile = createACPAuthenticationProfileIdentity({
1004
+ authentication: settings.authentication,
1005
+ providerAuthenticationCompatibility
1006
+ });
986
1007
  const resolvedProviderAuthentication = resolveACPProviderAuthentication({
987
1008
  auth: {
988
1009
  mode: settings.auth,
989
1010
  providerAuthentication: settings.providerAuthentication,
990
1011
  clientApp
991
1012
  },
992
- env: process.env,
1013
+ env,
993
1014
  compatibility: providerAuthenticationCompatibility
994
1015
  });
995
1016
  const sandboxSession = startOptions.sandboxSession;
@@ -1204,8 +1225,8 @@ function createACPV1({
1204
1225
  command: `node ${shellQuote(`${resolvedBridgeDir}/bridge.mjs`)} --workdir ${shellQuote(workDir)} --bridge-state-dir ${shellQuote(bridgeStateDir)} --implementation-dir ${shellQuote(resolvedImplementationDir)} --bridge-type ${shellQuote(settings.harnessId)}`,
1205
1226
  env: {
1206
1227
  ...resolveImplementationEnvironment({
1207
- implementation: settings.implementation,
1208
- env: process.env
1228
+ implementation,
1229
+ env
1209
1230
  }),
1210
1231
  ...createACPBridgeEnvironment({
1211
1232
  authentication: settings.authentication,
@@ -2000,7 +2021,7 @@ function deserializeBridgeError({
2000
2021
  }
2001
2022
 
2002
2023
  // src/version.ts
2003
- var VERSION = true ? "1.0.0" : "0.0.0-test";
2024
+ var VERSION = true ? "1.0.1" : "0.0.0-test";
2004
2025
 
2005
2026
  // src/acp-harness.ts
2006
2027
  var ACP_CLIENT_APP = {
@@ -2046,39 +2067,13 @@ function createACP(settings) {
2046
2067
  switch (version) {
2047
2068
  case "v1": {
2048
2069
  const clientApp = settings.clientApp ?? ACP_CLIENT_APP;
2049
- const providerAuthenticationCompatibility = resolveACPProviderAuthenticationCompatibility({
2050
- auth: settings.auth,
2051
- providerAuthentication: settings.providerAuthentication,
2052
- env: process.env
2053
- });
2054
- const implementationIdentity = createImplementationIdentity({
2055
- harnessId: settings.harnessId,
2056
- acpVersion: version,
2057
- implementation: settings.implementation,
2058
- clientApp,
2059
- providerAuthentication: providerAuthenticationCompatibility,
2060
- permissionModeMapping: settings.permissionModeMapping
2061
- });
2062
- const authenticationProfile = createACPAuthenticationProfileIdentity({
2063
- authentication: settings.authentication,
2064
- providerAuthenticationCompatibility
2065
- });
2066
- const lifecycleStateSchema = acpResumeStateSchema.extend({
2067
- implementationIdentity: z4.literal(implementationIdentity),
2068
- authenticationProfile: acpResumeStateSchema.shape.authenticationProfile.unwrap().extend({
2069
- digest: z4.literal(authenticationProfile.digest)
2070
- }).optional()
2071
- });
2072
2070
  return createACPV1({
2073
2071
  settings,
2074
2072
  builtinTools: settings.builtinTools ?? ACP_BUILTIN_TOOLS,
2075
2073
  port: settings.port,
2076
2074
  startupTimeoutMs: settings.startupTimeoutMs,
2077
2075
  clientApp,
2078
- implementationIdentity,
2079
- authenticationProfile,
2080
- providerAuthenticationCompatibility,
2081
- lifecycleStateSchema
2076
+ lifecycleStateSchema: acpResumeStateSchema
2082
2077
  });
2083
2078
  }
2084
2079
  default: