dryai 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -0
- package/dest/commands/install.d.ts +3 -0
- package/dest/commands/install.js +4 -0
- package/dest/commands/skills/add.d.ts +12 -0
- package/dest/commands/skills/add.js +99 -0
- package/dest/commands/skills/index.d.ts +11 -0
- package/dest/commands/skills/index.js +90 -0
- package/dest/commands/skills/list.d.ts +6 -0
- package/dest/commands/skills/list.js +26 -0
- package/dest/commands/skills/remove.d.ts +8 -0
- package/dest/commands/skills/remove.js +17 -0
- package/dest/commands/skills/update-all.d.ts +6 -0
- package/dest/commands/skills/update-all.js +39 -0
- package/dest/commands/skills/update.d.ts +8 -0
- package/dest/commands/skills/update.js +35 -0
- package/dest/lib/command-options.d.ts +18 -0
- package/dest/lib/command-options.js +31 -0
- package/dest/lib/context.d.ts +73 -0
- package/dest/lib/context.js +104 -0
- package/dest/lib/frontmatter.d.ts +104 -0
- package/dest/lib/frontmatter.js +96 -0
- package/dest/lib/install.d.ts +8 -0
- package/dest/lib/install.js +380 -0
- package/dest/lib/skills.d.ts +192 -0
- package/dest/lib/skills.js +329 -0
- package/dest/main.d.ts +3 -0
- package/dest/main.js +115 -0
- package/package.json +45 -0
package/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Share AI config CLI
|
|
2
|
+
|
|
3
|
+
Installs command, rule, and skill sources from `~/.config/agents` by default into Copilot and Cursor targets.
|
|
4
|
+
|
|
5
|
+
Pass `--input <path>` to read configs from a different root such as `./config`.
|
|
6
|
+
|
|
7
|
+
Pass `--output <path>` to write generated output somewhere other than your home directory.
|
|
8
|
+
|
|
9
|
+
`--test` is a shortcut for `--output ./output-test`, and if both are provided, `--output` wins.
|
|
10
|
+
|
|
11
|
+
## Input
|
|
12
|
+
|
|
13
|
+
Input config files live under the selected input root:
|
|
14
|
+
|
|
15
|
+
- `commands`
|
|
16
|
+
- `rules`
|
|
17
|
+
- `skills`
|
|
18
|
+
|
|
19
|
+
Live output is written to:
|
|
20
|
+
|
|
21
|
+
- `~/.copilot/prompts`
|
|
22
|
+
- `~/.copilot/instructions`
|
|
23
|
+
- `~/.copilot/skills`
|
|
24
|
+
- `~/.cursor/rules`
|
|
25
|
+
- `~/.cursor/skills`
|
|
26
|
+
|
|
27
|
+
## Commands
|
|
28
|
+
|
|
29
|
+
```sh
|
|
30
|
+
dryai install
|
|
31
|
+
dryai skills list List local skills
|
|
32
|
+
dryai skills add [options] <repo> Add managed skills from a remote repository
|
|
33
|
+
dryai skills remove <name> Remove a managed skill
|
|
34
|
+
dryai skills update <name> Update a managed skill from its tracked source
|
|
35
|
+
dryai skills update-all Update all managed skills from their tracked sources
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`<repo>` may be a full git remote URL or a GitHub `owner/repo` shorthand such as `anthropics/skills`.
|
|
39
|
+
|
|
40
|
+
## Managed Skills
|
|
41
|
+
|
|
42
|
+
Imported skills are copied into `config/skills/<name>/` and tracked in `skills.lock.json`.
|
|
43
|
+
|
|
44
|
+
`skills add` requires at least one `--skill <name>` value. Each requested skill is always resolved from `<repo root>/skills/<name>`.
|
|
45
|
+
|
|
46
|
+
Use `--as <name>` to choose a different local managed skill name when importing exactly one skill.
|
|
47
|
+
|
|
48
|
+
Examples:
|
|
49
|
+
|
|
50
|
+
```sh
|
|
51
|
+
dryai skills add anthropics/skills --skill skill-creator
|
|
52
|
+
dryai skills add vercel-labs/agent-skills --skill pr-review commit
|
|
53
|
+
dryai skills add https://github.com/vercel-labs/agent-skills.git --skill pr-review commit
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
By default, imports track the requested ref. With no `--ref`, that means the remote default branch `HEAD` is tracked. Use `--pin` to store the currently resolved commit instead, so later `skills update` operations stay pinned to that commit.
|
|
57
|
+
|
|
58
|
+
The lockfile records:
|
|
59
|
+
|
|
60
|
+
- the local skill name
|
|
61
|
+
- the source repository
|
|
62
|
+
- the source path within that repository
|
|
63
|
+
- the requested git ref, when one was provided
|
|
64
|
+
- the resolved commit that was imported
|
|
65
|
+
|
|
66
|
+
`skills update` and `skills update-all` re-fetch the tracked repository snapshot and replace the local copied skill directory.
|
|
67
|
+
|
|
68
|
+
`skills remove` deletes the local copied skill directory and removes its lockfile entry.
|
|
69
|
+
|
|
70
|
+
`skills list` reports local skill directories, annotating managed entries from the lockfile and flagging managed entries whose local directory is missing.
|
|
71
|
+
|
|
72
|
+
## Development
|
|
73
|
+
|
|
74
|
+
For development, use `pnpm dev` to rebuild into `dest/` on change and `pnpm dev:dryai --test install` to run the built CLI.
|
|
75
|
+
|
|
76
|
+
Run `pnpm run setup:editor` after installing dependencies if you want the Effect language service workspace patch applied locally.
|
|
77
|
+
|
|
78
|
+
```sh
|
|
79
|
+
pnpm run setup:editor
|
|
80
|
+
pnpm run build
|
|
81
|
+
pnpm run dev
|
|
82
|
+
pnpm run test
|
|
83
|
+
pnpm run test:watch
|
|
84
|
+
|
|
85
|
+
pnpm dev:dryai install
|
|
86
|
+
pnpm dev:dryai --test install
|
|
87
|
+
pnpm dev:dryai --output ./tmp/install-root install
|
|
88
|
+
pnpm dev:dryai --input ./config install
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## CI and Release
|
|
92
|
+
|
|
93
|
+
- On pull request open or update
|
|
94
|
+
- Run CI validation with build, test, and `npm pack --dry-run`.
|
|
95
|
+
- On changes landing on `main`
|
|
96
|
+
- Run the same CI validation with build, test, and `npm pack --dry-run`.
|
|
97
|
+
- On `v*` tag pushed to `main`
|
|
98
|
+
- Verify the tag matches the checked-in `package.json` version.
|
|
99
|
+
- Verify the tagged commit is on `main`.
|
|
100
|
+
- Build and test the CLI.
|
|
101
|
+
- Create a tarball with `npm pack`.
|
|
102
|
+
- Publish the package to npm using the repository `NPM_TOKEN` secret.
|
|
103
|
+
- Create or update the matching GitHub Release.
|
|
104
|
+
- Upload the tarball as a release asset.
|
|
105
|
+
|
|
106
|
+
Example release flow:
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
git tag v0.1.0
|
|
110
|
+
git push origin v0.1.0
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Install from the release tarball with:
|
|
114
|
+
|
|
115
|
+
```sh
|
|
116
|
+
npm install -g https://github.com/willmruzek/share-ai-config/releases/download/v0.1.0/share-ai-config-0.1.0.tgz
|
|
117
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentsContext } from '../../lib/context.js';
|
|
2
|
+
/**
|
|
3
|
+
* Imports one or more managed skills from a remote repository `skills/` directory into the local skills directory.
|
|
4
|
+
*/
|
|
5
|
+
export declare function runSkillsAddCommand(context: AgentsContext, input: {
|
|
6
|
+
repo: string;
|
|
7
|
+
skillNames: string[];
|
|
8
|
+
asName: string | undefined;
|
|
9
|
+
pin: boolean;
|
|
10
|
+
ref: string | undefined;
|
|
11
|
+
}): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=add.d.ts.map
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import { cloneRemoteRepo, createImportedSkillRecord, ensureSkillsLockfile, ensureSkillsRoot, findManagedSkill, formatManagedSkillSummary, getManagedSkillDirectory, loadSkillsLockfile, normalizeRemoteRepo, replaceManagedSkillDirectory, resolveManagedSkillImportPath, resolveSkillSourceDir, saveSkillsLockfile, timestampNow, upsertManagedSkill, } from '../../lib/skills.js';
|
|
3
|
+
/**
|
|
4
|
+
* Normalizes and de-duplicates requested skill names while preserving their input order.
|
|
5
|
+
*/
|
|
6
|
+
function normalizeRequestedSkillNames(skillNames) {
|
|
7
|
+
const uniqueSkillNames = [];
|
|
8
|
+
const seenSkillNames = new Set();
|
|
9
|
+
for (const rawSkillName of skillNames) {
|
|
10
|
+
const normalizedSkillPath = resolveManagedSkillImportPath({
|
|
11
|
+
skillName: rawSkillName,
|
|
12
|
+
});
|
|
13
|
+
const skillName = normalizedSkillPath.slice('skills/'.length);
|
|
14
|
+
if (seenSkillNames.has(skillName)) {
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
seenSkillNames.add(skillName);
|
|
18
|
+
uniqueSkillNames.push(skillName);
|
|
19
|
+
}
|
|
20
|
+
return uniqueSkillNames;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Imports one or more managed skills from a remote repository `skills/` directory into the local skills directory.
|
|
24
|
+
*/
|
|
25
|
+
export async function runSkillsAddCommand(context, input) {
|
|
26
|
+
const repo = normalizeRemoteRepo(input.repo);
|
|
27
|
+
if (input.skillNames.length === 0) {
|
|
28
|
+
throw new Error('At least one skill name must be provided with --skill');
|
|
29
|
+
}
|
|
30
|
+
const requestedSkillNames = normalizeRequestedSkillNames(input.skillNames);
|
|
31
|
+
if (requestedSkillNames.length === 0) {
|
|
32
|
+
throw new Error('At least one skill name must be provided with --skill');
|
|
33
|
+
}
|
|
34
|
+
if (input.asName && requestedSkillNames.length !== 1) {
|
|
35
|
+
throw new Error('--as may only be used when importing exactly one skill');
|
|
36
|
+
}
|
|
37
|
+
await ensureSkillsRoot(context);
|
|
38
|
+
await ensureSkillsLockfile(context);
|
|
39
|
+
let lockfile = await loadSkillsLockfile(context);
|
|
40
|
+
const checkout = await cloneRemoteRepo({
|
|
41
|
+
ref: input.ref,
|
|
42
|
+
repo,
|
|
43
|
+
});
|
|
44
|
+
const skippedSkillNames = [];
|
|
45
|
+
const importedSkillSummaries = [];
|
|
46
|
+
try {
|
|
47
|
+
for (const requestedSkillName of requestedSkillNames) {
|
|
48
|
+
const skillName = input.asName ?? requestedSkillName;
|
|
49
|
+
const importedSkillPath = resolveManagedSkillImportPath({
|
|
50
|
+
skillName: requestedSkillName,
|
|
51
|
+
});
|
|
52
|
+
const existingManagedSkill = findManagedSkill(lockfile, {
|
|
53
|
+
name: skillName,
|
|
54
|
+
});
|
|
55
|
+
if (existingManagedSkill) {
|
|
56
|
+
skippedSkillNames.push(skillName);
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const targetDir = getManagedSkillDirectory(context, { skillName });
|
|
60
|
+
if (await fs.pathExists(targetDir)) {
|
|
61
|
+
throw new Error(`A local skill directory already exists: ${targetDir}`);
|
|
62
|
+
}
|
|
63
|
+
const sourceDir = await resolveSkillSourceDir({
|
|
64
|
+
checkoutDir: checkout.checkoutDir,
|
|
65
|
+
repo,
|
|
66
|
+
skillName: requestedSkillName,
|
|
67
|
+
});
|
|
68
|
+
await replaceManagedSkillDirectory({
|
|
69
|
+
targetDir,
|
|
70
|
+
sourceDir,
|
|
71
|
+
});
|
|
72
|
+
const importedSkill = createImportedSkillRecord({
|
|
73
|
+
commit: checkout.commit,
|
|
74
|
+
importedAt: timestampNow(),
|
|
75
|
+
name: skillName,
|
|
76
|
+
path: importedSkillPath,
|
|
77
|
+
ref: input.pin ? checkout.commit : input.ref,
|
|
78
|
+
repo,
|
|
79
|
+
});
|
|
80
|
+
lockfile = upsertManagedSkill(lockfile, {
|
|
81
|
+
updatedSkill: importedSkill,
|
|
82
|
+
});
|
|
83
|
+
await saveSkillsLockfile(context, { lockfile });
|
|
84
|
+
importedSkillSummaries.push(formatManagedSkillSummary(importedSkill));
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
await checkout.cleanup();
|
|
89
|
+
}
|
|
90
|
+
for (const importedSkillSummary of importedSkillSummaries) {
|
|
91
|
+
console.log(`Imported ${importedSkillSummary}`);
|
|
92
|
+
}
|
|
93
|
+
if (skippedSkillNames.length > 0) {
|
|
94
|
+
console.warn(`Skipped already-imported skills: ${skippedSkillNames.join(', ')}`);
|
|
95
|
+
}
|
|
96
|
+
if (importedSkillSummaries.length === 0) {
|
|
97
|
+
console.log('No skills were imported.');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { type AgentsContext } from '../../lib/context.js';
|
|
3
|
+
/**
|
|
4
|
+
* Registers the managed skills command tree on the parent CLI program.
|
|
5
|
+
*/
|
|
6
|
+
export declare function addSkillsCommand(input: {
|
|
7
|
+
parent: Command;
|
|
8
|
+
commandName: string;
|
|
9
|
+
resolveContext: () => AgentsContext;
|
|
10
|
+
}): Command;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import dedent from 'dedent';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { nonEmptyOptionStringSchema, parseOptionsObject, parseOptionValue, } from '../../lib/command-options.js';
|
|
5
|
+
import {} from '../../lib/context.js';
|
|
6
|
+
import { runSkillsAddCommand } from './add.js';
|
|
7
|
+
import { runSkillsListCommand } from './list.js';
|
|
8
|
+
import { runSkillsRemoveCommand } from './remove.js';
|
|
9
|
+
import { runSkillsUpdateAllCommand } from './update-all.js';
|
|
10
|
+
import { runSkillsUpdateCommand } from './update.js';
|
|
11
|
+
const skillsImportOptionsSchema = z.object({
|
|
12
|
+
skill: z.array(z.string()).optional(),
|
|
13
|
+
as: nonEmptyOptionStringSchema.optional(),
|
|
14
|
+
pin: z.boolean().optional().default(false),
|
|
15
|
+
ref: nonEmptyOptionStringSchema.optional(),
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Registers the managed skills command tree on the parent CLI program.
|
|
19
|
+
*/
|
|
20
|
+
export function addSkillsCommand(input) {
|
|
21
|
+
const { parent, commandName, resolveContext } = input;
|
|
22
|
+
const skills = parent
|
|
23
|
+
.command('skills')
|
|
24
|
+
.description('Manage imported skills')
|
|
25
|
+
.usage('<subcommand> [args]')
|
|
26
|
+
.helpOption('-h, --help', 'Display this message')
|
|
27
|
+
.helpCommand(false)
|
|
28
|
+
.addHelpText('after', dedent `
|
|
29
|
+
Examples:
|
|
30
|
+
${commandName} list
|
|
31
|
+
${commandName} add anthropics/skills --skill skill-creator
|
|
32
|
+
${commandName} add vercel-labs/agent-skills --skill pr-review commit
|
|
33
|
+
${commandName} update skill-creator
|
|
34
|
+
`)
|
|
35
|
+
.action(() => {
|
|
36
|
+
skills.outputHelp();
|
|
37
|
+
});
|
|
38
|
+
skills
|
|
39
|
+
.command('list')
|
|
40
|
+
.description('List local skills')
|
|
41
|
+
.action(async () => {
|
|
42
|
+
await runSkillsListCommand(resolveContext());
|
|
43
|
+
});
|
|
44
|
+
skills
|
|
45
|
+
.command('add <repo>')
|
|
46
|
+
.description('Add managed skills from a remote repository')
|
|
47
|
+
.option('--skill <names...>', 'Import one or more skills from the repository root skills/ directory')
|
|
48
|
+
.option('--as <name>', 'Store the imported skill under a different local managed name', parseOptionValue({
|
|
49
|
+
schema: nonEmptyOptionStringSchema,
|
|
50
|
+
optionLabel: '--as',
|
|
51
|
+
}))
|
|
52
|
+
.option('--pin', 'Pin the import to the currently resolved commit instead of tracking a moving ref')
|
|
53
|
+
.option('--ref <gitRef>', 'Fetch a specific git ref instead of the remote default', parseOptionValue({
|
|
54
|
+
schema: nonEmptyOptionStringSchema,
|
|
55
|
+
optionLabel: '--ref',
|
|
56
|
+
}))
|
|
57
|
+
.action(async (repo, options) => {
|
|
58
|
+
const parsedOptions = parseOptionsObject({
|
|
59
|
+
schema: skillsImportOptionsSchema,
|
|
60
|
+
options,
|
|
61
|
+
optionsLabel: 'skills add options',
|
|
62
|
+
});
|
|
63
|
+
await runSkillsAddCommand(resolveContext(), {
|
|
64
|
+
repo,
|
|
65
|
+
skillNames: parsedOptions.skill ?? [],
|
|
66
|
+
asName: parsedOptions.as,
|
|
67
|
+
pin: parsedOptions.pin,
|
|
68
|
+
ref: parsedOptions.ref,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
skills
|
|
72
|
+
.command('remove <name>')
|
|
73
|
+
.description('Remove a managed skill')
|
|
74
|
+
.action(async (skillName) => {
|
|
75
|
+
await runSkillsRemoveCommand(resolveContext(), { skillName });
|
|
76
|
+
});
|
|
77
|
+
skills
|
|
78
|
+
.command('update <name>')
|
|
79
|
+
.description('Update a managed skill from its tracked source')
|
|
80
|
+
.action(async (skillName) => {
|
|
81
|
+
await runSkillsUpdateCommand(resolveContext(), { skillName });
|
|
82
|
+
});
|
|
83
|
+
skills
|
|
84
|
+
.command('update-all')
|
|
85
|
+
.description('Update all managed skills from their tracked sources')
|
|
86
|
+
.action(async () => {
|
|
87
|
+
await runSkillsUpdateAllCommand(resolveContext());
|
|
88
|
+
});
|
|
89
|
+
return skills;
|
|
90
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AgentsContext } from '../../lib/context.js';
|
|
2
|
+
/**
|
|
3
|
+
* Lists local skills and annotates which ones are managed by the lockfile.
|
|
4
|
+
*/
|
|
5
|
+
export declare function runSkillsListCommand(context: AgentsContext): Promise<void>;
|
|
6
|
+
//# sourceMappingURL=list.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ensureSkillsRoot, findManagedSkill, formatManagedSkillSummary, listLocalSkillDirectories, loadSkillsLockfile, } from '../../lib/skills.js';
|
|
2
|
+
/**
|
|
3
|
+
* Lists local skills and annotates which ones are managed by the lockfile.
|
|
4
|
+
*/
|
|
5
|
+
export async function runSkillsListCommand(context) {
|
|
6
|
+
await ensureSkillsRoot(context);
|
|
7
|
+
const [localSkillDirectories, lockfile] = await Promise.all([
|
|
8
|
+
listLocalSkillDirectories(context),
|
|
9
|
+
loadSkillsLockfile(context),
|
|
10
|
+
]);
|
|
11
|
+
const localSkillLines = localSkillDirectories.map((skillName) => {
|
|
12
|
+
const managedSkill = findManagedSkill(lockfile, { name: skillName });
|
|
13
|
+
return managedSkill
|
|
14
|
+
? `- ${formatManagedSkillSummary(managedSkill)}`
|
|
15
|
+
: `- ${skillName} unmanaged`;
|
|
16
|
+
});
|
|
17
|
+
const missingManagedLines = lockfile.skills
|
|
18
|
+
.filter((managedSkill) => !localSkillDirectories.includes(managedSkill.name))
|
|
19
|
+
.map((managedSkill) => `- ${formatManagedSkillSummary(managedSkill)} missing-local-directory`);
|
|
20
|
+
const outputLines = [...localSkillLines, ...missingManagedLines];
|
|
21
|
+
if (outputLines.length === 0) {
|
|
22
|
+
console.log('No local skills found.');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
console.log(outputLines.join('\n'));
|
|
26
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AgentsContext } from '../../lib/context.js';
|
|
2
|
+
/**
|
|
3
|
+
* Removes a managed skill from the local directory and updates the lockfile.
|
|
4
|
+
*/
|
|
5
|
+
export declare function runSkillsRemoveCommand(context: AgentsContext, input: {
|
|
6
|
+
skillName: string;
|
|
7
|
+
}): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=remove.d.ts.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { findManagedSkill, formatManagedSkillSummary, loadSkillsLockfile, removeManagedSkill, removeManagedSkillDirectory, saveSkillsLockfile, } from '../../lib/skills.js';
|
|
2
|
+
/**
|
|
3
|
+
* Removes a managed skill from the local directory and updates the lockfile.
|
|
4
|
+
*/
|
|
5
|
+
export async function runSkillsRemoveCommand(context, input) {
|
|
6
|
+
const { skillName } = input;
|
|
7
|
+
const lockfile = await loadSkillsLockfile(context);
|
|
8
|
+
const managedSkill = findManagedSkill(lockfile, { name: skillName });
|
|
9
|
+
if (!managedSkill) {
|
|
10
|
+
throw new Error(`Managed skill not found: ${skillName}`);
|
|
11
|
+
}
|
|
12
|
+
await removeManagedSkillDirectory(context, { skillName });
|
|
13
|
+
await saveSkillsLockfile(context, {
|
|
14
|
+
lockfile: removeManagedSkill(lockfile, { name: skillName }),
|
|
15
|
+
});
|
|
16
|
+
console.log(`Removed ${formatManagedSkillSummary(managedSkill)}`);
|
|
17
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AgentsContext } from '../../lib/context.js';
|
|
2
|
+
/**
|
|
3
|
+
* Updates every managed skill from its tracked remote source and saves the refreshed lockfile.
|
|
4
|
+
*/
|
|
5
|
+
export declare function runSkillsUpdateAllCommand(context: AgentsContext): Promise<void>;
|
|
6
|
+
//# sourceMappingURL=update-all.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createUpdatedSkillRecord, fetchRemoteSkillSnapshot, formatManagedSkillSummary, getManagedSkillDirectory, loadSkillsLockfile, replaceManagedSkillDirectory, saveSkillsLockfile, timestampNow, upsertManagedSkill, } from '../../lib/skills.js';
|
|
2
|
+
/**
|
|
3
|
+
* Updates every managed skill from its tracked remote source and saves the refreshed lockfile.
|
|
4
|
+
*/
|
|
5
|
+
export async function runSkillsUpdateAllCommand(context) {
|
|
6
|
+
let lockfile = await loadSkillsLockfile(context);
|
|
7
|
+
if (lockfile.skills.length === 0) {
|
|
8
|
+
console.log('No managed skills to update.');
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const updatedLines = [];
|
|
12
|
+
for (const managedSkill of lockfile.skills) {
|
|
13
|
+
const snapshot = await fetchRemoteSkillSnapshot({
|
|
14
|
+
ref: managedSkill.ref,
|
|
15
|
+
repo: managedSkill.repo,
|
|
16
|
+
skillPath: managedSkill.path,
|
|
17
|
+
});
|
|
18
|
+
try {
|
|
19
|
+
await replaceManagedSkillDirectory({
|
|
20
|
+
targetDir: getManagedSkillDirectory(context, {
|
|
21
|
+
skillName: managedSkill.name,
|
|
22
|
+
}),
|
|
23
|
+
sourceDir: snapshot.sourceDir,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
await snapshot.cleanup();
|
|
28
|
+
}
|
|
29
|
+
const updatedSkill = createUpdatedSkillRecord({
|
|
30
|
+
commit: snapshot.commit,
|
|
31
|
+
existingSkill: managedSkill,
|
|
32
|
+
updatedAt: timestampNow(),
|
|
33
|
+
});
|
|
34
|
+
lockfile = upsertManagedSkill(lockfile, { updatedSkill });
|
|
35
|
+
updatedLines.push(`- ${formatManagedSkillSummary(updatedSkill)}`);
|
|
36
|
+
}
|
|
37
|
+
await saveSkillsLockfile(context, { lockfile });
|
|
38
|
+
console.log(`Updated ${updatedLines.length} managed skills:\n${updatedLines.join('\n')}`);
|
|
39
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AgentsContext } from '../../lib/context.js';
|
|
2
|
+
/**
|
|
3
|
+
* Updates one managed skill from its tracked remote source and refreshes the lockfile.
|
|
4
|
+
*/
|
|
5
|
+
export declare function runSkillsUpdateCommand(context: AgentsContext, input: {
|
|
6
|
+
skillName: string;
|
|
7
|
+
}): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=update.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createUpdatedSkillRecord, fetchRemoteSkillSnapshot, findManagedSkill, formatManagedSkillSummary, getManagedSkillDirectory, loadSkillsLockfile, replaceManagedSkillDirectory, saveSkillsLockfile, timestampNow, upsertManagedSkill, } from '../../lib/skills.js';
|
|
2
|
+
/**
|
|
3
|
+
* Updates one managed skill from its tracked remote source and refreshes the lockfile.
|
|
4
|
+
*/
|
|
5
|
+
export async function runSkillsUpdateCommand(context, input) {
|
|
6
|
+
const { skillName } = input;
|
|
7
|
+
const lockfile = await loadSkillsLockfile(context);
|
|
8
|
+
const managedSkill = findManagedSkill(lockfile, { name: skillName });
|
|
9
|
+
if (!managedSkill) {
|
|
10
|
+
throw new Error(`Managed skill not found: ${skillName}`);
|
|
11
|
+
}
|
|
12
|
+
const snapshot = await fetchRemoteSkillSnapshot({
|
|
13
|
+
ref: managedSkill.ref,
|
|
14
|
+
repo: managedSkill.repo,
|
|
15
|
+
skillPath: managedSkill.path,
|
|
16
|
+
});
|
|
17
|
+
try {
|
|
18
|
+
await replaceManagedSkillDirectory({
|
|
19
|
+
targetDir: getManagedSkillDirectory(context, { skillName }),
|
|
20
|
+
sourceDir: snapshot.sourceDir,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
await snapshot.cleanup();
|
|
25
|
+
}
|
|
26
|
+
const updatedSkill = createUpdatedSkillRecord({
|
|
27
|
+
commit: snapshot.commit,
|
|
28
|
+
existingSkill: managedSkill,
|
|
29
|
+
updatedAt: timestampNow(),
|
|
30
|
+
});
|
|
31
|
+
await saveSkillsLockfile(context, {
|
|
32
|
+
lockfile: upsertManagedSkill(lockfile, { updatedSkill }),
|
|
33
|
+
});
|
|
34
|
+
console.log(`Updated ${formatManagedSkillSummary(updatedSkill)}`);
|
|
35
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const nonEmptyOptionStringSchema: z.ZodString;
|
|
3
|
+
/**
|
|
4
|
+
* Parses one Commander option value with a Zod schema.
|
|
5
|
+
*/
|
|
6
|
+
export declare function parseOptionValue<TSchema extends z.ZodTypeAny>({ schema, optionLabel, }: {
|
|
7
|
+
schema: TSchema;
|
|
8
|
+
optionLabel: string;
|
|
9
|
+
}): (value: z.input<TSchema>) => z.output<TSchema>;
|
|
10
|
+
/**
|
|
11
|
+
* Parses a Commander options object with a Zod schema.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseOptionsObject<TSchema extends z.ZodTypeAny>({ schema, options, optionsLabel, }: {
|
|
14
|
+
schema: TSchema;
|
|
15
|
+
options: unknown;
|
|
16
|
+
optionsLabel: string;
|
|
17
|
+
}): z.output<TSchema>;
|
|
18
|
+
//# sourceMappingURL=command-options.d.ts.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { InvalidArgumentError } from 'commander';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
export const nonEmptyOptionStringSchema = z.string().trim().min(1);
|
|
4
|
+
/**
|
|
5
|
+
* Parses a value with a Zod schema, throwing a Commander InvalidArgumentError on failure.
|
|
6
|
+
*/
|
|
7
|
+
function parseWithSchema({ schema, value, label, }) {
|
|
8
|
+
const result = schema.safeParse(value);
|
|
9
|
+
if (result.success) {
|
|
10
|
+
return result.data;
|
|
11
|
+
}
|
|
12
|
+
const issues = result.error.issues
|
|
13
|
+
.map((issue) => {
|
|
14
|
+
const issuePath = issue.path.length > 0 ? `${issue.path.join('.')}: ` : '';
|
|
15
|
+
return `${issuePath}${issue.message}`;
|
|
16
|
+
})
|
|
17
|
+
.join('; ');
|
|
18
|
+
throw new InvalidArgumentError(`${label}: ${issues}`);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parses one Commander option value with a Zod schema.
|
|
22
|
+
*/
|
|
23
|
+
export function parseOptionValue({ schema, optionLabel, }) {
|
|
24
|
+
return (value) => parseWithSchema({ schema, value, label: optionLabel });
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Parses a Commander options object with a Zod schema.
|
|
28
|
+
*/
|
|
29
|
+
export function parseOptionsObject({ schema, options, optionsLabel, }) {
|
|
30
|
+
return parseWithSchema({ schema, value: options, label: optionsLabel });
|
|
31
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export type TargetRoots = {
|
|
2
|
+
copilotPrompts: string;
|
|
3
|
+
copilotInstructions: string;
|
|
4
|
+
copilotSkills: string;
|
|
5
|
+
cursorRules: string;
|
|
6
|
+
cursorSkills: string;
|
|
7
|
+
};
|
|
8
|
+
export type SourceRoots = {
|
|
9
|
+
commands: string;
|
|
10
|
+
rules: string;
|
|
11
|
+
skills: string;
|
|
12
|
+
};
|
|
13
|
+
export type AgentsContext = {
|
|
14
|
+
inputRoot: string;
|
|
15
|
+
outputRoot: string;
|
|
16
|
+
skillsLockfilePath: string;
|
|
17
|
+
sourceRoots: SourceRoots;
|
|
18
|
+
targetRoots: TargetRoots;
|
|
19
|
+
};
|
|
20
|
+
export declare const DEFAULT_INPUT_ROOT_SEGMENTS: readonly [".config", "agents"];
|
|
21
|
+
export declare const DEFAULT_TEST_OUTPUT_DIR_NAME = "output-test";
|
|
22
|
+
export declare const DEFAULT_SOURCE_ROOT_NAMES: {
|
|
23
|
+
readonly commands: "commands";
|
|
24
|
+
readonly rules: "rules";
|
|
25
|
+
readonly skills: "skills";
|
|
26
|
+
};
|
|
27
|
+
export declare const DEFAULT_TARGET_ROOT_SEGMENTS: {
|
|
28
|
+
readonly copilotPrompts: readonly [".copilot", "prompts"];
|
|
29
|
+
readonly copilotInstructions: readonly [".copilot", "instructions"];
|
|
30
|
+
readonly copilotSkills: readonly [".copilot", "skills"];
|
|
31
|
+
readonly cursorRules: readonly [".cursor", "rules"];
|
|
32
|
+
readonly cursorSkills: readonly [".cursor", "skills"];
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Creates the Copilot and Cursor output root paths under one base directory.
|
|
36
|
+
*/
|
|
37
|
+
export declare function createTargetRoots(baseDir: string): TargetRoots;
|
|
38
|
+
/**
|
|
39
|
+
* Creates the commands, rules, and skills input roots under one base directory.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createSourceRoots(baseDir: string): SourceRoots;
|
|
42
|
+
/**
|
|
43
|
+
* Expands a leading `~` in a path to the current user's home directory.
|
|
44
|
+
*/
|
|
45
|
+
export declare function expandHomePath(inputPath: string, homeDir: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Returns the requested output-root override derived from CLI-style options.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveRequestedOutputRoot(input: {
|
|
50
|
+
test: boolean;
|
|
51
|
+
outputRoot?: string;
|
|
52
|
+
}): string | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Returns the filesystem path to use for generated output.
|
|
55
|
+
*/
|
|
56
|
+
export declare function resolveOutputRoot(input: {
|
|
57
|
+
homeDir: string;
|
|
58
|
+
outputRoot?: string;
|
|
59
|
+
}): string;
|
|
60
|
+
/**
|
|
61
|
+
* Returns a copy of the context with generated output redirected under one
|
|
62
|
+
* explicit output root.
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveOutputContext(context: AgentsContext, outputRoot: string): AgentsContext;
|
|
65
|
+
/**
|
|
66
|
+
* Creates the base CLI context with repository, input, and output paths
|
|
67
|
+
* resolved.
|
|
68
|
+
*/
|
|
69
|
+
export declare function createAgentsContext(options?: {
|
|
70
|
+
inputRoot?: string;
|
|
71
|
+
outputRoot?: string;
|
|
72
|
+
}): AgentsContext;
|
|
73
|
+
//# sourceMappingURL=context.d.ts.map
|