yeka-skills 0.2.1 → 0.2.3
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 +6 -3
- package/dist/cli.js +46 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,8 +31,10 @@ yeka-skills logout
|
|
|
31
31
|
## Share a local skill with the team
|
|
32
32
|
|
|
33
33
|
`yeka-skills share <skill>` packages one of your local skill folders and sends it to the private
|
|
34
|
-
submission inbox, where
|
|
35
|
-
|
|
34
|
+
submission inbox, where the submission bot turns it into a team-repo pull request. Nothing bypasses
|
|
35
|
+
review — but the reviewers are machines: the repository checks and an AI safety review gate the
|
|
36
|
+
merge, and they run from `main`, not from the pull request. The catalogue page was written from your
|
|
37
|
+
skill's own source and confirmed by you during the share conversation.
|
|
36
38
|
|
|
37
39
|
- The CLI looks for the folder in the same local roots the installer knows. If a skill exists in
|
|
38
40
|
several of them, it picks the one it would install into first (the current Codex folder, then
|
|
@@ -46,7 +48,8 @@ by a share — a person reviews every submission first.
|
|
|
46
48
|
the review bot can find it, read it, and strip it before the skill content is unpacked. Do not
|
|
47
49
|
create a `_yeka` folder inside your skill yourself.
|
|
48
50
|
- A successful share answers with one sentence: the team is notified the moment the upload
|
|
49
|
-
lands, and
|
|
51
|
+
lands, and the skill goes live on its own once the automatic checks pass — usually about ten
|
|
52
|
+
minutes — announced in #yeka-skills. A failed check messages the author, not the operator.
|
|
50
53
|
|
|
51
54
|
Use `--dry-run` with `add`, `update`, or `remove` to verify and report changes without mutating the
|
|
52
55
|
managed installation. Removal is fully offline and uses local receipts. It refuses locally edited
|
package/dist/cli.js
CHANGED
|
@@ -2358,7 +2358,7 @@ var statusCommand = async (context = {}) => {
|
|
|
2358
2358
|
return Promise.all(
|
|
2359
2359
|
receipts.map((receipt) => inspectLocalStatus(receipt, remoteByName.get(receipt.skillName), home))
|
|
2360
2360
|
);
|
|
2361
|
-
});
|
|
2361
|
+
}, context.session);
|
|
2362
2362
|
for (const status of statuses) {
|
|
2363
2363
|
output(
|
|
2364
2364
|
context,
|
|
@@ -2366,17 +2366,21 @@ var statusCommand = async (context = {}) => {
|
|
|
2366
2366
|
);
|
|
2367
2367
|
}
|
|
2368
2368
|
};
|
|
2369
|
-
var
|
|
2369
|
+
var updateBlocker = (skillName, statuses) => {
|
|
2370
2370
|
const modified = statuses.find((status) => status.kind === "modified");
|
|
2371
2371
|
if (modified !== void 0) {
|
|
2372
|
-
|
|
2373
|
-
"local_changes",
|
|
2374
|
-
`${skillName} has local changes for ${modified.receipt.runtime}. It was not changed.`
|
|
2375
|
-
|
|
2372
|
+
return {
|
|
2373
|
+
code: "local_changes",
|
|
2374
|
+
message: `${skillName} has local changes for ${modified.receipt.runtime}. It was not changed.`
|
|
2375
|
+
};
|
|
2376
2376
|
}
|
|
2377
2377
|
if (statuses.some((status) => status.kind === "unavailable")) {
|
|
2378
|
-
|
|
2378
|
+
return {
|
|
2379
|
+
code: "skill_unavailable",
|
|
2380
|
+
message: `${skillName} is no longer available in the private registry.`
|
|
2381
|
+
};
|
|
2379
2382
|
}
|
|
2383
|
+
return void 0;
|
|
2380
2384
|
};
|
|
2381
2385
|
var updateCommand = async (skillNameInput, options, context = {}) => {
|
|
2382
2386
|
const selectedName = skillNameInput === void 0 ? void 0 : validatedSkillName(skillNameInput);
|
|
@@ -2396,17 +2400,25 @@ var updateCommand = async (skillNameInput, options, context = {}) => {
|
|
|
2396
2400
|
const remoteByName = new Map(manifest.skills.map((skill) => [skill.name, skill]));
|
|
2397
2401
|
const selectedGroups = [...groups.entries()].filter(([name]) => selectedName === void 0 || name === selectedName);
|
|
2398
2402
|
const prepared = [];
|
|
2403
|
+
const skipped = [];
|
|
2399
2404
|
for (const [name, receipts] of selectedGroups) {
|
|
2400
2405
|
const remote = remoteByName.get(name);
|
|
2401
2406
|
const statuses = await Promise.all(
|
|
2402
2407
|
receipts.map((receipt) => inspectLocalStatus(receipt, remote, home))
|
|
2403
2408
|
);
|
|
2404
|
-
|
|
2405
|
-
if (
|
|
2406
|
-
|
|
2409
|
+
const blocker = updateBlocker(name, statuses) ?? (remote === void 0 ? { code: "skill_unavailable", message: `${name} is no longer available in the private registry.` } : void 0);
|
|
2410
|
+
if (blocker !== void 0) {
|
|
2411
|
+
if (selectedName !== void 0) {
|
|
2412
|
+
throw new CliError(blocker.code, blocker.message);
|
|
2413
|
+
}
|
|
2414
|
+
skipped.push(blocker.message);
|
|
2415
|
+
continue;
|
|
2407
2416
|
}
|
|
2408
2417
|
prepared.push({ name, receipts, skill: remote, statuses });
|
|
2409
2418
|
}
|
|
2419
|
+
for (const message of skipped) {
|
|
2420
|
+
output(context, message);
|
|
2421
|
+
}
|
|
2410
2422
|
const updated = [];
|
|
2411
2423
|
for (const item of prepared) {
|
|
2412
2424
|
if (item.statuses.every((status) => status.kind === "current")) {
|
|
@@ -2428,7 +2440,7 @@ var updateCommand = async (skillNameInput, options, context = {}) => {
|
|
|
2428
2440
|
});
|
|
2429
2441
|
}
|
|
2430
2442
|
return updated;
|
|
2431
|
-
});
|
|
2443
|
+
}, context.session);
|
|
2432
2444
|
for (const result of results) {
|
|
2433
2445
|
printActions(context, result.name, result.actions, options.dryRun === true);
|
|
2434
2446
|
}
|
|
@@ -2496,6 +2508,23 @@ var shareCommand = async (skillNameInput, options, context = {}) => {
|
|
|
2496
2508
|
const notes = options.notesFile === void 0 ? void 0 : await readNotesFile(options.notesFile);
|
|
2497
2509
|
const check = await checkSkillFolder(folder.folderPath, skillName, void 0, notes);
|
|
2498
2510
|
if (options.check === true) {
|
|
2511
|
+
try {
|
|
2512
|
+
const taken = await withRegistrySession(async (token) => {
|
|
2513
|
+
const manifest = await (context.client ?? new RegistryClient()).getManifest(token);
|
|
2514
|
+
return manifest.skills.some((skill) => skill.name === skillName);
|
|
2515
|
+
}, context.session);
|
|
2516
|
+
if (taken) {
|
|
2517
|
+
output(
|
|
2518
|
+
context,
|
|
2519
|
+
`The catalogue already has a skill called ${skillName}. If it is yours, sharing it now updates it. If it is not, rename your folder and its SKILL.md \`name:\` first, or the team's checks will turn it away.`
|
|
2520
|
+
);
|
|
2521
|
+
}
|
|
2522
|
+
} catch {
|
|
2523
|
+
output(
|
|
2524
|
+
context,
|
|
2525
|
+
"Could not reach the catalogue to see whether that name is free, so this only checked the folder."
|
|
2526
|
+
);
|
|
2527
|
+
}
|
|
2499
2528
|
if (check.warnings.length === 0) {
|
|
2500
2529
|
output(context, "Nothing looked risky.");
|
|
2501
2530
|
} else {
|
|
@@ -2514,7 +2543,8 @@ var shareCommand = async (skillNameInput, options, context = {}) => {
|
|
|
2514
2543
|
const client = context.client ?? new RegistryClient();
|
|
2515
2544
|
try {
|
|
2516
2545
|
await withRegistrySession(
|
|
2517
|
-
(token) => client.uploadSubmission(skillName, packaged.sha256, packaged.bytes, token)
|
|
2546
|
+
(token) => client.uploadSubmission(skillName, packaged.sha256, packaged.bytes, token),
|
|
2547
|
+
context.session
|
|
2518
2548
|
);
|
|
2519
2549
|
} catch (error) {
|
|
2520
2550
|
if (error instanceof CliError && error.code.startsWith("login_")) {
|
|
@@ -2525,7 +2555,10 @@ var shareCommand = async (skillNameInput, options, context = {}) => {
|
|
|
2525
2555
|
}
|
|
2526
2556
|
throw error;
|
|
2527
2557
|
}
|
|
2528
|
-
output(
|
|
2558
|
+
output(
|
|
2559
|
+
context,
|
|
2560
|
+
"Shared. The team was notified the moment it landed. It goes live on its own once the automatic checks pass, usually about ten minutes, announced in #yeka-skills. If a check fails you get a Slack message saying what to fix."
|
|
2561
|
+
);
|
|
2529
2562
|
};
|
|
2530
2563
|
var loginCommand = async (context = {}) => {
|
|
2531
2564
|
await deleteSession();
|