gooseworks 0.6.0-dev.77.f7d39aeb → 0.6.0-dev.79.b03f791c
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/.claude-plugin/marketplace.json +18 -4
- package/README.md +33 -18
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +17 -10
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +11 -9
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/skills.d.ts +35 -16
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +52 -34
- package/dist/commands/skills.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +15 -7
- package/dist/commands/update.js.map +1 -1
- package/dist/skills/installer.d.ts +51 -9
- package/dist/skills/installer.d.ts.map +1 -1
- package/dist/skills/installer.js +230 -35
- package/dist/skills/installer.js.map +1 -1
- package/dist/skills/names.d.ts +12 -6
- package/dist/skills/names.d.ts.map +1 -1
- package/dist/skills/names.js +21 -9
- package/dist/skills/names.js.map +1 -1
- package/dist/skills/releases.d.ts +8 -6
- package/dist/skills/releases.d.ts.map +1 -1
- package/dist/skills/releases.js +9 -78
- package/dist/skills/releases.js.map +1 -1
- package/dist/skills/standalone-packages.d.ts +2 -1
- package/dist/skills/standalone-packages.d.ts.map +1 -1
- package/dist/skills/standalone-packages.js +4 -1
- package/dist/skills/standalone-packages.js.map +1 -1
- package/package.json +4 -7
- package/.claude-plugin/plugin.json +0 -13
- package/.codex-plugin/plugin.json +0 -17
- package/dist/skills/master-skill.d.ts +0 -28
- package/dist/skills/master-skill.d.ts.map +0 -1
- package/dist/skills/master-skill.js +0 -225
- package/dist/skills/master-skill.js.map +0 -1
- package/dist/skills/routes.d.ts +0 -73
- package/dist/skills/routes.d.ts.map +0 -1
- package/dist/skills/routes.js +0 -147
- package/dist/skills/routes.js.map +0 -1
- package/dist/skills/server-entry-skills.d.ts +0 -14
- package/dist/skills/server-entry-skills.d.ts.map +0 -1
- package/dist/skills/server-entry-skills.js +0 -163
- package/dist/skills/server-entry-skills.js.map +0 -1
- package/skills/goose-ads/SKILL.md +0 -41
- package/skills/goose-product-photos/SKILL.md +0 -39
- package/skills/goose-video/SKILL.md +0 -42
- package/skills/goose-video-local/SKILL.md +0 -7
- package/skills/gooseworks/SKILL.md +0 -104
- package/skills/make-custom-video/SKILL.md +0 -55
- package/skills/manifest.json +0 -12
- package/skills/routes.json +0 -163
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/commands/skills.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/commands/skills.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,eAAO,MAAM,aAAa,SAmFtB,CAAC"}
|
package/dist/commands/update.js
CHANGED
|
@@ -42,13 +42,12 @@ const claude_mcp_1 = require("../agents/claude-mcp");
|
|
|
42
42
|
const codex_1 = require("../agents/codex");
|
|
43
43
|
const cursor_1 = require("../agents/cursor");
|
|
44
44
|
const detect_1 = require("../agents/detect");
|
|
45
|
-
const master_skill_1 = require("../skills/master-skill");
|
|
46
45
|
const logger = __importStar(require("../utils/logger"));
|
|
47
46
|
const skills_1 = require("./skills");
|
|
48
47
|
const environment_1 = require("../environment");
|
|
49
48
|
const staging_1 = require("../agents/staging");
|
|
50
49
|
exports.updateCommand = new commander_1.Command('update')
|
|
51
|
-
.description('Refresh entry skills from
|
|
50
|
+
.description('Refresh entry skills from the GooseWorks skill catalog; preserve edited files and saved recipes')
|
|
52
51
|
.option('--overwrite-modified', 'Replace edited or untracked managed entry files after you back them up')
|
|
53
52
|
.option('--project <folder>', 'Required for the staging installation to refresh')
|
|
54
53
|
.action(async (opts) => {
|
|
@@ -60,7 +59,10 @@ exports.updateCommand = new commander_1.Command('update')
|
|
|
60
59
|
const manifest = JSON.parse(fs.readFileSync(projectProfile(opts.project).manifest, 'utf8'));
|
|
61
60
|
for (const agent of manifest.agents)
|
|
62
61
|
(0, staging_1.stagingLaunch)(opts.project, agent);
|
|
63
|
-
const
|
|
62
|
+
const loaded = await (0, skills_1.loadEntryCatalog)();
|
|
63
|
+
if (!loaded.catalog)
|
|
64
|
+
throw new Error(`Could not download the GooseWorks entry skills from goose-skills (${loaded.error}). No skill files were changed.`);
|
|
65
|
+
const results = (0, installer_1.installManagedEntrySkills)(loaded.catalog.skills, { overwriteModified: opts.overwriteModified });
|
|
64
66
|
if (results.some(result => result.action === 'preserved'))
|
|
65
67
|
throw new Error('Review/back up edited staging entry files before --overwrite-modified');
|
|
66
68
|
(0, staging_1.installStagingProject)(opts.project, manifest.agents);
|
|
@@ -74,15 +76,21 @@ exports.updateCommand = new commander_1.Command('update')
|
|
|
74
76
|
logger.error('Not logged in. Run "gooseworks login" first.');
|
|
75
77
|
process.exit(1);
|
|
76
78
|
}
|
|
77
|
-
const
|
|
79
|
+
const loaded = await (0, skills_1.loadEntryCatalog)();
|
|
80
|
+
const freshness = await (0, skills_1.readEntryFreshnessReport)(loaded);
|
|
78
81
|
await (0, skills_1.reportEntrySkillFreshness)(freshness);
|
|
79
82
|
if (freshness.cli === 'outdated') {
|
|
80
|
-
logger.error('Entry refresh refused: upgrade this CLI
|
|
83
|
+
logger.error('Entry refresh refused: upgrade this CLI first; the current entry skills are written for the published CLI. No skill files were changed.');
|
|
84
|
+
process.exit(1);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (!loaded.catalog) {
|
|
88
|
+
logger.error(`Could not download the GooseWorks entry skills from goose-skills (${loaded.error}). No skill files were changed; run gooseworks update again once goose-skills is reachable.`);
|
|
81
89
|
process.exit(1);
|
|
82
90
|
return;
|
|
83
91
|
}
|
|
84
92
|
logger.step(1, 2, 'Updating skills...');
|
|
85
|
-
for (const r of (0, installer_1.installManagedEntrySkills)(
|
|
93
|
+
for (const r of (0, installer_1.installManagedEntrySkills)(loaded.catalog.skills, { overwriteModified: opts.overwriteModified })) {
|
|
86
94
|
if (r.action === 'preserved')
|
|
87
95
|
logger.warn(`Preserved edited or untracked ${r.name}; review/back up before --overwrite-modified.`);
|
|
88
96
|
else
|
|
@@ -121,6 +129,6 @@ exports.updateCommand = new commander_1.Command('update')
|
|
|
121
129
|
logger.info('Cursor installed but MCP was not previously configured — skipped');
|
|
122
130
|
}
|
|
123
131
|
}
|
|
124
|
-
logger.done('
|
|
132
|
+
logger.done('Entry skill refresh complete. Standalone recipes and project-pinned packages were preserved.');
|
|
125
133
|
});
|
|
126
134
|
//# sourceMappingURL=update.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yCAAoC;AACpC,qDAAqD;AACrD,mDAAgE;AAChE,6CAAmD;AACnD,qDAA0D;AAC1D,2CAAoE;AACpE,6CAA8E;AAC9E,6CAAoD;AACpD,
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { EntrySkill } from './master-skill';
|
|
2
1
|
/** The goose-skills repository the CLI installs skills and loads kit parts from. */
|
|
3
2
|
export declare const GOOSE_SKILLS_REPO = "gooseworks-ai/goose-skills";
|
|
4
3
|
/** Today's goose-skills origin. Staging reads the `dev` branch instead. */
|
|
@@ -29,28 +28,71 @@ export interface InstallStandaloneSkillOptions {
|
|
|
29
28
|
overwriteModified?: boolean;
|
|
30
29
|
}
|
|
31
30
|
export declare function getSkillsBasePath(): string;
|
|
32
|
-
export declare
|
|
33
|
-
export
|
|
31
|
+
export declare const ENTRY_SOURCE_FILE = ".gooseworks-source.json";
|
|
32
|
+
export interface EntrySkill {
|
|
33
|
+
/** Install dir name under the skills folder AND the skill `name`. */
|
|
34
|
+
name: string;
|
|
35
|
+
/** The SKILL.md text. */
|
|
36
|
+
content: string;
|
|
37
|
+
/** The skill folder's other files, by path relative to the folder. */
|
|
38
|
+
files?: Record<string, Buffer>;
|
|
39
|
+
/** The catalog's version of this skill. */
|
|
40
|
+
version?: string;
|
|
41
|
+
/** Where the files were downloaded from. */
|
|
42
|
+
source?: string;
|
|
43
|
+
}
|
|
44
|
+
export interface EntrySkillCatalog {
|
|
45
|
+
/** The goose-skills address the files came from. */
|
|
46
|
+
source: string;
|
|
47
|
+
skills: EntrySkill[];
|
|
48
|
+
/** Entry skill names the catalog does not list. They are left as installed. */
|
|
49
|
+
missing: string[];
|
|
50
|
+
}
|
|
51
|
+
/** The digest an installed copy of `skill` has when it is unchanged. */
|
|
52
|
+
export declare function entrySkillDigest(skill: EntrySkill): string;
|
|
53
|
+
export interface InstalledEntrySkill {
|
|
54
|
+
/** SHA-256 of the installed SKILL.md. */
|
|
34
55
|
hash?: string;
|
|
56
|
+
/** `entrySkillDigest` of the installed folder. */
|
|
57
|
+
digest?: string;
|
|
58
|
+
/** The catalog version recorded at install time (older CLIs recorded none). */
|
|
59
|
+
version?: string;
|
|
60
|
+
/** Edited, linked, or written by something other than the CLI. */
|
|
35
61
|
modified: boolean;
|
|
36
62
|
missing: boolean;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
63
|
+
}
|
|
64
|
+
export declare function inspectEntrySkill(name: string): InstalledEntrySkill;
|
|
65
|
+
/** Checks the actual files, not just a stamp left behind before a user edit. */
|
|
66
|
+
export declare function isEntrySkillFresh(skill: EntrySkill): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Write one entry skill with its stamp and record. The folder is built next to
|
|
69
|
+
* the target and swapped in with a rename, so a failure never leaves a
|
|
70
|
+
* half-written folder.
|
|
71
|
+
*/
|
|
41
72
|
export declare function installEntrySkill(skill: EntrySkill): void;
|
|
42
73
|
export interface EntrySkillInstallResult {
|
|
43
74
|
name: string;
|
|
44
75
|
action: 'installed' | 'skipped' | 'preserved';
|
|
45
76
|
}
|
|
46
77
|
/**
|
|
47
|
-
*
|
|
48
|
-
* user explicitly allows their replacement. `force` never authorizes data loss.
|
|
78
|
+
* Install or refresh entry skills. Preserve edited or untracked files unless
|
|
79
|
+
* the user explicitly allows their replacement. `force` never authorizes data loss.
|
|
49
80
|
*/
|
|
50
81
|
export declare function installManagedEntrySkills(skills: EntrySkill[], { force, overwriteModified }?: {
|
|
51
82
|
force?: boolean;
|
|
52
83
|
overwriteModified?: boolean;
|
|
53
84
|
}): EntrySkillInstallResult[];
|
|
85
|
+
/**
|
|
86
|
+
* Download the entry skills from goose-skills (`gooseSkillsSource()`: `main`
|
|
87
|
+
* for production, `dev` for staging, or GOOSE_SKILLS_RAW_BASE). Reads
|
|
88
|
+
* `skills-index.json`, takes each entry skill's listed `files` under
|
|
89
|
+
* `skills/entry/<name>/`, and downloads all of them before returning, so a
|
|
90
|
+
* caller writes nothing unless every file arrived. Staging rewrites `.md` files
|
|
91
|
+
* for the staging server, as standalone installs do.
|
|
92
|
+
*/
|
|
93
|
+
export declare function fetchEntrySkills({ timeoutMs }?: {
|
|
94
|
+
timeoutMs?: number;
|
|
95
|
+
}): Promise<EntrySkillCatalog>;
|
|
54
96
|
export declare function installStandaloneSkill(slug: string, options?: InstallStandaloneSkillOptions): Promise<void>;
|
|
55
97
|
export declare function getInstalledSkills(): string[];
|
|
56
98
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/skills/installer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"installer.d.ts","sourceRoot":"","sources":["../../src/skills/installer.ts"],"names":[],"mappings":"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"}
|
package/dist/skills/installer.js
CHANGED
|
@@ -33,14 +33,15 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.GOOSE_SKILLS_RAW_BASE_ENV = exports.GOOSE_SKILLS_RAW_BASE = exports.GOOSE_SKILLS_REPO = void 0;
|
|
36
|
+
exports.ENTRY_SOURCE_FILE = exports.GOOSE_SKILLS_RAW_BASE_ENV = exports.GOOSE_SKILLS_RAW_BASE = exports.GOOSE_SKILLS_REPO = void 0;
|
|
37
37
|
exports.gooseSkillsSource = gooseSkillsSource;
|
|
38
38
|
exports.getSkillsBasePath = getSkillsBasePath;
|
|
39
|
-
exports.
|
|
39
|
+
exports.entrySkillDigest = entrySkillDigest;
|
|
40
40
|
exports.inspectEntrySkill = inspectEntrySkill;
|
|
41
41
|
exports.isEntrySkillFresh = isEntrySkillFresh;
|
|
42
42
|
exports.installEntrySkill = installEntrySkill;
|
|
43
43
|
exports.installManagedEntrySkills = installManagedEntrySkills;
|
|
44
|
+
exports.fetchEntrySkills = fetchEntrySkills;
|
|
44
45
|
exports.installStandaloneSkill = installStandaloneSkill;
|
|
45
46
|
exports.getInstalledSkills = getInstalledSkills;
|
|
46
47
|
exports.removeAllSkills = removeAllSkills;
|
|
@@ -104,23 +105,73 @@ const DOWNLOAD_CONCURRENCY = 6;
|
|
|
104
105
|
function getSkillsBasePath() {
|
|
105
106
|
return skillsBase();
|
|
106
107
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
108
|
+
// ── Entry skills from the goose-skills catalog ──────────────────────────────
|
|
109
|
+
// The entry skills (ENTRY_SKILL_NAMES) live in goose-skills at
|
|
110
|
+
// `skills/entry/<name>/`. install, update and the login refresh download them
|
|
111
|
+
// (`fetchEntrySkills`) and write each one to <skills folder>/<name>/
|
|
112
|
+
// (`installManagedEntrySkills`). Every install is stamped:
|
|
113
|
+
// - `.gooseworks-version` holds the first 16 hex characters of the SKILL.md
|
|
114
|
+
// hash, the format older CLIs wrote, so their installs stay recognized;
|
|
115
|
+
// - `.gooseworks-source.json` records each file's hash, the catalog version
|
|
116
|
+
// and where the files came from.
|
|
117
|
+
// A folder whose files no longer match its record is the user's edit and is
|
|
118
|
+
// preserved unless they pass --overwrite-modified.
|
|
119
|
+
exports.ENTRY_SOURCE_FILE = '.gooseworks-source.json';
|
|
120
|
+
const ENTRY_DOWNLOAD_TIMEOUT_MS = 30_000;
|
|
121
|
+
/** Bookkeeping files that are not part of the skill's content. */
|
|
122
|
+
const ENTRY_IGNORED_FILES = new Set([names_1.STAMP_FILE, exports.ENTRY_SOURCE_FILE, '.DS_Store']);
|
|
123
|
+
function entryFiles(skill) {
|
|
124
|
+
const files = new Map(Object.entries(skill.files || {}));
|
|
125
|
+
files.set('SKILL.md', Buffer.from(skill.content, 'utf-8'));
|
|
126
|
+
return files;
|
|
111
127
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
128
|
+
function hashFiles(files) {
|
|
129
|
+
return Object.fromEntries([...files.keys()].sort().map((name) => [name, (0, releases_1.skillContentHash)(files.get(name))]));
|
|
130
|
+
}
|
|
131
|
+
/** One hash for a whole skill folder: every file's path and content hash. */
|
|
132
|
+
function folderDigest(hashes) {
|
|
133
|
+
return (0, releases_1.skillContentHash)(Object.keys(hashes).sort().map((name) => `${name}\0${hashes[name]}\n`).join(''));
|
|
134
|
+
}
|
|
135
|
+
/** The digest an installed copy of `skill` has when it is unchanged. */
|
|
136
|
+
function entrySkillDigest(skill) {
|
|
137
|
+
return folderDigest(hashFiles(entryFiles(skill)));
|
|
138
|
+
}
|
|
139
|
+
function isSafeRelativePath(relative) {
|
|
140
|
+
return !!relative && !path.isAbsolute(relative) && !relative.includes('\\')
|
|
141
|
+
&& relative.split('/').every((part) => part && part !== '.' && part !== '..');
|
|
142
|
+
}
|
|
143
|
+
function sameHashes(a, b) {
|
|
144
|
+
const keys = Object.keys(a);
|
|
145
|
+
return keys.length === Object.keys(b).length && keys.every((key) => a[key] === b[key]);
|
|
146
|
+
}
|
|
147
|
+
function isHashRecord(value) {
|
|
148
|
+
return !!value && typeof value === 'object' && !Array.isArray(value)
|
|
149
|
+
&& Object.values(value).every((hash) => typeof hash === 'string');
|
|
150
|
+
}
|
|
151
|
+
/** Hashes every regular file in the folder; null when it holds a link or anything else. */
|
|
152
|
+
function readEntryFolder(dir) {
|
|
153
|
+
const hashes = {};
|
|
154
|
+
const visit = (current, prefix) => {
|
|
155
|
+
for (const name of fs.readdirSync(current)) {
|
|
156
|
+
if (name === '.DS_Store' || (!prefix && ENTRY_IGNORED_FILES.has(name)))
|
|
157
|
+
continue;
|
|
158
|
+
const file = path.join(current, name);
|
|
159
|
+
const stat = fs.lstatSync(file);
|
|
160
|
+
if (stat.isDirectory()) {
|
|
161
|
+
if (!visit(file, `${prefix}${name}/`))
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
else if (stat.isFile())
|
|
165
|
+
hashes[`${prefix}${name}`] = (0, releases_1.skillContentHash)(fs.readFileSync(file));
|
|
166
|
+
else
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
return true;
|
|
170
|
+
};
|
|
171
|
+
return visit(dir, '') ? hashes : null;
|
|
121
172
|
}
|
|
122
173
|
function hasLinkedEntryPath(dir) {
|
|
123
|
-
return [dir, path.join(dir, 'SKILL.md'), path.join(dir, names_1.STAMP_FILE)]
|
|
174
|
+
return [dir, path.join(dir, 'SKILL.md'), path.join(dir, names_1.STAMP_FILE), path.join(dir, exports.ENTRY_SOURCE_FILE)]
|
|
124
175
|
.some((file) => fs.lstatSync(file, { throwIfNoEntry: false })?.isSymbolicLink());
|
|
125
176
|
}
|
|
126
177
|
function inspectEntrySkill(name) {
|
|
@@ -131,47 +182,193 @@ function inspectEntrySkill(name) {
|
|
|
131
182
|
if (!fs.existsSync(path.join(dir, 'SKILL.md')))
|
|
132
183
|
return { modified: fs.existsSync(dir), missing: true };
|
|
133
184
|
const hash = (0, releases_1.skillContentHash)(fs.readFileSync(path.join(dir, 'SKILL.md')));
|
|
185
|
+
const hashes = readEntryFolder(dir);
|
|
186
|
+
if (!hashes)
|
|
187
|
+
return { hash, modified: true, missing: false };
|
|
134
188
|
let stamp = '';
|
|
135
189
|
try {
|
|
136
190
|
stamp = fs.readFileSync(path.join(dir, names_1.STAMP_FILE), 'utf-8').trim();
|
|
137
191
|
}
|
|
138
192
|
catch { /* provenance unknown */ }
|
|
139
|
-
|
|
193
|
+
let record;
|
|
194
|
+
try {
|
|
195
|
+
record = JSON.parse(fs.readFileSync(path.join(dir, exports.ENTRY_SOURCE_FILE), 'utf-8'));
|
|
196
|
+
}
|
|
197
|
+
catch { /* older CLIs wrote no record */ }
|
|
198
|
+
// An install from an older CLI holds only SKILL.md and the stamp.
|
|
199
|
+
const recorded = isHashRecord(record?.fileHashes) ? record.fileHashes : { 'SKILL.md': hash };
|
|
200
|
+
const modified = !/^[a-f0-9]{16}$/.test(stamp) || hash.slice(0, 16) !== stamp || !sameHashes(hashes, recorded);
|
|
201
|
+
return { hash, digest: folderDigest(hashes), version: typeof record?.version === 'string' ? record.version : undefined, modified, missing: false };
|
|
140
202
|
}
|
|
141
203
|
catch {
|
|
142
204
|
return { modified: true, missing: false };
|
|
143
205
|
}
|
|
144
206
|
}
|
|
145
|
-
/** Checks the actual
|
|
146
|
-
function isEntrySkillFresh(
|
|
147
|
-
|
|
207
|
+
/** Checks the actual files, not just a stamp left behind before a user edit. */
|
|
208
|
+
function isEntrySkillFresh(skill) {
|
|
209
|
+
const installed = inspectEntrySkill(skill.name);
|
|
210
|
+
return !installed.missing && installed.digest === entrySkillDigest(skill);
|
|
148
211
|
}
|
|
149
|
-
/**
|
|
212
|
+
/**
|
|
213
|
+
* Write one entry skill with its stamp and record. The folder is built next to
|
|
214
|
+
* the target and swapped in with a rename, so a failure never leaves a
|
|
215
|
+
* half-written folder.
|
|
216
|
+
*/
|
|
150
217
|
function installEntrySkill(skill) {
|
|
151
|
-
const
|
|
218
|
+
const base = skillsBase();
|
|
219
|
+
const dir = path.join(base, skill.name);
|
|
152
220
|
if (hasLinkedEntryPath(dir))
|
|
153
221
|
throw new Error(`Linked ${skill.name} entry preserved; replace the link yourself before installing.`);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
222
|
+
const files = entryFiles(skill);
|
|
223
|
+
for (const name of files.keys()) {
|
|
224
|
+
if (!isSafeRelativePath(name) || ENTRY_IGNORED_FILES.has(name))
|
|
225
|
+
throw new Error(`Unsafe file path in ${skill.name}: ${name}`);
|
|
226
|
+
}
|
|
227
|
+
fs.mkdirSync(base, { recursive: true });
|
|
228
|
+
const staging = fs.mkdtempSync(path.join(base, '.entry-installing-'));
|
|
229
|
+
let keepStaging = false;
|
|
230
|
+
try {
|
|
231
|
+
const staged = path.join(staging, skill.name);
|
|
232
|
+
for (const [name, bytes] of files) {
|
|
233
|
+
const target = path.join(staged, name);
|
|
234
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
235
|
+
fs.writeFileSync(target, bytes);
|
|
236
|
+
}
|
|
237
|
+
fs.writeFileSync(path.join(staged, names_1.STAMP_FILE), (0, releases_1.skillContentHash)(skill.content).slice(0, 16), 'utf-8');
|
|
238
|
+
fs.writeFileSync(path.join(staged, exports.ENTRY_SOURCE_FILE), JSON.stringify({
|
|
239
|
+
environment: (0, environment_1.getEnvironment)(),
|
|
240
|
+
source: skill.source ?? null,
|
|
241
|
+
version: skill.version ?? null,
|
|
242
|
+
fileHashes: hashFiles(files),
|
|
243
|
+
}, null, 2) + '\n', 'utf-8');
|
|
244
|
+
const backup = fs.lstatSync(dir, { throwIfNoEntry: false }) ? path.join(staging, `${skill.name}.previous`) : null;
|
|
245
|
+
if (backup)
|
|
246
|
+
fs.renameSync(dir, backup);
|
|
247
|
+
try {
|
|
248
|
+
fs.renameSync(staged, dir);
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
if (backup) {
|
|
252
|
+
try {
|
|
253
|
+
fs.renameSync(backup, dir);
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
keepStaging = true;
|
|
257
|
+
throw new Error(`Could not replace ${skill.name}. The previous copy is preserved at ${backup}.`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
finally {
|
|
264
|
+
if (!keepStaging)
|
|
265
|
+
fs.rmSync(staging, { recursive: true, force: true });
|
|
266
|
+
}
|
|
157
267
|
}
|
|
158
268
|
/**
|
|
159
|
-
*
|
|
160
|
-
* user explicitly allows their replacement. `force` never authorizes data loss.
|
|
269
|
+
* Install or refresh entry skills. Preserve edited or untracked files unless
|
|
270
|
+
* the user explicitly allows their replacement. `force` never authorizes data loss.
|
|
161
271
|
*/
|
|
162
272
|
function installManagedEntrySkills(skills, { force = false, overwriteModified = false } = {}) {
|
|
163
273
|
return skills.map((skill) => {
|
|
274
|
+
const wanted = entrySkillDigest(skill);
|
|
164
275
|
const installed = inspectEntrySkill(skill.name);
|
|
165
|
-
if (installed.modified && installed.
|
|
276
|
+
if (installed.modified && installed.digest !== wanted && !overwriteModified) {
|
|
166
277
|
return { name: skill.name, action: 'preserved' };
|
|
167
278
|
}
|
|
168
|
-
if (!force && !installed.modified &&
|
|
279
|
+
if (!force && !installed.modified && !installed.missing && installed.digest === wanted) {
|
|
169
280
|
return { name: skill.name, action: 'skipped' };
|
|
170
281
|
}
|
|
171
282
|
installEntrySkill(skill);
|
|
172
283
|
return { name: skill.name, action: 'installed' };
|
|
173
284
|
});
|
|
174
285
|
}
|
|
286
|
+
/**
|
|
287
|
+
* Download the entry skills from goose-skills (`gooseSkillsSource()`: `main`
|
|
288
|
+
* for production, `dev` for staging, or GOOSE_SKILLS_RAW_BASE). Reads
|
|
289
|
+
* `skills-index.json`, takes each entry skill's listed `files` under
|
|
290
|
+
* `skills/entry/<name>/`, and downloads all of them before returning, so a
|
|
291
|
+
* caller writes nothing unless every file arrived. Staging rewrites `.md` files
|
|
292
|
+
* for the staging server, as standalone installs do.
|
|
293
|
+
*/
|
|
294
|
+
async function fetchEntrySkills({ timeoutMs = ENTRY_DOWNLOAD_TIMEOUT_MS } = {}) {
|
|
295
|
+
const source = gooseSkillsSource();
|
|
296
|
+
const signal = AbortSignal.timeout(timeoutMs);
|
|
297
|
+
const indexBytes = await fetchCatalogFile(source.rawBase, 'skills-index.json', signal);
|
|
298
|
+
let index;
|
|
299
|
+
try {
|
|
300
|
+
index = JSON.parse(indexBytes.toString('utf8'));
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
throw new Error('the goose-skills skills-index.json is not valid JSON');
|
|
304
|
+
}
|
|
305
|
+
if (!index || !Array.isArray(index.skills))
|
|
306
|
+
throw new Error('the goose-skills index has no skills list');
|
|
307
|
+
const entries = index.skills;
|
|
308
|
+
const plans = [];
|
|
309
|
+
const missing = [];
|
|
310
|
+
for (const name of names_1.ENTRY_SKILL_NAMES) {
|
|
311
|
+
const entry = entries.find((candidate) => candidate && candidate.slug === name);
|
|
312
|
+
if (!entry) {
|
|
313
|
+
missing.push(name);
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
const expected = `skills/entry/${name}`;
|
|
317
|
+
if (entry.path !== expected)
|
|
318
|
+
throw new Error(`goose-skills lists ${name} at ${String(entry.path)}, not ${expected}`);
|
|
319
|
+
const prefix = `${expected}/`;
|
|
320
|
+
const files = [...new Set(Array.isArray(entry.files) ? entry.files : [])];
|
|
321
|
+
if (files.some((file) => typeof file !== 'string' || !file.startsWith(prefix) || !isSafeRelativePath(file.slice(prefix.length)) || ENTRY_IGNORED_FILES.has(file.slice(prefix.length)))) {
|
|
322
|
+
throw new Error(`goose-skills lists an unsafe file for ${name}`);
|
|
323
|
+
}
|
|
324
|
+
if (!files.includes(`${prefix}SKILL.md`))
|
|
325
|
+
throw new Error(`the goose-skills index lists no SKILL.md for ${name}`);
|
|
326
|
+
const version = typeof entry.version === 'string' ? entry.version : typeof entry.metadata?.version === 'string' ? entry.metadata.version : undefined;
|
|
327
|
+
plans.push({ name, version, files: files, prefix });
|
|
328
|
+
}
|
|
329
|
+
if (!plans.some((plan) => plan.name === 'gooseworks'))
|
|
330
|
+
throw new Error('the goose-skills index has no gooseworks entry skill');
|
|
331
|
+
const downloaded = new Map();
|
|
332
|
+
await withConcurrency(plans.flatMap((plan) => plan.files), DOWNLOAD_CONCURRENCY, async (file) => {
|
|
333
|
+
downloaded.set(file, await fetchCatalogFile(source.rawBase, file, signal));
|
|
334
|
+
});
|
|
335
|
+
const staging = (0, environment_1.getEnvironment)() === 'staging';
|
|
336
|
+
const skills = plans.map((plan) => {
|
|
337
|
+
let content = '';
|
|
338
|
+
const files = {};
|
|
339
|
+
for (const file of plan.files) {
|
|
340
|
+
const relative = file.slice(plan.prefix.length);
|
|
341
|
+
let bytes = downloaded.get(file);
|
|
342
|
+
if (staging && relative.endsWith('.md'))
|
|
343
|
+
bytes = Buffer.from((0, staging_content_1.stagingContent)(bytes.toString('utf8')), 'utf-8');
|
|
344
|
+
if (relative === 'SKILL.md')
|
|
345
|
+
content = bytes.toString('utf8');
|
|
346
|
+
else
|
|
347
|
+
files[relative] = bytes;
|
|
348
|
+
}
|
|
349
|
+
return { name: plan.name, content, files, version: plan.version, source: source.rawBase };
|
|
350
|
+
});
|
|
351
|
+
return { source: source.rawBase, skills, missing };
|
|
352
|
+
}
|
|
353
|
+
async function fetchCatalogFile(rawBase, filePath, signal) {
|
|
354
|
+
const url = `${rawBase}/${filePath.split('/').map(encodeURIComponent).join('/')}`;
|
|
355
|
+
let response;
|
|
356
|
+
try {
|
|
357
|
+
response = await fetch(url, { signal });
|
|
358
|
+
}
|
|
359
|
+
catch (error) {
|
|
360
|
+
const reason = signal.aborted ? 'timed out' : error instanceof Error ? error.message : String(error);
|
|
361
|
+
throw new Error(`could not reach goose-skills for ${filePath} (${reason})`);
|
|
362
|
+
}
|
|
363
|
+
if (!response.ok)
|
|
364
|
+
throw new Error(`could not download ${filePath} from goose-skills (${response.status})`);
|
|
365
|
+
return assertNotLfsPointer(Buffer.from(await response.arrayBuffer()), filePath);
|
|
366
|
+
}
|
|
367
|
+
function assertNotLfsPointer(buffer, filePath) {
|
|
368
|
+
if (buffer.subarray(0, 100).toString().startsWith('version https://git-lfs.github.com/spec/v1'))
|
|
369
|
+
throw new Error(`Unresolved Git LFS asset in ${filePath}`);
|
|
370
|
+
return buffer;
|
|
371
|
+
}
|
|
175
372
|
async function installStandaloneSkill(slug, options = {}) {
|
|
176
373
|
if (!/^[a-z0-9][a-z0-9-]*$/.test(slug)) {
|
|
177
374
|
throw new Error(`invalid skill slug '${slug}'. Use a slug like goose-graphics.`);
|
|
@@ -188,8 +385,9 @@ async function installStandaloneSkill(slug, options = {}) {
|
|
|
188
385
|
const revision = await fetchGooseSkillsRevision(source, signal);
|
|
189
386
|
const index = JSON.parse((await fetchRawSkillFile(source.repo, 'skills-index.json', revision, signal)).toString('utf8'));
|
|
190
387
|
const retired = index.retired_skills?.find(entry => entry.slug === slug);
|
|
191
|
-
|
|
192
|
-
|
|
388
|
+
const successor = retired?.replacement;
|
|
389
|
+
if (successor && /^[a-z0-9][a-z0-9-]*$/.test(successor) && index.skills.some(entry => entry.slug === successor))
|
|
390
|
+
replacement = successor;
|
|
193
391
|
}
|
|
194
392
|
catch { /* Offline or invalid metadata must never replace a local package. */ }
|
|
195
393
|
if (replacement)
|
|
@@ -405,9 +603,6 @@ async function fetchRawSkillFile(repo, filePath, revision, signal) {
|
|
|
405
603
|
if (!response.ok) {
|
|
406
604
|
throw new Error(`could not download ${filePath} from goose-skills (${response.status})`);
|
|
407
605
|
}
|
|
408
|
-
|
|
409
|
-
if (buffer.subarray(0, 100).toString().startsWith('version https://git-lfs.github.com/spec/v1'))
|
|
410
|
-
throw new Error(`Unresolved Git LFS asset in ${filePath}`);
|
|
411
|
-
return buffer;
|
|
606
|
+
return assertNotLfsPointer(Buffer.from(await response.arrayBuffer()), filePath);
|
|
412
607
|
}
|
|
413
608
|
//# sourceMappingURL=installer.js.map
|