@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/CHANGELOG.md +11 -0
- package/README.md +5 -6
- package/dist/bridge/host-tool-mcp.mjs +1 -1
- package/dist/bridge/index.mjs +71 -32
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.d.ts +25 -19
- package/dist/index.js +98 -103
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/acp-harness.ts +7 -60
- package/src/index.ts +3 -3
- package/src/v1/acp-v1-harness.ts +32 -18
- package/src/v1/acp-v1-settings.ts +19 -20
- package/src/v1/bridge/acp-diagnostics.ts +27 -1
- package/src/v1/bridge/agent-stderr-monitor.ts +52 -0
- package/src/v1/bridge/index.ts +19 -34
- package/src/v1/implementation.ts +73 -47
- package/src/v1/index.ts +3 -3
package/src/v1/implementation.ts
CHANGED
|
@@ -4,11 +4,42 @@ import type {
|
|
|
4
4
|
ACPProviderAuthenticationCompatibility,
|
|
5
5
|
} from '../acp-auth';
|
|
6
6
|
import type {
|
|
7
|
-
|
|
7
|
+
ACPNpmSimpleSource,
|
|
8
8
|
ACPPermissionModeMapping,
|
|
9
|
-
|
|
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
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
60
|
-
|
|
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
|
-
[
|
|
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
|
-
|
|
85
|
-
|
|
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
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
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
|
|
200
|
-
|
|
228
|
+
function validateNpmSimpleSource({
|
|
229
|
+
source,
|
|
201
230
|
}: {
|
|
202
|
-
|
|
231
|
+
source: ACPNpmSimpleSource;
|
|
203
232
|
}): void {
|
|
204
|
-
if (!PACKAGE_NAME_REGEXP.test(
|
|
233
|
+
if (!PACKAGE_NAME_REGEXP.test(source.packageName)) {
|
|
205
234
|
throw new Error(
|
|
206
|
-
`ACP npm package name is invalid: ${JSON.stringify(
|
|
235
|
+
`ACP npm package name is invalid: ${JSON.stringify(source.packageName)}.`,
|
|
207
236
|
);
|
|
208
237
|
}
|
|
209
|
-
if (
|
|
238
|
+
if (
|
|
239
|
+
source.packageVersion != null &&
|
|
240
|
+
!EXACT_SEMVER_REGEXP.test(source.packageVersion)
|
|
241
|
+
) {
|
|
210
242
|
throw new Error(
|
|
211
|
-
`ACP npm
|
|
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
|
-
|
|
5
|
-
|
|
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
|
-
|
|
13
|
+
ACPSource,
|
|
14
14
|
ACPV1Settings,
|
|
15
15
|
ACPValueSource,
|
|
16
16
|
} from './acp-v1-settings';
|