hngr 0.2.0 → 0.4.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.
- package/README.md +6 -3
- package/dist/{auth-BT8HuCif.mjs → auth-ByGgd_Yn.mjs} +221 -40
- package/dist/{catalog-jU0-wzh3.mjs → catalog-Bv304SXJ.mjs} +1154 -122
- package/dist/{commands-BchmocR_.mjs → commands-CLqLwQHY.mjs} +1 -1
- package/dist/{http-2HWxLIOq.mjs → http-DgHX7Fux.mjs} +13 -7
- package/dist/index.mjs +126 -29
- package/dist/{mcp-DeWHHgQK.mjs → mcp-DWF_ELDU.mjs} +29 -50
- package/dist/{pagination-BbKLKSw3.mjs → pagination-BXyFxGYA.mjs} +1 -1
- package/dist/{publish-D7zaQl9x.mjs → scope-Ch6wZCgE.mjs} +63 -12
- package/dist/{skills-DwoDzsXd.mjs → skills-CxMeJ5PF.mjs} +23 -39
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { _ as
|
|
1
|
+
import { C as HngrError, b as writeDirectoryAtomically, g as resolveConnection, r as apiRequest } from "./http-DgHX7Fux.mjs";
|
|
2
|
+
import { _ as resolveCapability, a as errorBody, c as runBatch, f as homeDir, g as parseCapabilityPath, h as SKILL_KIND, i as runPublish, l as stringValues, n as explicitName, o as failedResult, p as downloadContent, r as readPublishFlags, s as positionalPaths, t as resolveInstallScope, u as AGENTS, v as resolveCapabilityVersion } from "./scope-Ch6wZCgE.mjs";
|
|
3
3
|
import { lstat, mkdir, readFile, readdir, rename, rm, symlink, writeFile } from "node:fs/promises";
|
|
4
4
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
@@ -92,13 +92,6 @@ function downloadSkillPackage(connection, capabilityId, version, signal) {
|
|
|
92
92
|
async function pathExists(path) {
|
|
93
93
|
return lstat(path).then(() => true, () => false);
|
|
94
94
|
}
|
|
95
|
-
function targetExistsError(path) {
|
|
96
|
-
return new HngrError({
|
|
97
|
-
type: "io",
|
|
98
|
-
title: `Target already exists: ${path}`,
|
|
99
|
-
detail: "Pass --force to replace it."
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
95
|
async function writeEntries(dest, entries) {
|
|
103
96
|
await mkdir(dest, { recursive: true });
|
|
104
97
|
for (const entry of entries) {
|
|
@@ -114,25 +107,22 @@ async function writeEntries(dest, entries) {
|
|
|
114
107
|
}
|
|
115
108
|
/**
|
|
116
109
|
* Writes a skill through "temp directory → validate → rename": the target is
|
|
117
|
-
* either absent or complete, never half-written.
|
|
118
|
-
* directory
|
|
110
|
+
* either absent or complete, never half-written. Re-installing replaces the
|
|
111
|
+
* previous directory, with the old one moved aside so a failed swap puts it
|
|
112
|
+
* back.
|
|
119
113
|
*/
|
|
120
|
-
async function installAtomically(dest, entries
|
|
121
|
-
await writeDirectoryAtomically(dest, (temp) => writeEntries(temp, entries)
|
|
122
|
-
force,
|
|
123
|
-
existsError: () => targetExistsError(dest)
|
|
124
|
-
});
|
|
114
|
+
async function installAtomically(dest, entries) {
|
|
115
|
+
await writeDirectoryAtomically(dest, (temp) => writeEntries(temp, entries));
|
|
125
116
|
}
|
|
126
117
|
/**
|
|
127
118
|
* Creates a relative symlink to the canonical directory, falling back to a
|
|
128
119
|
* copy when the platform refuses the link (Windows without Developer Mode).
|
|
129
120
|
* Windows prefers a junction, which does not need elevated privileges; its
|
|
130
121
|
* target must be absolute. A temp link plus rename replaces an existing link
|
|
131
|
-
* atomically.
|
|
122
|
+
* atomically; re-installing replaces an existing directory or link.
|
|
132
123
|
*/
|
|
133
|
-
async function linkAtomically(canonical, target, entries,
|
|
124
|
+
async function linkAtomically(canonical, target, entries, options = {}) {
|
|
134
125
|
const exists = await pathExists(target);
|
|
135
|
-
if (exists && !force) throw targetExistsError(target);
|
|
136
126
|
await mkdir(dirname(target), { recursive: true });
|
|
137
127
|
const temp = resolve(dirname(target), `.hngr-${basename(target)}-${randomUUID()}.link`);
|
|
138
128
|
const windows = (options.platform ?? process.platform) === "win32";
|
|
@@ -150,7 +140,7 @@ async function linkAtomically(canonical, target, entries, force, options = {}) {
|
|
|
150
140
|
return { mode: "symlink" };
|
|
151
141
|
} catch {
|
|
152
142
|
await rm(temp, { force: true }).catch(() => {});
|
|
153
|
-
await installAtomically(target, entries
|
|
143
|
+
await installAtomically(target, entries);
|
|
154
144
|
return {
|
|
155
145
|
mode: "copy",
|
|
156
146
|
warning: `warning: could not create a link at ${target}; copied instead`
|
|
@@ -158,8 +148,8 @@ async function linkAtomically(canonical, target, entries, force, options = {}) {
|
|
|
158
148
|
}
|
|
159
149
|
}
|
|
160
150
|
/** Copies one target directory atomically, without a canonical store. */
|
|
161
|
-
async function copyAtomically(target, entries
|
|
162
|
-
await installAtomically(target, entries
|
|
151
|
+
async function copyAtomically(target, entries) {
|
|
152
|
+
await installAtomically(target, entries);
|
|
163
153
|
}
|
|
164
154
|
// src/skills/resolve.ts
|
|
165
155
|
/** Parses `<name>` or `<namespace>/<name>`, with an optional `@YYYY.MM.DD.N`. */
|
|
@@ -657,16 +647,12 @@ function planInstall(cwd, env, destName, agents, options) {
|
|
|
657
647
|
async function install(ctx, plan, entries) {
|
|
658
648
|
const cwd = process.cwd();
|
|
659
649
|
const display = (path) => displayPath(path, cwd);
|
|
660
|
-
|
|
661
|
-
if (!ctx.flags.force) {
|
|
662
|
-
for (const path of destinations) if (await pathExists(path)) throw targetExistsError(display(path));
|
|
663
|
-
}
|
|
664
|
-
if (plan.canonical) await installAtomically(plan.canonical, entries, ctx.flags.force);
|
|
650
|
+
if (plan.canonical) await installAtomically(plan.canonical, entries);
|
|
665
651
|
const installed = [];
|
|
666
652
|
let failure = null;
|
|
667
653
|
for (const target of plan.targets) try {
|
|
668
654
|
if (target.mode === "copy" || !plan.canonical) {
|
|
669
|
-
await copyAtomically(target.path, entries
|
|
655
|
+
await copyAtomically(target.path, entries);
|
|
670
656
|
installed.push({
|
|
671
657
|
agent: target.agent,
|
|
672
658
|
path: display(target.path),
|
|
@@ -675,7 +661,7 @@ async function install(ctx, plan, entries) {
|
|
|
675
661
|
});
|
|
676
662
|
continue;
|
|
677
663
|
}
|
|
678
|
-
const result = await linkAtomically(plan.canonical, target.path, entries
|
|
664
|
+
const result = await linkAtomically(plan.canonical, target.path, entries);
|
|
679
665
|
if (result.warning) ctx.summary(result.warning);
|
|
680
666
|
installed.push({
|
|
681
667
|
agent: target.agent,
|
|
@@ -708,9 +694,6 @@ async function addOne(ctx, connection, parsed, destName, agents, dir, global, co
|
|
|
708
694
|
});
|
|
709
695
|
const canonicalPath = plan.canonical ? displayPath(plan.canonical, process.cwd()) : null;
|
|
710
696
|
if (ctx.flags.dryRun) {
|
|
711
|
-
if (!ctx.flags.force) {
|
|
712
|
-
for (const path of [plan.canonical, ...plan.targets.map((target) => target.path)]) if (path && await pathExists(path)) throw targetExistsError(displayPath(path, process.cwd()));
|
|
713
|
-
}
|
|
714
697
|
ctx.summary(`resolved ${parsed.namespace}/${parsed.name} to version ${version}`);
|
|
715
698
|
return { result: {
|
|
716
699
|
name: capability.name,
|
|
@@ -784,9 +767,9 @@ function skillPrepared(pkg, metadata) {
|
|
|
784
767
|
name: "readme",
|
|
785
768
|
value: metadata.readme
|
|
786
769
|
});
|
|
787
|
-
if (metadata.
|
|
788
|
-
name: "
|
|
789
|
-
value: metadata.
|
|
770
|
+
if (metadata.category !== void 0) parts.push({
|
|
771
|
+
name: "category",
|
|
772
|
+
value: metadata.category
|
|
790
773
|
});
|
|
791
774
|
parts.push(packagePart(pkg, metadata.name));
|
|
792
775
|
return parts;
|
|
@@ -809,7 +792,7 @@ function skillPrepared(pkg, metadata) {
|
|
|
809
792
|
if (metadata.description !== void 0) preview.description = metadata.description;
|
|
810
793
|
preview.visibility = metadata.visibility;
|
|
811
794
|
if (metadata.readme !== void 0) preview.readme = metadata.readme;
|
|
812
|
-
if (metadata.
|
|
795
|
+
if (metadata.category !== void 0) preview.category = metadata.category;
|
|
813
796
|
preview.package = `<${pkg.fileCount} files, ${pkg.byteCount} bytes>`;
|
|
814
797
|
return preview;
|
|
815
798
|
},
|
|
@@ -828,7 +811,7 @@ function skillPrepared(pkg, metadata) {
|
|
|
828
811
|
async function publish(ctx, argv) {
|
|
829
812
|
const rawPaths = positionalPaths(argv.paths);
|
|
830
813
|
if (rawPaths.length === 0) throw usage("No skill directory given", "Pass one or more local directories that contain SKILL.md.");
|
|
831
|
-
const flags = await readPublishFlags(argv
|
|
814
|
+
const flags = await readPublishFlags(argv);
|
|
832
815
|
const forcedName = explicitName(argv, rawPaths.length);
|
|
833
816
|
const items = rawPaths.map((dir) => ({
|
|
834
817
|
name: forcedName ?? basename(resolve(dir)),
|
|
@@ -849,12 +832,13 @@ async function add(ctx, argv) {
|
|
|
849
832
|
const dir = stringFlag(argv, "dir");
|
|
850
833
|
const as = stringFlag(argv, "as");
|
|
851
834
|
if (as !== void 0 && (as.includes("/") || as.includes("\\") || as === "." || as === "..")) throw usage(`Invalid --as name ${JSON.stringify(as)}`, "Pass a single directory name.");
|
|
852
|
-
const
|
|
835
|
+
const requestedGlobal = argv.global === true;
|
|
853
836
|
const copy = argv.copy === true;
|
|
854
|
-
if (dir !== void 0 &&
|
|
837
|
+
if (dir !== void 0 && requestedGlobal) throw usage("--dir cannot be combined with --global");
|
|
855
838
|
if (dir !== void 0 && (stringValues(argv.agent).length > 0 || argv.all === true)) throw usage("--dir cannot be combined with --agent or --all");
|
|
856
839
|
if (as !== void 0) assertNotReserved(as);
|
|
857
840
|
for (const parsed of parsedPaths) assertNotReserved(as ?? parsed.name);
|
|
841
|
+
const global = dir === void 0 ? await resolveInstallScope(ctx, requestedGlobal) === "global" : false;
|
|
858
842
|
const agents = dir === void 0 ? await selectAgents(ctx, argv, rawPaths[0] ?? "", global) : [];
|
|
859
843
|
const connection = await resolveConnection(ctx.flags, ctx.env);
|
|
860
844
|
const { results, failed } = await runBatch({
|