agentwheel 0.20.18 → 0.20.20
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/README.md +11 -0
- package/dist/{apply-ZGCJLZMZ.js → apply-Z5GVCPA4.js} +3 -3
- package/dist/{chunk-A44XYLUT.js → chunk-45WVSUJA.js} +2 -2
- package/dist/{chunk-GE7F76AC.js → chunk-BNIF3FUR.js} +9 -0
- package/dist/{chunk-FP26KSBM.js → chunk-FGFPAZ4J.js} +209 -4
- package/dist/{chunk-U2GRG4UI.js → chunk-QABA4WUP.js} +1 -1
- package/dist/{identify-O54QXPQR.js → identify-M6IA4RS7.js} +2 -2
- package/dist/index.js +410 -445
- package/dist/{transaction-4KBNHDQX.js → transaction-NLAIJ2ZZ.js} +2 -2
- package/openpack.json +1 -1
- package/package.json +1 -1
- package/skills/agentwheel/SKILL.md +30 -1
- package/skills/agentwheel-discovery/SKILL.md +1 -1
package/dist/index.js
CHANGED
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
uninstall,
|
|
38
38
|
withManifestRevision,
|
|
39
39
|
writeInstallManifest
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-45WVSUJA.js";
|
|
41
41
|
import {
|
|
42
42
|
CURRENT_WORKSPACE_SCHEMA_VERSION,
|
|
43
43
|
GovernedMutation,
|
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
findExistingWorkspaceRoot,
|
|
57
57
|
findWorkspaceRoot,
|
|
58
58
|
fleetIdSchema,
|
|
59
|
+
getAdapter,
|
|
59
60
|
globalWorkspaceConfigPath,
|
|
60
61
|
installManifestPath,
|
|
61
62
|
installRootForAdapterInstallationType,
|
|
@@ -74,6 +75,7 @@ import {
|
|
|
74
75
|
packageItemRequireSchema,
|
|
75
76
|
packageItemSuggestSchema,
|
|
76
77
|
packageSupersedesEntrySchema,
|
|
78
|
+
packagesForTarget,
|
|
77
79
|
parseSemver,
|
|
78
80
|
readApplyJournal,
|
|
79
81
|
readMergedWorkspaceConfig,
|
|
@@ -98,25 +100,26 @@ import {
|
|
|
98
100
|
workspaceSelectionImportSchema,
|
|
99
101
|
writeApplyJournal,
|
|
100
102
|
writeWorkspaceConfig
|
|
101
|
-
} from "./chunk-
|
|
103
|
+
} from "./chunk-FGFPAZ4J.js";
|
|
102
104
|
import {
|
|
103
105
|
inferSourceDriverName
|
|
104
|
-
} from "./chunk-
|
|
106
|
+
} from "./chunk-QABA4WUP.js";
|
|
105
107
|
import {
|
|
106
108
|
hashPath,
|
|
107
109
|
isAlreadyExists,
|
|
108
110
|
isIgnoredGeneratedEntry,
|
|
109
111
|
listFiles,
|
|
110
112
|
pathExists,
|
|
113
|
+
removeOnFailure,
|
|
111
114
|
withFilesystemLock,
|
|
112
115
|
writeJsonAtomic
|
|
113
|
-
} from "./chunk-
|
|
116
|
+
} from "./chunk-BNIF3FUR.js";
|
|
114
117
|
|
|
115
118
|
// src/cli/index.ts
|
|
116
119
|
import { createHash as createHash16 } from "crypto";
|
|
117
120
|
import { existsSync } from "fs";
|
|
118
|
-
import { mkdir as mkdir16, mkdtemp as
|
|
119
|
-
import { homedir as homedir12, tmpdir as
|
|
121
|
+
import { mkdir as mkdir16, mkdtemp as mkdtemp3, realpath as realpath3, rm as rm10, writeFile as writeFile13 } from "fs/promises";
|
|
122
|
+
import { homedir as homedir12, tmpdir as tmpdir4 } from "os";
|
|
120
123
|
import { basename as basename21, dirname as dirname23, isAbsolute as isAbsolute5, join as join46, relative as relative11, resolve as resolve27 } from "path";
|
|
121
124
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
122
125
|
import { Command } from "commander";
|
|
@@ -124,185 +127,6 @@ import { Command } from "commander";
|
|
|
124
127
|
// src/adapters/resolve.ts
|
|
125
128
|
import { resolve as resolve2 } from "path";
|
|
126
129
|
|
|
127
|
-
// src/adapters/claude.ts
|
|
128
|
-
var claudeAdapter = {
|
|
129
|
-
name: "claude",
|
|
130
|
-
displayName: "Claude Code",
|
|
131
|
-
targets: {
|
|
132
|
-
instructions: {
|
|
133
|
-
local: { enabled: true, dest: "CLAUDE.md", mode: "managed-block" },
|
|
134
|
-
user: { enabled: true, root: "home", dest: ".claude/CLAUDE.md", mode: "managed-block" }
|
|
135
|
-
},
|
|
136
|
-
rules: {
|
|
137
|
-
local: { enabled: true, dest: ".claude/rules", formats: ["markdown-rule", "claude-markdown-rule"] },
|
|
138
|
-
user: { enabled: true, root: "home", dest: ".claude/rules", formats: ["markdown-rule", "claude-markdown-rule"] }
|
|
139
|
-
},
|
|
140
|
-
skills: {
|
|
141
|
-
local: { enabled: true, dest: ".claude/skills" },
|
|
142
|
-
user: { enabled: true, root: "home", dest: ".claude/skills" }
|
|
143
|
-
},
|
|
144
|
-
commands: {
|
|
145
|
-
local: { enabled: true, dest: ".claude/commands" },
|
|
146
|
-
user: { enabled: true, root: "home", dest: ".claude/commands" }
|
|
147
|
-
},
|
|
148
|
-
subagents: {
|
|
149
|
-
local: { enabled: true, dest: ".claude/agents" },
|
|
150
|
-
user: { enabled: true, root: "home", dest: ".claude/agents" }
|
|
151
|
-
},
|
|
152
|
-
plugins: {
|
|
153
|
-
local: { enabled: true, dest: ".agentwheel/plugins/claude", semantic: "claude-plugin" },
|
|
154
|
-
user: { enabled: true, root: "home", dest: ".agentwheel/plugins/claude", semantic: "claude-plugin" }
|
|
155
|
-
},
|
|
156
|
-
mcp: {
|
|
157
|
-
local: { enabled: true, dest: ".mcp.json", merge: "json-deep" }
|
|
158
|
-
},
|
|
159
|
-
hooks: {
|
|
160
|
-
local: { enabled: true, dest: ".claude/settings.json", merge: "json-deep" },
|
|
161
|
-
user: { enabled: true, root: "home", dest: ".claude/settings.json", merge: "json-deep" }
|
|
162
|
-
},
|
|
163
|
-
settings: {
|
|
164
|
-
local: { enabled: true, dest: ".claude/settings.json", merge: "json-deep" },
|
|
165
|
-
user: { enabled: true, root: "home", dest: ".claude/settings.json", merge: "json-deep" }
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
// src/adapters/copilot.ts
|
|
171
|
-
var copilotAdapter = {
|
|
172
|
-
name: "copilot",
|
|
173
|
-
displayName: "GitHub Copilot CLI",
|
|
174
|
-
targets: {
|
|
175
|
-
instructions: {
|
|
176
|
-
local: { enabled: true, dest: ".github/copilot-instructions.md", mode: "managed-block" },
|
|
177
|
-
user: { enabled: true, root: "home", dest: ".copilot/copilot-instructions.md", mode: "managed-block" }
|
|
178
|
-
},
|
|
179
|
-
rules: {
|
|
180
|
-
local: { enabled: true, dest: ".github/instructions", formats: ["markdown-rule", "copilot-instruction-rule"], semantic: "copilot-instruction" },
|
|
181
|
-
user: { enabled: true, root: "home", dest: ".copilot/instructions", formats: ["markdown-rule", "copilot-instruction-rule"], semantic: "copilot-instruction" }
|
|
182
|
-
},
|
|
183
|
-
commands: {
|
|
184
|
-
local: { enabled: true, dest: ".github/prompts", semantic: "copilot-prompt" }
|
|
185
|
-
},
|
|
186
|
-
skills: {
|
|
187
|
-
local: { enabled: true, dest: ".github/skills" },
|
|
188
|
-
user: { enabled: true, root: "home", dest: ".copilot/skills" }
|
|
189
|
-
},
|
|
190
|
-
plugins: {
|
|
191
|
-
user: { enabled: true, root: "home", dest: ".agentwheel/plugins/copilot", semantic: "copilot-plugin" }
|
|
192
|
-
},
|
|
193
|
-
subagents: {
|
|
194
|
-
local: { enabled: true, dest: ".github/agents", semantic: "copilot-agent" },
|
|
195
|
-
user: { enabled: true, root: "home", dest: ".copilot/agents", semantic: "copilot-agent" }
|
|
196
|
-
},
|
|
197
|
-
mcp: {
|
|
198
|
-
local: { enabled: true, dest: ".github/mcp.json", merge: "json-deep" },
|
|
199
|
-
user: { enabled: true, root: "home", dest: ".copilot/mcp-config.json", merge: "json-deep" }
|
|
200
|
-
},
|
|
201
|
-
hooks: {
|
|
202
|
-
local: { enabled: true, dest: ".github/hooks" },
|
|
203
|
-
user: { enabled: true, root: "home", dest: ".copilot/hooks" }
|
|
204
|
-
},
|
|
205
|
-
settings: {
|
|
206
|
-
local: { enabled: true, dest: ".github/settings.json", merge: "json-deep" },
|
|
207
|
-
user: { enabled: true, root: "home", dest: ".copilot/settings.json", merge: "json-deep" }
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
};
|
|
211
|
-
|
|
212
|
-
// src/adapters/codex.ts
|
|
213
|
-
var codexAdapter = {
|
|
214
|
-
name: "codex",
|
|
215
|
-
displayName: "Codex CLI",
|
|
216
|
-
targets: {
|
|
217
|
-
instructions: {
|
|
218
|
-
local: { enabled: true, dest: "AGENTS.md", mode: "managed-block" },
|
|
219
|
-
user: { enabled: true, root: "home", dest: ".codex/AGENTS.md", mode: "managed-block" }
|
|
220
|
-
},
|
|
221
|
-
skills: {
|
|
222
|
-
local: { enabled: true, dest: ".agents/skills" },
|
|
223
|
-
user: { enabled: true, root: "home", dest: ".agents/skills" }
|
|
224
|
-
},
|
|
225
|
-
plugins: {
|
|
226
|
-
local: { enabled: true, dest: ".agentwheel/plugins/codex", semantic: "codex-plugin" },
|
|
227
|
-
user: { enabled: true, root: "home", dest: ".agentwheel/plugins/codex", semantic: "codex-plugin" }
|
|
228
|
-
},
|
|
229
|
-
subagents: {
|
|
230
|
-
local: { enabled: true, dest: ".codex/agents", semantic: "codex-subagent" },
|
|
231
|
-
user: { enabled: true, root: "home", dest: ".codex/agents", semantic: "codex-subagent" }
|
|
232
|
-
},
|
|
233
|
-
mcp: {
|
|
234
|
-
local: { enabled: true, dest: ".codex/config.toml", merge: "codex-toml-mcp" },
|
|
235
|
-
user: { enabled: true, root: "home", dest: ".codex/config.toml", merge: "codex-toml-mcp" }
|
|
236
|
-
},
|
|
237
|
-
hooks: {
|
|
238
|
-
local: { enabled: true, dest: ".codex/hooks.json", merge: "json-deep" },
|
|
239
|
-
user: { enabled: true, root: "home", dest: ".codex/hooks.json", merge: "json-deep" }
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
|
|
244
|
-
// src/adapters/hermes.ts
|
|
245
|
-
var hermesAdapter = {
|
|
246
|
-
name: "hermes",
|
|
247
|
-
displayName: "Hermes",
|
|
248
|
-
targets: {
|
|
249
|
-
instructions: {
|
|
250
|
-
local: { enabled: true, dest: "AGENTS.md", mode: "managed-block" },
|
|
251
|
-
// Hermes documents SOUL.md as the user-level instruction surface.
|
|
252
|
-
user: { enabled: true, root: "home", dest: ".hermes/SOUL.md", mode: "managed-block" }
|
|
253
|
-
},
|
|
254
|
-
skills: {
|
|
255
|
-
user: { enabled: true, root: "home", dest: ".hermes/skills" }
|
|
256
|
-
},
|
|
257
|
-
mcp: {
|
|
258
|
-
user: { enabled: true, root: "home", dest: ".hermes/config.yaml", merge: "yaml-deep" }
|
|
259
|
-
},
|
|
260
|
-
settings: {
|
|
261
|
-
user: { enabled: true, root: "home", dest: ".hermes/config.yaml", merge: "yaml-deep" }
|
|
262
|
-
},
|
|
263
|
-
plugins: {
|
|
264
|
-
user: { enabled: true, root: "home", dest: ".agentwheel/plugins/hermes", semantic: "hermes-plugin" }
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
};
|
|
268
|
-
|
|
269
|
-
// src/adapters/openclaw.ts
|
|
270
|
-
var openClawAdapter = {
|
|
271
|
-
name: "openclaw",
|
|
272
|
-
displayName: "OpenClaw",
|
|
273
|
-
targets: {
|
|
274
|
-
instructions: {
|
|
275
|
-
user: { enabled: true, root: "home", dest: ".openclaw/workspace/AGENTS.md", mode: "managed-block" }
|
|
276
|
-
},
|
|
277
|
-
skills: {
|
|
278
|
-
local: { enabled: true, dest: "skills" },
|
|
279
|
-
user: { enabled: true, root: "home", dest: ".openclaw/skills" }
|
|
280
|
-
},
|
|
281
|
-
subagents: {
|
|
282
|
-
user: { enabled: true, root: "home", dest: ".openclaw/workspace-subagents", semantic: "openclaw-subagent" }
|
|
283
|
-
},
|
|
284
|
-
mcp: {
|
|
285
|
-
user: { enabled: true, root: "home", dest: ".openclaw/openclaw.json", merge: "openclaw-json-deep" }
|
|
286
|
-
},
|
|
287
|
-
settings: {
|
|
288
|
-
user: { enabled: true, root: "home", dest: ".openclaw/openclaw.json", merge: "openclaw-json-deep" }
|
|
289
|
-
},
|
|
290
|
-
plugins: {
|
|
291
|
-
local: { enabled: true, dest: ".openclaw/plugins", formats: ["openclaw-plugin", "openclaw-clawhub-plugin"], semantic: "openclaw-plugin" }
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
// src/adapters/index.ts
|
|
297
|
-
var adapters = [openClawAdapter, claudeAdapter, codexAdapter, hermesAdapter, copilotAdapter];
|
|
298
|
-
function getAdapter(name) {
|
|
299
|
-
const adapter = adapters.find((candidate) => candidate.name === name);
|
|
300
|
-
if (!adapter) {
|
|
301
|
-
throw new Error(`Unknown adapter: ${name}`);
|
|
302
|
-
}
|
|
303
|
-
return adapter;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
130
|
// src/adapters/programmatic.ts
|
|
307
131
|
import { stat, readFile, writeFile } from "fs/promises";
|
|
308
132
|
import { tmpdir } from "os";
|
|
@@ -4079,6 +3903,58 @@ function errorMessage3(error) {
|
|
|
4079
3903
|
return error instanceof Error ? error.message : String(error);
|
|
4080
3904
|
}
|
|
4081
3905
|
|
|
3906
|
+
// src/source/git-source.ts
|
|
3907
|
+
import { posix } from "path";
|
|
3908
|
+
var SUBPATH_SEPARATOR = "//";
|
|
3909
|
+
function parseGitSource(source) {
|
|
3910
|
+
if (source.startsWith("github:")) {
|
|
3911
|
+
const rest = source.slice("github:".length);
|
|
3912
|
+
const hashIndex = rest.indexOf("#");
|
|
3913
|
+
const repo = hashIndex >= 0 ? rest.slice(0, hashIndex) : rest;
|
|
3914
|
+
if (!repo.includes("/")) throw new Error(`Invalid GitHub source: ${source}`);
|
|
3915
|
+
return {
|
|
3916
|
+
url: `https://github.com/${repo.replace(/\.git$/i, "")}.git`,
|
|
3917
|
+
...splitFragment(hashIndex >= 0 ? rest.slice(hashIndex + 1) : void 0, source)
|
|
3918
|
+
};
|
|
3919
|
+
}
|
|
3920
|
+
if (source.startsWith("git:")) {
|
|
3921
|
+
const rest = source.slice("git:".length);
|
|
3922
|
+
const hashIndex = rest.lastIndexOf("#");
|
|
3923
|
+
if (hashIndex < 0) return { url: rest };
|
|
3924
|
+
return { url: rest.slice(0, hashIndex), ...splitFragment(rest.slice(hashIndex + 1), source) };
|
|
3925
|
+
}
|
|
3926
|
+
throw new Error(`Invalid git source: ${source}`);
|
|
3927
|
+
}
|
|
3928
|
+
function formatGitSource(url, ref, subpath) {
|
|
3929
|
+
return subpath ? `git:${url}#${ref}${SUBPATH_SEPARATOR}${subpath}` : `git:${url}#${ref}`;
|
|
3930
|
+
}
|
|
3931
|
+
function normalizeGitSubpath(subpath, source) {
|
|
3932
|
+
if (subpath === void 0) return void 0;
|
|
3933
|
+
if (subpath.includes("\\")) throw new Error(`Git source subpath must use forward slashes: ${source}`);
|
|
3934
|
+
if (subpath.startsWith("/")) throw new Error(`Git source subpath must be relative to the repository: ${source}`);
|
|
3935
|
+
const normalized = posix.normalize(subpath).replace(/\/+$/g, "");
|
|
3936
|
+
if (normalized === "." || normalized === "") return void 0;
|
|
3937
|
+
if (normalized === ".." || normalized.startsWith("../")) {
|
|
3938
|
+
throw new Error(`Git source subpath escapes the repository: ${source}`);
|
|
3939
|
+
}
|
|
3940
|
+
return normalized;
|
|
3941
|
+
}
|
|
3942
|
+
function resolveGitRelativeSubpath(declaringSubpath, relative12, source) {
|
|
3943
|
+
const joined = posix.normalize(posix.join(declaringSubpath ?? ".", relative12));
|
|
3944
|
+
if (joined === ".." || joined.startsWith("../")) {
|
|
3945
|
+
throw new Error(`Relative dependency '${relative12}' escapes the git repository it is declared in: ${source}`);
|
|
3946
|
+
}
|
|
3947
|
+
return normalizeGitSubpath(joined, source);
|
|
3948
|
+
}
|
|
3949
|
+
function splitFragment(fragment, source) {
|
|
3950
|
+
if (fragment === void 0) return {};
|
|
3951
|
+
const separator = fragment.indexOf(SUBPATH_SEPARATOR);
|
|
3952
|
+
if (separator < 0) return fragment ? { ref: fragment } : {};
|
|
3953
|
+
const ref = fragment.slice(0, separator);
|
|
3954
|
+
const subpath = normalizeGitSubpath(fragment.slice(separator + SUBPATH_SEPARATOR.length), source);
|
|
3955
|
+
return { ...ref ? { ref } : {}, ...subpath ? { subpath } : {} };
|
|
3956
|
+
}
|
|
3957
|
+
|
|
4082
3958
|
// src/source/git.ts
|
|
4083
3959
|
var execFileAsync = promisify(execFile);
|
|
4084
3960
|
var GitSourceDriver = class {
|
|
@@ -4138,15 +4014,18 @@ var GitSourceDriver = class {
|
|
|
4138
4014
|
return { path, leasePath };
|
|
4139
4015
|
}
|
|
4140
4016
|
);
|
|
4141
|
-
const
|
|
4142
|
-
|
|
4017
|
+
const packageRoot = parsed.subpath ? join19(snapshot.path, parsed.subpath) : snapshot.path;
|
|
4018
|
+
if (parsed.subpath && !await isDirectory(packageRoot)) {
|
|
4019
|
+
throw new Error(`Git source subpath '${parsed.subpath}' does not exist at ${resolvedCommit} in ${parsed.url}`);
|
|
4020
|
+
}
|
|
4021
|
+
const manifest = await readPackageManifest(packageRoot);
|
|
4143
4022
|
return {
|
|
4144
4023
|
...resolved,
|
|
4145
|
-
resolvedPath:
|
|
4024
|
+
resolvedPath: packageRoot,
|
|
4146
4025
|
packageName: manifest?.name,
|
|
4147
4026
|
packageVersion: manifest?.version,
|
|
4148
4027
|
resolvedCommit,
|
|
4149
|
-
sourceHash: await hashPath(
|
|
4028
|
+
sourceHash: await hashPath(packageRoot),
|
|
4150
4029
|
cacheLeasePath: snapshot.leasePath
|
|
4151
4030
|
};
|
|
4152
4031
|
}, "git cache");
|
|
@@ -4164,22 +4043,12 @@ var GitSourceDriver = class {
|
|
|
4164
4043
|
return resolved;
|
|
4165
4044
|
}
|
|
4166
4045
|
};
|
|
4167
|
-
function
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
return { url: `https://github.com/${repo}.git`, ref };
|
|
4173
|
-
}
|
|
4174
|
-
if (source.startsWith("git:")) {
|
|
4175
|
-
const rest = source.slice("git:".length);
|
|
4176
|
-
const hashIndex = rest.lastIndexOf("#");
|
|
4177
|
-
if (hashIndex >= 0) {
|
|
4178
|
-
return { url: rest.slice(0, hashIndex), ref: rest.slice(hashIndex + 1) };
|
|
4179
|
-
}
|
|
4180
|
-
return { url: rest };
|
|
4046
|
+
async function isDirectory(path) {
|
|
4047
|
+
try {
|
|
4048
|
+
return (await stat4(path)).isDirectory();
|
|
4049
|
+
} catch {
|
|
4050
|
+
return false;
|
|
4181
4051
|
}
|
|
4182
|
-
throw new Error(`Invalid git source: ${source}`);
|
|
4183
4052
|
}
|
|
4184
4053
|
function cachePathFor2(url, cacheRoot) {
|
|
4185
4054
|
const root = cacheRoot ? resolve5(cacheRoot) : join19(homedir2(), ".agentwheel", "cache");
|
|
@@ -5337,7 +5206,8 @@ function claudeAgentName(artifact) {
|
|
|
5337
5206
|
|
|
5338
5207
|
// src/staging/staging.ts
|
|
5339
5208
|
async function stageSource(driver, source, options = {}) {
|
|
5340
|
-
|
|
5209
|
+
const raw = await stageSourceRaw(driver, source, options);
|
|
5210
|
+
return removeOnFailure(raw.root, () => renderStagedBundle(raw, options));
|
|
5341
5211
|
}
|
|
5342
5212
|
async function stageSourceRaw(driver, source, options = {}) {
|
|
5343
5213
|
const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(source, options))));
|
|
@@ -5352,25 +5222,27 @@ async function stageResolvedSourceRaw(driver, resolved) {
|
|
|
5352
5222
|
const artifacts = await driver.list(resolved);
|
|
5353
5223
|
return stageResolvedArtifactsRaw(resolved, artifacts);
|
|
5354
5224
|
}
|
|
5355
|
-
async function stageResolvedArtifactsRaw(resolved, artifacts) {
|
|
5356
|
-
const root = await mkdtemp(join27(
|
|
5225
|
+
async function stageResolvedArtifactsRaw(resolved, artifacts, parentDir = tmpdir2()) {
|
|
5226
|
+
const root = await mkdtemp(join27(parentDir, "agentwheel-stage-"));
|
|
5357
5227
|
const stagedArtifacts = [];
|
|
5358
|
-
|
|
5359
|
-
const
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5228
|
+
await removeOnFailure(root, async () => {
|
|
5229
|
+
for (const artifact of artifacts) {
|
|
5230
|
+
const stagedPath = join27(root, artifact.relativePath);
|
|
5231
|
+
await mkdir11(dirname13(stagedPath), { recursive: true });
|
|
5232
|
+
await cp3(artifact.sourcePath, stagedPath, {
|
|
5233
|
+
recursive: artifact.kind === "dir",
|
|
5234
|
+
dereference: true,
|
|
5235
|
+
filter: (path) => !isIgnoredGeneratedEntry(basename16(path))
|
|
5236
|
+
});
|
|
5237
|
+
await composeAssets(artifact, resolved.resolvedPath, stagedPath);
|
|
5238
|
+
stagedArtifacts.push({
|
|
5239
|
+
...artifact,
|
|
5240
|
+
stagedPath,
|
|
5241
|
+
hash: await hashPath(stagedPath),
|
|
5242
|
+
channel: artifact.channel ?? "managed"
|
|
5243
|
+
});
|
|
5244
|
+
}
|
|
5245
|
+
});
|
|
5374
5246
|
return {
|
|
5375
5247
|
root,
|
|
5376
5248
|
source: resolved,
|
|
@@ -5527,8 +5399,7 @@ import { dirname as dirname15, join as join30, relative as relative6 } from "pat
|
|
|
5527
5399
|
|
|
5528
5400
|
// src/resolve/graph.ts
|
|
5529
5401
|
import { createHash as createHash6 } from "crypto";
|
|
5530
|
-
import {
|
|
5531
|
-
import { tmpdir as tmpdir3 } from "os";
|
|
5402
|
+
import { readdir as readdir7, readFile as readFile17, stat as stat11 } from "fs/promises";
|
|
5532
5403
|
import { basename as basename17, extname as extname4, join as join29 } from "path";
|
|
5533
5404
|
|
|
5534
5405
|
// src/model/workspace-composition.ts
|
|
@@ -5789,7 +5660,7 @@ var RegistryClient = class {
|
|
|
5789
5660
|
}
|
|
5790
5661
|
};
|
|
5791
5662
|
async function resolvePackageSource(source, workspaceRoot, options = {}) {
|
|
5792
|
-
const { isExplicitSource } = await import("./identify-
|
|
5663
|
+
const { isExplicitSource } = await import("./identify-M6IA4RS7.js");
|
|
5793
5664
|
if (await isExplicitSource(source)) return { source };
|
|
5794
5665
|
const entry = await new RegistryClient({ workspaceRoot, offline: options.offline, warn: options.warn }).resolve(source);
|
|
5795
5666
|
if (!entry) {
|
|
@@ -5831,6 +5702,17 @@ async function normalizeDependencySource(source, options) {
|
|
|
5831
5702
|
if (isBareRegistryName(trimmed)) {
|
|
5832
5703
|
return normalizeRegistrySource(trimmed, options);
|
|
5833
5704
|
}
|
|
5705
|
+
if (options.declaringGitSource && (trimmed === "." || trimmed === ".." || trimmed.startsWith("./") || trimmed.startsWith("../"))) {
|
|
5706
|
+
const declaring = options.declaringGitSource;
|
|
5707
|
+
const subpath = resolveGitRelativeSubpath(declaring.subpath, trimmed, source);
|
|
5708
|
+
const normalizedSource = formatGitSource(declaring.url, declaring.commit, subpath);
|
|
5709
|
+
return {
|
|
5710
|
+
source: normalizedSource,
|
|
5711
|
+
normalizedSource,
|
|
5712
|
+
driver: "git",
|
|
5713
|
+
requestedRef: declaring.commit
|
|
5714
|
+
};
|
|
5715
|
+
}
|
|
5834
5716
|
if (isLocalSource(trimmed)) {
|
|
5835
5717
|
const path = localSourcePath(trimmed);
|
|
5836
5718
|
const resolvedPath = resolveLocalPath(path, options.declaringPackageRoot);
|
|
@@ -5841,10 +5723,10 @@ async function normalizeDependencySource(source, options) {
|
|
|
5841
5723
|
};
|
|
5842
5724
|
}
|
|
5843
5725
|
if (trimmed.startsWith("github:") || trimmed.startsWith("git:")) {
|
|
5844
|
-
const parsed =
|
|
5726
|
+
const parsed = parseGitSource(trimmed);
|
|
5845
5727
|
const requestedRef = options.ref ?? parsed.ref ?? "HEAD";
|
|
5846
5728
|
const url = normalizeGitRemoteUrl(parsed.url, options.declaringPackageRoot);
|
|
5847
|
-
const normalizedSource =
|
|
5729
|
+
const normalizedSource = formatGitSource(url, requestedRef, parsed.subpath);
|
|
5848
5730
|
return {
|
|
5849
5731
|
source: normalizedSource,
|
|
5850
5732
|
normalizedSource,
|
|
@@ -5921,20 +5803,6 @@ async function normalizeRegistrySource(name, options) {
|
|
|
5921
5803
|
normalizedSource: `registry:${name}:${resolved.normalizedSource}`
|
|
5922
5804
|
};
|
|
5923
5805
|
}
|
|
5924
|
-
function parseGitSource2(source) {
|
|
5925
|
-
if (source.startsWith("github:")) {
|
|
5926
|
-
const rest2 = source.slice("github:".length);
|
|
5927
|
-
const [repo, ref] = rest2.split("#", 2);
|
|
5928
|
-
if (!repo.includes("/")) throw new Error(`Invalid GitHub dependency source: ${source}`);
|
|
5929
|
-
return { url: `https://github.com/${repo.replace(/\.git$/i, "")}.git`, ref };
|
|
5930
|
-
}
|
|
5931
|
-
const rest = source.slice("git:".length);
|
|
5932
|
-
const hashIndex = rest.lastIndexOf("#");
|
|
5933
|
-
if (hashIndex >= 0) {
|
|
5934
|
-
return { url: rest.slice(0, hashIndex), ref: rest.slice(hashIndex + 1) };
|
|
5935
|
-
}
|
|
5936
|
-
return { url: rest };
|
|
5937
|
-
}
|
|
5938
5806
|
function normalizeGitRemoteUrl(url, declaringPackageRoot) {
|
|
5939
5807
|
if (url.startsWith("./") || url.startsWith("../") || url.startsWith("/") || url === "~" || url.startsWith("~/")) {
|
|
5940
5808
|
return resolveLocalPath(url, declaringPackageRoot);
|
|
@@ -5985,8 +5853,7 @@ var SnapshotConflictError = class extends Error {
|
|
|
5985
5853
|
};
|
|
5986
5854
|
var cacheLocks = /* @__PURE__ */ new Map();
|
|
5987
5855
|
async function resolveDependencyGraph(roots, options) {
|
|
5988
|
-
if (roots.length === 0) throw new Error("At least one graph root is required.");
|
|
5989
|
-
const graphRoot = await mkdtemp2(join29(tmpdir3(), "agentwheel-graph-"));
|
|
5856
|
+
if (roots.length === 0 && !options.allowEmptyRoots) throw new Error("At least one graph root is required.");
|
|
5990
5857
|
const fetchCache = /* @__PURE__ */ new Map();
|
|
5991
5858
|
const nodesByKey = /* @__PURE__ */ new Map();
|
|
5992
5859
|
const nodesBySource = /* @__PURE__ */ new Map();
|
|
@@ -6052,7 +5919,6 @@ async function resolveDependencyGraph(roots, options) {
|
|
|
6052
5919
|
}
|
|
6053
5920
|
detectDirectCollisions(rawNodes);
|
|
6054
5921
|
return {
|
|
6055
|
-
root: graphRoot,
|
|
6056
5922
|
roots: rootResults.sort((a, b) => a.rootId.localeCompare(b.rootId)),
|
|
6057
5923
|
nodes: rawNodes.map((state) => state.node),
|
|
6058
5924
|
rawNodes,
|
|
@@ -6094,6 +5960,7 @@ async function processRequirement(requirement, options, fetchCache, nodesByKey,
|
|
|
6094
5960
|
let lockedByReference = lockedNodeForRequirementReference(requirement, options, lockLabel);
|
|
6095
5961
|
let normalized = lockedByReference ? normalizedSourceFromLockedNode(lockedByReference.node) : await normalizeDependencySource(requirement.source, {
|
|
6096
5962
|
declaringPackageRoot: requirement.declaringPackageRoot,
|
|
5963
|
+
declaringGitSource: requirement.declaringGitSource,
|
|
6097
5964
|
workspaceRoot: options.workspaceRoot,
|
|
6098
5965
|
ref: requirement.ref,
|
|
6099
5966
|
registryClient: options.registryClient
|
|
@@ -6101,6 +5968,7 @@ async function processRequirement(requirement, options, fetchCache, nodesByKey,
|
|
|
6101
5968
|
if (lockedByReference && shouldCheckLockedRootSource(requirement)) {
|
|
6102
5969
|
const declared = await normalizeDependencySource(requirement.source, {
|
|
6103
5970
|
declaringPackageRoot: requirement.declaringPackageRoot,
|
|
5971
|
+
declaringGitSource: requirement.declaringGitSource,
|
|
6104
5972
|
workspaceRoot: options.workspaceRoot,
|
|
6105
5973
|
ref: requirement.ref,
|
|
6106
5974
|
registryClient: options.registryClient
|
|
@@ -6378,6 +6246,7 @@ function dependencyRequirement(state, fetched, alias, dependency, select, chain,
|
|
|
6378
6246
|
useLock: dependency.mode !== "tracking" || options.lockedResolution === true && !updateClosure,
|
|
6379
6247
|
updateClosure,
|
|
6380
6248
|
declaringPackageRoot: fetched.resolved.resolvedPath,
|
|
6249
|
+
declaringGitSource: declaringGitSource(fetched),
|
|
6381
6250
|
requiredBy: state.node.id,
|
|
6382
6251
|
alias,
|
|
6383
6252
|
parentId: state.node.id,
|
|
@@ -6885,6 +6754,15 @@ async function mapLimit(items, limit, fn) {
|
|
|
6885
6754
|
if (failure !== void 0) throw failure;
|
|
6886
6755
|
return out;
|
|
6887
6756
|
}
|
|
6757
|
+
function declaringGitSource(fetched) {
|
|
6758
|
+
if (fetched.resolved.driver !== "git" || !fetched.resolved.resolvedCommit) return void 0;
|
|
6759
|
+
const parsed = parseGitSource(fetched.resolved.source);
|
|
6760
|
+
return {
|
|
6761
|
+
url: normalizeGitRemoteUrl(parsed.url, fetched.resolved.resolvedPath),
|
|
6762
|
+
commit: fetched.resolved.resolvedCommit,
|
|
6763
|
+
subpath: parsed.subpath
|
|
6764
|
+
};
|
|
6765
|
+
}
|
|
6888
6766
|
|
|
6889
6767
|
// src/lifecycle/customization.ts
|
|
6890
6768
|
async function remember(workspaceRoot, runtime, text) {
|
|
@@ -7039,7 +6917,7 @@ import { rm as rm7 } from "fs/promises";
|
|
|
7039
6917
|
// src/lifecycle/source-plan.ts
|
|
7040
6918
|
import { createHash as createHash8 } from "crypto";
|
|
7041
6919
|
import { mkdir as mkdir14, readdir as readdir9 } from "fs/promises";
|
|
7042
|
-
import { basename as basename18, dirname as dirname17, join as join33, posix as
|
|
6920
|
+
import { basename as basename18, dirname as dirname17, join as join33, posix as posix3, resolve as resolve16 } from "path";
|
|
7043
6921
|
|
|
7044
6922
|
// src/resolve/graph-diff.ts
|
|
7045
6923
|
function diffGraphLocks(previous, next) {
|
|
@@ -7202,11 +7080,14 @@ function formatSelectionImport(root) {
|
|
|
7202
7080
|
|
|
7203
7081
|
// src/resolve/render.ts
|
|
7204
7082
|
import { createHash as createHash7 } from "crypto";
|
|
7205
|
-
import { readFile as readFile18, mkdtemp as
|
|
7206
|
-
import { tmpdir as
|
|
7083
|
+
import { readFile as readFile18, mkdtemp as mkdtemp2 } from "fs/promises";
|
|
7084
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
7207
7085
|
import { join as join31 } from "path";
|
|
7208
7086
|
async function renderGraphForTarget(graph, targetContext = {}) {
|
|
7209
|
-
const root = await
|
|
7087
|
+
const root = await mkdtemp2(join31(tmpdir3(), "agentwheel-render-"));
|
|
7088
|
+
return removeOnFailure(root, () => renderGraphIntoRoot(root, graph, targetContext));
|
|
7089
|
+
}
|
|
7090
|
+
async function renderGraphIntoRoot(root, graph, targetContext) {
|
|
7210
7091
|
const artifacts = [];
|
|
7211
7092
|
const stagedNodes = /* @__PURE__ */ new Map();
|
|
7212
7093
|
const includeEdges = /* @__PURE__ */ new Map();
|
|
@@ -7214,7 +7095,7 @@ async function renderGraphForTarget(graph, targetContext = {}) {
|
|
|
7214
7095
|
for (const rawNode of graph.rawNodes) {
|
|
7215
7096
|
const ownsCompositionRules = rawNode.depth === 0 && rawNode.manifest?.schemaVersion === 3 && Boolean(rawNode.manifest.compositionRules?.length);
|
|
7216
7097
|
if (rawNode.node.selected.length === 0 && !ownsCompositionRules) continue;
|
|
7217
|
-
const rawBundle = await stageResolvedArtifactsRaw(rawNode.resolved, rawNode.artifacts);
|
|
7098
|
+
const rawBundle = await stageResolvedArtifactsRaw(rawNode.resolved, rawNode.artifacts, root);
|
|
7218
7099
|
const fragmentCustomized = targetContext.workspaceRoot && targetContext.adapter ? await applyFragmentCustomizations(rawBundle.artifacts, {
|
|
7219
7100
|
workspaceRoot: targetContext.workspaceRoot,
|
|
7220
7101
|
adapter: targetContext.adapter,
|
|
@@ -8081,7 +7962,7 @@ function containsPath(parent, candidate) {
|
|
|
8081
7962
|
}
|
|
8082
7963
|
|
|
8083
7964
|
// src/model/target-state.ts
|
|
8084
|
-
import { posix, resolve as resolve15 } from "path";
|
|
7965
|
+
import { posix as posix2, resolve as resolve15 } from "path";
|
|
8085
7966
|
var targetEvolutionFields = /* @__PURE__ */ new Set([
|
|
8086
7967
|
"adapterCodeHash",
|
|
8087
7968
|
"adapterConfig",
|
|
@@ -8114,7 +7995,7 @@ function persistentTargetParts(value) {
|
|
|
8114
7995
|
);
|
|
8115
7996
|
}
|
|
8116
7997
|
function normalizeInstallRoot(path, transportKind) {
|
|
8117
|
-
return transportKind === "ssh" ?
|
|
7998
|
+
return transportKind === "ssh" ? posix2.normalize(path) : resolve15(path);
|
|
8118
7999
|
}
|
|
8119
8000
|
function targetEndpoint(value, transportKind) {
|
|
8120
8001
|
if (transportKind !== "ssh") return { kind: "local" };
|
|
@@ -8139,7 +8020,7 @@ function targetEndpoint(value, transportKind) {
|
|
|
8139
8020
|
|
|
8140
8021
|
// src/lifecycle/source-plan.ts
|
|
8141
8022
|
async function createGraphSourcePlan(options) {
|
|
8142
|
-
if (options.roots.length === 0) {
|
|
8023
|
+
if (options.roots.length === 0 && !options.allowEmptyRoots) {
|
|
8143
8024
|
throw new Error("At least one source is required for a graph plan.");
|
|
8144
8025
|
}
|
|
8145
8026
|
if (options.freshGraphOnly && options.readOnly !== true) {
|
|
@@ -8255,7 +8136,8 @@ async function createGraphSourcePlan(options) {
|
|
|
8255
8136
|
offline: options.offline,
|
|
8256
8137
|
previousLock,
|
|
8257
8138
|
warn,
|
|
8258
|
-
runtime: options.adapter.name
|
|
8139
|
+
runtime: options.adapter.name,
|
|
8140
|
+
allowEmptyRoots: options.allowEmptyRoots
|
|
8259
8141
|
});
|
|
8260
8142
|
assertFrozenGraph(previousLock, graph, lockMode, lockLabel);
|
|
8261
8143
|
assertTrustArtifactPolicy(graph, trustPolicy);
|
|
@@ -8271,85 +8153,97 @@ async function createGraphSourcePlan(options) {
|
|
|
8271
8153
|
noDeps: options.noDeps,
|
|
8272
8154
|
warn
|
|
8273
8155
|
});
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
|
|
8279
|
-
|
|
8280
|
-
const resolvedInstallationType = resolveInstallationTypeForArtifacts(options.adapter, desiredArtifacts.map((artifact) => artifact.type), installationType);
|
|
8281
|
-
const resolvedInstallRoot = installRootForArtifacts(options.adapter, options.targetRoot, resolvedInstallationType, desiredArtifacts.map((artifact) => artifact.type), transport.kind === "ssh");
|
|
8282
|
-
const graphLockDigest = digestGraphLock(bundle.graphLock);
|
|
8283
|
-
const graphDiff = diffGraphLocks(previousLock, bundle.graphLock);
|
|
8284
|
-
if (normalizeInstallRoot2(resolvedInstallRoot, transport.kind) !== normalizeInstallRoot2(installRoot, transport.kind)) {
|
|
8285
|
-
throw new Error(
|
|
8286
|
-
`Adapter ${options.adapter.name} resolved a different install root after rendering; target state identity cannot be proven.`
|
|
8156
|
+
return removeOnFailure(bundle.root, async () => {
|
|
8157
|
+
const desiredArtifacts = filterArtifactsByAdapterTargets(
|
|
8158
|
+
desiredArtifactsFromGraphBundle(bundle),
|
|
8159
|
+
options.adapter,
|
|
8160
|
+
installationType,
|
|
8161
|
+
{ warn }
|
|
8287
8162
|
);
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8291
|
-
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
{
|
|
8297
|
-
installationType: resolvedInstallationType,
|
|
8298
|
-
stateKey,
|
|
8299
|
-
workspaceOwner,
|
|
8300
|
-
expectedFromWorkspaceOwner: options.expectedFromWorkspaceOwner,
|
|
8301
|
-
graphLockDigest
|
|
8163
|
+
const resolvedInstallationType = resolveInstallationTypeForArtifacts(options.adapter, desiredArtifacts.map((artifact) => artifact.type), installationType);
|
|
8164
|
+
const resolvedInstallRoot = installRootForArtifacts(options.adapter, options.targetRoot, resolvedInstallationType, desiredArtifacts.map((artifact) => artifact.type), transport.kind === "ssh");
|
|
8165
|
+
const graphLockDigest = digestGraphLock(bundle.graphLock);
|
|
8166
|
+
const graphDiff = diffGraphLocks(previousLock, bundle.graphLock);
|
|
8167
|
+
if (normalizeInstallRoot2(resolvedInstallRoot, transport.kind) !== normalizeInstallRoot2(installRoot, transport.kind)) {
|
|
8168
|
+
throw new Error(
|
|
8169
|
+
`Adapter ${options.adapter.name} resolved a different install root after rendering; target state identity cannot be proven.`
|
|
8170
|
+
);
|
|
8302
8171
|
}
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
forceDrift: options.forceDrift,
|
|
8310
|
-
forceConflict: options.forceConflict,
|
|
8311
|
-
replaceConflict: options.replaceConflict,
|
|
8312
|
-
stateMigration: priorState.migration,
|
|
8313
|
-
warn
|
|
8314
|
-
});
|
|
8315
|
-
const plan = priorState.migration && !basePlan.stateMigration ? { ...basePlan, stateMigration: priorState.migration } : basePlan;
|
|
8316
|
-
plan.targetStateFilePreconditions = {
|
|
8317
|
-
graphLockPath,
|
|
8318
|
-
graphLockRevision: stableLock ? digestGraphLock(stableLock) : null,
|
|
8319
|
-
sourceLockRevision: computeSourceLockRevision(stableSourceLock)
|
|
8320
|
-
};
|
|
8321
|
-
let foreignStateObservations = [];
|
|
8322
|
-
if (options.forceForeignState !== true && options.deferForeignStateCheck !== true) {
|
|
8323
|
-
foreignStateObservations = await assertNoForeignWorkspaceState({
|
|
8324
|
-
installRoot: resolvedInstallRoot,
|
|
8325
|
-
adapter: options.adapter.name,
|
|
8172
|
+
const manifest = priorState.manifest;
|
|
8173
|
+
const basePlan = options.retireExactMcp ? await createExactMcpRetirementPlan(
|
|
8174
|
+
desiredArtifacts,
|
|
8175
|
+
options.adapter,
|
|
8176
|
+
options.targetRoot,
|
|
8177
|
+
manifest,
|
|
8326
8178
|
transport,
|
|
8327
|
-
|
|
8179
|
+
{
|
|
8180
|
+
installationType: resolvedInstallationType,
|
|
8181
|
+
stateKey,
|
|
8182
|
+
workspaceOwner,
|
|
8183
|
+
expectedFromWorkspaceOwner: options.expectedFromWorkspaceOwner,
|
|
8184
|
+
graphLockDigest
|
|
8185
|
+
}
|
|
8186
|
+
) : await createCombinedInstallPlan(desiredArtifacts, options.adapter, options.targetRoot, manifest, transport, {
|
|
8187
|
+
baseRevision: manifest?.revision ?? null,
|
|
8188
|
+
graphLockDigest,
|
|
8328
8189
|
workspaceOwner,
|
|
8329
|
-
|
|
8190
|
+
installationType: resolvedInstallationType,
|
|
8330
8191
|
stateKey,
|
|
8331
|
-
|
|
8332
|
-
|
|
8333
|
-
|
|
8192
|
+
forceDrift: options.forceDrift,
|
|
8193
|
+
forceConflict: options.forceConflict,
|
|
8194
|
+
replaceConflict: options.replaceConflict,
|
|
8195
|
+
stateMigration: priorState.migration,
|
|
8196
|
+
warn
|
|
8334
8197
|
});
|
|
8335
|
-
plan
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
foreignStateObservations
|
|
8352
|
-
|
|
8198
|
+
const plan = priorState.migration && !basePlan.stateMigration ? { ...basePlan, stateMigration: priorState.migration } : basePlan;
|
|
8199
|
+
if (options.excludedRootIds?.length && previousLock) {
|
|
8200
|
+
const excludedRoots = new Set(options.excludedRootIds);
|
|
8201
|
+
const excludedNodeIds = new Set(previousLock.canonical.roots.filter((root) => excludedRoots.has(root.rootId)).map((root) => root.graphNodeId));
|
|
8202
|
+
for (const operation of plan.operations) {
|
|
8203
|
+
const excludedOwner = operation.owners?.length && operation.owners.every((owner) => excludedRoots.has(owner));
|
|
8204
|
+
if (operation.action === "remove" && (excludedOwner || operation.graphNodeId && excludedNodeIds.has(operation.graphNodeId))) {
|
|
8205
|
+
operation.reason = "excluded by package runtimes";
|
|
8206
|
+
}
|
|
8207
|
+
}
|
|
8208
|
+
}
|
|
8209
|
+
plan.targetStateFilePreconditions = {
|
|
8210
|
+
graphLockPath,
|
|
8211
|
+
graphLockRevision: stableLock ? digestGraphLock(stableLock) : null,
|
|
8212
|
+
sourceLockRevision: computeSourceLockRevision(stableSourceLock)
|
|
8213
|
+
};
|
|
8214
|
+
let foreignStateObservations = [];
|
|
8215
|
+
if (options.forceForeignState !== true && options.deferForeignStateCheck !== true) {
|
|
8216
|
+
foreignStateObservations = await assertNoForeignWorkspaceState({
|
|
8217
|
+
installRoot: resolvedInstallRoot,
|
|
8218
|
+
adapter: options.adapter.name,
|
|
8219
|
+
transport,
|
|
8220
|
+
workspaceRoot,
|
|
8221
|
+
workspaceOwner,
|
|
8222
|
+
globalRoot: options.globalRoot,
|
|
8223
|
+
stateKey,
|
|
8224
|
+
migratingStateKey: priorState.migration?.fromStateKey,
|
|
8225
|
+
plannedPaths: plan.operations.map((operation) => operation.relativeDestPath),
|
|
8226
|
+
plannedOperations: plan.operations
|
|
8227
|
+
});
|
|
8228
|
+
plan.hasBlockingChanges = plan.operations.some((operation) => operation.action === "drift" || operation.action === "conflict");
|
|
8229
|
+
}
|
|
8230
|
+
return {
|
|
8231
|
+
plan,
|
|
8232
|
+
graph,
|
|
8233
|
+
bundle,
|
|
8234
|
+
desiredArtifacts,
|
|
8235
|
+
graphLockPath,
|
|
8236
|
+
graphLockDigest,
|
|
8237
|
+
targetFingerprint,
|
|
8238
|
+
warnings,
|
|
8239
|
+
newTransitiveSources: trustEvaluation.promptSources,
|
|
8240
|
+
graphDiff,
|
|
8241
|
+
recoveredPendingApply,
|
|
8242
|
+
previousManifest: priorState.manifest,
|
|
8243
|
+
previousGraphLock: priorState.graphLock,
|
|
8244
|
+
foreignStateObservations
|
|
8245
|
+
};
|
|
8246
|
+
});
|
|
8353
8247
|
}
|
|
8354
8248
|
async function assertNoForeignWorkspaceStateForPlan(plan, options) {
|
|
8355
8249
|
if (!plan.stateKey) throw new Error(`Foreign-state validation requires a state key for ${plan.adapter}.`);
|
|
@@ -8708,7 +8602,7 @@ function stableJson2(value) {
|
|
|
8708
8602
|
return `{${Object.keys(record).filter((key) => record[key] !== void 0).sort((left, right) => left.localeCompare(right)).map((key) => `${JSON.stringify(key)}:${stableJson2(record[key])}`).join(",")}}`;
|
|
8709
8603
|
}
|
|
8710
8604
|
function normalizeInstallRoot2(path, transportKind) {
|
|
8711
|
-
return transportKind === "ssh" ?
|
|
8605
|
+
return transportKind === "ssh" ? posix3.normalize(path) : resolve16(path);
|
|
8712
8606
|
}
|
|
8713
8607
|
var workspaceOwnerPrefix2 = "workspace-root:";
|
|
8714
8608
|
async function assertNoForeignWorkspaceState(check) {
|
|
@@ -9196,8 +9090,17 @@ async function syncProfile(options) {
|
|
|
9196
9090
|
if (selected && packages.some((pkg) => pkg.selection)) {
|
|
9197
9091
|
throw new Error("--select/--skill cannot be combined with a package selection import.");
|
|
9198
9092
|
}
|
|
9093
|
+
if (!options.source) {
|
|
9094
|
+
const adapters = new Set(profile.runtimes.map((runtime) => resolveProfileRuntimeTarget(runtime, config, options.workspaceRoot, options.installationType, options.fleetId).adapter));
|
|
9095
|
+
for (const pkg of packages) {
|
|
9096
|
+
if (pkg.runtimes && !pkg.runtimes.some((runtime) => adapters.has(runtime))) {
|
|
9097
|
+
options.warn?.(`Package '${pkg.name}' matches no runtime in profile '${options.profile}'.`);
|
|
9098
|
+
}
|
|
9099
|
+
}
|
|
9100
|
+
}
|
|
9199
9101
|
for (const runtime of profile.runtimes) {
|
|
9200
9102
|
const target = resolveProfileRuntimeTarget(runtime, config, options.workspaceRoot, options.installationType, options.fleetId);
|
|
9103
|
+
const runtimePackages = options.source ? packages : packagesForTarget(packages, target);
|
|
9201
9104
|
const transport = transportForTarget(target);
|
|
9202
9105
|
const adapter = await resolveAdapter({
|
|
9203
9106
|
adapter: target.adapter,
|
|
@@ -9210,7 +9113,7 @@ async function syncProfile(options) {
|
|
|
9210
9113
|
const installationType = target.installationType ?? defaultInstallationType;
|
|
9211
9114
|
resolveInstallationTypeForAdapter(adapter, installationType);
|
|
9212
9115
|
const graphPlan = await createGraphSourcePlan({
|
|
9213
|
-
roots:
|
|
9116
|
+
roots: runtimePackages.map((pkg) => ({
|
|
9214
9117
|
rootId: pkg.name,
|
|
9215
9118
|
source: pkg.source,
|
|
9216
9119
|
mode: options.mode ?? pkg.mode,
|
|
@@ -9259,14 +9162,16 @@ async function syncProfile(options) {
|
|
|
9259
9162
|
forceConflict: options.forceConflict,
|
|
9260
9163
|
forceForeignState: options.forceForeignState,
|
|
9261
9164
|
replaceConflict: options.replaceConflict,
|
|
9262
|
-
recoverLegacyState: options.recoverLegacyState
|
|
9165
|
+
recoverLegacyState: options.recoverLegacyState,
|
|
9166
|
+
allowEmptyRoots: runtimePackages.length === 0,
|
|
9167
|
+
excludedRootIds: options.source ? [] : packages.filter((pkg) => !runtimePackages.includes(pkg)).map((pkg) => pkg.name)
|
|
9263
9168
|
});
|
|
9264
9169
|
try {
|
|
9265
9170
|
const result = {
|
|
9266
9171
|
runtime: adapter.name,
|
|
9267
9172
|
targetRoot: installRootForAdapterInstallationType(adapter, target.targetRoot, installationType, transport.kind === "ssh"),
|
|
9268
9173
|
transport: transport.kind,
|
|
9269
|
-
packageName:
|
|
9174
|
+
packageName: runtimePackages.map((pkg) => pkg.name).join(",") || "(no packages)",
|
|
9270
9175
|
plan: graphPlan.plan,
|
|
9271
9176
|
graphPlan,
|
|
9272
9177
|
graphLockDigest: graphPlan.graphLockDigest,
|
|
@@ -9785,6 +9690,7 @@ function resolveCliVersion() {
|
|
|
9785
9690
|
|
|
9786
9691
|
// src/lifecycle/ownership.ts
|
|
9787
9692
|
import { resolve as resolve20 } from "path";
|
|
9693
|
+
var unknownWorkspaceOwner = "workspace:unknown";
|
|
9788
9694
|
async function planArtifactOwnershipHandoff(request) {
|
|
9789
9695
|
return validateOwnershipHandoff(request, request.transport ?? localTransport);
|
|
9790
9696
|
}
|
|
@@ -9803,6 +9709,9 @@ async function applyArtifactOwnershipHandoff(request) {
|
|
|
9803
9709
|
throw new Error("Cannot hand off ownership while an apply journal is pending. Recover or abort it first.");
|
|
9804
9710
|
}
|
|
9805
9711
|
const plan = await validateOwnershipHandoff(request, transport);
|
|
9712
|
+
if (plan.drifted && !request.expectedRuntimeHash) {
|
|
9713
|
+
throw new Error("Applying a drifted ownership handoff requires expectedRuntimeHash from a reviewed dry-run.");
|
|
9714
|
+
}
|
|
9806
9715
|
const manifest = await readInstallManifest(request.targetRoot, request.adapter, transport, scope);
|
|
9807
9716
|
if (!manifest || manifest.version !== 2) {
|
|
9808
9717
|
throw new Error("Ownership handoff requires an Agentwheel v2 install manifest.");
|
|
@@ -9833,6 +9742,13 @@ async function applyArtifactOwnershipHandoff(request) {
|
|
|
9833
9742
|
async function validateOwnershipHandoff(request, transport) {
|
|
9834
9743
|
if (request.expectedHash) assertSha256(request.expectedHash, "expected artifact hash");
|
|
9835
9744
|
if (request.expectedRevision) assertSha256(request.expectedRevision, "expected manifest revision");
|
|
9745
|
+
if (request.expectedRuntimeHash) {
|
|
9746
|
+
assertSha256(request.expectedRuntimeHash, "expected runtime hash");
|
|
9747
|
+
if (request.carryDrift !== true) throw new Error("An expected runtime hash is only valid with carryDrift.");
|
|
9748
|
+
}
|
|
9749
|
+
if (request.fromWorkspaceRoot === void 0 === (request.fromUnknownOwner !== true)) {
|
|
9750
|
+
throw new Error("Ownership handoff requires exactly one of fromWorkspaceRoot or fromUnknownOwner.");
|
|
9751
|
+
}
|
|
9836
9752
|
const scope = { installationType: request.installationType, stateKey: request.stateKey };
|
|
9837
9753
|
const manifest = await readInstallManifest(request.targetRoot, request.adapter, transport, scope);
|
|
9838
9754
|
if (!manifest) throw new Error(`No install manifest for ${request.adapter} at ${request.targetRoot}`);
|
|
@@ -9850,7 +9766,7 @@ async function validateOwnershipHandoff(request, transport) {
|
|
|
9850
9766
|
);
|
|
9851
9767
|
}
|
|
9852
9768
|
const entry = matches[0];
|
|
9853
|
-
const fromOwner = workspaceOwnerForRoot(request.fromWorkspaceRoot);
|
|
9769
|
+
const fromOwner = request.fromUnknownOwner === true ? unknownWorkspaceOwner : workspaceOwnerForRoot(request.fromWorkspaceRoot);
|
|
9854
9770
|
const toOwner = workspaceOwnerForRoot(request.toWorkspaceRoot, request.toFleetId);
|
|
9855
9771
|
if (fromOwner === toOwner) throw new Error("Ownership handoff requires different workspace roots.");
|
|
9856
9772
|
if (entry.workspaceOwner !== fromOwner) {
|
|
@@ -9861,9 +9777,14 @@ async function validateOwnershipHandoff(request, transport) {
|
|
|
9861
9777
|
}
|
|
9862
9778
|
const destPath = containedArtifactPath(request.targetRoot, entry.path);
|
|
9863
9779
|
if (!await transport.pathExists(destPath)) throw new Error(`Managed artifact is missing: ${entry.path}`);
|
|
9864
|
-
const
|
|
9865
|
-
|
|
9866
|
-
|
|
9780
|
+
const runtimeHash = await verifiedEntryHash(entry, destPath, transport, request.carryDrift === true);
|
|
9781
|
+
const drifted = runtimeHash !== entry.hash;
|
|
9782
|
+
if (drifted) {
|
|
9783
|
+
if (request.expectedRuntimeHash && runtimeHash !== request.expectedRuntimeHash) {
|
|
9784
|
+
throw new Error(`Runtime hash precondition failed for ${entry.path}: expected ${request.expectedRuntimeHash}, found ${runtimeHash}`);
|
|
9785
|
+
}
|
|
9786
|
+
} else if (request.expectedRuntimeHash) {
|
|
9787
|
+
throw new Error(`Runtime hash precondition failed for ${entry.path}: the artifact is no longer drifted`);
|
|
9867
9788
|
}
|
|
9868
9789
|
return {
|
|
9869
9790
|
adapter: request.adapter,
|
|
@@ -9872,13 +9793,15 @@ async function validateOwnershipHandoff(request, transport) {
|
|
|
9872
9793
|
targetRoot: request.targetRoot,
|
|
9873
9794
|
selector: `${request.artifactType}/${request.artifactName}`,
|
|
9874
9795
|
path: entry.path,
|
|
9875
|
-
artifactHash:
|
|
9796
|
+
artifactHash: entry.hash,
|
|
9797
|
+
runtimeHash,
|
|
9798
|
+
drifted,
|
|
9876
9799
|
manifestRevision: manifest.revision,
|
|
9877
9800
|
fromOwner,
|
|
9878
9801
|
toOwner
|
|
9879
9802
|
};
|
|
9880
9803
|
}
|
|
9881
|
-
async function verifiedEntryHash(entry, destPath, transport) {
|
|
9804
|
+
async function verifiedEntryHash(entry, destPath, transport, carryFileDrift = false) {
|
|
9882
9805
|
if (entry.semanticPlugin) throw new Error(`Ownership handoff cannot verify semantic plugin state at ${destPath}`);
|
|
9883
9806
|
if (entry.mode === "managed-block") {
|
|
9884
9807
|
const selector = managedInstructionSelector(entry.logicalSelector, entry.artifactType, entry.artifactName);
|
|
@@ -9896,7 +9819,7 @@ async function verifiedEntryHash(entry, destPath, transport) {
|
|
|
9896
9819
|
return entry.hash;
|
|
9897
9820
|
}
|
|
9898
9821
|
const currentHash = await transport.hashPath(destPath);
|
|
9899
|
-
if (currentHash !== entry.hash) {
|
|
9822
|
+
if (currentHash !== entry.hash && !carryFileDrift) {
|
|
9900
9823
|
throw new Error(`Managed artifact is drifted at ${destPath}: manifest ${entry.hash}, current ${currentHash}`);
|
|
9901
9824
|
}
|
|
9902
9825
|
return currentHash;
|
|
@@ -10226,7 +10149,7 @@ import { isAbsolute as isAbsolute3, relative as relative9, resolve as resolve23
|
|
|
10226
10149
|
// src/lifecycle/legacy-recovery-plan.ts
|
|
10227
10150
|
import { createHash as createHash10 } from "crypto";
|
|
10228
10151
|
import { lstat as lstat3, readdir as readdir10 } from "fs/promises";
|
|
10229
|
-
import { basename as basename20, dirname as dirname21, join as join39, posix as
|
|
10152
|
+
import { basename as basename20, dirname as dirname21, join as join39, posix as posix4, relative as relative8, resolve as resolve22 } from "path";
|
|
10230
10153
|
async function inventoryHistoricalLocks(fleetRoot) {
|
|
10231
10154
|
const root = join39(fleetRoot, ".agentwheel", "locks");
|
|
10232
10155
|
const found = [];
|
|
@@ -10384,7 +10307,7 @@ function claimFor(item, entry, locks, binding) {
|
|
|
10384
10307
|
const matches = locks.filter((candidate) => candidate.digest === digest2);
|
|
10385
10308
|
const evidence = [];
|
|
10386
10309
|
const owner = "workspaceOwner" in entry ? entry.workspaceOwner : legacyUnownedWorkspaceOwner;
|
|
10387
|
-
const sameRoot = binding.transportKind === "ssh" ?
|
|
10310
|
+
const sameRoot = binding.transportKind === "ssh" ? posix4.normalize(item.manifest.targetRoot) === posix4.normalize(binding.installRoot) : resolve22(item.manifest.targetRoot) === resolve22(binding.installRoot);
|
|
10388
10311
|
const inTargetDir = matches.filter((candidate) => resolve22(dirname21(candidate.path)) === resolve22(binding.targetLockDir));
|
|
10389
10312
|
const boundLocks = inTargetDir.filter((candidate) => lockBindsState(candidate, item, binding));
|
|
10390
10313
|
if (owner !== binding.expectedOwner) evidence.push("workspace owner differs from selected Fleet target");
|
|
@@ -12390,7 +12313,7 @@ async function planFleetNormalization(request) {
|
|
|
12390
12313
|
const destinationDeclaration = canonicalJson2(destinationPackage);
|
|
12391
12314
|
if (sourceDeclaration !== destinationDeclaration) {
|
|
12392
12315
|
throw new Error(
|
|
12393
|
-
`Package '${name}' has divergent declarations. Source, driver, adapter, adapter configuration, installation type, version policy, selections, aliases, overrides, and suggestions must match before normalization.`
|
|
12316
|
+
`Package '${name}' has divergent declarations. Source, driver, adapter, adapter configuration, installation type, version policy, runtime restrictions, selections, aliases, overrides, and suggestions must match before normalization.`
|
|
12394
12317
|
);
|
|
12395
12318
|
}
|
|
12396
12319
|
packages.push({ name, declarationDigest: sha2565(sourceDeclaration) });
|
|
@@ -14355,10 +14278,13 @@ program.command("remember").description("append text to the local instructions o
|
|
|
14355
14278
|
console.log(nextInstallNudge());
|
|
14356
14279
|
});
|
|
14357
14280
|
var ownershipCommand = program.command("ownership").description("inspect and transfer manifest ownership without rewriting runtime artifacts");
|
|
14358
|
-
ownershipCommand.command("handoff").description("transfer one managed artifact between Agentwheel workspace roots").argument("<selector>", "exact artifact selector in type/name form").
|
|
14281
|
+
ownershipCommand.command("handoff").description("transfer one managed artifact between Agentwheel workspace roots").argument("<selector>", "exact artifact selector in type/name form").option("--from-workspace-root <path>", "current owning workspace root").option("--from-unknown-owner", "hand off an artifact recorded as workspace:unknown", false).requiredOption("--to-workspace-root <path>", "new owning workspace root").option("--to-fleet <id>", "qualify the new owner with a registered fleet id").option("--expected-hash <sha256>", "expected recorded artifact hash; required when applying").option("--expected-revision <sha256>", "expected install manifest revision; required when applying").option("--carry-drift", "accept a file or directory whose runtime differs from the recorded hash; the recorded hash is kept", false).option("--expected-runtime-hash <sha256>", "expected drifted runtime hash; required when applying with --carry-drift").option("--adapter <adapter>", "built-in adapter").option("-i, --installation-type <type>", "installation type (for example local or user)").option("--user", "use the user workspace", false).option("--local", "use the nearest local workspace", false).option("--fleet <id>", "use one registered named fleet").option("--adapter-config <path>", "adapter JSON/JSONC file").option("--adapter-module <path>", "local programmatic adapter module").option("--allow-adapter-code", "allow loading local adapter code", false).option("-t, --target-root <path>", "runtime/project root").option("--agent <name>", "named agent from merged config").option("--profile <name>", "workspace runtime profile (must resolve to one target)").option("--dry-run", "validate all preconditions without writing the manifest", false).action(async (selector, options) => {
|
|
14359
14282
|
if (!options.dryRun && (!options.expectedHash || !options.expectedRevision)) {
|
|
14360
14283
|
throw new Error("Applying an ownership handoff requires --expected-hash and --expected-revision from a reviewed --dry-run.");
|
|
14361
14284
|
}
|
|
14285
|
+
if (Boolean(options.fromWorkspaceRoot) === (options.fromUnknownOwner === true)) {
|
|
14286
|
+
throw new Error("Ownership handoff requires exactly one of --from-workspace-root or --from-unknown-owner.");
|
|
14287
|
+
}
|
|
14362
14288
|
const normalizedOptions = normalizeRuntimeScopeOptions(options);
|
|
14363
14289
|
const targets = await resolveCliTargets(normalizedOptions);
|
|
14364
14290
|
if (targets.length !== 1) {
|
|
@@ -14390,11 +14316,13 @@ ownershipCommand.command("handoff").description("transfer one managed artifact b
|
|
|
14390
14316
|
adapter: adapter.name,
|
|
14391
14317
|
artifactType,
|
|
14392
14318
|
artifactName,
|
|
14393
|
-
fromWorkspaceRoot: normalizeCliPath(options.fromWorkspaceRoot),
|
|
14319
|
+
...options.fromUnknownOwner === true ? { fromUnknownOwner: true } : { fromWorkspaceRoot: normalizeCliPath(options.fromWorkspaceRoot) },
|
|
14394
14320
|
toWorkspaceRoot,
|
|
14395
14321
|
toFleetId: options.toFleet,
|
|
14396
14322
|
expectedHash: options.expectedHash,
|
|
14397
14323
|
expectedRevision: options.expectedRevision,
|
|
14324
|
+
carryDrift: options.carryDrift === true,
|
|
14325
|
+
expectedRuntimeHash: options.expectedRuntimeHash,
|
|
14398
14326
|
transport: transportForTarget(target)
|
|
14399
14327
|
};
|
|
14400
14328
|
const result = options.dryRun ? await planArtifactOwnershipHandoff(request) : await applyArtifactOwnershipHandoff(request);
|
|
@@ -14402,6 +14330,7 @@ ownershipCommand.command("handoff").description("transfer one managed artifact b
|
|
|
14402
14330
|
console.log(`Target: ${result.adapter}/${result.installationType ?? "default"} at ${result.targetRoot}`);
|
|
14403
14331
|
console.log(`Path: ${result.path}`);
|
|
14404
14332
|
console.log(`Hash: ${result.artifactHash}`);
|
|
14333
|
+
if (result.drifted) console.log(`Runtime hash: ${result.runtimeHash} (drift carried; the recorded hash is kept)`);
|
|
14405
14334
|
console.log(`Manifest revision: ${result.manifestRevision}`);
|
|
14406
14335
|
console.log(`Owner: ${result.fromOwner} -> ${result.toOwner}`);
|
|
14407
14336
|
});
|
|
@@ -14420,8 +14349,9 @@ ownershipCommand.command("recovery-plan").description("write a read-only per-pat
|
|
|
14420
14349
|
}
|
|
14421
14350
|
const installationType = target.installationType ?? resolveInstallationTypeForAdapter(adapter, void 0);
|
|
14422
14351
|
const config = await readMergedWorkspaceConfig(target.workspaceRoot);
|
|
14423
|
-
|
|
14424
|
-
|
|
14352
|
+
const targetPackages = packagesForCliTarget(config.packages, target, {});
|
|
14353
|
+
if (targetPackages.length === 0) throw new Error("Fleet target has no configured source packages.");
|
|
14354
|
+
await withFreshReadOnlyGraphPlan(target, adapter, adapterOptionsForTarget(target, {}), installationType, targetPackages, async (graphPlan) => {
|
|
14425
14355
|
const installRoot = installRootForAdapterInstallationType(adapter, target.targetRoot, installationType, transport.kind === "ssh");
|
|
14426
14356
|
const report = await planLegacyRecovery({
|
|
14427
14357
|
graphPlan,
|
|
@@ -14548,7 +14478,7 @@ ownershipCommand.command("adopt-legacy").description("move proven legacy-keyed o
|
|
|
14548
14478
|
if (target.transport === "ssh") throw new Error("Legacy ownership adoption does not support SSH targets.");
|
|
14549
14479
|
const config = await readMergedWorkspaceConfig(target.workspaceRoot);
|
|
14550
14480
|
const groups = /* @__PURE__ */ new Map();
|
|
14551
|
-
for (const pkg of config.packages) graphGroupForPackage(groups, target, pkg, plainInstallOptions).packages.push(pkg);
|
|
14481
|
+
for (const pkg of packagesForCliTarget(config.packages, target, plainInstallOptions)) graphGroupForPackage(groups, target, pkg, plainInstallOptions).packages.push(pkg);
|
|
14552
14482
|
if (groups.size === 0) throw new Error(`No configured source packages in ${target.workspaceRoot}.`);
|
|
14553
14483
|
const installationTypes = [...new Set([...groups.values()].map((candidate) => candidate.installationType))];
|
|
14554
14484
|
if (installationTypes.length > 1) {
|
|
@@ -14890,7 +14820,7 @@ async function runInstallCommand(nameOrSource, options, behavior) {
|
|
|
14890
14820
|
for (const target of targets) {
|
|
14891
14821
|
const targetOptions = optionsForResolvedTarget(normalizedOptions, target);
|
|
14892
14822
|
const config = await readMergedWorkspaceConfig(target.workspaceRoot);
|
|
14893
|
-
const configured = nameOrSource ? findConfiguredPackageForTarget(config.packages, nameOrSource, targetOptions, target) : void 0;
|
|
14823
|
+
const configured = nameOrSource ? findConfiguredPackageForTarget(packagesForCliTarget(config.packages, target, targetOptions), nameOrSource, targetOptions, target) : void 0;
|
|
14894
14824
|
let source;
|
|
14895
14825
|
let scope = configured?.name;
|
|
14896
14826
|
let extraPackage;
|
|
@@ -14911,30 +14841,34 @@ async function runInstallCommand(nameOrSource, options, behavior) {
|
|
|
14911
14841
|
throw teachingInstallError(nameOrSource, error);
|
|
14912
14842
|
}
|
|
14913
14843
|
}
|
|
14914
|
-
|
|
14915
|
-
|
|
14916
|
-
|
|
14917
|
-
|
|
14918
|
-
if (
|
|
14919
|
-
|
|
14920
|
-
|
|
14921
|
-
|
|
14922
|
-
executePlugins
|
|
14923
|
-
|
|
14924
|
-
|
|
14925
|
-
|
|
14926
|
-
|
|
14927
|
-
|
|
14928
|
-
|
|
14929
|
-
|
|
14930
|
-
|
|
14931
|
-
|
|
14932
|
-
|
|
14933
|
-
if (
|
|
14844
|
+
const results = await buildGraphPlansForTarget(target, source, { ...targetOptions, scope, extraPackage, reportFormat: outputFormat }, { mode: "install" });
|
|
14845
|
+
try {
|
|
14846
|
+
for (const result of results) {
|
|
14847
|
+
if (!behavior.quiet) console.log(formatGraphPlan(result));
|
|
14848
|
+
if (behavior.apply) {
|
|
14849
|
+
declareMutationPath(result.graphLockPath);
|
|
14850
|
+
if (extraPackage && !targetOptions.onlySource) declareMutationPath(workspaceConfigPath(target.workspaceRoot));
|
|
14851
|
+
const transport = transportForTarget(target);
|
|
14852
|
+
const executePlugins = target.executePlugins ?? targetOptions.executePlugins;
|
|
14853
|
+
await applyCombinedInstallPlan(result.plan, {
|
|
14854
|
+
executePlugins,
|
|
14855
|
+
transport,
|
|
14856
|
+
graphLockDigest: result.graphLockDigest,
|
|
14857
|
+
graphLock: { path: result.graphLockPath, lock: result.bundle.graphLock }
|
|
14858
|
+
});
|
|
14859
|
+
const reloaded = await reloadRuntimeAfterPluginChanges(result.plan, target, transport, {
|
|
14860
|
+
enabled: target.reloadRuntimes ?? shouldReloadRuntimes(targetOptions),
|
|
14861
|
+
executePlugins
|
|
14862
|
+
});
|
|
14863
|
+
if (!behavior.quiet) {
|
|
14864
|
+
console.log(`Applied ${result.plan.adapter} at ${result.plan.targetRoot}.`);
|
|
14865
|
+
if (reloaded) console.log(`Reloaded runtime via ${formatReloadCommands(target.reloadCommands)}.`);
|
|
14866
|
+
}
|
|
14934
14867
|
}
|
|
14868
|
+
if (result.plan.hasBlockingChanges) process.exitCode = 1;
|
|
14935
14869
|
}
|
|
14936
|
-
|
|
14937
|
-
|
|
14870
|
+
} finally {
|
|
14871
|
+
await Promise.all(results.map((result) => rm10(result.bundle.root, { recursive: true, force: true })));
|
|
14938
14872
|
}
|
|
14939
14873
|
if (behavior.apply && extraPackage && !targetOptions.onlySource) {
|
|
14940
14874
|
await writeWorkspaceConfig(target.workspaceRoot, upsertPackage(await readWorkspaceConfig(target.workspaceRoot), extraPackage));
|
|
@@ -14977,11 +14911,11 @@ async function buildPlanReport(nameOrSource, options) {
|
|
|
14977
14911
|
yes: normalizedOptions.yes,
|
|
14978
14912
|
trustPatterns: normalizedOptions.trust ?? [],
|
|
14979
14913
|
readOnly: true,
|
|
14980
|
-
isTTY: false
|
|
14914
|
+
isTTY: false,
|
|
14915
|
+
warn: collectWarning
|
|
14981
14916
|
});
|
|
14982
14917
|
for (const result of results) {
|
|
14983
14918
|
reportTargets.push(installPlanReportTarget(result.plan, result.graphLockDigest));
|
|
14984
|
-
reportWarnings.push(...result.warnings);
|
|
14985
14919
|
}
|
|
14986
14920
|
return planReport(reportTargets, reportWarnings);
|
|
14987
14921
|
}
|
|
@@ -14989,7 +14923,7 @@ async function buildPlanReport(nameOrSource, options) {
|
|
|
14989
14923
|
for (const target of targets) {
|
|
14990
14924
|
const targetOptions = optionsForResolvedTarget(normalizedOptions, target);
|
|
14991
14925
|
const config = await readMergedWorkspaceConfig(target.workspaceRoot);
|
|
14992
|
-
const configured = nameOrSource ? findConfiguredPackageForTarget(config.packages, nameOrSource, targetOptions, target) : void 0;
|
|
14926
|
+
const configured = nameOrSource ? findConfiguredPackageForTarget(packagesForCliTarget(config.packages, target, targetOptions), nameOrSource, targetOptions, target) : void 0;
|
|
14993
14927
|
let source;
|
|
14994
14928
|
let scope = configured?.name;
|
|
14995
14929
|
let extraPackage;
|
|
@@ -15219,13 +15153,13 @@ async function resolveCliTargets(options, behavior = {}) {
|
|
|
15219
15153
|
if (normalizedOptions.profile && (normalizedOptions.all || normalizedOptions.allDetected || normalizedOptions.agent)) {
|
|
15220
15154
|
throw new Error("--profile cannot be combined with --all, --all-detected, or --agent.");
|
|
15221
15155
|
}
|
|
15222
|
-
const
|
|
15223
|
-
if (
|
|
15156
|
+
const adapters = adapterListFromOption(normalizedOptions.adapter);
|
|
15157
|
+
if (adapters.length > 1) {
|
|
15224
15158
|
if (normalizedOptions.all || normalizedOptions.allDetected || normalizedOptions.agent || normalizedOptions.profile) {
|
|
15225
15159
|
throw new Error("--adapter <a,b> cannot be combined with --all, --all-detected, --agent, or --profile. Use a profile for mixed configured targets.");
|
|
15226
15160
|
}
|
|
15227
15161
|
const targets = [];
|
|
15228
|
-
for (const adapter of
|
|
15162
|
+
for (const adapter of adapters) {
|
|
15229
15163
|
targets.push(await resolveRuntimeTarget({
|
|
15230
15164
|
cwd: scopeRoot,
|
|
15231
15165
|
targetRoot: normalizedOptions.targetRoot,
|
|
@@ -15371,7 +15305,7 @@ async function runSkillUpdateCommand(skillName, options) {
|
|
|
15371
15305
|
const targets = await resolveCliTargets(normalizedOptions, { preferAllProfile: true });
|
|
15372
15306
|
for (const target of targets) {
|
|
15373
15307
|
const config = await readMergedWorkspaceConfig(target.workspaceRoot);
|
|
15374
|
-
const owner = await configuredPackageForSkill(target, config.packages, skillName, normalizedOptions, options.package);
|
|
15308
|
+
const owner = await configuredPackageForSkill(target, packagesForCliTarget(config.packages, target, normalizedOptions), skillName, normalizedOptions, options.package);
|
|
15375
15309
|
const mode = owner.mode === "tracking" ? "update" : "install";
|
|
15376
15310
|
console.log(`Skill ${skillName}: ${owner.name} (${mode}).`);
|
|
15377
15311
|
await runConfiguredGraphPackages(target, {
|
|
@@ -15385,49 +15319,67 @@ async function runSkillUpdateCommand(skillName, options) {
|
|
|
15385
15319
|
}
|
|
15386
15320
|
async function runConfiguredGraphPackages(target, options, behavior) {
|
|
15387
15321
|
const results = await buildGraphPlansForTarget(target, void 0, options, behavior);
|
|
15388
|
-
|
|
15389
|
-
|
|
15390
|
-
|
|
15391
|
-
|
|
15392
|
-
|
|
15393
|
-
|
|
15394
|
-
|
|
15395
|
-
|
|
15396
|
-
|
|
15397
|
-
|
|
15398
|
-
|
|
15399
|
-
|
|
15400
|
-
|
|
15401
|
-
|
|
15402
|
-
|
|
15403
|
-
|
|
15404
|
-
|
|
15405
|
-
|
|
15406
|
-
|
|
15322
|
+
try {
|
|
15323
|
+
for (const result of results) {
|
|
15324
|
+
console.log(`${behavior.mode === "update" ? "Update" : "Install"} ${result.plan.adapter} at ${result.plan.targetRoot}:`);
|
|
15325
|
+
console.log(formatGraphPlan(result));
|
|
15326
|
+
if (!options.dryRun) {
|
|
15327
|
+
declareMutationPath(result.graphLockPath);
|
|
15328
|
+
const transport = transportForTarget(target);
|
|
15329
|
+
const executePlugins = target.executePlugins ?? options.executePlugins;
|
|
15330
|
+
await applyCombinedInstallPlan(result.plan, {
|
|
15331
|
+
executePlugins,
|
|
15332
|
+
transport,
|
|
15333
|
+
graphLockDigest: result.graphLockDigest,
|
|
15334
|
+
graphLock: { path: result.graphLockPath, lock: result.bundle.graphLock }
|
|
15335
|
+
});
|
|
15336
|
+
const reloaded = await reloadRuntimeAfterPluginChanges(result.plan, target, transport, {
|
|
15337
|
+
enabled: target.reloadRuntimes ?? shouldReloadRuntimes(options),
|
|
15338
|
+
executePlugins
|
|
15339
|
+
});
|
|
15340
|
+
console.log(`Applied ${result.plan.adapter} at ${result.plan.targetRoot}.`);
|
|
15341
|
+
if (reloaded) console.log(`Reloaded runtime via ${formatReloadCommands(target.reloadCommands)}.`);
|
|
15342
|
+
}
|
|
15343
|
+
if (result.plan.hasBlockingChanges) process.exitCode = 1;
|
|
15407
15344
|
}
|
|
15408
|
-
|
|
15409
|
-
|
|
15345
|
+
} finally {
|
|
15346
|
+
await Promise.all(results.map((result) => rm10(result.bundle.root, { recursive: true, force: true })));
|
|
15410
15347
|
}
|
|
15411
15348
|
}
|
|
15412
15349
|
async function buildGraphPlansForTarget(target, source, options, behavior) {
|
|
15350
|
+
const bundleRoots = [];
|
|
15351
|
+
try {
|
|
15352
|
+
return await collectGraphPlansForTarget(target, source, options, behavior, bundleRoots);
|
|
15353
|
+
} catch (error) {
|
|
15354
|
+
await Promise.all(bundleRoots.map((root) => rm10(root, { recursive: true, force: true })));
|
|
15355
|
+
throw error;
|
|
15356
|
+
}
|
|
15357
|
+
}
|
|
15358
|
+
async function collectGraphPlansForTarget(target, source, options, behavior, bundleRoots) {
|
|
15413
15359
|
const targetOptions = optionsForResolvedTarget(options, target);
|
|
15414
15360
|
const config = await readMergedWorkspaceConfig(target.workspaceRoot);
|
|
15361
|
+
const targetPackages = packagesForCliTarget(config.packages, target, targetOptions);
|
|
15415
15362
|
const groups = /* @__PURE__ */ new Map();
|
|
15416
15363
|
const selectedArtifacts = selectedArtifactsFromOptions(targetOptions);
|
|
15417
15364
|
const dependencyUpdateSelectors = sortedUniqueValues(targetOptions.dependency ?? []);
|
|
15418
15365
|
const scopedDependencyUpdate = behavior.mode === "update" && dependencyUpdateSelectors.length > 0;
|
|
15419
|
-
const scopedPackage = targetOptions.scope ? findConfiguredPackage(
|
|
15366
|
+
const scopedPackage = targetOptions.scope ? findConfiguredPackage(targetPackages, targetOptions.scope) : void 0;
|
|
15420
15367
|
const scopedRootId = scopedPackage?.name ?? (source ? targetOptions.scope : void 0);
|
|
15421
15368
|
if (targetOptions.scope && !scopedPackage && !source) throw new Error(`Configured package not found: ${targetOptions.scope}`);
|
|
15422
15369
|
if (scopedPackage && targetOptions.onlySource) {
|
|
15423
15370
|
const group = graphGroupForPackage(groups, target, scopedPackage, targetOptions);
|
|
15424
15371
|
group.packages.push(scopedPackage);
|
|
15425
15372
|
} else if (!source || !targetOptions.onlySource) {
|
|
15426
|
-
for (const pkg of
|
|
15373
|
+
for (const pkg of targetPackages) {
|
|
15427
15374
|
const group = graphGroupForPackage(groups, target, pkg, targetOptions);
|
|
15428
15375
|
group.packages.push(pkg);
|
|
15429
15376
|
}
|
|
15430
15377
|
}
|
|
15378
|
+
if (!source && !targetOptions.scope) {
|
|
15379
|
+
for (const pkg of config.packages.filter((candidate) => !targetPackages.includes(candidate))) {
|
|
15380
|
+
graphGroupForPackage(groups, target, pkg, targetOptions);
|
|
15381
|
+
}
|
|
15382
|
+
}
|
|
15431
15383
|
if (source) {
|
|
15432
15384
|
let entry = targetOptions.extraPackage ?? await packageEntryFromSource(source, target.workspaceRoot, {
|
|
15433
15385
|
...targetOptions,
|
|
@@ -15467,6 +15419,11 @@ async function buildGraphPlansForTarget(target, source, options, behavior) {
|
|
|
15467
15419
|
const adapter = await resolveAdapterForTarget(group.target, { ...group.adapterOptions, warn: targetOptions.warn });
|
|
15468
15420
|
const transport = transportForTarget(group.target);
|
|
15469
15421
|
const allPackages = [...group.packages, ...group.extraPackages];
|
|
15422
|
+
const excludedRootIds = config.packages.filter((pkg) => !targetPackages.includes(pkg) && graphGroupKey(targetForPackage(target, pkg, targetOptions), {
|
|
15423
|
+
installationType: targetOptions.installationType ?? pkg.installationType ?? target.installationType ?? "local",
|
|
15424
|
+
adapterConfig: targetOptions.adapterConfig ?? target.adapterConfig ?? pkg.adapterConfig,
|
|
15425
|
+
adapterModule: targetOptions.adapterModule ?? target.adapterModule ?? pkg.adapterModule
|
|
15426
|
+
}) === graphGroupKey(group.target, { ...group.adapterOptions, installationType: group.installationType })).map((pkg) => pkg.name);
|
|
15470
15427
|
const groupHasScope = !scopedRootId || allPackages.some((pkg) => pkg.name === scopedRootId || pkg.source === targetOptions.scope);
|
|
15471
15428
|
if (behavior.mode === "install" && scopedRootId && !groupHasScope) continue;
|
|
15472
15429
|
if (behavior.readOnly !== true && targetOptions.dryRun !== true) {
|
|
@@ -15565,15 +15522,16 @@ async function buildGraphPlansForTarget(target, source, options, behavior) {
|
|
|
15565
15522
|
];
|
|
15566
15523
|
if (behavior.mode === "update") {
|
|
15567
15524
|
const changed = roots.filter((root) => root.useLock === false);
|
|
15568
|
-
if (changed.length === 0 && !scopedDependencyUpdate) {
|
|
15525
|
+
if (changed.length === 0 && !scopedDependencyUpdate && excludedRootIds.length === 0) {
|
|
15569
15526
|
const label = targetOptions.scope ? ` ${targetOptions.scope}` : "";
|
|
15570
15527
|
console.log(`No tracking packages to update${label}.`);
|
|
15571
15528
|
continue;
|
|
15572
15529
|
}
|
|
15573
15530
|
}
|
|
15574
|
-
if (roots.length === 0) continue;
|
|
15575
15531
|
const result = await createGraphSourcePlan({
|
|
15576
15532
|
roots,
|
|
15533
|
+
allowEmptyRoots: roots.length === 0,
|
|
15534
|
+
excludedRootIds,
|
|
15577
15535
|
targetRoot: group.target.targetRoot,
|
|
15578
15536
|
workspaceRoot: group.target.workspaceRoot,
|
|
15579
15537
|
fleetId: group.target.fleetId,
|
|
@@ -15603,6 +15561,7 @@ async function buildGraphPlansForTarget(target, source, options, behavior) {
|
|
|
15603
15561
|
expectedFromWorkspaceOwner: targetOptions.expectedFromWorkspaceOwner,
|
|
15604
15562
|
recoverLegacyState: targetOptions.recoverLegacyState
|
|
15605
15563
|
});
|
|
15564
|
+
bundleRoots.push(result.bundle.root);
|
|
15606
15565
|
if ((behavior.mode === "install" || behavior.mode === "update") && scopedRootId) {
|
|
15607
15566
|
const manifest = result.previousManifest;
|
|
15608
15567
|
const previousLock = result.previousGraphLock;
|
|
@@ -16206,7 +16165,7 @@ async function uninstallConfiguredPackage(target, packageName, options) {
|
|
|
16206
16165
|
if (removed.length === 0) {
|
|
16207
16166
|
throw new Error(`Configured package not found: ${packageName}`);
|
|
16208
16167
|
}
|
|
16209
|
-
const remaining = config.packages.filter((pkg) => !removed.includes(pkg));
|
|
16168
|
+
const remaining = packagesForCliTarget(config.packages.filter((pkg) => !removed.includes(pkg)), target, options);
|
|
16210
16169
|
const groups = /* @__PURE__ */ new Map();
|
|
16211
16170
|
for (const pkg of remaining) {
|
|
16212
16171
|
const group = graphGroupForPackage(groups, target, pkg, options);
|
|
@@ -16239,7 +16198,7 @@ async function uninstallConfiguredPackage(target, packageName, options) {
|
|
|
16239
16198
|
let renderedRoot;
|
|
16240
16199
|
if (remainingGroup && remainingGroup.packages.length > 0) {
|
|
16241
16200
|
const remainingAdapter = await resolveAdapterForTarget(remainingGroup.target, remainingGroup.adapterOptions);
|
|
16242
|
-
const
|
|
16201
|
+
const result = await createGraphSourcePlan({
|
|
16243
16202
|
roots: remainingGroup.packages.map((pkg2) => ({
|
|
16244
16203
|
rootId: pkg2.name,
|
|
16245
16204
|
source: pkg2.source,
|
|
@@ -16271,46 +16230,49 @@ async function uninstallConfiguredPackage(target, packageName, options) {
|
|
|
16271
16230
|
readOnly: options.dryRun === true,
|
|
16272
16231
|
isTTY: process.stdin.isTTY === true
|
|
16273
16232
|
});
|
|
16274
|
-
remainingGraphPlan =
|
|
16275
|
-
remainingDesired = desiredArtifactsFromGraphBundle(
|
|
16276
|
-
renderedRoot =
|
|
16233
|
+
remainingGraphPlan = result;
|
|
16234
|
+
remainingDesired = desiredArtifactsFromGraphBundle(result.bundle);
|
|
16235
|
+
renderedRoot = result.bundle.root;
|
|
16277
16236
|
}
|
|
16278
|
-
|
|
16279
|
-
|
|
16280
|
-
|
|
16281
|
-
|
|
16282
|
-
|
|
16283
|
-
|
|
16284
|
-
|
|
16285
|
-
|
|
16286
|
-
|
|
16287
|
-
|
|
16288
|
-
|
|
16289
|
-
|
|
16290
|
-
|
|
16291
|
-
|
|
16292
|
-
|
|
16293
|
-
|
|
16294
|
-
|
|
16295
|
-
|
|
16296
|
-
|
|
16297
|
-
|
|
16298
|
-
const result = await uninstall(plan, {
|
|
16299
|
-
dryRun: options.dryRun,
|
|
16300
|
-
force: options.force,
|
|
16301
|
-
keepFiles: options.keepFiles,
|
|
16302
|
-
transport,
|
|
16303
|
-
...graphLockFinalState,
|
|
16304
|
-
workspaceConfig: {
|
|
16305
|
-
path: workspaceConfigPath(target.workspaceRoot),
|
|
16306
|
-
data: { ...config, packages: remaining }
|
|
16237
|
+
try {
|
|
16238
|
+
const uninstallPlan = await createOwnershipUninstallPlan(manifest, remainingDesired, adapter, transport, {
|
|
16239
|
+
graphLockDigest: remainingGraphPlan?.graphLockDigest
|
|
16240
|
+
});
|
|
16241
|
+
const transitionPlan = remainingGraphPlan?.plan;
|
|
16242
|
+
const plan = {
|
|
16243
|
+
...uninstallPlan,
|
|
16244
|
+
stateKey: transitionPlan?.stateKey ?? removedState.stableStateKey,
|
|
16245
|
+
stateMigration: transitionPlan?.stateMigration ?? removedState.migration,
|
|
16246
|
+
targetStateFilePreconditions: transitionPlan?.targetStateFilePreconditions ?? removedState.targetStateFilePreconditions
|
|
16247
|
+
};
|
|
16248
|
+
console.log(`Uninstall ${pkg.name} (${adapter.name} at ${removedTarget.targetRoot}):`);
|
|
16249
|
+
console.log(formatPlan(plan));
|
|
16250
|
+
const graphLockFinalState = remainingGraphPlan ? { graphLock: { path: remainingGraphPlan.graphLockPath, lock: remainingGraphPlan.bundle.graphLock } } : {
|
|
16251
|
+
removeGraphLockPath: removedState.graphLockPath ?? removedState.stableGraphLockPath
|
|
16252
|
+
};
|
|
16253
|
+
if (!options.dryRun) {
|
|
16254
|
+
declareMutationPath(workspaceConfigPath(target.workspaceRoot));
|
|
16255
|
+
const declarativeGraphPath = remainingGraphPlan ? remainingGraphPlan.graphLockPath : removedState.graphLockPath ?? removedState.stableGraphLockPath;
|
|
16256
|
+
declareMutationPath(declarativeGraphPath);
|
|
16307
16257
|
}
|
|
16308
|
-
|
|
16309
|
-
|
|
16310
|
-
|
|
16258
|
+
const result = await uninstall(plan, {
|
|
16259
|
+
dryRun: options.dryRun,
|
|
16260
|
+
force: options.force,
|
|
16261
|
+
keepFiles: options.keepFiles,
|
|
16262
|
+
transport,
|
|
16263
|
+
...graphLockFinalState,
|
|
16264
|
+
workspaceConfig: {
|
|
16265
|
+
path: workspaceConfigPath(target.workspaceRoot),
|
|
16266
|
+
data: { ...config, packages: remaining }
|
|
16267
|
+
}
|
|
16268
|
+
});
|
|
16269
|
+
if (!options.dryRun) {
|
|
16270
|
+
console.log(formatUninstallResult(result));
|
|
16271
|
+
}
|
|
16272
|
+
if (plan.hasBlockingChanges) process.exitCode = 1;
|
|
16273
|
+
} finally {
|
|
16274
|
+
if (renderedRoot) await rm10(renderedRoot, { recursive: true, force: true });
|
|
16311
16275
|
}
|
|
16312
|
-
if (renderedRoot) await rm10(renderedRoot, { recursive: true, force: true });
|
|
16313
|
-
if (plan.hasBlockingChanges) process.exitCode = 1;
|
|
16314
16276
|
}
|
|
16315
16277
|
}
|
|
16316
16278
|
function graphGroupForPackage(groups, target, pkg, options) {
|
|
@@ -16339,6 +16301,9 @@ function targetForPackage(target, pkg, options) {
|
|
|
16339
16301
|
const installationType = options.installationType ?? pkg.installationType ?? target.installationType;
|
|
16340
16302
|
return options.adapter || target.source !== "cwd" ? { ...target, installationType } : { ...target, adapter: pkg.adapter, installationType };
|
|
16341
16303
|
}
|
|
16304
|
+
function packagesForCliTarget(packages, target, options) {
|
|
16305
|
+
return packagesForTarget(packages, target, (pkg) => targetForPackage(target, pkg, options));
|
|
16306
|
+
}
|
|
16342
16307
|
function graphGroupKey(target, options) {
|
|
16343
16308
|
return JSON.stringify({
|
|
16344
16309
|
adapter: target.adapter,
|
|
@@ -16367,7 +16332,7 @@ function targetFingerprintParts(target, adapter, options, installationType) {
|
|
|
16367
16332
|
};
|
|
16368
16333
|
}
|
|
16369
16334
|
async function withFreshReadOnlyGraphPlan(target, adapter, adapterOptions, installationType, packages, use) {
|
|
16370
|
-
const stage = await
|
|
16335
|
+
const stage = await mkdtemp3(join46(tmpdir4(), "agentwheel-recovery-"));
|
|
16371
16336
|
const priorTmpdir = process.env.TMPDIR;
|
|
16372
16337
|
try {
|
|
16373
16338
|
process.env.TMPDIR = stage;
|
|
@@ -16515,7 +16480,7 @@ async function collectTargetStatus(target, options) {
|
|
|
16515
16480
|
observation.manifestRevision
|
|
16516
16481
|
]).sort())).digest("hex") : null;
|
|
16517
16482
|
const packages = [];
|
|
16518
|
-
for (const pkg of config.packages) {
|
|
16483
|
+
for (const pkg of packagesForCliTarget(config.packages, target, options)) {
|
|
16519
16484
|
const root = effectiveGraphLock?.canonical.roots.find((candidate) => candidate.rootId === pkg.name);
|
|
16520
16485
|
const node = root ? effectiveGraphLock?.canonical.nodes.find((candidate) => candidate.id === root.graphNodeId) : void 0;
|
|
16521
16486
|
const availability = await discoverPackageVersions(pkg, target.workspaceRoot, {
|
|
@@ -17253,9 +17218,9 @@ function isHomePath(path) {
|
|
|
17253
17218
|
}
|
|
17254
17219
|
function adapterListFromOption(adapter) {
|
|
17255
17220
|
if (!adapter) return [];
|
|
17256
|
-
const
|
|
17257
|
-
const unique = [...new Set(
|
|
17258
|
-
if (unique.length !==
|
|
17221
|
+
const adapters = splitSelectorList(adapter);
|
|
17222
|
+
const unique = [...new Set(adapters)];
|
|
17223
|
+
if (unique.length !== adapters.length) {
|
|
17259
17224
|
throw new Error(`Duplicate adapter in --adapter: ${adapter}`);
|
|
17260
17225
|
}
|
|
17261
17226
|
return unique;
|