@ai-sdk/harness-acp 1.0.0 → 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.
@@ -4,11 +4,42 @@ import type {
4
4
  ACPProviderAuthenticationCompatibility,
5
5
  } from '../acp-auth';
6
6
  import type {
7
- ACPNpmImplementation,
7
+ ACPNpmSimpleSource,
8
8
  ACPPermissionModeMapping,
9
- ACPSimpleNpmImplementation,
9
+ ACPSource,
10
+ ACPV1Settings,
10
11
  } from './acp-v1-settings';
11
12
 
13
+ /*
14
+ * Launch descriptor assembled from the launch-related settings fields. The
15
+ * fields are declared here rather than derived from ACPV1Settings so that the
16
+ * settings type stays free to describe the configuration surface while this
17
+ * type describes what the bootstrap, install, and identity logic consume. The
18
+ * two shapes are required to agree, and createACPV1Implementation is the only
19
+ * place that maps between them.
20
+ */
21
+ export type ACPNpmImplementation = {
22
+ readonly source: ACPSource;
23
+ readonly executable: string;
24
+ readonly args?: ReadonlyArray<string>;
25
+ readonly forwardEnv?: ReadonlyArray<string>;
26
+ readonly env?: Readonly<Record<string, string>>;
27
+ };
28
+
29
+ export function createACPV1Implementation({
30
+ settings,
31
+ }: {
32
+ settings: ACPV1Settings;
33
+ }): ACPNpmImplementation {
34
+ return {
35
+ source: settings.source,
36
+ executable: settings.executable,
37
+ args: settings.args,
38
+ forwardEnv: settings.forwardEnv,
39
+ env: settings.env,
40
+ };
41
+ }
42
+
12
43
  const EXACT_SEMVER_REGEXP =
13
44
  /^(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-]+)*)?$/;
14
45
  const PACKAGE_NAME_REGEXP =
@@ -19,19 +50,16 @@ const ENVIRONMENT_VARIABLE_NAME_REGEXP = /^[A-Za-z_][A-Za-z0-9_]*$/;
19
50
  export function validateACPV1Implementation(
20
51
  implementation: ACPNpmImplementation,
21
52
  ): void {
22
- if (isLockedImplementation(implementation)) {
23
- if (implementation.packageJson.length === 0) {
24
- throw new Error(
25
- 'ACP locked npm implementation packageJson must not be empty.',
26
- );
53
+ const { source } = implementation;
54
+ if (source.type === 'npm-locked') {
55
+ if (source.packageJson.length === 0) {
56
+ throw new Error('ACP source.packageJson must not be empty.');
27
57
  }
28
- if (implementation.pnpmLockYaml.length === 0) {
29
- throw new Error(
30
- 'ACP locked npm implementation pnpmLockYaml must not be empty.',
31
- );
58
+ if (source.pnpmLockYaml.length === 0) {
59
+ throw new Error('ACP source.pnpmLockYaml must not be empty.');
32
60
  }
33
61
  } else {
34
- validateSimpleImplementation({ implementation });
62
+ validateNpmSimpleSource({ source });
35
63
  }
36
64
  if (!EXECUTABLE_NAME_REGEXP.test(implementation.executable)) {
37
65
  throw new Error(
@@ -56,8 +84,9 @@ export function createImplementationManifest({
56
84
  }: {
57
85
  implementation: ACPNpmImplementation;
58
86
  }): string {
59
- if (isLockedImplementation(implementation)) {
60
- return implementation.packageJson;
87
+ const { source } = implementation;
88
+ if (source.type === 'npm-locked') {
89
+ return source.packageJson;
61
90
  }
62
91
  return (
63
92
  JSON.stringify(
@@ -67,7 +96,7 @@ export function createImplementationManifest({
67
96
  private: true,
68
97
  type: 'module',
69
98
  dependencies: {
70
- [implementation.packageName]: implementation.version,
99
+ [source.packageName]: source.packageVersion ?? 'latest',
71
100
  },
72
101
  },
73
102
  null,
@@ -81,17 +110,14 @@ export function getImplementationLockfile({
81
110
  }: {
82
111
  implementation: ACPNpmImplementation;
83
112
  }): string | undefined {
84
- return isLockedImplementation(implementation)
85
- ? implementation.pnpmLockYaml
86
- : undefined;
113
+ const { source } = implementation;
114
+ return source.type === 'npm-locked' ? source.pnpmLockYaml : undefined;
87
115
  }
88
116
 
89
117
  export function createImplementationDescriptor({
90
118
  implementation,
91
- implementationIdentity,
92
119
  }: {
93
120
  implementation: ACPNpmImplementation;
94
- implementationIdentity: string;
95
121
  }): string {
96
122
  return (
97
123
  JSON.stringify(
@@ -99,7 +125,6 @@ export function createImplementationDescriptor({
99
125
  executable: implementation.executable,
100
126
  args: implementation.args ?? [],
101
127
  envKeys: getImplementationEnvironmentKeys({ implementation }),
102
- implementationIdentity,
103
128
  },
104
129
  null,
105
130
  2,
@@ -122,17 +147,21 @@ export function createImplementationIdentity({
122
147
  providerAuthentication: ACPProviderAuthenticationCompatibility | undefined;
123
148
  permissionModeMapping?: ACPPermissionModeMapping;
124
149
  }): string {
125
- const acquisition = isLockedImplementation(implementation)
126
- ? {
127
- mode: 'locked',
128
- packageJson: implementation.packageJson,
129
- pnpmLockYaml: implementation.pnpmLockYaml,
130
- }
131
- : {
132
- mode: 'simple',
133
- packageName: implementation.packageName,
134
- version: implementation.version,
135
- };
150
+ const { source } = implementation;
151
+ const sourceIdentity =
152
+ source.type === 'npm-locked'
153
+ ? {
154
+ type: source.type,
155
+ packageJson: source.packageJson,
156
+ pnpmLockYaml: source.pnpmLockYaml,
157
+ }
158
+ : {
159
+ type: source.type,
160
+ packageName: source.packageName,
161
+ ...(source.packageVersion == null
162
+ ? {}
163
+ : { packageVersion: source.packageVersion }),
164
+ };
136
165
  const forwardedEnvironment = [
137
166
  ...new Set(implementation.forwardEnv ?? []),
138
167
  ].sort();
@@ -144,7 +173,7 @@ export function createImplementationIdentity({
144
173
  const payload = {
145
174
  harnessId,
146
175
  acpVersion,
147
- acquisition,
176
+ source: sourceIdentity,
148
177
  executable: implementation.executable,
149
178
  args: implementation.args ?? [],
150
179
  clientApp,
@@ -171,7 +200,7 @@ export function createImplementationInstallCommand({
171
200
  }): string {
172
201
  return (
173
202
  `pnpm --dir ${implementationDir} install` +
174
- (isLockedImplementation(implementation) ? ' --frozen-lockfile' : '') +
203
+ (implementation.source.type === 'npm-locked' ? ' --frozen-lockfile' : '') +
175
204
  ` --prod --store-dir ${storeDir}`
176
205
  );
177
206
  }
@@ -196,19 +225,22 @@ export function resolveImplementationEnvironment({
196
225
  };
197
226
  }
198
227
 
199
- function validateSimpleImplementation({
200
- implementation,
228
+ function validateNpmSimpleSource({
229
+ source,
201
230
  }: {
202
- implementation: ACPSimpleNpmImplementation;
231
+ source: ACPNpmSimpleSource;
203
232
  }): void {
204
- if (!PACKAGE_NAME_REGEXP.test(implementation.packageName)) {
233
+ if (!PACKAGE_NAME_REGEXP.test(source.packageName)) {
205
234
  throw new Error(
206
- `ACP npm package name is invalid: ${JSON.stringify(implementation.packageName)}.`,
235
+ `ACP npm package name is invalid: ${JSON.stringify(source.packageName)}.`,
207
236
  );
208
237
  }
209
- if (!EXACT_SEMVER_REGEXP.test(implementation.version)) {
238
+ if (
239
+ source.packageVersion != null &&
240
+ !EXACT_SEMVER_REGEXP.test(source.packageVersion)
241
+ ) {
210
242
  throw new Error(
211
- `ACP npm implementation version must be an exact semantic version; received ${JSON.stringify(implementation.version)}.`,
243
+ `ACP npm package version must be an exact semantic version; received ${JSON.stringify(source.packageVersion)}.`,
212
244
  );
213
245
  }
214
246
  }
@@ -257,12 +289,6 @@ function getImplementationEnvironmentKeys({
257
289
  ].sort();
258
290
  }
259
291
 
260
- function isLockedImplementation(
261
- implementation: ACPNpmImplementation,
262
- ): implementation is Extract<ACPNpmImplementation, { mode: 'locked' }> {
263
- return implementation.mode === 'locked';
264
- }
265
-
266
292
  function stableStringify({ value }: { value: unknown }): string {
267
293
  return JSON.stringify(sortValue({ value }));
268
294
  }
package/src/v1/index.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  export { createACPV1 } from './acp-v1-harness';
2
2
  export type {
3
3
  ACPAuthentication,
4
- ACPLockedNpmImplementation,
5
- ACPNpmImplementation,
4
+ ACPNpmLockedSource,
5
+ ACPNpmSimpleSource,
6
6
  ACPPermissionModeMapping,
7
7
  ACPPermissionModeTarget,
8
8
  ACPProfileValue,
@@ -10,7 +10,7 @@ export type {
10
10
  ACPProviderAuthenticationMode,
11
11
  ACPSerializablePrimitive,
12
12
  ACPSerializableValue,
13
- ACPSimpleNpmImplementation,
13
+ ACPSource,
14
14
  ACPV1Settings,
15
15
  ACPValueSource,
16
16
  } from './acp-v1-settings';