@vltpkg/cli-sdk 1.4.0 → 1.6.0

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.
Files changed (74) hide show
  1. package/dist/allow-skills.d.ts +36 -0
  2. package/dist/allow-skills.js +49 -0
  3. package/dist/commands/build.d.ts +15 -4
  4. package/dist/commands/build.js +50 -12
  5. package/dist/commands/ci.d.ts +2 -2
  6. package/dist/commands/ci.js +10 -2
  7. package/dist/commands/create.d.ts +2 -1
  8. package/dist/commands/create.js +2 -3
  9. package/dist/commands/exec.d.ts +2 -1
  10. package/dist/commands/exec.js +2 -3
  11. package/dist/commands/init.js +4 -3
  12. package/dist/commands/install/reporter.d.ts +1 -1
  13. package/dist/commands/install/reporter.js +91 -5
  14. package/dist/commands/install.d.ts +50 -4
  15. package/dist/commands/install.js +107 -25
  16. package/dist/commands/list.js +8 -2
  17. package/dist/commands/publish.d.ts +0 -1
  18. package/dist/commands/publish.js +27 -16
  19. package/dist/commands/query.js +8 -2
  20. package/dist/commands/setup.d.ts +28 -2
  21. package/dist/commands/setup.js +185 -3
  22. package/dist/commands/skills.d.ts +56 -0
  23. package/dist/commands/skills.js +267 -0
  24. package/dist/commands/token.js +1 -1
  25. package/dist/commands/uninstall.d.ts +15 -4
  26. package/dist/commands/uninstall.js +32 -4
  27. package/dist/commands/unpublish.d.ts +0 -1
  28. package/dist/commands/unpublish.js +17 -4
  29. package/dist/commands/update.d.ts +13 -1
  30. package/dist/commands/update.js +18 -1
  31. package/dist/config/definition.d.ts +52 -0
  32. package/dist/config/definition.js +109 -1
  33. package/dist/config/index.d.ts +26 -3
  34. package/dist/config/index.js +149 -7
  35. package/dist/custom-help.js +4 -0
  36. package/dist/global-bin-dir.d.ts +37 -0
  37. package/dist/global-bin-dir.js +138 -0
  38. package/dist/global-project.d.ts +18 -0
  39. package/dist/global-project.js +67 -0
  40. package/dist/global-state.d.ts +24 -0
  41. package/dist/global-state.js +94 -0
  42. package/dist/global.d.ts +78 -0
  43. package/dist/global.js +409 -0
  44. package/dist/index.js +14 -3
  45. package/dist/install-receipt.d.ts +40 -0
  46. package/dist/install-receipt.js +69 -0
  47. package/dist/load-command.d.ts +2 -0
  48. package/dist/migrate-workspaces.d.ts +16 -0
  49. package/dist/migrate-workspaces.js +44 -0
  50. package/dist/output.js +13 -0
  51. package/dist/parse-add-remove-args.js +2 -14
  52. package/dist/print-err.js +4 -1
  53. package/dist/publish-config.d.ts +9 -0
  54. package/dist/publish-config.js +8 -0
  55. package/dist/query-auth.d.ts +3 -2
  56. package/dist/query-auth.js +6 -4
  57. package/dist/reload-config.js +2 -1
  58. package/dist/require-registry.d.ts +7 -0
  59. package/dist/require-registry.js +13 -1
  60. package/dist/self-update.d.ts +74 -0
  61. package/dist/self-update.js +401 -0
  62. package/dist/shell-setup/env.d.ts +9 -0
  63. package/dist/shell-setup/env.js +25 -0
  64. package/dist/shell-setup/index.d.ts +69 -0
  65. package/dist/shell-setup/index.js +213 -0
  66. package/dist/shell-setup/posix.d.ts +36 -0
  67. package/dist/shell-setup/posix.js +158 -0
  68. package/dist/shell-setup/windows.d.ts +39 -0
  69. package/dist/shell-setup/windows.js +151 -0
  70. package/dist/shell.d.ts +18 -0
  71. package/dist/shell.js +110 -0
  72. package/dist/skills-prompt.d.ts +28 -0
  73. package/dist/skills-prompt.js +78 -0
  74. package/package.json +30 -28
@@ -0,0 +1,56 @@
1
+ import type { DepID } from '@vltpkg/dep-id';
2
+ import type { LinkSkillsResult, ListSkillsResult, UnscannedSkills } from '@vltpkg/graph';
3
+ import type { WhichConfig } from '@vltpkg/vlt-json';
4
+ import type { CommandFn, CommandUsage } from '../index.ts';
5
+ import type { ViewOptions } from '../view.ts';
6
+ export type SkillsResult = ({
7
+ action: 'list';
8
+ } & ListSkillsResult) | ({
9
+ action: 'link';
10
+ /** the `allow-skills` applied */
11
+ query: string;
12
+ /** the config file it was saved to, if changed */
13
+ saved?: WhichConfig;
14
+ } & LinkSkillsResult) | {
15
+ action: 'unchanged';
16
+ };
17
+ export declare const needsRegistry = true;
18
+ export declare const usage: CommandUsage;
19
+ export declare const views: {
20
+ readonly human: (r: SkillsResult, o?: ViewOptions) => string;
21
+ readonly json: (r: SkillsResult) => ({
22
+ action: "link";
23
+ /** the `allow-skills` applied */
24
+ query: string;
25
+ /** the config file it was saved to, if changed */
26
+ saved?: WhichConfig;
27
+ } & UnscannedSkills & {
28
+ linked: import("@vltpkg/graph").SkillRow[];
29
+ unchanged: import("@vltpkg/graph").SkillRow[];
30
+ removed: string[];
31
+ conflicts: string[];
32
+ dirs: string[];
33
+ skipped?: string[];
34
+ gitignore?: string[];
35
+ unmatched?: import("@vltpkg/graph").UnmatchedPattern[];
36
+ }) | {
37
+ action: "unchanged";
38
+ } | {
39
+ skills: {
40
+ frontmatterName?: string;
41
+ path: string;
42
+ linked: string[];
43
+ name: string;
44
+ description: string | undefined;
45
+ 'dependency-name': string;
46
+ 'package-id': DepID;
47
+ }[];
48
+ action: "list";
49
+ unscanned?: string[];
50
+ unscannedReason?: "timeout" | "unscanned";
51
+ dirs: string[];
52
+ skipped?: string[];
53
+ };
54
+ readonly mermaid: (r: SkillsResult) => string;
55
+ };
56
+ export declare const command: CommandFn<SkillsResult>;
@@ -0,0 +1,267 @@
1
+ import { styleText } from 'node:util';
2
+ import { error } from '@vltpkg/error-cause';
3
+ import { assertQuery, linkSkills, listSkills, mermaidOutput, } from '@vltpkg/graph';
4
+ import { configLabel, savedLine, storedAllowSkills, unmatchedLines, unscannedLines, } from "../allow-skills.js";
5
+ import { configWriteTarget } from "../config/index.js";
6
+ import { commandUsage } from "../config/usage.js";
7
+ import { confirm, editQuery, interactive } from "../skills-prompt.js";
8
+ export const needsRegistry = true;
9
+ export const usage = () => commandUsage({
10
+ command: 'skills',
11
+ usage: ['', 'list [<query>]', 'link [<query>]'],
12
+ description: `Manage the agent skills shipped by installed packages.
13
+
14
+ A skill is a folder with a \`SKILL.md\` file
15
+ (https://agentskills.io/specification). Packages ship them as a
16
+ root \`SKILL.md\`, or at \`<name>/SKILL.md\` in \`skills/\`,
17
+ \`dist/skills/\` or \`.agents/skills/\`: the first skill of a name
18
+ wins.
19
+
20
+ Skills are linked into the project's agent skill dirs:
21
+ \`.agents/skills\`, plus \`<folder>/skills\` for each agent folder
22
+ at the project root (e.g. \`.claude/\`), or the \`skills-dir\`
23
+ config. When packages ship skills with the same name, one is
24
+ linked and the others are reported. Only links made by vlt are
25
+ ever replaced or removed; anything else in the way is skipped.
26
+
27
+ Use --target or a query after the subcommand to select packages
28
+ using DSS query syntax. End a selector with
29
+ \`:skill(<name>, …)\` to pick single skills, e.g.
30
+ \`#skills:skill(find-skills)\`. Use
31
+ \`vlt install --allow-skills=<query>\` to link skills on install.`,
32
+ subcommands: {
33
+ list: {
34
+ usage: '[<query>]',
35
+ description: `List the skills of installed packages. The default.
36
+ Selects all packages (\`*\`) by default. Applies
37
+ \`:skill()\`: preview a query before \`link\` saves
38
+ it.`,
39
+ },
40
+ link: {
41
+ usage: '[<query>]',
42
+ description: `Set, save and apply \`allow-skills\`: link what the
43
+ query selects and remove vlt links to other skills.
44
+ With no query: the stored one, or
45
+ \`:not(:malware)\`. Asks before replacing or editing
46
+ a stored query (-y skips). Saves to the project
47
+ vlt.json, or the user one with --config=user.`,
48
+ },
49
+ },
50
+ options: {
51
+ target: {
52
+ value: '<query>',
53
+ description: 'Query selector to filter packages using DSS syntax.',
54
+ },
55
+ yes: {
56
+ description: 'Skip the prompts: replace or keep the stored allow-skills without asking.',
57
+ },
58
+ config: {
59
+ value: 'user|project',
60
+ description: 'vlt.json to save allow-skills to (default: project).',
61
+ },
62
+ view: {
63
+ value: '[human | json | mermaid]',
64
+ description: 'Output format. mermaid: list only.',
65
+ },
66
+ },
67
+ });
68
+ const plural = (n, s) => `${n} ${s}${n === 1 ? '' : 's'}`;
69
+ const lines = (header, items) => [header, ...items.map(i => ` ${i}`)].join('\n');
70
+ // warnings shared by list and link
71
+ const notes = (r) => [
72
+ ...(r.skipped ? [`⚠️ Skipped ${r.skipped.join(', ')}`] : []),
73
+ ...(r.gitignore ?
74
+ [`⚠️ Could not update ${r.gitignore.join(', ')}`]
75
+ : []),
76
+ ...unscannedLines(r),
77
+ ];
78
+ // `vlt ls` style
79
+ const pkgLabel = (s) => {
80
+ const pkg = s.version ? `${s.name}@${s.version}` : s.name;
81
+ return s.alias ? `${s.alias} (${pkg})` : pkg;
82
+ };
83
+ const linkedSuffix = (s, dirs) => dirs.length && dirs.every(d => s.linked.includes(d)) ? ' (linked)'
84
+ : s.linked.length ? ` (linked in ${s.linked.join(', ')})`
85
+ : '';
86
+ const row = (s, dirs) => `${s.skill} (${pkgLabel(s)})${linkedSuffix(s, dirs)}`;
87
+ const listNotes = (r) => [
88
+ ...(!r.dirs.length && !r.skipped ?
89
+ ['No agent skill dirs: skills-dir is empty']
90
+ : []),
91
+ ...notes(r),
92
+ ];
93
+ // colors as `vlt ls` / `vlt query`: linked skills = selected nodes
94
+ const humanList = (r, { colors } = {}) => {
95
+ const style = (format) => (s) => colors ? styleText(format, s, { validateStream: false }) : s;
96
+ const yellow = style('yellow');
97
+ const rows = r.skills.map(s => {
98
+ const x = row(s, r.dirs);
99
+ return s.linked.length ? yellow(x) : x;
100
+ });
101
+ const last = rows.length - 1;
102
+ return [
103
+ ...(rows.length ?
104
+ [
105
+ style('reset')([
106
+ r.project,
107
+ ...rows.map((x, i) => `${i === last ? '└──' : '├──'} ${x}`),
108
+ ].join('\n')),
109
+ ]
110
+ : ['No agent skills found in installed packages.']),
111
+ ...listNotes(r),
112
+ ].join('\n');
113
+ };
114
+ // the dependency graph down to each package, its skills as leaves
115
+ const mermaidList = (r) => {
116
+ const children = new Map();
117
+ for (const s of r.skills) {
118
+ const list = children.get(s.id) ?? [];
119
+ list.push({
120
+ edge: pkgLabel(s),
121
+ label: `${s.skill}${linkedSuffix(s, r.dirs)}`,
122
+ });
123
+ children.set(s.id, list);
124
+ }
125
+ const { graph } = r;
126
+ return [
127
+ mermaidOutput({
128
+ edges: [],
129
+ importers: new Set([graph.mainImporter]),
130
+ nodes: [...graph.nodes.values()].filter(n => n === graph.mainImporter || children.has(n.id)),
131
+ children,
132
+ }),
133
+ ...listNotes(r).map(n => `%% ${n}`),
134
+ ].join('\n');
135
+ };
136
+ // `name`: the skill, `dependency-name`: the dep it's installed as,
137
+ // `package-id`: its package
138
+ const jsonSkill = ({ skill, name, alias, version, id, description, ...rest }) => ({
139
+ name: skill,
140
+ description,
141
+ 'dependency-name': alias ?? name,
142
+ 'package-id': id,
143
+ ...rest,
144
+ });
145
+ // distinct skills, in any number of dirs
146
+ const count = (rows) => new Set(rows.map(r => `${r.id}\0${r.skill}`)).size;
147
+ const humanLink = (r) => {
148
+ const out = [];
149
+ if (r.linked.length) {
150
+ out.push(lines(`🔗 Linked ${plural(count(r.linked), 'agent skill')}:`, r.linked.map(s => s.mount)));
151
+ }
152
+ else if (r.unchanged.length) {
153
+ out.push(`${plural(count(r.unchanged), 'agent skill')} already linked.`);
154
+ }
155
+ if (r.removed.length) {
156
+ out.push(lines(`🧹 Removed ${plural(r.removed.length, 'skill link')}:`, r.removed));
157
+ }
158
+ if (r.conflicts.length) {
159
+ out.push(lines(`⚠️ Skipped ${plural(r.conflicts.length, 'skill')}, path in use or taken by another package:`, r.conflicts));
160
+ }
161
+ out.push(...notes(r));
162
+ return out.join('\n') || 'No agent skills found to link.';
163
+ };
164
+ const human = (r, o) => r.action === 'list' ? humanList(r, o)
165
+ : r.action === 'unchanged' ? 'No changes made.'
166
+ : [
167
+ humanLink(r),
168
+ ...unmatchedLines(r.unmatched),
169
+ ...(r.saved ? [savedLine(r.query, r.saved)] : []),
170
+ ].join('\n');
171
+ export const views = {
172
+ human,
173
+ json: (r) => {
174
+ if (r.action !== 'list')
175
+ return r;
176
+ // key order kept
177
+ const { project, graph, ...rest } = r;
178
+ return { ...rest, skills: rest.skills.map(jsonSkill) };
179
+ },
180
+ mermaid: (r) => r.action === 'list' ? mermaidList(r) : human(r),
181
+ };
182
+ const defaultQuery = ':not(:malware)';
183
+ const where = (which) => which === 'user' ?
184
+ 'in the user vlt.json'
185
+ : 'for this project (vlt.json)';
186
+ // the query to link; undefined: no changes
187
+ const pickQuery = async (conf, given) => {
188
+ const check = (q) => assertQuery(q, 'allow-skills', ['skill']);
189
+ const stored = storedAllowSkills(conf);
190
+ const yes = !!conf.get('yes');
191
+ const tty = interactive();
192
+ if (given) {
193
+ await check(given);
194
+ if (!stored || stored.query === given || yes)
195
+ return given;
196
+ if (!tty) {
197
+ throw error(`allow-skills is already set (${configLabel(stored.which)}): "${stored.query}"; pass -y to replace it`, { code: 'EUSAGE', found: given, wanted: stored.query });
198
+ }
199
+ if (!(await confirm(`allow-skills is already set ${where(stored.which)}: "${stored.query}". Replace it? [y/N] `))) {
200
+ return undefined;
201
+ }
202
+ return editQuery({ current: stored.query, prefill: given, check });
203
+ }
204
+ if (stored) {
205
+ if (yes || !tty)
206
+ return stored.query;
207
+ const edit = await confirm(`allow-skills is set ${where(stored.which)}: "${stored.query}". Edit it? [y/N] `);
208
+ // ctrl+C/D: cancel
209
+ if (edit === undefined)
210
+ return undefined;
211
+ return edit ?
212
+ editQuery({
213
+ current: stored.query,
214
+ prefill: stored.query,
215
+ check,
216
+ })
217
+ : stored.query;
218
+ }
219
+ if (yes || !tty)
220
+ return defaultQuery;
221
+ return editQuery({ prefill: defaultQuery, check });
222
+ };
223
+ export const command = async (conf) => {
224
+ const [sub = 'list', query] = conf.positionals;
225
+ const target = conf.get('target') || query;
226
+ const opts = {
227
+ ...conf.options,
228
+ projectRoot: conf.projectRoot,
229
+ skillsDirs: conf.get('skills-dir'),
230
+ };
231
+ switch (sub) {
232
+ case 'list':
233
+ case 'ls':
234
+ return {
235
+ action: 'list',
236
+ ...(await listSkills({ ...opts, target })),
237
+ };
238
+ case 'link': {
239
+ const query = await pickQuery(conf, target);
240
+ if (query === undefined)
241
+ return { action: 'unchanged' };
242
+ const res = await linkSkills({
243
+ ...opts,
244
+ target: query,
245
+ apply: true,
246
+ });
247
+ // after linking: a link error saves nothing
248
+ let saved;
249
+ if (storedAllowSkills(conf)?.query !== query) {
250
+ saved = configWriteTarget(conf, 'project');
251
+ await conf.addConfigToFile(saved, { 'allow-skills': query });
252
+ }
253
+ return {
254
+ action: 'link',
255
+ query,
256
+ ...(saved && { saved }),
257
+ ...res,
258
+ };
259
+ }
260
+ default:
261
+ throw error('Unknown skills subcommand', {
262
+ code: 'EUSAGE',
263
+ found: sub,
264
+ validOptions: ['list', 'ls', 'link'],
265
+ });
266
+ }
267
+ };
@@ -105,7 +105,7 @@ export const views = {
105
105
  },
106
106
  };
107
107
  const listTokens = async (rc, registry, identity, alias) => {
108
- const localTok = await getToken(normalizeRegistryKey(registry), identity);
108
+ const localTok = await getToken(normalizeRegistryKey(registry), identity, rc.defaultRegistryKey);
109
109
  if (!localTok) {
110
110
  return { registry, alias, tokens: [] };
111
111
  }
@@ -1,16 +1,27 @@
1
- import type { Graph } from '@vltpkg/graph';
1
+ import type { Graph, LinkSkillsResult } from '@vltpkg/graph';
2
2
  import type { CommandFn, CommandUsage } from '../index.ts';
3
+ import type { SelfRefused } from '../self-update.ts';
3
4
  export type UninstallResult = {
4
5
  /**
5
6
  * The resulting graph structure at the end of an uninstall.
6
7
  */
7
8
  graph: Graph;
9
+ /**
10
+ * Agent skill links added or removed.
11
+ */
12
+ skills?: LinkSkillsResult;
13
+ };
14
+ /** `vlt uninstall -g vlt` of a vlt that is not a global package */
15
+ export type UninstallCommandResult = UninstallResult | {
16
+ self: SelfRefused;
8
17
  };
9
18
  export declare const needsRegistry = true;
10
19
  export declare const needsNpmRegistry = true;
11
20
  export declare const usage: CommandUsage;
12
21
  export declare const views: {
13
- readonly json: (i: UninstallResult) => import("@vltpkg/graph").LockfileData;
14
- readonly human: import("../view.ts").LazyView<import("./install.ts").InstallResult>;
22
+ readonly json: (i: UninstallCommandResult) => import("@vltpkg/graph").LockfileData | {
23
+ self: SelfRefused;
24
+ };
25
+ readonly human: import("../view.ts").LazyView<Partial<import("./install.ts").InstallResult>>;
15
26
  };
16
- export declare const command: CommandFn<UninstallResult>;
27
+ export declare const command: CommandFn<UninstallCommandResult>;
@@ -1,6 +1,9 @@
1
1
  import { uninstall } from '@vltpkg/graph';
2
2
  import { commandUsage } from "../config/usage.js";
3
3
  import { parseRemoveArgs } from "../parse-add-remove-args.js";
4
+ import { assertGlobalOptions, parseGlobalRemoveArgs, removeGlobalPackages, } from "../global.js";
5
+ import { resolveGlobalBinDir } from "../global-bin-dir.js";
6
+ import { deferSelfRemove, refuseSelfUninstall, runningStoreDep, } from "../self-update.js";
4
7
  import { lazyView } from "../view.js";
5
8
  export const needsRegistry = true;
6
9
  export const needsNpmRegistry = true;
@@ -25,24 +28,49 @@ export const usage = () => commandUsage({
25
28
  value: '<query>',
26
29
  description: 'Filter which packages are allowed to run lifecycle scripts using DSS query syntax.',
27
30
  },
31
+ global: {
32
+ description: 'Uninstall global packages, removing their workspace and bins.',
33
+ },
28
34
  },
29
35
  });
30
36
  export const views = {
31
- json: i => i.graph.toJSON(),
37
+ json: i => ('graph' in i ? i.graph.toJSON() : { self: i.self }),
32
38
  human: lazyView(async () => (await import('./install/reporter.ts')).InstallReporter),
33
39
  };
34
40
  export const command = async (conf) => {
41
+ if (conf.globalRoot) {
42
+ assertGlobalOptions(conf);
43
+ const refused = await refuseSelfUninstall(conf);
44
+ if (refused)
45
+ return { self: refused };
46
+ }
35
47
  const { monorepo, scurry } = conf.options;
36
- const { remove } = parseRemoveArgs(conf, scurry, monorepo);
48
+ const global = conf.globalRoot ? parseGlobalRemoveArgs(conf) : undefined;
49
+ // only swept, so a bad --global-bin-dir must not block it
50
+ const binDir = global ?
51
+ await resolveGlobalBinDir(conf).catch(() => undefined)
52
+ : undefined;
53
+ const { remove } = global ?? parseRemoveArgs(conf, scurry, monorepo);
37
54
  /* c8 ignore start */
38
55
  const allowScripts = conf.get('allow-scripts') ?
39
56
  String(conf.get('allow-scripts'))
40
57
  : ':not(*)';
41
58
  /* c8 ignore stop */
42
- const { graph } = await uninstall({
59
+ // never removed from under itself
60
+ const keep = conf.globalRoot ?
61
+ await runningStoreDep(conf.globalRoot)
62
+ : undefined;
63
+ const { graph, skills } = await uninstall({
43
64
  ...conf.options,
44
65
  allowScripts,
66
+ allowSkills: conf.get('allow-skills'),
67
+ skillsDirs: conf.get('skills-dir'),
45
68
  lockfileOnly: conf.options['lockfile-only'],
69
+ ...(keep ? { keepNodes: new Set([keep]) } : null),
46
70
  }, remove);
47
- return { graph };
71
+ if (global) {
72
+ await deferSelfRemove(conf.projectRoot, graph, keep);
73
+ await removeGlobalPackages(conf.projectRoot, global.dirs, binDir?.dir ?? conf.globalBinDir);
74
+ }
75
+ return { graph, ...(skills ? { skills } : null) };
48
76
  };
@@ -1,5 +1,4 @@
1
1
  import type { CommandFn, CommandUsage } from '../index.ts';
2
- export declare const needsRegistry = true;
3
2
  export declare const usage: CommandUsage;
4
3
  export type CommandResult = {
5
4
  /** The package name */
@@ -1,9 +1,10 @@
1
1
  import { error } from '@vltpkg/error-cause';
2
- import { RegistryClient, assertOk, requestError, } from '@vltpkg/registry-client';
2
+ import { RegistryClient, assertOk, registryBase, requestError, } from '@vltpkg/registry-client';
3
3
  import { Spec } from '@vltpkg/spec';
4
+ import { dirname } from 'node:path';
4
5
  import { commandUsage } from "../config/usage.js";
6
+ import { getPublishConfig } from "../publish-config.js";
5
7
  import { resolveRegistry } from "../require-registry.js";
6
- export const needsRegistry = true;
7
8
  export const usage = () => commandUsage({
8
9
  command: 'unpublish',
9
10
  usage: ['<package>@<version>', '<package> --force'],
@@ -11,6 +12,8 @@ export const usage = () => commandUsage({
11
12
 
12
13
  To unpublish a single version, specify the package name and version.
13
14
  To unpublish an entire package, specify the package name and use --force.
15
+ A spec naming the package in the current directory uses its
16
+ \`publishConfig.registry\`, if set.
14
17
 
15
18
  ⚠️ Unpublishing is a destructive action that cannot be undone.
16
19
  Consider using \`vlt deprecate\` instead if you want to discourage
@@ -45,14 +48,22 @@ export const views = {
45
48
  },
46
49
  json: (r) => r,
47
50
  };
51
+ /** `publishConfig.registry` of the local package, if it is `name` */
52
+ const localPublishRegistry = (conf, name) => {
53
+ const path = conf.options.packageJson.find(process.cwd());
54
+ if (!path)
55
+ return undefined;
56
+ const manifest = conf.options.packageJson.read(dirname(path));
57
+ return manifest.name === name ?
58
+ getPublishConfig(manifest)?.registry
59
+ : undefined;
60
+ };
48
61
  export const command = async (conf) => {
49
62
  const specArg = conf.positionals[0];
50
63
  if (!specArg) {
51
64
  throw error('unpublish requires a package spec argument (e.g. pkg@version)', { code: 'EUSAGE' });
52
65
  }
53
66
  const { otp, force } = conf.options;
54
- const registry = await resolveRegistry(conf);
55
- const registryUrl = new URL(registry);
56
67
  const spec = Spec.parseArgs(specArg, conf.options);
57
68
  const name = spec.name;
58
69
  /* c8 ignore start - Spec.parseArgs always produces a name for valid input */
@@ -71,6 +82,8 @@ export const command = async (conf) => {
71
82
  'To unpublish all versions, use: vlt unpublish <package> --force');
72
83
  }
73
84
  }
85
+ const registryUrl = new URL(registryBase(localPublishRegistry(conf, name) ??
86
+ (await resolveRegistry(conf))));
74
87
  const rc = new RegistryClient(conf.options);
75
88
  const encodedName = name.startsWith('@') ? name.replace('/', '%2F') : name;
76
89
  if (version) {
@@ -5,11 +5,23 @@ export declare const needsNpmRegistry = true;
5
5
  export declare const usage: CommandUsage;
6
6
  export declare const views: {
7
7
  readonly json: (i: InstallResult) => {
8
+ allowSkills?: import("../allow-skills.ts").AllowSkillsSave | undefined;
9
+ skills?: {
10
+ unscanned?: string[];
11
+ unscannedReason?: "timeout" | "unscanned";
12
+ removed: string[];
13
+ conflicts: string[];
14
+ dirs: string[];
15
+ skipped?: string[];
16
+ gitignore?: string[];
17
+ unmatched?: import("@vltpkg/graph").UnmatchedPattern[];
18
+ linked: string[];
19
+ } | undefined;
8
20
  persistedConfig?: import("../persist-spec-config.ts").SpecConfigPersistPlan | undefined;
9
21
  graph: import("@vltpkg/graph").LockfileData;
10
22
  buildQueue?: import("@vltpkg/dep-id").DepID[] | undefined;
11
23
  message?: string | undefined;
12
24
  };
13
- readonly human: import("../view.ts").LazyView<InstallResult>;
25
+ readonly human: import("../view.ts").LazyView<Partial<InstallResult>>;
14
26
  };
15
27
  export declare const command: CommandFn<InstallResult>;
@@ -1,6 +1,7 @@
1
1
  import { update } from '@vltpkg/graph';
2
2
  import { error } from '@vltpkg/error-cause';
3
3
  import { commandUsage } from "../config/usage.js";
4
+ import { saveAllowSkills } from "../allow-skills.js";
4
5
  import { planSpecConfigPersist } from "../persist-spec-config.js";
5
6
  import { asUnknownSpecPrefix } from "../require-registry.js";
6
7
  import { lazyView } from "../view.js";
@@ -28,8 +29,17 @@ export const usage = () => commandUsage({
28
29
  value: '<query>',
29
30
  description: 'Filter which packages are allowed to run lifecycle scripts using DSS query syntax.',
30
31
  },
32
+ 'allow-skills': {
33
+ value: '<query>',
34
+ description: "Link agent skills of packages matching this DSS query into the project's agent skill dirs. Saved to vlt.json.",
35
+ },
31
36
  },
32
37
  });
38
+ // link mounts; `unchanged` left out
39
+ const skillsJson = ({ linked, unchanged: _, ...rest }) => ({
40
+ linked: linked.map(s => s.mount),
41
+ ...rest,
42
+ });
33
43
  export const views = {
34
44
  json: i => ({
35
45
  ...(i.buildQueue?.length ?
@@ -42,6 +52,8 @@ export const views = {
42
52
  ...(i.persistedConfig ?
43
53
  { persistedConfig: i.persistedConfig }
44
54
  : null),
55
+ ...(i.skills ? { skills: skillsJson(i.skills) } : null),
56
+ ...(i.allowSkills ? { allowSkills: i.allowSkills } : null),
45
57
  }),
46
58
  human: lazyView(async () => (await import('./install/reporter.ts')).InstallReporter),
47
59
  };
@@ -58,17 +70,22 @@ export const command = async (conf) => {
58
70
  String(conf.get('allow-scripts'))
59
71
  : ':not(*)';
60
72
  /* c8 ignore stop */
61
- const { buildQueue, graph } = await update({
73
+ const { buildQueue, graph, skills } = await update({
62
74
  ...conf.options,
63
75
  allowScripts,
76
+ allowSkills: conf.get('allow-skills'),
77
+ skillsDirs: conf.get('skills-dir'),
64
78
  }).catch((er) => {
65
79
  throw asUnknownSpecPrefix(er);
66
80
  });
67
81
  if (persist)
68
82
  await conf.addConfigToFile(persist.which, persist.values);
83
+ const allowSkillsSave = await saveAllowSkills(conf);
69
84
  return {
70
85
  buildQueue,
71
86
  graph,
72
87
  ...(persist ? { persistedConfig: persist } : null),
88
+ ...(skills ? { skills } : null),
89
+ ...(allowSkillsSave ? { allowSkills: allowSkillsSave } : null),
73
90
  };
74
91
  };
@@ -53,6 +53,7 @@ export declare const commands: {
53
53
  readonly 'run-exec': "run-exec";
54
54
  readonly run: "run";
55
55
  readonly setup: "setup";
56
+ readonly skills: "skills";
56
57
  readonly token: "token";
57
58
  readonly uninstall: "uninstall";
58
59
  readonly unpublish: "unpublish";
@@ -235,6 +236,38 @@ export declare const definition: import("jackspeak").Jack<{
235
236
  } & {
236
237
  workspace: import("jackspeak").ConfigOption<"string", true, readonly string[] | undefined>;
237
238
  'workspace-group': import("jackspeak").ConfigOption<"string", true, readonly string[] | undefined>;
239
+ } & {
240
+ global: {
241
+ short: string;
242
+ description: string;
243
+ };
244
+ } & {
245
+ global: import("jackspeak").ConfigOption<"boolean", false, undefined>;
246
+ } & {
247
+ 'global-dir': {
248
+ hint: string;
249
+ default: string;
250
+ description: string;
251
+ };
252
+ } & {
253
+ 'global-dir': import("jackspeak").ConfigOption<"string", false, readonly string[] | undefined>;
254
+ } & {
255
+ 'global-bin-dir': {
256
+ hint: string;
257
+ description: string;
258
+ };
259
+ } & {
260
+ 'global-bin-dir': import("jackspeak").ConfigOption<"string", false, readonly string[] | undefined>;
261
+ } & {
262
+ path: {
263
+ description: string;
264
+ };
265
+ 'no-modify-path': {
266
+ description: string;
267
+ };
268
+ } & {
269
+ path: import("jackspeak").ConfigOption<"boolean", false, undefined>;
270
+ 'no-modify-path': import("jackspeak").ConfigOption<"boolean", false, undefined>;
238
271
  } & {
239
272
  scope: {
240
273
  short: string;
@@ -371,6 +404,10 @@ export declare const definition: import("jackspeak").Jack<{
371
404
  'save-config': {
372
405
  description: string;
373
406
  };
407
+ 'migrate-workspaces': {
408
+ description: string;
409
+ default: true;
410
+ };
374
411
  } & {
375
412
  'save-dev': import("jackspeak").ConfigOption<"boolean", false, undefined>;
376
413
  'save-exact': import("jackspeak").ConfigOption<"boolean", false, undefined>;
@@ -379,6 +416,7 @@ export declare const definition: import("jackspeak").Jack<{
379
416
  'save-prod': import("jackspeak").ConfigOption<"boolean", false, undefined>;
380
417
  'save-types': import("jackspeak").ConfigOption<"boolean", false, undefined>;
381
418
  'save-config': import("jackspeak").ConfigOption<"boolean", false, undefined>;
419
+ 'migrate-workspaces': import("jackspeak").ConfigOption<"boolean", false, undefined>;
382
420
  } & {
383
421
  'save-prefix': {
384
422
  description: string;
@@ -429,6 +467,20 @@ export declare const definition: import("jackspeak").Jack<{
429
467
  };
430
468
  } & {
431
469
  'allow-scripts': import("jackspeak").ConfigOption<"string", false, readonly string[] | undefined>;
470
+ } & {
471
+ 'allow-skills': {
472
+ hint: string;
473
+ description: string;
474
+ };
475
+ } & {
476
+ 'allow-skills': import("jackspeak").ConfigOption<"string", false, readonly string[] | undefined>;
477
+ } & {
478
+ 'skills-dir': {
479
+ hint: string;
480
+ description: string;
481
+ };
482
+ } & {
483
+ 'skills-dir': import("jackspeak").ConfigOption<"string", true, readonly string[] | undefined>;
432
484
  } & {
433
485
  access: {
434
486
  description: string;