@callmeradical/augy 0.1.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.
@@ -0,0 +1,192 @@
1
+ import {
2
+ filterableMultiselect
3
+ } from "./chunk-UJX6VJ3S.js";
4
+ import {
5
+ resolveSkillFromTaps
6
+ } from "./chunk-YXCEZ3EY.js";
7
+ import {
8
+ AGENTS,
9
+ agentSkillPath
10
+ } from "./chunk-R2TJ3UDO.js";
11
+ import {
12
+ discoverSkills,
13
+ downloadSkill,
14
+ parseGitHubUrl
15
+ } from "./chunk-EU54UQ4C.js";
16
+ import {
17
+ createSkillRecord,
18
+ getSkill,
19
+ readRegistry,
20
+ shortSha,
21
+ writeRegistry
22
+ } from "./chunk-ZW6ZKHTF.js";
23
+
24
+ // src/commands/install.ts
25
+ import {
26
+ cancel,
27
+ confirm,
28
+ intro,
29
+ isCancel,
30
+ multiselect,
31
+ outro,
32
+ select,
33
+ spinner,
34
+ text
35
+ } from "@clack/prompts";
36
+ import chalk from "chalk";
37
+ import { mkdir, rm } from "fs/promises";
38
+ async function installCommand(urlArg, opts = {}) {
39
+ intro(chalk.bold("augy") + chalk.dim(" \u2014 skill installer"));
40
+ const registry = await readRegistry();
41
+ const rawUrl = urlArg ?? await promptUrl();
42
+ if (isCancel(rawUrl) || !rawUrl) return bail();
43
+ const isBare = !String(rawUrl).includes("/") && !String(rawUrl).startsWith("http");
44
+ let discovered;
45
+ let resolvedSource;
46
+ let resolvedTap;
47
+ if (isBare) {
48
+ const s = spinner();
49
+ s.start(`Searching taps for "${rawUrl}"\u2026`);
50
+ const tapResult = await resolveSkillFromTaps(registry, String(rawUrl));
51
+ if (!tapResult) {
52
+ s.stop(chalk.yellow(`"${rawUrl}" not found in any tap`));
53
+ cancel(
54
+ `No taps contain a skill named "${rawUrl}".
55
+ Try: augy install owner/repo/path or add a tap with: augy tap add owner/repo`
56
+ );
57
+ process.exit(1);
58
+ }
59
+ let chosen;
60
+ if (Array.isArray(tapResult)) {
61
+ s.stop(`Found "${rawUrl}" in ${tapResult.length} taps \u2014 please choose`);
62
+ const pick = await select({
63
+ message: "Which tap should this skill be installed from?",
64
+ options: tapResult.map((ts) => ({
65
+ value: ts,
66
+ label: ts.tapKey,
67
+ hint: chalk.dim("@" + shortSha(ts.sha))
68
+ }))
69
+ });
70
+ if (isCancel(pick)) return bail();
71
+ chosen = pick;
72
+ } else {
73
+ chosen = tapResult;
74
+ s.stop(`Found in tap ${chalk.cyan(chosen.tapKey)}`);
75
+ }
76
+ discovered = [chosen];
77
+ resolvedSource = `${chosen.tapKey}/${chosen.repoPath}`;
78
+ resolvedTap = chosen.tapKey;
79
+ } else {
80
+ const s = spinner();
81
+ s.start("Resolving skills from GitHub\u2026");
82
+ try {
83
+ const coords = parseGitHubUrl(String(rawUrl));
84
+ discovered = await discoverSkills(coords);
85
+ resolvedSource = String(rawUrl);
86
+ } catch (err) {
87
+ s.stop(chalk.red("Failed to resolve skills"));
88
+ cancel(String(err));
89
+ process.exit(1);
90
+ }
91
+ if (!discovered.length) {
92
+ s.stop(chalk.yellow("No skills found at that location"));
93
+ cancel("Make sure the path contains a SKILL.md file or subdirectories that do.");
94
+ process.exit(1);
95
+ }
96
+ s.stop(`Found ${chalk.green(String(discovered.length))} skill(s)`);
97
+ }
98
+ const selectedSkills = await promptSkillSelection(discovered);
99
+ if (isCancel(selectedSkills) || !selectedSkills.length) return bail();
100
+ const preselectedAgents = opts.agent ?? [];
101
+ const selectedAgents = preselectedAgents.length > 0 ? AGENTS.filter((a) => preselectedAgents.includes(a.id)) : await promptAgentSelection();
102
+ if (isCancel(selectedAgents) || !selectedAgents.length) return bail();
103
+ const lines = selectedSkills.map(
104
+ (sk) => ` ${chalk.cyan(sk.name)} ${chalk.dim("@" + shortSha(sk.sha))} \u2192 ${selectedAgents.map((a) => chalk.bold(a.name)).join(", ")}`
105
+ );
106
+ console.log("\n" + lines.join("\n") + "\n");
107
+ const ok = await confirm({ message: "Install the above skill(s)?" });
108
+ if (isCancel(ok) || !ok) return bail();
109
+ for (const skill of selectedSkills) {
110
+ const s2 = spinner();
111
+ s2.start(`Installing ${chalk.cyan(skill.name)}\u2026`);
112
+ try {
113
+ const existing = getSkill(registry, skill.name);
114
+ if (existing) {
115
+ s2.message(`${chalk.cyan(skill.name)} already installed \u2014 updating record`);
116
+ }
117
+ const agentPaths = {};
118
+ for (const agent of selectedAgents) {
119
+ agentPaths[agent.id] = agentSkillPath(agent, skill.name);
120
+ }
121
+ for (const agent of selectedAgents) {
122
+ const dest = agentPaths[agent.id];
123
+ await mkdir(dest, { recursive: true });
124
+ await rm(dest, { recursive: true, force: true });
125
+ await downloadSkill(skill.gigetSource, dest);
126
+ }
127
+ const record = createSkillRecord({
128
+ name: skill.name,
129
+ source: resolvedSource,
130
+ gigetSource: skill.gigetSource,
131
+ sha: skill.sha,
132
+ agentIds: selectedAgents.map((a) => a.id),
133
+ agentPaths,
134
+ tap: resolvedTap
135
+ });
136
+ if (existing) {
137
+ record.installedAt = existing.installedAt;
138
+ record.pinned = existing.pinned;
139
+ record.history = existing.history;
140
+ }
141
+ registry.skills[skill.name] = record;
142
+ s2.stop(`${chalk.green("\u2713")} ${chalk.cyan(skill.name)} ${chalk.dim("@" + shortSha(skill.sha))}`);
143
+ } catch (err) {
144
+ s2.stop(`${chalk.red("\u2717")} ${chalk.cyan(skill.name)} \u2014 ${String(err)}`);
145
+ }
146
+ }
147
+ await writeRegistry(registry);
148
+ outro(
149
+ chalk.green("Done!") + chalk.dim(` Registry saved \u2192 ~/.augy/registry.json`)
150
+ );
151
+ }
152
+ async function promptUrl() {
153
+ return text({
154
+ message: "GitHub URL or owner/repo[/path]",
155
+ placeholder: "https://github.com/owner/repo or owner/repo/skills/my-skill",
156
+ validate: (v) => v.trim() ? void 0 : "Please enter a URL or repo path"
157
+ });
158
+ }
159
+ async function promptSkillSelection(skills) {
160
+ const installed = new Set(Object.keys((await readRegistry()).skills));
161
+ return filterableMultiselect({
162
+ message: "Select skills to install",
163
+ options: skills.map((s) => {
164
+ const isInstalled = installed.has(s.name);
165
+ return {
166
+ value: s,
167
+ label: s.name,
168
+ hint: chalk.dim("@" + shortSha(s.sha)) + (isInstalled ? chalk.yellow(" already installed") : " " + chalk.dim(s.repoPath)),
169
+ selected: !isInstalled
170
+ // pre-select everything not yet installed
171
+ };
172
+ })
173
+ });
174
+ }
175
+ async function promptAgentSelection() {
176
+ return multiselect({
177
+ message: "Install for which agents?",
178
+ options: AGENTS.map((a) => ({
179
+ value: a,
180
+ label: a.name,
181
+ hint: chalk.dim(a.skillsPath)
182
+ })),
183
+ required: true
184
+ });
185
+ }
186
+ function bail() {
187
+ cancel("Installation cancelled");
188
+ process.exit(0);
189
+ }
190
+ export {
191
+ installCommand
192
+ };
@@ -0,0 +1,70 @@
1
+ import {
2
+ AGENTS
3
+ } from "./chunk-R2TJ3UDO.js";
4
+ import {
5
+ listSkills,
6
+ readRegistry
7
+ } from "./chunk-ZW6ZKHTF.js";
8
+
9
+ // src/commands/list.ts
10
+ import chalk from "chalk";
11
+ async function listCommand(opts = {}) {
12
+ const registry = await readRegistry();
13
+ const skills = listSkills(registry);
14
+ if (opts.json) {
15
+ console.log(JSON.stringify(registry, null, 2));
16
+ return;
17
+ }
18
+ if (!skills.length) {
19
+ console.log(chalk.dim("No skills installed. Run `augy install` to get started."));
20
+ return;
21
+ }
22
+ console.log(
23
+ `
24
+ ${chalk.bold("Installed skills")} ${chalk.dim(`(${skills.length} total)`)}
25
+ `
26
+ );
27
+ for (const skill of skills) {
28
+ printSkill(skill);
29
+ }
30
+ console.log();
31
+ }
32
+ function printSkill(skill) {
33
+ const pinTag = skill.pinned ? chalk.yellow(" [pinned]") : "";
34
+ const historyTag = skill.history.length > 0 ? chalk.dim(` (${skill.history.length} previous version${skill.history.length === 1 ? "" : "s"})`) : "";
35
+ const noSource = !skill.source || skill.sha === "unversioned";
36
+ const shaDisplay = noSource ? chalk.yellow("untracked") : chalk.green("@" + skill.shortSha);
37
+ const sourceNote = noSource ? chalk.yellow(" \u26A0 no source \u2014 run `augy set-source " + skill.name + " <url>` to enable updates") : "";
38
+ console.log(
39
+ ` ${chalk.cyan.bold(skill.name)}${pinTag} ${shaDisplay}${historyTag}${sourceNote}`
40
+ );
41
+ if (skill.source) {
42
+ console.log(` ${chalk.dim("source:")} ${skill.source}`);
43
+ } else {
44
+ console.log(` ${chalk.dim("source:")} ${chalk.dim("unknown")}`);
45
+ }
46
+ const agentEntries = Object.entries(skill.agents);
47
+ if (agentEntries.length) {
48
+ const agentLabels = agentEntries.map(([id, install]) => {
49
+ const agent = AGENTS.find((a) => a.id === id);
50
+ const name = agent?.name ?? id;
51
+ const status = install.active ? chalk.green(name) : chalk.dim(`${name} (inactive)`);
52
+ return status;
53
+ });
54
+ console.log(` ${chalk.dim("agents:")} ${agentLabels.join(chalk.dim(", "))}`);
55
+ }
56
+ const updated = new Date(skill.updatedAt).toLocaleDateString();
57
+ console.log(` ${chalk.dim("updated:")} ${updated}`);
58
+ if (skill.history.length > 0) {
59
+ const prev = skill.history.slice(-3).reverse();
60
+ const lines = prev.map(
61
+ (v) => ` ${chalk.dim(v.sha.slice(0, 7))} ${chalk.dim(new Date(v.installedAt).toLocaleDateString())}`
62
+ );
63
+ console.log(` ${chalk.dim("history:")}`);
64
+ lines.forEach((l) => console.log(l));
65
+ }
66
+ console.log();
67
+ }
68
+ export {
69
+ listCommand
70
+ };
@@ -0,0 +1,38 @@
1
+ import {
2
+ addTap,
3
+ augyHome,
4
+ createSkillRecord,
5
+ getSkill,
6
+ getTap,
7
+ listSkills,
8
+ listTaps,
9
+ readRegistry,
10
+ registryPath,
11
+ removeSkill,
12
+ removeTap,
13
+ shortSha,
14
+ tapKey,
15
+ upsertSkill,
16
+ versionArchivePath,
17
+ versionsDir,
18
+ writeRegistry
19
+ } from "./chunk-ZW6ZKHTF.js";
20
+ export {
21
+ addTap,
22
+ augyHome,
23
+ createSkillRecord,
24
+ getSkill,
25
+ getTap,
26
+ listSkills,
27
+ listTaps,
28
+ readRegistry,
29
+ registryPath,
30
+ removeSkill,
31
+ removeTap,
32
+ shortSha,
33
+ tapKey,
34
+ upsertSkill,
35
+ versionArchivePath,
36
+ versionsDir,
37
+ writeRegistry
38
+ };
@@ -0,0 +1,105 @@
1
+ import {
2
+ archiveExists,
3
+ restoreVersion
4
+ } from "./chunk-PX2LVUHV.js";
5
+ import {
6
+ agentById,
7
+ agentSkillPath
8
+ } from "./chunk-R2TJ3UDO.js";
9
+ import {
10
+ getSkill,
11
+ readRegistry,
12
+ shortSha,
13
+ writeRegistry
14
+ } from "./chunk-ZW6ZKHTF.js";
15
+
16
+ // src/commands/rollback.ts
17
+ import { cancel, intro, isCancel, outro, select, spinner } from "@clack/prompts";
18
+ import chalk from "chalk";
19
+ async function rollbackCommand(nameArg, shaArg) {
20
+ intro(chalk.bold("augy") + chalk.dim(" \u2014 rollback"));
21
+ const registry = await readRegistry();
22
+ const skill = getSkill(registry, nameArg);
23
+ if (!skill) {
24
+ cancel(`Skill "${nameArg}" not found in registry. Run \`augy list\` to see installed skills.`);
25
+ process.exit(1);
26
+ }
27
+ if (!skill.history.length) {
28
+ cancel(`No previous versions for "${nameArg}". Cannot roll back.`);
29
+ process.exit(0);
30
+ }
31
+ let targetSha;
32
+ if (shaArg) {
33
+ const match = skill.history.find((v) => v.sha.startsWith(shaArg));
34
+ if (!match) {
35
+ cancel(
36
+ `Version "${shaArg}" not found in history for "${nameArg}".
37
+ Available: ${skill.history.map((v) => v.sha.slice(0, 7)).join(", ")}`
38
+ );
39
+ process.exit(1);
40
+ }
41
+ targetSha = match.sha;
42
+ } else {
43
+ const versions = [...skill.history].reverse();
44
+ const chosen = await select({
45
+ message: `Roll back "${nameArg}" to which version?`,
46
+ options: versions.map((v) => {
47
+ const exists = archiveExists(nameArg, v.sha);
48
+ return {
49
+ value: v.sha,
50
+ label: shortSha(v.sha),
51
+ hint: new Date(v.installedAt).toLocaleDateString() + (exists ? "" : chalk.red(" [archive missing]"))
52
+ };
53
+ })
54
+ });
55
+ if (isCancel(chosen)) {
56
+ cancel("Rollback cancelled");
57
+ process.exit(0);
58
+ }
59
+ targetSha = chosen;
60
+ }
61
+ if (!archiveExists(nameArg, targetSha)) {
62
+ cancel(
63
+ `Archive not found for "${nameArg}" @ ${shortSha(targetSha)}.
64
+ The snapshot may have been pruned.`
65
+ );
66
+ process.exit(1);
67
+ }
68
+ const destPaths = Object.entries(skill.agents).filter(([, install]) => install.active).map(([agentId]) => {
69
+ const agent = agentById(agentId);
70
+ return agent ? agentSkillPath(agent, nameArg) : null;
71
+ }).filter((p) => p !== null);
72
+ const s = spinner();
73
+ s.start(`Restoring ${chalk.cyan(nameArg)} to ${chalk.yellow(shortSha(targetSha))}\u2026`);
74
+ try {
75
+ const currentDest = destPaths[0];
76
+ if (currentDest) {
77
+ const { archiveVersion } = await import("./versions-OMI6OFJC.js");
78
+ await archiveVersion(currentDest, nameArg, skill.sha);
79
+ }
80
+ await restoreVersion(nameArg, targetSha, destPaths);
81
+ const restoredEntry = skill.history.find((v) => v.sha === targetSha);
82
+ const displacedEntry = {
83
+ sha: skill.sha,
84
+ installedAt: skill.updatedAt,
85
+ archivePath: `${process.env["HOME"] ?? "~"}/.augy/versions/${nameArg}/${skill.sha}`
86
+ };
87
+ skill.history = skill.history.filter((v) => v.sha !== targetSha);
88
+ skill.history.push(displacedEntry);
89
+ skill.sha = targetSha;
90
+ skill.shortSha = shortSha(targetSha);
91
+ skill.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
92
+ registry.skills[nameArg] = skill;
93
+ await writeRegistry(registry);
94
+ s.stop(
95
+ `${chalk.green("\u2713")} Rolled back ${chalk.cyan(nameArg)} to ` + chalk.yellow(shortSha(targetSha))
96
+ );
97
+ outro(chalk.dim(`Previous version archived for future rollback.`));
98
+ } catch (err) {
99
+ s.stop(`${chalk.red("\u2717")} Rollback failed \u2014 ${String(err)}`);
100
+ process.exit(1);
101
+ }
102
+ }
103
+ export {
104
+ rollbackCommand
105
+ };