ctxbin 1.0.1 → 1.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.
- package/README.md +4 -4
- package/dist/cli.js +53 -33
- package/dist/cli.js.map +1 -1
- package/dist/skills/ctxbin/SKILL.md +5 -4
- package/package.json +1 -1
- package/skills/ctxbin/SKILL.md +4 -3
package/README.md
CHANGED
|
@@ -81,13 +81,13 @@ npx ctxbin ctx delete
|
|
|
81
81
|
When the key is omitted, ctxbin infers it **only inside a git repository**:
|
|
82
82
|
```
|
|
83
83
|
key = {project}/{branch}
|
|
84
|
-
project =
|
|
84
|
+
project = package.json "name" field, or folder name if no package.json
|
|
85
85
|
branch = git rev-parse --abbrev-ref HEAD
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
> **Note:**
|
|
89
|
-
>
|
|
90
|
-
>
|
|
88
|
+
> **Note:** If `package.json` exists, the `name` field is used as the project name.
|
|
89
|
+
> If the name differs from the folder name, a warning is printed to stderr.
|
|
90
|
+
> Without `package.json`, the folder name is used (not the git remote URL—parsing remote URLs across different git services is fragile).
|
|
91
91
|
|
|
92
92
|
Explicit key example (useful outside git repos; not recommended for normal use):
|
|
93
93
|
```bash
|
package/dist/cli.js
CHANGED
|
@@ -27,7 +27,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
27
27
|
var import_node_util2 = require("util");
|
|
28
28
|
var import_node_process2 = __toESM(require("process"));
|
|
29
29
|
var import_node_path8 = __toESM(require("path"));
|
|
30
|
-
var
|
|
30
|
+
var import_promises10 = __toESM(require("fs/promises"));
|
|
31
31
|
var import_node_fs3 = require("fs");
|
|
32
32
|
|
|
33
33
|
// src/errors.ts
|
|
@@ -181,6 +181,7 @@ function createStore(url, token) {
|
|
|
181
181
|
|
|
182
182
|
// src/git.ts
|
|
183
183
|
var import_node_child_process = require("child_process");
|
|
184
|
+
var import_promises2 = require("fs/promises");
|
|
184
185
|
var import_node_path2 = __toESM(require("path"));
|
|
185
186
|
var import_node_util = require("util");
|
|
186
187
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
@@ -192,34 +193,53 @@ async function git(args) {
|
|
|
192
193
|
return fail("NOT_IN_GIT", "not inside a git repository");
|
|
193
194
|
}
|
|
194
195
|
}
|
|
196
|
+
async function getPackageJsonName(root) {
|
|
197
|
+
try {
|
|
198
|
+
const content = await (0, import_promises2.readFile)(import_node_path2.default.join(root, "package.json"), "utf8");
|
|
199
|
+
const pkg = JSON.parse(content);
|
|
200
|
+
return typeof pkg.name === "string" ? pkg.name : null;
|
|
201
|
+
} catch {
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
195
205
|
async function inferCtxKey() {
|
|
196
206
|
const root = await git(["rev-parse", "--show-toplevel"]);
|
|
197
207
|
const branch = await git(["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
198
|
-
const
|
|
199
|
-
if (!
|
|
208
|
+
const folderName = import_node_path2.default.basename(root);
|
|
209
|
+
if (!folderName || !branch) {
|
|
200
210
|
return fail("NOT_IN_GIT", "unable to infer ctx key from git repository");
|
|
201
211
|
}
|
|
202
|
-
|
|
212
|
+
const pkgName = await getPackageJsonName(root);
|
|
213
|
+
if (pkgName) {
|
|
214
|
+
if (pkgName !== folderName) {
|
|
215
|
+
process.stderr.write(
|
|
216
|
+
`CTXBIN_WARN: package.json name "${pkgName}" differs from folder name "${folderName}". Using "${pkgName}".
|
|
217
|
+
`
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
return `${pkgName}/${branch}`;
|
|
221
|
+
}
|
|
222
|
+
return `${folderName}/${branch}`;
|
|
203
223
|
}
|
|
204
224
|
|
|
205
225
|
// src/skillpack.ts
|
|
206
|
-
var
|
|
226
|
+
var import_promises6 = __toESM(require("fs/promises"));
|
|
207
227
|
var import_node_fs = require("fs");
|
|
208
228
|
var import_node_path6 = __toESM(require("path"));
|
|
209
229
|
var import_node_os2 = __toESM(require("os"));
|
|
210
230
|
var import_node_zlib = __toESM(require("zlib"));
|
|
211
|
-
var
|
|
231
|
+
var import_promises7 = require("stream/promises");
|
|
212
232
|
var import_tar2 = __toESM(require("tar"));
|
|
213
233
|
|
|
214
234
|
// src/fs-ops.ts
|
|
215
|
-
var
|
|
235
|
+
var import_promises4 = __toESM(require("fs/promises"));
|
|
216
236
|
var import_node_path3 = __toESM(require("path"));
|
|
217
237
|
|
|
218
238
|
// src/chmod.ts
|
|
219
|
-
var
|
|
239
|
+
var import_promises3 = __toESM(require("fs/promises"));
|
|
220
240
|
async function safeChmod(path9, mode) {
|
|
221
241
|
try {
|
|
222
|
-
await
|
|
242
|
+
await import_promises3.default.chmod(path9, mode);
|
|
223
243
|
} catch (err) {
|
|
224
244
|
if (process.platform === "win32") {
|
|
225
245
|
return;
|
|
@@ -230,27 +250,27 @@ async function safeChmod(path9, mode) {
|
|
|
230
250
|
|
|
231
251
|
// src/fs-ops.ts
|
|
232
252
|
async function ensureDir(dir) {
|
|
233
|
-
await
|
|
253
|
+
await import_promises4.default.mkdir(dir, { recursive: true });
|
|
234
254
|
}
|
|
235
255
|
function toPosix(p) {
|
|
236
256
|
return p.split(import_node_path3.default.sep).join("/");
|
|
237
257
|
}
|
|
238
258
|
async function copyDirContents(src, dest) {
|
|
239
259
|
await ensureDir(dest);
|
|
240
|
-
const entries = await
|
|
260
|
+
const entries = await import_promises4.default.readdir(src, { withFileTypes: true });
|
|
241
261
|
for (const entry of entries) {
|
|
242
262
|
const srcPath = import_node_path3.default.join(src, entry.name);
|
|
243
263
|
const destPath = import_node_path3.default.join(dest, entry.name);
|
|
244
264
|
if (entry.isDirectory()) {
|
|
245
265
|
await copyDirContents(srcPath, destPath);
|
|
246
|
-
const stat = await
|
|
266
|
+
const stat = await import_promises4.default.stat(srcPath);
|
|
247
267
|
await safeChmod(destPath, stat.mode & 511);
|
|
248
268
|
continue;
|
|
249
269
|
}
|
|
250
270
|
if (entry.isFile()) {
|
|
251
271
|
await ensureDir(import_node_path3.default.dirname(destPath));
|
|
252
|
-
await
|
|
253
|
-
const stat = await
|
|
272
|
+
await import_promises4.default.copyFile(srcPath, destPath);
|
|
273
|
+
const stat = await import_promises4.default.stat(srcPath);
|
|
254
274
|
await safeChmod(destPath, stat.mode & 511);
|
|
255
275
|
continue;
|
|
256
276
|
}
|
|
@@ -259,11 +279,11 @@ async function copyDirContents(src, dest) {
|
|
|
259
279
|
}
|
|
260
280
|
|
|
261
281
|
// src/perm.ts
|
|
262
|
-
var
|
|
282
|
+
var import_promises5 = __toESM(require("fs/promises"));
|
|
263
283
|
var import_node_path4 = __toESM(require("path"));
|
|
264
284
|
async function applyNormalizedPermissions(root, execSet) {
|
|
265
285
|
async function walk(absDir) {
|
|
266
|
-
const entries = await
|
|
286
|
+
const entries = await import_promises5.default.readdir(absDir, { withFileTypes: true });
|
|
267
287
|
for (const entry of entries) {
|
|
268
288
|
const absPath = import_node_path4.default.join(absDir, entry.name);
|
|
269
289
|
if (entry.isDirectory()) {
|
|
@@ -374,12 +394,12 @@ async function listTarEntries(file) {
|
|
|
374
394
|
// src/skillpack.ts
|
|
375
395
|
var ALLOWED_TYPES = /* @__PURE__ */ new Set(["File", "Directory"]);
|
|
376
396
|
async function createSkillpackFromDir(dirPath) {
|
|
377
|
-
const stats = await
|
|
397
|
+
const stats = await import_promises6.default.stat(dirPath).catch(() => null);
|
|
378
398
|
if (!stats || !stats.isDirectory()) {
|
|
379
399
|
return fail("INVALID_INPUT", `--dir is not a directory: ${dirPath}`);
|
|
380
400
|
}
|
|
381
401
|
const entries = await collectEntries(dirPath);
|
|
382
|
-
const tmpDir = await
|
|
402
|
+
const tmpDir = await import_promises6.default.mkdtemp(import_node_path6.default.join(import_node_os2.default.tmpdir(), "ctxbin-skillpack-"));
|
|
383
403
|
const tarPath = import_node_path6.default.join(tmpDir, "skillpack.tar.gz");
|
|
384
404
|
try {
|
|
385
405
|
const tarStream = import_tar2.default.c(
|
|
@@ -391,19 +411,19 @@ async function createSkillpackFromDir(dirPath) {
|
|
|
391
411
|
entries
|
|
392
412
|
);
|
|
393
413
|
const gzip = import_node_zlib.default.createGzip({ mtime: 0 });
|
|
394
|
-
await (0,
|
|
395
|
-
const stat = await
|
|
414
|
+
await (0, import_promises7.pipeline)(tarStream, gzip, (0, import_node_fs.createWriteStream)(tarPath));
|
|
415
|
+
const stat = await import_promises6.default.stat(tarPath);
|
|
396
416
|
if (stat.size > MAX_SKILLPACK_BYTES) {
|
|
397
417
|
return fail(
|
|
398
418
|
"SIZE_LIMIT",
|
|
399
419
|
`skillpack tar.gz size ${stat.size} bytes exceeds ${MAX_SKILLPACK_BYTES} bytes`
|
|
400
420
|
);
|
|
401
421
|
}
|
|
402
|
-
const data = await
|
|
422
|
+
const data = await import_promises6.default.readFile(tarPath);
|
|
403
423
|
const b64 = data.toString("base64");
|
|
404
424
|
return SKILLPACK_HEADER + b64;
|
|
405
425
|
} finally {
|
|
406
|
-
await
|
|
426
|
+
await import_promises6.default.rm(tmpDir, { recursive: true, force: true });
|
|
407
427
|
}
|
|
408
428
|
}
|
|
409
429
|
async function extractSkillpackToDir(value, targetDir) {
|
|
@@ -414,9 +434,9 @@ async function extractSkillpackToDir(value, targetDir) {
|
|
|
414
434
|
} catch {
|
|
415
435
|
return fail("IO", "invalid skillpack base64 data");
|
|
416
436
|
}
|
|
417
|
-
const tmpRoot = await
|
|
437
|
+
const tmpRoot = await import_promises6.default.mkdtemp(import_node_path6.default.join(import_node_os2.default.tmpdir(), "ctxbin-skillpack-"));
|
|
418
438
|
const tarPath = import_node_path6.default.join(tmpRoot, "skillpack.tar.gz");
|
|
419
|
-
await
|
|
439
|
+
await import_promises6.default.writeFile(tarPath, buffer);
|
|
420
440
|
try {
|
|
421
441
|
const entries = await listTarEntries(tarPath);
|
|
422
442
|
const execSet = validateTarEntries(entries);
|
|
@@ -432,13 +452,13 @@ async function extractSkillpackToDir(value, targetDir) {
|
|
|
432
452
|
await ensureDir(targetDir);
|
|
433
453
|
await copyDirContents(extractDir, targetDir);
|
|
434
454
|
} finally {
|
|
435
|
-
await
|
|
455
|
+
await import_promises6.default.rm(tmpRoot, { recursive: true, force: true });
|
|
436
456
|
}
|
|
437
457
|
}
|
|
438
458
|
async function collectEntries(root) {
|
|
439
459
|
const results = [];
|
|
440
460
|
async function walk(absDir, relDir) {
|
|
441
|
-
const entries = await
|
|
461
|
+
const entries = await import_promises6.default.readdir(absDir, { withFileTypes: true });
|
|
442
462
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
443
463
|
for (const entry of entries) {
|
|
444
464
|
if (DEFAULT_EXCLUDES.includes(entry.name)) {
|
|
@@ -451,7 +471,7 @@ async function collectEntries(root) {
|
|
|
451
471
|
}
|
|
452
472
|
const absPath = import_node_path6.default.join(absDir, entry.name);
|
|
453
473
|
const relPath = relDir ? import_node_path6.default.posix.join(relDir, entry.name) : entry.name;
|
|
454
|
-
const stat = await
|
|
474
|
+
const stat = await import_promises6.default.lstat(absPath);
|
|
455
475
|
if (stat.isSymbolicLink()) {
|
|
456
476
|
return fail("IO", `symlink not allowed in skillpack: ${absPath}`);
|
|
457
477
|
}
|
|
@@ -489,7 +509,7 @@ function validateTarEntries(entries) {
|
|
|
489
509
|
}
|
|
490
510
|
|
|
491
511
|
// src/skillref.ts
|
|
492
|
-
var
|
|
512
|
+
var import_promises8 = __toESM(require("fs/promises"));
|
|
493
513
|
var import_node_path7 = __toESM(require("path"));
|
|
494
514
|
var import_node_os3 = __toESM(require("os"));
|
|
495
515
|
var import_node_fs2 = require("fs");
|
|
@@ -530,7 +550,7 @@ function parseSkillrefValue(value) {
|
|
|
530
550
|
async function loadSkillrefToDir(value, targetDir) {
|
|
531
551
|
const skillref = parseSkillrefValue(value);
|
|
532
552
|
const resolvedRef = skillref.ref ?? await fetchDefaultBranch(skillref.url);
|
|
533
|
-
const tmpRoot = await
|
|
553
|
+
const tmpRoot = await import_promises8.default.mkdtemp(import_node_path7.default.join(import_node_os3.default.tmpdir(), "ctxbin-skillref-"));
|
|
534
554
|
const tarPath = import_node_path7.default.join(tmpRoot, "skillref.tar.gz");
|
|
535
555
|
try {
|
|
536
556
|
await downloadArchive(skillref.url, resolvedRef, tarPath);
|
|
@@ -554,7 +574,7 @@ async function loadSkillrefToDir(value, targetDir) {
|
|
|
554
574
|
await ensureDir(targetDir);
|
|
555
575
|
await copyDirContents(extractDir, targetDir);
|
|
556
576
|
} finally {
|
|
557
|
-
await
|
|
577
|
+
await import_promises8.default.rm(tmpRoot, { recursive: true, force: true });
|
|
558
578
|
}
|
|
559
579
|
}
|
|
560
580
|
async function downloadArchive(repoUrl, ref, outPath) {
|
|
@@ -784,7 +804,7 @@ function detectSkillValueType(value) {
|
|
|
784
804
|
}
|
|
785
805
|
|
|
786
806
|
// src/input.ts
|
|
787
|
-
var
|
|
807
|
+
var import_promises9 = __toESM(require("fs/promises"));
|
|
788
808
|
var import_node_process = __toESM(require("process"));
|
|
789
809
|
async function resolveSaveInput(resource, opts, stdinIsTTY = Boolean(import_node_process.default.stdin.isTTY)) {
|
|
790
810
|
const hasFile = typeof opts.file === "string";
|
|
@@ -819,7 +839,7 @@ async function resolveSaveInput(resource, opts, stdinIsTTY = Boolean(import_node
|
|
|
819
839
|
return { kind: "skillref", value };
|
|
820
840
|
}
|
|
821
841
|
if (hasFile) {
|
|
822
|
-
const content = await
|
|
842
|
+
const content = await import_promises9.default.readFile(opts.file, "utf8");
|
|
823
843
|
return { kind: "string", value: content };
|
|
824
844
|
}
|
|
825
845
|
if (hasValue) {
|
|
@@ -1066,7 +1086,7 @@ main().catch((err) => {
|
|
|
1066
1086
|
async function loadBundledSkill() {
|
|
1067
1087
|
try {
|
|
1068
1088
|
const bundled = import_node_path8.default.resolve(__dirname, "skills", "ctxbin", "SKILL.md");
|
|
1069
|
-
return await
|
|
1089
|
+
return await import_promises10.default.readFile(bundled, "utf8");
|
|
1070
1090
|
} catch {
|
|
1071
1091
|
return null;
|
|
1072
1092
|
}
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/errors.ts","../src/config.ts","../src/constants.ts","../src/store.ts","../src/git.ts","../src/skillpack.ts","../src/fs-ops.ts","../src/chmod.ts","../src/perm.ts","../src/validators.ts","../src/tar-utils.ts","../src/skillref.ts","../src/value.ts","../src/input.ts"],"sourcesContent":["import { parseArgs } from \"node:util\";\nimport process from \"node:process\";\nimport path from \"node:path\";\nimport fs from \"node:fs/promises\";\nimport { readFileSync } from \"node:fs\";\nimport { formatError, fail } from \"./errors\";\nimport { loadConfig, writeConfig } from \"./config\";\nimport { createStore } from \"./store\";\nimport { inferCtxKey } from \"./git\";\nimport { extractSkillpackToDir } from \"./skillpack\";\nimport { loadSkillrefToDir } from \"./skillref\";\nimport { detectSkillValueType } from \"./value\";\nimport { resolveSaveInput } from \"./input\";\n\nasync function main(): Promise<void> {\n let positionals: string[];\n let values: Record<string, unknown>;\n try {\n ({ positionals, values } = parseArgs({\n args: process.argv.slice(2),\n options: {\n append: { type: \"boolean\" },\n version: { type: \"boolean\", short: \"v\" },\n file: { type: \"string\" },\n value: { type: \"string\" },\n dir: { type: \"string\" },\n url: { type: \"string\" },\n ref: { type: \"string\" },\n path: { type: \"string\" },\n },\n allowPositionals: true,\n }));\n } catch (err) {\n return fail(\"INVALID_INPUT\", err instanceof Error ? err.message : \"invalid arguments\");\n }\n\n const [resource, command, keyArg, ...extra] = positionals;\n if (values.version) {\n process.stdout.write(getVersion() + \"\\n\");\n return;\n }\n if (!resource) {\n return fail(\"INVALID_INPUT\", \"missing resource\");\n }\n\n if (resource === \"init\") {\n if (command || keyArg || extra.length) {\n return fail(\"INVALID_INPUT\", \"init does not accept additional arguments\");\n }\n await runInit();\n return;\n }\n\n if (resource === \"help\") {\n if (command || keyArg || extra.length) {\n return fail(\"INVALID_INPUT\", \"help does not accept additional arguments\");\n }\n const content = await loadBundledSkill();\n if (content) {\n process.stdout.write(content);\n return;\n }\n return fail(\"IO\", \"bundled skill not found\");\n }\n\n if (!command) {\n return fail(\"INVALID_INPUT\", \"missing command\");\n }\n if (extra.length > 0) {\n return fail(\"INVALID_INPUT\", \"too many positional arguments\");\n }\n\n const opts = {\n append: Boolean(values.append),\n file: values.file as string | undefined,\n value: values.value as string | undefined,\n dir: values.dir as string | undefined,\n url: values.url as string | undefined,\n ref: values.ref as string | undefined,\n path: values.path as string | undefined,\n };\n\n let store: ReturnType<typeof createStore>;\n try {\n const storeConfig = await loadConfig();\n store = createStore(storeConfig.url, storeConfig.token);\n } catch (err) {\n if (resource === \"skill\" && command === \"load\" && keyArg === \"ctxbin\") {\n const fallback = await loadBundledSkill();\n if (fallback) {\n process.stdout.write(fallback);\n return;\n }\n }\n throw err;\n }\n\n const hash = resolveHash(resource);\n\n if (command === \"list\") {\n if (keyArg) {\n return fail(\"INVALID_INPUT\", \"list does not accept a key\");\n }\n ensureNoListFlags(opts);\n await handleList(store, resource, hash);\n return;\n }\n\n const key = await resolveKey(resource, keyArg);\n\n switch (command) {\n case \"load\":\n await handleLoad(store, resource, hash, key, opts);\n return;\n case \"save\":\n await handleSave(store, resource, hash, key, opts);\n return;\n case \"delete\":\n await handleDelete(store, resource, hash, key, opts);\n return;\n default:\n return fail(\"INVALID_INPUT\", `unknown command: ${command}`);\n }\n}\n\nasync function runInit(): Promise<void> {\n const readline = await import(\"node:readline/promises\");\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const url = (await rl.question(\"CTXBIN_STORE_URL: \")).trim();\n const token = (await rl.question(\"CTXBIN_STORE_TOKEN: \")).trim();\n await rl.close();\n\n if (!url || !token) {\n return fail(\"INVALID_INPUT\", \"both URL and token are required\");\n }\n\n await writeConfig({ url, token });\n}\n\nfunction resolveHash(resource: string): \"ctx\" | \"agent\" | \"skill\" {\n if (resource === \"ctx\" || resource === \"agent\" || resource === \"skill\") {\n return resource;\n }\n return fail(\"INVALID_INPUT\", `unknown resource: ${resource}`);\n}\n\nasync function resolveKey(resource: string, keyArg?: string): Promise<string> {\n if (resource === \"ctx\") {\n if (keyArg) return keyArg;\n return inferCtxKey();\n }\n if (!keyArg) {\n return fail(\"MISSING_KEY\", \"key is required\");\n }\n return keyArg;\n}\n\nasync function handleLoad(\n store: ReturnType<typeof createStore>,\n resource: string,\n hash: string,\n key: string,\n opts: {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n }\n): Promise<void> {\n ensureNoSaveInput(opts, \"load\");\n\n const value = await store.get(hash, key);\n if (value === null) {\n if (resource === \"skill\" && key === \"ctxbin\") {\n const fallback = await loadBundledSkill();\n if (fallback) {\n process.stdout.write(fallback);\n return;\n }\n }\n return fail(\"NOT_FOUND\", `no value for ${hash}:${key}`);\n }\n\n if (resource === \"skill\") {\n const kind = detectSkillValueType(value);\n if (kind === \"string\") {\n if (opts.dir) {\n return fail(\"TYPE_MISMATCH\", \"--dir cannot be used with string values\");\n }\n process.stdout.write(value);\n return;\n }\n if (!opts.dir) {\n return fail(\"TYPE_MISMATCH\", \"--dir is required for skillpack/skillref load\");\n }\n if (kind === \"skillpack\") {\n await extractSkillpackToDir(value, opts.dir);\n return;\n }\n if (kind === \"skillref\") {\n await loadSkillrefToDir(value, opts.dir);\n return;\n }\n }\n\n if (opts.dir) {\n return fail(\"TYPE_MISMATCH\", \"--dir is only valid for skill values\");\n }\n process.stdout.write(value);\n}\n\nasync function handleSave(\n store: ReturnType<typeof createStore>,\n resource: string,\n hash: string,\n key: string,\n opts: {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n }\n): Promise<void> {\n const input = await resolveSaveInput(resource, opts);\n\n if (opts.append) {\n if (input.kind !== \"string\") {\n return fail(\"INVALID_INPUT\", \"--append only applies to string inputs\");\n }\n const existing = await store.get(hash, key);\n if (resource === \"skill\" && existing && detectSkillValueType(existing) !== \"string\") {\n return fail(\"TYPE_MISMATCH\", \"cannot append to skillpack/skillref values\");\n }\n const merged = existing ? `${existing}\\n\\n${input.value}` : input.value;\n await store.set(hash, key, merged);\n return;\n }\n\n if (input.kind !== \"string\" && resource !== \"skill\") {\n return fail(\"TYPE_MISMATCH\", \"non-string inputs are only valid for skill\" );\n }\n\n await store.set(hash, key, input.value);\n}\n\nasync function handleDelete(\n store: ReturnType<typeof createStore>,\n resource: string,\n hash: string,\n key: string,\n opts: {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n }\n): Promise<void> {\n ensureNoSaveInput(opts, \"delete\");\n if (opts.dir) {\n return fail(\"INVALID_INPUT\", \"--dir is not valid for delete\");\n }\n await store.delete(hash, key);\n}\n\nasync function handleList(\n store: ReturnType<typeof createStore>,\n resource: string,\n hash: string\n): Promise<void> {\n const entries = await store.list(hash);\n if (entries.length === 0) return;\n\n const lines = entries.map(({ field, value }) => {\n let type = \"--value\";\n if (resource === \"skill\") {\n const kind = detectSkillValueType(value);\n if (kind === \"skillpack\") type = \"--dir\";\n if (kind === \"skillref\") type = \"--url\";\n }\n return `${field}\\t${type}`;\n });\n\n process.stdout.write(lines.join(\"\\n\") + \"\\n\");\n}\n\n\nfunction ensureNoSaveInput(\n opts: {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n },\n command: \"load\" | \"delete\"\n): void {\n if (opts.append || opts.file || opts.value || opts.url || opts.ref || opts.path) {\n return fail(\"INVALID_INPUT\", `${command} does not accept input flags`);\n }\n}\n\nfunction ensureNoListFlags(opts: {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n}): void {\n if (opts.append || opts.file || opts.value || opts.dir || opts.url || opts.ref || opts.path) {\n return fail(\"INVALID_INPUT\", \"list does not accept input flags\");\n }\n}\n\nmain().catch((err) => {\n process.stderr.write(formatError(err) + \"\\n\");\n process.exit(1);\n});\n\nasync function loadBundledSkill(): Promise<string | null> {\n try {\n const bundled = path.resolve(__dirname, \"skills\", \"ctxbin\", \"SKILL.md\");\n return await fs.readFile(bundled, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction getVersion(): string {\n try {\n const pkgPath = path.resolve(__dirname, \"..\", \"package.json\");\n const raw = readFileSync(pkgPath, \"utf8\");\n const data = JSON.parse(raw);\n if (data && typeof data.version === \"string\") {\n return data.version;\n }\n } catch {\n // ignore\n }\n return \"0.0.0\";\n}\n","export type ErrorCode =\n | \"INVALID_INPUT\"\n | \"MISSING_KEY\"\n | \"INVALID_URL\"\n | \"INVALID_REF\"\n | \"INVALID_PATH\"\n | \"NOT_IN_GIT\"\n | \"NOT_FOUND\"\n | \"TYPE_MISMATCH\"\n | \"SIZE_LIMIT\"\n | \"NETWORK\"\n | \"IO\";\n\nexport class CtxbinError extends Error {\n readonly code: ErrorCode;\n\n constructor(code: ErrorCode, message: string) {\n super(message);\n this.code = code;\n }\n}\n\nexport function fail(code: ErrorCode, message: string): never {\n throw new CtxbinError(code, message);\n}\n\nexport function formatError(err: unknown): string {\n if (err instanceof CtxbinError) {\n return `CTXBIN_ERR ${err.code}: ${err.message}`;\n }\n const message = err instanceof Error ? err.message : String(err);\n return `CTXBIN_ERR IO: ${message}`;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { fail } from \"./errors\";\n\nexport interface StoreConfig {\n url: string;\n token: string;\n}\n\nconst ENV_URL = \"CTXBIN_STORE_URL\";\nconst ENV_TOKEN = \"CTXBIN_STORE_TOKEN\";\n\nexport async function loadConfig(): Promise<StoreConfig> {\n const envUrl = process.env[ENV_URL];\n const envToken = process.env[ENV_TOKEN];\n\n if (envUrl || envToken) {\n if (!envUrl || !envToken) {\n return fail(\"INVALID_INPUT\", \"both CTXBIN_STORE_URL and CTXBIN_STORE_TOKEN must be set\");\n }\n return { url: envUrl, token: envToken };\n }\n\n const configPath = path.join(os.homedir(), \".ctxbin\", \"config.json\");\n let raw: string;\n try {\n raw = await fs.readFile(configPath, \"utf8\");\n } catch {\n return fail(\"INVALID_INPUT\", \"missing CTXBIN_STORE_URL/CTXBIN_STORE_TOKEN and no ~/.ctxbin/config.json. Create a Redis database at https://upstash.com and run `npx ctxbin init` to configure.\");\n }\n\n let parsed: any;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return fail(\"INVALID_INPUT\", \"invalid JSON in ~/.ctxbin/config.json\");\n }\n\n const url = parsed.store_url || parsed.storeUrl || parsed.url;\n const token = parsed.store_token || parsed.storeToken || parsed.token;\n if (!url || !token) {\n return fail(\"INVALID_INPUT\", \"config.json must include store_url and store_token\");\n }\n\n return { url, token };\n}\n\nexport async function writeConfig(config: StoreConfig): Promise<void> {\n const dir = path.join(os.homedir(), \".ctxbin\");\n const configPath = path.join(dir, \"config.json\");\n await fs.mkdir(dir, { recursive: true, mode: 0o700 });\n const payload = {\n store_url: config.url,\n store_token: config.token,\n };\n await fs.writeFile(configPath, JSON.stringify(payload, null, 2), \"utf8\");\n}\n","export const SKILLPACK_HEADER = \"ctxbin-skillpack@1\\n\";\nexport const SKILLREF_HEADER = \"ctxbin-skillref@1\\n\";\n\nexport const MAX_SKILLPACK_BYTES = 7 * 1024 * 1024;\nexport const MAX_SKILLREF_DOWNLOAD_BYTES = 20 * 1024 * 1024;\nexport const MAX_SKILLREF_EXTRACT_BYTES = 100 * 1024 * 1024;\nexport const MAX_SKILLREF_FILES = 5000;\n\nexport const SKILLREF_CONNECT_TIMEOUT_MS = 5000;\nexport const SKILLREF_DOWNLOAD_TIMEOUT_MS = 30000;\n\nexport const DEFAULT_EXCLUDES = [\".git\", \"node_modules\", \".DS_Store\"];\n\nexport const STORE_REQUEST_TIMEOUT_MS = 5000;\n","import { fail } from \"./errors\";\nimport { STORE_REQUEST_TIMEOUT_MS } from \"./constants\";\n\nexport interface Store {\n get(hash: string, field: string): Promise<string | null>;\n set(hash: string, field: string, value: string): Promise<void>;\n delete(hash: string, field: string): Promise<void>;\n list(hash: string): Promise<Array<{ field: string; value: string }>>;\n}\n\ninterface UpstashResponse<T> {\n result?: T;\n error?: string;\n}\n\nexport function createStore(url: string, token: string): Store {\n const baseUrl = url.replace(/\\/$/, \"\");\n\n async function command<T>(cmd: string, ...args: string[]): Promise<T> {\n let res: Response;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), STORE_REQUEST_TIMEOUT_MS);\n try {\n res = await fetch(baseUrl, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify([cmd, ...args]),\n signal: controller.signal,\n });\n } catch (err) {\n if (controller.signal.aborted) {\n return fail(\"NETWORK\", `store request timed out after ${STORE_REQUEST_TIMEOUT_MS}ms`);\n }\n return fail(\"NETWORK\", `store request failed: ${err instanceof Error ? err.message : String(err)}`);\n } finally {\n clearTimeout(timeout);\n }\n\n if (!res.ok) {\n const text = await res.text();\n return fail(\"NETWORK\", `store request failed (${res.status}): ${text}`);\n }\n\n let data: UpstashResponse<T>;\n try {\n data = (await res.json()) as UpstashResponse<T>;\n } catch {\n return fail(\"NETWORK\", \"store response was not valid JSON\");\n }\n\n if (data.error) {\n return fail(\"NETWORK\", data.error);\n }\n\n return data.result as T;\n }\n\n return {\n async get(hash, field) {\n const result = await command<string | null>(\"HGET\", hash, field);\n return result ?? null;\n },\n async set(hash, field, value) {\n await command<number>(\"HSET\", hash, field, value);\n },\n async delete(hash, field) {\n await command<number>(\"HDEL\", hash, field);\n },\n async list(hash) {\n const result = await command<unknown>(\"HGETALL\", hash);\n if (!result) return [];\n if (!Array.isArray(result)) {\n return fail(\"NETWORK\", \"store response for HGETALL was not an array\");\n }\n const pairs: Array<{ field: string; value: string }> = [];\n for (let i = 0; i < result.length; i += 2) {\n const field = result[i];\n const value = result[i + 1];\n if (typeof field !== \"string\" || typeof value !== \"string\") {\n return fail(\"NETWORK\", \"store response for HGETALL contained invalid entries\");\n }\n pairs.push({ field, value });\n }\n pairs.sort((a, b) => a.field.localeCompare(b.field));\n return pairs;\n },\n };\n}\n","import { execFile } from \"node:child_process\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { fail } from \"./errors\";\n\nconst execFileAsync = promisify(execFile);\n\nasync function git(args: string[]): Promise<string> {\n try {\n const { stdout } = await execFileAsync(\"git\", args, { encoding: \"utf8\" });\n return stdout.trim();\n } catch {\n return fail(\"NOT_IN_GIT\", \"not inside a git repository\");\n }\n}\n\nexport async function inferCtxKey(): Promise<string> {\n const root = await git([\"rev-parse\", \"--show-toplevel\"]);\n const branch = await git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n const project = path.basename(root);\n if (!project || !branch) {\n return fail(\"NOT_IN_GIT\", \"unable to infer ctx key from git repository\");\n }\n return `${project}/${branch}`;\n}\n","import fs from \"node:fs/promises\";\nimport { createWriteStream } from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport zlib from \"node:zlib\";\nimport { pipeline } from \"node:stream/promises\";\nimport tar from \"tar\";\nimport { DEFAULT_EXCLUDES, MAX_SKILLPACK_BYTES, SKILLPACK_HEADER } from \"./constants\";\nimport { fail } from \"./errors\";\nimport { ensureDir, copyDirContents } from \"./fs-ops\";\nimport { applyNormalizedPermissions } from \"./perm\";\nimport { assertSafeTarPath } from \"./validators\";\nimport { listTarEntries } from \"./tar-utils\";\n\nconst ALLOWED_TYPES = new Set([\"File\", \"Directory\"]);\n\nexport async function createSkillpackFromDir(dirPath: string): Promise<string> {\n const stats = await fs.stat(dirPath).catch(() => null);\n if (!stats || !stats.isDirectory()) {\n return fail(\"INVALID_INPUT\", `--dir is not a directory: ${dirPath}`);\n }\n\n const entries = await collectEntries(dirPath);\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), \"ctxbin-skillpack-\"));\n const tarPath = path.join(tmpDir, \"skillpack.tar.gz\");\n\n try {\n const tarStream = tar.c(\n {\n cwd: dirPath,\n portable: true,\n mtime: new Date(0),\n },\n entries\n );\n\n const gzip = zlib.createGzip({ mtime: 0 });\n await pipeline(tarStream, gzip, createWriteStream(tarPath));\n\n const stat = await fs.stat(tarPath);\n if (stat.size > MAX_SKILLPACK_BYTES) {\n return fail(\n \"SIZE_LIMIT\",\n `skillpack tar.gz size ${stat.size} bytes exceeds ${MAX_SKILLPACK_BYTES} bytes`\n );\n }\n\n const data = await fs.readFile(tarPath);\n const b64 = data.toString(\"base64\");\n return SKILLPACK_HEADER + b64;\n } finally {\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n}\n\nexport async function extractSkillpackToDir(value: string, targetDir: string): Promise<void> {\n const base64 = value.slice(SKILLPACK_HEADER.length);\n let buffer: Buffer;\n try {\n buffer = Buffer.from(base64, \"base64\");\n } catch {\n return fail(\"IO\", \"invalid skillpack base64 data\");\n }\n\n const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"ctxbin-skillpack-\"));\n const tarPath = path.join(tmpRoot, \"skillpack.tar.gz\");\n await fs.writeFile(tarPath, buffer);\n\n try {\n const entries = await listTarEntries(tarPath);\n const execSet = validateTarEntries(entries);\n\n const extractDir = path.join(tmpRoot, \"extract\");\n await ensureDir(extractDir);\n await tar.x({\n file: tarPath,\n cwd: extractDir,\n preserveOwner: false,\n noMtime: true,\n });\n\n await applyNormalizedPermissions(extractDir, execSet);\n await ensureDir(targetDir);\n await copyDirContents(extractDir, targetDir);\n } finally {\n await fs.rm(tmpRoot, { recursive: true, force: true });\n }\n}\n\nasync function collectEntries(root: string): Promise<string[]> {\n const results: string[] = [];\n\n async function walk(absDir: string, relDir: string): Promise<void> {\n const entries = await fs.readdir(absDir, { withFileTypes: true });\n entries.sort((a, b) => a.name.localeCompare(b.name));\n\n for (const entry of entries) {\n if (DEFAULT_EXCLUDES.includes(entry.name)) {\n if (entry.isDirectory()) {\n continue;\n }\n if (entry.isFile() && entry.name === \".DS_Store\") {\n continue;\n }\n }\n\n const absPath = path.join(absDir, entry.name);\n const relPath = relDir ? path.posix.join(relDir, entry.name) : entry.name;\n const stat = await fs.lstat(absPath);\n if (stat.isSymbolicLink()) {\n return fail(\"IO\", `symlink not allowed in skillpack: ${absPath}`);\n }\n\n if (entry.isDirectory()) {\n results.push(relPath);\n await walk(absPath, relPath);\n continue;\n }\n\n if (entry.isFile()) {\n if (entry.name === \".DS_Store\") {\n continue;\n }\n results.push(relPath);\n continue;\n }\n\n return fail(\"IO\", `unsupported file type in skillpack: ${absPath}`);\n }\n }\n\n await walk(root, \"\");\n results.sort();\n return results;\n}\n\nfunction validateTarEntries(entries: { path: string; type: string; mode: number }[]): Set<string> {\n const execSet = new Set<string>();\n for (const entry of entries) {\n assertSafeTarPath(entry.path);\n if (!ALLOWED_TYPES.has(entry.type)) {\n return fail(\"IO\", `unsupported entry type in skillpack: ${entry.path}`);\n }\n if (entry.type === \"File\" && (entry.mode & 0o111)) {\n execSet.add(entry.path);\n }\n }\n return execSet;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fail } from \"./errors\";\nimport { safeChmod } from \"./chmod\";\n\nexport async function ensureDir(dir: string): Promise<void> {\n await fs.mkdir(dir, { recursive: true });\n}\n\nexport function toPosix(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n\nexport async function copyDirContents(src: string, dest: string): Promise<void> {\n await ensureDir(dest);\n const entries = await fs.readdir(src, { withFileTypes: true });\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name);\n const destPath = path.join(dest, entry.name);\n if (entry.isDirectory()) {\n await copyDirContents(srcPath, destPath);\n const stat = await fs.stat(srcPath);\n await safeChmod(destPath, stat.mode & 0o777);\n continue;\n }\n if (entry.isFile()) {\n await ensureDir(path.dirname(destPath));\n await fs.copyFile(srcPath, destPath);\n const stat = await fs.stat(srcPath);\n await safeChmod(destPath, stat.mode & 0o777);\n continue;\n }\n return fail(\"IO\", `unsupported file type during copy: ${srcPath}`);\n }\n}\n","import fs from \"node:fs/promises\";\n\nexport async function safeChmod(path: string, mode: number): Promise<void> {\n try {\n await fs.chmod(path, mode);\n } catch (err) {\n if (process.platform === \"win32\") {\n return;\n }\n throw err;\n }\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fail } from \"./errors\";\nimport { toPosix } from \"./fs-ops\";\nimport { safeChmod } from \"./chmod\";\n\nexport async function applyNormalizedPermissions(root: string, execSet: Set<string>): Promise<void> {\n async function walk(absDir: string): Promise<void> {\n const entries = await fs.readdir(absDir, { withFileTypes: true });\n for (const entry of entries) {\n const absPath = path.join(absDir, entry.name);\n if (entry.isDirectory()) {\n await safeChmod(absPath, 0o755);\n await walk(absPath);\n continue;\n }\n if (entry.isFile()) {\n const rel = toPosix(path.relative(root, absPath));\n const mode = execSet.has(rel) ? 0o755 : 0o644;\n await safeChmod(absPath, mode);\n continue;\n }\n return fail(\"IO\", `unsupported file type after extract: ${absPath}`);\n }\n }\n\n await walk(root);\n}\n","import path from \"node:path\";\nimport { fail } from \"./errors\";\n\nexport function normalizeGithubUrl(input: string): string {\n let url: URL;\n try {\n url = new URL(input);\n } catch {\n return fail(\"INVALID_URL\", \"invalid URL\");\n }\n\n if (url.protocol !== \"https:\") {\n return fail(\"INVALID_URL\", \"URL must use https\");\n }\n if (url.hostname !== \"github.com\") {\n return fail(\"INVALID_URL\", \"only github.com is supported\");\n }\n if (url.search || url.hash) {\n return fail(\"INVALID_URL\", \"URL must not include query or hash\");\n }\n\n const parts = url.pathname.split(\"/\").filter(Boolean);\n if (parts.length !== 2) {\n return fail(\"INVALID_URL\", \"URL must be https://github.com/<owner>/<repo>\");\n }\n const owner = parts[0];\n let repo = parts[1];\n if (repo.endsWith(\".git\")) {\n repo = repo.slice(0, -4);\n }\n if (!owner || !repo) {\n return fail(\"INVALID_URL\", \"URL must be https://github.com/<owner>/<repo>\");\n }\n\n return `https://github.com/${owner}/${repo}`;\n}\n\nexport function validateCommitSha(ref: string): string {\n if (!/^[0-9a-f]{40}$/.test(ref)) {\n return fail(\"INVALID_REF\", \"ref must be a 40-hex commit SHA\");\n }\n return ref;\n}\n\nexport function normalizeSkillPath(input: string): string {\n const trimmed = input.trim();\n if (!trimmed) {\n return fail(\"INVALID_PATH\", \"path must be a non-empty directory path\");\n }\n const cleaned = trimmed.replace(/\\\\/g, \"/\");\n if (cleaned.startsWith(\"/\")) {\n return fail(\"INVALID_PATH\", \"path must be relative, not absolute\");\n }\n const normalized = path.posix.normalize(cleaned).replace(/^\\.\\//, \"\");\n if (normalized === \".\" || normalized === \"\") {\n return fail(\"INVALID_PATH\", \"path must be a non-empty directory path\");\n }\n if (normalized.startsWith(\"../\") || normalized.includes(\"/../\") || normalized === \"..\") {\n return fail(\"INVALID_PATH\", \"path must not include .. segments\");\n }\n if (normalized.endsWith(\"/\")) {\n return normalized.slice(0, -1);\n }\n return normalized;\n}\n\nexport function assertSafeTarPath(entryPath: string): void {\n const cleaned = entryPath.replace(/\\\\/g, \"/\");\n if (cleaned.startsWith(\"/\")) {\n return fail(\"INVALID_PATH\", `tar entry path must be relative: ${entryPath}`);\n }\n const normalized = path.posix.normalize(cleaned);\n if (normalized.startsWith(\"../\") || normalized === \"..\" || normalized.includes(\"/../\")) {\n return fail(\"INVALID_PATH\", `tar entry path contains traversal: ${entryPath}`);\n }\n}\n","import tar from \"tar\";\n\nexport interface TarEntryInfo {\n path: string;\n type: string;\n size: number;\n mode: number;\n}\n\nexport async function listTarEntries(file: string): Promise<TarEntryInfo[]> {\n const entries: TarEntryInfo[] = [];\n await tar.t({\n file,\n onentry(entry) {\n entries.push({\n path: entry.path,\n type: entry.type,\n size: entry.size ?? 0,\n mode: entry.mode ?? 0,\n });\n },\n });\n return entries;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { createWriteStream } from \"node:fs\";\nimport { SKILLREF_HEADER, MAX_SKILLREF_DOWNLOAD_BYTES, MAX_SKILLREF_EXTRACT_BYTES, MAX_SKILLREF_FILES, SKILLREF_CONNECT_TIMEOUT_MS, SKILLREF_DOWNLOAD_TIMEOUT_MS } from \"./constants\";\nimport { fail, CtxbinError } from \"./errors\";\nimport { normalizeGithubUrl, normalizeSkillPath, validateCommitSha, assertSafeTarPath } from \"./validators\";\nimport { listTarEntries, TarEntryInfo } from \"./tar-utils\";\nimport tar from \"tar\";\nimport { ensureDir, copyDirContents } from \"./fs-ops\";\nimport { applyNormalizedPermissions } from \"./perm\";\n\nconst ALLOWED_TYPES = new Set([\"File\", \"Directory\"]);\n\nexport interface Skillref {\n url: string;\n path: string;\n ref?: string;\n track?: \"default\";\n}\n\nexport function createSkillrefValue(url: string, skillPath: string, ref?: string): string {\n const normalizedUrl = normalizeGithubUrl(url);\n const normalizedPath = normalizeSkillPath(skillPath);\n const payload = ref\n ? JSON.stringify({ url: normalizedUrl, path: normalizedPath, ref: validateCommitSha(ref) })\n : JSON.stringify({ url: normalizedUrl, path: normalizedPath, track: \"default\" });\n return SKILLREF_HEADER + payload;\n}\n\nexport function parseSkillrefValue(value: string): Skillref {\n if (!value.startsWith(SKILLREF_HEADER)) {\n return fail(\"TYPE_MISMATCH\", \"value is not a skillref\");\n }\n const raw = value.slice(SKILLREF_HEADER.length);\n let parsed: any;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return fail(\"IO\", \"invalid skillref payload JSON\");\n }\n if (!parsed || typeof parsed.url !== \"string\" || typeof parsed.path !== \"string\") {\n return fail(\"IO\", \"invalid skillref payload fields\");\n }\n const normalized = {\n url: normalizeGithubUrl(parsed.url),\n path: normalizeSkillPath(parsed.path),\n } satisfies Pick<Skillref, \"url\" | \"path\">;\n\n if (typeof parsed.ref === \"string\") {\n return { ...normalized, ref: validateCommitSha(parsed.ref) };\n }\n\n if (parsed.track === \"default\") {\n return { ...normalized, track: \"default\" };\n }\n\n return fail(\"IO\", \"invalid skillref payload fields\");\n}\n\nexport async function loadSkillrefToDir(value: string, targetDir: string): Promise<void> {\n const skillref = parseSkillrefValue(value);\n const resolvedRef = skillref.ref ?? (await fetchDefaultBranch(skillref.url));\n const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"ctxbin-skillref-\"));\n const tarPath = path.join(tmpRoot, \"skillref.tar.gz\");\n\n try {\n await downloadArchive(skillref.url, resolvedRef, tarPath);\n\n const entries = await listTarEntries(tarPath).catch(() => fail(\"IO\", \"failed to parse tar archive\"));\n const analysis = analyzeEntries(entries, skillref.path);\n\n const extractDir = path.join(tmpRoot, \"extract\");\n await ensureDir(extractDir);\n\n const stripCount = 1 + skillref.path.split(\"/\").length;\n await tar.x({\n file: tarPath,\n cwd: extractDir,\n preserveOwner: false,\n noMtime: true,\n strip: stripCount,\n filter: (p, entry) => {\n const entryPath = entry?.path ?? p;\n return isUnderPath(entryPath, analysis.prefix, skillref.path);\n },\n });\n\n await applyNormalizedPermissions(extractDir, analysis.execSet);\n await ensureDir(targetDir);\n await copyDirContents(extractDir, targetDir);\n } finally {\n await fs.rm(tmpRoot, { recursive: true, force: true });\n }\n}\n\nasync function downloadArchive(repoUrl: string, ref: string, outPath: string): Promise<void> {\n const { owner, repo } = splitGithubUrl(repoUrl);\n const url = `https://codeload.github.com/${owner}/${repo}/tar.gz/${ref}`;\n const controller = new AbortController();\n const totalTimer = setTimeout(() => controller.abort(), SKILLREF_DOWNLOAD_TIMEOUT_MS);\n let res: Response;\n try {\n res = await fetchWithRedirect(url, 1, controller, [\"github.com\", \"codeload.github.com\"]);\n } catch (err) {\n clearTimeout(totalTimer);\n return fail(\"NETWORK\", `download failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n if (!res.ok) {\n clearTimeout(totalTimer);\n const text = await res.text();\n return fail(\"NETWORK\", `download failed (${res.status}): ${text}`);\n }\n if (!res.body) {\n clearTimeout(totalTimer);\n return fail(\"NETWORK\", \"download failed: empty response body\");\n }\n\n const fileStream = createWriteStream(outPath);\n let total = 0;\n let magic = Buffer.alloc(0);\n\n try {\n for await (const chunk of res.body as AsyncIterable<Buffer>) {\n if (magic.length < 2) {\n const needed = 2 - magic.length;\n magic = Buffer.concat([magic, chunk.subarray(0, needed)]);\n if (magic.length === 2) {\n if (magic[0] !== 0x1f || magic[1] !== 0x8b) {\n fileStream.close();\n controller.abort();\n return fail(\"IO\", \"downloaded file is not gzip data\");\n }\n }\n }\n\n total += chunk.length;\n if (total > MAX_SKILLREF_DOWNLOAD_BYTES) {\n fileStream.close();\n controller.abort();\n return fail(\n \"SIZE_LIMIT\",\n `downloaded archive size ${total} exceeds ${MAX_SKILLREF_DOWNLOAD_BYTES} bytes`\n );\n }\n\n fileStream.write(chunk);\n }\n } catch (err) {\n fileStream.close();\n clearTimeout(totalTimer);\n if (err instanceof CtxbinError) {\n throw err;\n }\n return fail(\"NETWORK\", `download failed: ${err instanceof Error ? err.message : String(err)}`);\n } finally {\n clearTimeout(totalTimer);\n }\n\n if (magic.length < 2) {\n fileStream.close();\n return fail(\"IO\", \"downloaded file is incomplete\");\n }\n\n await new Promise<void>((resolve, reject) => {\n fileStream.end(() => resolve());\n fileStream.on(\"error\", reject);\n });\n}\n\nasync function fetchWithRedirect(\n url: string,\n redirectsLeft: number,\n controller: AbortController,\n allowedHosts: string[],\n init?: RequestInit\n): Promise<Response> {\n const connectTimer = setTimeout(() => controller.abort(), SKILLREF_CONNECT_TIMEOUT_MS);\n\n const res = await fetch(url, {\n ...init,\n signal: controller.signal,\n redirect: \"manual\",\n });\n\n clearTimeout(connectTimer);\n\n if (isRedirect(res.status)) {\n if (redirectsLeft <= 0) {\n return fail(\"NETWORK\", \"too many redirects\");\n }\n const location = res.headers.get(\"location\");\n if (!location) {\n return fail(\"NETWORK\", \"redirect without location header\");\n }\n const nextUrl = new URL(location, url).toString();\n const host = new URL(nextUrl).hostname;\n if (!allowedHosts.includes(host)) {\n return fail(\"NETWORK\", `redirected to unsupported host: ${host}`);\n }\n return fetchWithRedirect(nextUrl, redirectsLeft - 1, controller, allowedHosts, init);\n }\n\n return res;\n}\n\nfunction isRedirect(status: number): boolean {\n return [301, 302, 303, 307, 308].includes(status);\n}\n\nfunction splitGithubUrl(repoUrl: string): { owner: string; repo: string } {\n const url = new URL(repoUrl);\n const parts = url.pathname.split(\"/\").filter(Boolean);\n if (parts.length !== 2) {\n return fail(\"INVALID_URL\", \"URL must be https://github.com/<owner>/<repo>\");\n }\n return { owner: parts[0], repo: parts[1] };\n}\n\nasync function fetchDefaultBranch(repoUrl: string): Promise<string> {\n const { owner, repo } = splitGithubUrl(repoUrl);\n const url = `https://api.github.com/repos/${owner}/${repo}`;\n const controller = new AbortController();\n const totalTimer = setTimeout(() => controller.abort(), SKILLREF_DOWNLOAD_TIMEOUT_MS);\n let res: Response;\n try {\n res = await fetchWithRedirect(url, 1, controller, [\"github.com\", \"api.github.com\"], {\n headers: {\n \"User-Agent\": \"ctxbin\",\n Accept: \"application/vnd.github+json\",\n },\n });\n } catch (err) {\n clearTimeout(totalTimer);\n return fail(\"NETWORK\", `default branch lookup failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n if (!res.ok) {\n clearTimeout(totalTimer);\n const text = await res.text();\n return fail(\"NETWORK\", `default branch lookup failed (${res.status}): ${text}`);\n }\n\n let data: any;\n try {\n data = await res.json();\n } catch {\n clearTimeout(totalTimer);\n return fail(\"NETWORK\", \"default branch lookup returned invalid JSON\");\n }\n\n clearTimeout(totalTimer);\n if (!data || typeof data.default_branch !== \"string\" || data.default_branch.length === 0) {\n return fail(\"NETWORK\", \"default branch lookup returned no default_branch\");\n }\n return data.default_branch;\n}\n\nfunction analyzeEntries(entries: TarEntryInfo[], requestedPath: string): {\n prefix: string;\n execSet: Set<string>;\n} {\n if (entries.length === 0) {\n return fail(\"NOT_FOUND\", \"archive contained no entries\");\n }\n\n const prefix = entries[0].path.split(\"/\")[0];\n if (!prefix) {\n return fail(\"IO\", \"unable to determine archive prefix\");\n }\n\n const execSet = new Set<string>();\n let entryCount = 0;\n let totalSize = 0;\n let matched = false;\n\n for (const entry of entries) {\n assertSafeTarPath(entry.path);\n if (!ALLOWED_TYPES.has(entry.type)) {\n return fail(\"IO\", `unsupported entry type in archive: ${entry.path}`);\n }\n\n if (entry.path === prefix) {\n continue;\n }\n if (!entry.path.startsWith(`${prefix}/`)) {\n return fail(\"IO\", \"archive has unexpected top-level layout\");\n }\n\n const rel = entry.path.slice(prefix.length + 1);\n if (!rel) {\n continue;\n }\n\n const relToReq = stripRequestedPath(rel, requestedPath);\n if (relToReq === null) {\n continue;\n }\n\n matched = true;\n entryCount += 1;\n if (rel === requestedPath && entry.type === \"File\") {\n return fail(\"INVALID_PATH\", \"requested path is not a directory\");\n }\n if (entry.type === \"File\") {\n totalSize += entry.size ?? 0;\n if (entry.mode & 0o111) {\n execSet.add(relToReq);\n }\n }\n }\n\n if (!matched) {\n return fail(\"NOT_FOUND\", \"requested path not found in archive\");\n }\n if (entryCount > MAX_SKILLREF_FILES) {\n return fail(\"SIZE_LIMIT\", `extracted entry count ${entryCount} exceeds ${MAX_SKILLREF_FILES}`);\n }\n if (totalSize > MAX_SKILLREF_EXTRACT_BYTES) {\n return fail(\"SIZE_LIMIT\", `extracted size ${totalSize} exceeds ${MAX_SKILLREF_EXTRACT_BYTES}`);\n }\n\n return { prefix, execSet };\n}\n\nfunction stripRequestedPath(rel: string, requestedPath: string): string | null {\n if (rel === requestedPath) {\n return \"\";\n }\n const prefix = requestedPath + \"/\";\n if (rel.startsWith(prefix)) {\n return rel.slice(prefix.length);\n }\n return null;\n}\n\nfunction isUnderPath(entryPath: string, prefix: string, requestedPath: string): boolean {\n if (entryPath === prefix) {\n return false;\n }\n if (!entryPath.startsWith(`${prefix}/`)) {\n return false;\n }\n const rel = entryPath.slice(prefix.length + 1);\n if (!rel) {\n return false;\n }\n if (rel === requestedPath || rel.startsWith(requestedPath + \"/\")) {\n return true;\n }\n return false;\n}\n","import { SKILLPACK_HEADER, SKILLREF_HEADER } from \"./constants\";\n\nexport type SkillValueType = \"skillpack\" | \"skillref\" | \"string\";\n\nexport function detectSkillValueType(value: string): SkillValueType {\n if (value.startsWith(SKILLPACK_HEADER)) return \"skillpack\";\n if (value.startsWith(SKILLREF_HEADER)) return \"skillref\";\n return \"string\";\n}\n","import fs from \"node:fs/promises\";\nimport process from \"node:process\";\nimport { fail } from \"./errors\";\nimport { createSkillpackFromDir } from \"./skillpack\";\nimport { createSkillrefValue } from \"./skillref\";\n\nexport type SaveInput = { kind: \"string\" | \"skillpack\" | \"skillref\"; value: string };\n\nexport interface SaveOptions {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n}\n\nexport async function resolveSaveInput(\n resource: string,\n opts: SaveOptions,\n stdinIsTTY: boolean = Boolean(process.stdin.isTTY)\n): Promise<SaveInput> {\n const hasFile = typeof opts.file === \"string\";\n const hasValue = typeof opts.value === \"string\";\n const hasDir = typeof opts.dir === \"string\";\n const urlFlagsUsed = Boolean(opts.url || opts.ref || opts.path);\n const hasUrl = Boolean(opts.url && opts.path);\n const explicitCount = [hasFile, hasValue, hasDir, hasUrl].filter(Boolean).length;\n const hasStdin = !stdinIsTTY && explicitCount === 0;\n\n if (urlFlagsUsed && !hasUrl) {\n return fail(\"INVALID_INPUT\", \"--url and --path must be provided together\");\n }\n\n const methods = explicitCount + (hasStdin ? 1 : 0);\n if (methods !== 1) {\n return fail(\"INVALID_INPUT\", \"exactly one input method must be used\");\n }\n\n if (hasDir && resource !== \"skill\") {\n return fail(\"INVALID_INPUT\", \"--dir is only valid for skill save\");\n }\n if (hasUrl && resource !== \"skill\") {\n return fail(\"INVALID_INPUT\", \"--url/--ref/--path are only valid for skill save\");\n }\n if (opts.append && (hasDir || hasUrl)) {\n return fail(\"INVALID_INPUT\", \"--append cannot be used with --dir or --url\");\n }\n\n if (hasDir) {\n const value = await createSkillpackFromDir(opts.dir as string);\n return { kind: \"skillpack\", value };\n }\n\n if (hasUrl) {\n const value = createSkillrefValue(opts.url as string, opts.path as string, opts.ref as string | undefined);\n return { kind: \"skillref\", value };\n }\n\n if (hasFile) {\n const content = await fs.readFile(opts.file as string, \"utf8\");\n return { kind: \"string\", value: content };\n }\n\n if (hasValue) {\n return { kind: \"string\", value: opts.value as string };\n }\n\n const stdin = await readStdin();\n return { kind: \"string\", value: stdin };\n}\n\nasync function readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n let data = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk) => {\n data += chunk;\n });\n process.stdin.on(\"end\", () => resolve(data));\n process.stdin.on(\"error\", reject);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,IAAAA,oBAA0B;AAC1B,IAAAC,uBAAoB;AACpB,IAAAC,oBAAiB;AACjB,IAAAC,mBAAe;AACf,IAAAC,kBAA6B;;;ACStB,IAAM,cAAN,cAA0B,MAAM;AAAA,EAC5B;AAAA,EAET,YAAY,MAAiB,SAAiB;AAC5C,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAEO,SAAS,KAAK,MAAiB,SAAwB;AAC5D,QAAM,IAAI,YAAY,MAAM,OAAO;AACrC;AAEO,SAAS,YAAY,KAAsB;AAChD,MAAI,eAAe,aAAa;AAC9B,WAAO,cAAc,IAAI,IAAI,KAAK,IAAI,OAAO;AAAA,EAC/C;AACA,QAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,SAAO,kBAAkB,OAAO;AAClC;;;AChCA,sBAAe;AACf,uBAAiB;AACjB,qBAAe;AAQf,IAAM,UAAU;AAChB,IAAM,YAAY;AAElB,eAAsB,aAAmC;AACvD,QAAM,SAAS,QAAQ,IAAI,OAAO;AAClC,QAAM,WAAW,QAAQ,IAAI,SAAS;AAEtC,MAAI,UAAU,UAAU;AACtB,QAAI,CAAC,UAAU,CAAC,UAAU;AACxB,aAAO,KAAK,iBAAiB,0DAA0D;AAAA,IACzF;AACA,WAAO,EAAE,KAAK,QAAQ,OAAO,SAAS;AAAA,EACxC;AAEA,QAAM,aAAa,iBAAAC,QAAK,KAAK,eAAAC,QAAG,QAAQ,GAAG,WAAW,aAAa;AACnE,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,gBAAAC,QAAG,SAAS,YAAY,MAAM;AAAA,EAC5C,QAAQ;AACN,WAAO,KAAK,iBAAiB,kKAAkK;AAAA,EACjM;AAEA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,QAAQ;AACN,WAAO,KAAK,iBAAiB,uCAAuC;AAAA,EACtE;AAEA,QAAM,MAAM,OAAO,aAAa,OAAO,YAAY,OAAO;AAC1D,QAAM,QAAQ,OAAO,eAAe,OAAO,cAAc,OAAO;AAChE,MAAI,CAAC,OAAO,CAAC,OAAO;AAClB,WAAO,KAAK,iBAAiB,oDAAoD;AAAA,EACnF;AAEA,SAAO,EAAE,KAAK,MAAM;AACtB;AAEA,eAAsB,YAAY,QAAoC;AACpE,QAAM,MAAM,iBAAAF,QAAK,KAAK,eAAAC,QAAG,QAAQ,GAAG,SAAS;AAC7C,QAAM,aAAa,iBAAAD,QAAK,KAAK,KAAK,aAAa;AAC/C,QAAM,gBAAAE,QAAG,MAAM,KAAK,EAAE,WAAW,MAAM,MAAM,IAAM,CAAC;AACpD,QAAM,UAAU;AAAA,IACd,WAAW,OAAO;AAAA,IAClB,aAAa,OAAO;AAAA,EACtB;AACA,QAAM,gBAAAA,QAAG,UAAU,YAAY,KAAK,UAAU,SAAS,MAAM,CAAC,GAAG,MAAM;AACzE;;;ACzDO,IAAM,mBAAmB;AACzB,IAAM,kBAAkB;AAExB,IAAM,sBAAsB,IAAI,OAAO;AACvC,IAAM,8BAA8B,KAAK,OAAO;AAChD,IAAM,6BAA6B,MAAM,OAAO;AAChD,IAAM,qBAAqB;AAE3B,IAAM,8BAA8B;AACpC,IAAM,+BAA+B;AAErC,IAAM,mBAAmB,CAAC,QAAQ,gBAAgB,WAAW;AAE7D,IAAM,2BAA2B;;;ACEjC,SAAS,YAAY,KAAa,OAAsB;AAC7D,QAAM,UAAU,IAAI,QAAQ,OAAO,EAAE;AAErC,iBAAe,QAAW,QAAgB,MAA4B;AACpE,QAAI;AACJ,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,wBAAwB;AAC7E,QAAI;AACF,YAAM,MAAM,MAAM,SAAS;AAAA,QACzB,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,eAAe,UAAU,KAAK;AAAA,UAC9B,gBAAgB;AAAA,QAClB;AAAA,QACA,MAAM,KAAK,UAAU,CAAC,KAAK,GAAG,IAAI,CAAC;AAAA,QACnC,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,UAAI,WAAW,OAAO,SAAS;AAC7B,eAAO,KAAK,WAAW,iCAAiC,wBAAwB,IAAI;AAAA,MACtF;AACA,aAAO,KAAK,WAAW,yBAAyB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,IACpG,UAAE;AACA,mBAAa,OAAO;AAAA,IACtB;AAEA,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,aAAO,KAAK,WAAW,yBAAyB,IAAI,MAAM,MAAM,IAAI,EAAE;AAAA,IACxE;AAEA,QAAI;AACJ,QAAI;AACF,aAAQ,MAAM,IAAI,KAAK;AAAA,IACzB,QAAQ;AACN,aAAO,KAAK,WAAW,mCAAmC;AAAA,IAC5D;AAEA,QAAI,KAAK,OAAO;AACd,aAAO,KAAK,WAAW,KAAK,KAAK;AAAA,IACnC;AAEA,WAAO,KAAK;AAAA,EACd;AAEA,SAAO;AAAA,IACL,MAAM,IAAI,MAAM,OAAO;AACrB,YAAM,SAAS,MAAM,QAAuB,QAAQ,MAAM,KAAK;AAC/D,aAAO,UAAU;AAAA,IACnB;AAAA,IACA,MAAM,IAAI,MAAM,OAAO,OAAO;AAC5B,YAAM,QAAgB,QAAQ,MAAM,OAAO,KAAK;AAAA,IAClD;AAAA,IACA,MAAM,OAAO,MAAM,OAAO;AACxB,YAAM,QAAgB,QAAQ,MAAM,KAAK;AAAA,IAC3C;AAAA,IACA,MAAM,KAAK,MAAM;AACf,YAAM,SAAS,MAAM,QAAiB,WAAW,IAAI;AACrD,UAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,UAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,eAAO,KAAK,WAAW,6CAA6C;AAAA,MACtE;AACA,YAAM,QAAiD,CAAC;AACxD,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;AACzC,cAAM,QAAQ,OAAO,CAAC;AACtB,cAAM,QAAQ,OAAO,IAAI,CAAC;AAC1B,YAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;AAC1D,iBAAO,KAAK,WAAW,sDAAsD;AAAA,QAC/E;AACA,cAAM,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,MAC7B;AACA,YAAM,KAAK,CAAC,GAAG,MAAM,EAAE,MAAM,cAAc,EAAE,KAAK,CAAC;AACnD,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC1FA,gCAAyB;AACzB,IAAAC,oBAAiB;AACjB,uBAA0B;AAG1B,IAAM,oBAAgB,4BAAU,kCAAQ;AAExC,eAAe,IAAI,MAAiC;AAClD,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,cAAc,OAAO,MAAM,EAAE,UAAU,OAAO,CAAC;AACxE,WAAO,OAAO,KAAK;AAAA,EACrB,QAAQ;AACN,WAAO,KAAK,cAAc,6BAA6B;AAAA,EACzD;AACF;AAEA,eAAsB,cAA+B;AACnD,QAAM,OAAO,MAAM,IAAI,CAAC,aAAa,iBAAiB,CAAC;AACvD,QAAM,SAAS,MAAM,IAAI,CAAC,aAAa,gBAAgB,MAAM,CAAC;AAC9D,QAAM,UAAU,kBAAAC,QAAK,SAAS,IAAI;AAClC,MAAI,CAAC,WAAW,CAAC,QAAQ;AACvB,WAAO,KAAK,cAAc,6CAA6C;AAAA,EACzE;AACA,SAAO,GAAG,OAAO,IAAI,MAAM;AAC7B;;;ACxBA,IAAAC,mBAAe;AACf,qBAAkC;AAClC,IAAAC,oBAAiB;AACjB,IAAAC,kBAAe;AACf,uBAAiB;AACjB,IAAAF,mBAAyB;AACzB,IAAAG,cAAgB;;;ACNhB,IAAAC,mBAAe;AACf,IAAAC,oBAAiB;;;ACDjB,IAAAC,mBAAe;AAEf,eAAsB,UAAUC,OAAc,MAA6B;AACzE,MAAI;AACF,UAAM,iBAAAC,QAAG,MAAMD,OAAM,IAAI;AAAA,EAC3B,SAAS,KAAK;AACZ,QAAI,QAAQ,aAAa,SAAS;AAChC;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;;;ADNA,eAAsB,UAAU,KAA4B;AAC1D,QAAM,iBAAAE,QAAG,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACzC;AAEO,SAAS,QAAQ,GAAmB;AACzC,SAAO,EAAE,MAAM,kBAAAC,QAAK,GAAG,EAAE,KAAK,GAAG;AACnC;AAEA,eAAsB,gBAAgB,KAAa,MAA6B;AAC9E,QAAM,UAAU,IAAI;AACpB,QAAM,UAAU,MAAM,iBAAAD,QAAG,QAAQ,KAAK,EAAE,eAAe,KAAK,CAAC;AAC7D,aAAW,SAAS,SAAS;AAC3B,UAAM,UAAU,kBAAAC,QAAK,KAAK,KAAK,MAAM,IAAI;AACzC,UAAM,WAAW,kBAAAA,QAAK,KAAK,MAAM,MAAM,IAAI;AAC3C,QAAI,MAAM,YAAY,GAAG;AACvB,YAAM,gBAAgB,SAAS,QAAQ;AACvC,YAAM,OAAO,MAAM,iBAAAD,QAAG,KAAK,OAAO;AAClC,YAAM,UAAU,UAAU,KAAK,OAAO,GAAK;AAC3C;AAAA,IACF;AACA,QAAI,MAAM,OAAO,GAAG;AAClB,YAAM,UAAU,kBAAAC,QAAK,QAAQ,QAAQ,CAAC;AACtC,YAAM,iBAAAD,QAAG,SAAS,SAAS,QAAQ;AACnC,YAAM,OAAO,MAAM,iBAAAA,QAAG,KAAK,OAAO;AAClC,YAAM,UAAU,UAAU,KAAK,OAAO,GAAK;AAC3C;AAAA,IACF;AACA,WAAO,KAAK,MAAM,sCAAsC,OAAO,EAAE;AAAA,EACnE;AACF;;;AElCA,IAAAE,mBAAe;AACf,IAAAC,oBAAiB;AAKjB,eAAsB,2BAA2B,MAAc,SAAqC;AAClG,iBAAe,KAAK,QAA+B;AACjD,UAAM,UAAU,MAAM,iBAAAC,QAAG,QAAQ,QAAQ,EAAE,eAAe,KAAK,CAAC;AAChE,eAAW,SAAS,SAAS;AAC3B,YAAM,UAAU,kBAAAC,QAAK,KAAK,QAAQ,MAAM,IAAI;AAC5C,UAAI,MAAM,YAAY,GAAG;AACvB,cAAM,UAAU,SAAS,GAAK;AAC9B,cAAM,KAAK,OAAO;AAClB;AAAA,MACF;AACA,UAAI,MAAM,OAAO,GAAG;AAClB,cAAM,MAAM,QAAQ,kBAAAA,QAAK,SAAS,MAAM,OAAO,CAAC;AAChD,cAAM,OAAO,QAAQ,IAAI,GAAG,IAAI,MAAQ;AACxC,cAAM,UAAU,SAAS,IAAI;AAC7B;AAAA,MACF;AACA,aAAO,KAAK,MAAM,wCAAwC,OAAO,EAAE;AAAA,IACrE;AAAA,EACF;AAEA,QAAM,KAAK,IAAI;AACjB;;;AC3BA,IAAAC,oBAAiB;AAGV,SAAS,mBAAmB,OAAuB;AACxD,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,IAAI,KAAK;AAAA,EACrB,QAAQ;AACN,WAAO,KAAK,eAAe,aAAa;AAAA,EAC1C;AAEA,MAAI,IAAI,aAAa,UAAU;AAC7B,WAAO,KAAK,eAAe,oBAAoB;AAAA,EACjD;AACA,MAAI,IAAI,aAAa,cAAc;AACjC,WAAO,KAAK,eAAe,8BAA8B;AAAA,EAC3D;AACA,MAAI,IAAI,UAAU,IAAI,MAAM;AAC1B,WAAO,KAAK,eAAe,oCAAoC;AAAA,EACjE;AAEA,QAAM,QAAQ,IAAI,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AACpD,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,KAAK,eAAe,+CAA+C;AAAA,EAC5E;AACA,QAAM,QAAQ,MAAM,CAAC;AACrB,MAAI,OAAO,MAAM,CAAC;AAClB,MAAI,KAAK,SAAS,MAAM,GAAG;AACzB,WAAO,KAAK,MAAM,GAAG,EAAE;AAAA,EACzB;AACA,MAAI,CAAC,SAAS,CAAC,MAAM;AACnB,WAAO,KAAK,eAAe,+CAA+C;AAAA,EAC5E;AAEA,SAAO,sBAAsB,KAAK,IAAI,IAAI;AAC5C;AAEO,SAAS,kBAAkB,KAAqB;AACrD,MAAI,CAAC,iBAAiB,KAAK,GAAG,GAAG;AAC/B,WAAO,KAAK,eAAe,iCAAiC;AAAA,EAC9D;AACA,SAAO;AACT;AAEO,SAAS,mBAAmB,OAAuB;AACxD,QAAM,UAAU,MAAM,KAAK;AAC3B,MAAI,CAAC,SAAS;AACZ,WAAO,KAAK,gBAAgB,yCAAyC;AAAA,EACvE;AACA,QAAM,UAAU,QAAQ,QAAQ,OAAO,GAAG;AAC1C,MAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,WAAO,KAAK,gBAAgB,qCAAqC;AAAA,EACnE;AACA,QAAM,aAAa,kBAAAC,QAAK,MAAM,UAAU,OAAO,EAAE,QAAQ,SAAS,EAAE;AACpE,MAAI,eAAe,OAAO,eAAe,IAAI;AAC3C,WAAO,KAAK,gBAAgB,yCAAyC;AAAA,EACvE;AACA,MAAI,WAAW,WAAW,KAAK,KAAK,WAAW,SAAS,MAAM,KAAK,eAAe,MAAM;AACtF,WAAO,KAAK,gBAAgB,mCAAmC;AAAA,EACjE;AACA,MAAI,WAAW,SAAS,GAAG,GAAG;AAC5B,WAAO,WAAW,MAAM,GAAG,EAAE;AAAA,EAC/B;AACA,SAAO;AACT;AAEO,SAAS,kBAAkB,WAAyB;AACzD,QAAM,UAAU,UAAU,QAAQ,OAAO,GAAG;AAC5C,MAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,WAAO,KAAK,gBAAgB,oCAAoC,SAAS,EAAE;AAAA,EAC7E;AACA,QAAM,aAAa,kBAAAA,QAAK,MAAM,UAAU,OAAO;AAC/C,MAAI,WAAW,WAAW,KAAK,KAAK,eAAe,QAAQ,WAAW,SAAS,MAAM,GAAG;AACtF,WAAO,KAAK,gBAAgB,sCAAsC,SAAS,EAAE;AAAA,EAC/E;AACF;;;AC3EA,iBAAgB;AAShB,eAAsB,eAAe,MAAuC;AAC1E,QAAM,UAA0B,CAAC;AACjC,QAAM,WAAAC,QAAI,EAAE;AAAA,IACV;AAAA,IACA,QAAQ,OAAO;AACb,cAAQ,KAAK;AAAA,QACX,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM;AAAA,QACZ,MAAM,MAAM,QAAQ;AAAA,QACpB,MAAM,MAAM,QAAQ;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACD,SAAO;AACT;;;ALTA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,QAAQ,WAAW,CAAC;AAEnD,eAAsB,uBAAuB,SAAkC;AAC7E,QAAM,QAAQ,MAAM,iBAAAC,QAAG,KAAK,OAAO,EAAE,MAAM,MAAM,IAAI;AACrD,MAAI,CAAC,SAAS,CAAC,MAAM,YAAY,GAAG;AAClC,WAAO,KAAK,iBAAiB,6BAA6B,OAAO,EAAE;AAAA,EACrE;AAEA,QAAM,UAAU,MAAM,eAAe,OAAO;AAC5C,QAAM,SAAS,MAAM,iBAAAA,QAAG,QAAQ,kBAAAC,QAAK,KAAK,gBAAAC,QAAG,OAAO,GAAG,mBAAmB,CAAC;AAC3E,QAAM,UAAU,kBAAAD,QAAK,KAAK,QAAQ,kBAAkB;AAEpD,MAAI;AACF,UAAM,YAAY,YAAAE,QAAI;AAAA,MACpB;AAAA,QACE,KAAK;AAAA,QACL,UAAU;AAAA,QACV,OAAO,oBAAI,KAAK,CAAC;AAAA,MACnB;AAAA,MACA;AAAA,IACF;AAEA,UAAM,OAAO,iBAAAC,QAAK,WAAW,EAAE,OAAO,EAAE,CAAC;AACzC,cAAM,2BAAS,WAAW,UAAM,kCAAkB,OAAO,CAAC;AAE1D,UAAM,OAAO,MAAM,iBAAAJ,QAAG,KAAK,OAAO;AAClC,QAAI,KAAK,OAAO,qBAAqB;AACnC,aAAO;AAAA,QACL;AAAA,QACA,yBAAyB,KAAK,IAAI,kBAAkB,mBAAmB;AAAA,MACzE;AAAA,IACF;AAEA,UAAM,OAAO,MAAM,iBAAAA,QAAG,SAAS,OAAO;AACtC,UAAM,MAAM,KAAK,SAAS,QAAQ;AAClC,WAAO,mBAAmB;AAAA,EAC5B,UAAE;AACA,UAAM,iBAAAA,QAAG,GAAG,QAAQ,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACtD;AACF;AAEA,eAAsB,sBAAsB,OAAe,WAAkC;AAC3F,QAAM,SAAS,MAAM,MAAM,iBAAiB,MAAM;AAClD,MAAI;AACJ,MAAI;AACF,aAAS,OAAO,KAAK,QAAQ,QAAQ;AAAA,EACvC,QAAQ;AACN,WAAO,KAAK,MAAM,+BAA+B;AAAA,EACnD;AAEA,QAAM,UAAU,MAAM,iBAAAA,QAAG,QAAQ,kBAAAC,QAAK,KAAK,gBAAAC,QAAG,OAAO,GAAG,mBAAmB,CAAC;AAC5E,QAAM,UAAU,kBAAAD,QAAK,KAAK,SAAS,kBAAkB;AACrD,QAAM,iBAAAD,QAAG,UAAU,SAAS,MAAM;AAElC,MAAI;AACF,UAAM,UAAU,MAAM,eAAe,OAAO;AAC5C,UAAM,UAAU,mBAAmB,OAAO;AAE1C,UAAM,aAAa,kBAAAC,QAAK,KAAK,SAAS,SAAS;AAC/C,UAAM,UAAU,UAAU;AAC1B,UAAM,YAAAE,QAAI,EAAE;AAAA,MACV,MAAM;AAAA,MACN,KAAK;AAAA,MACL,eAAe;AAAA,MACf,SAAS;AAAA,IACX,CAAC;AAED,UAAM,2BAA2B,YAAY,OAAO;AACpD,UAAM,UAAU,SAAS;AACzB,UAAM,gBAAgB,YAAY,SAAS;AAAA,EAC7C,UAAE;AACA,UAAM,iBAAAH,QAAG,GAAG,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACvD;AACF;AAEA,eAAe,eAAe,MAAiC;AAC7D,QAAM,UAAoB,CAAC;AAE3B,iBAAe,KAAK,QAAgB,QAA+B;AACjE,UAAM,UAAU,MAAM,iBAAAA,QAAG,QAAQ,QAAQ,EAAE,eAAe,KAAK,CAAC;AAChE,YAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAEnD,eAAW,SAAS,SAAS;AAC3B,UAAI,iBAAiB,SAAS,MAAM,IAAI,GAAG;AACzC,YAAI,MAAM,YAAY,GAAG;AACvB;AAAA,QACF;AACA,YAAI,MAAM,OAAO,KAAK,MAAM,SAAS,aAAa;AAChD;AAAA,QACF;AAAA,MACF;AAEA,YAAM,UAAU,kBAAAC,QAAK,KAAK,QAAQ,MAAM,IAAI;AAC5C,YAAM,UAAU,SAAS,kBAAAA,QAAK,MAAM,KAAK,QAAQ,MAAM,IAAI,IAAI,MAAM;AACrE,YAAM,OAAO,MAAM,iBAAAD,QAAG,MAAM,OAAO;AACnC,UAAI,KAAK,eAAe,GAAG;AACzB,eAAO,KAAK,MAAM,qCAAqC,OAAO,EAAE;AAAA,MAClE;AAEA,UAAI,MAAM,YAAY,GAAG;AACvB,gBAAQ,KAAK,OAAO;AACpB,cAAM,KAAK,SAAS,OAAO;AAC3B;AAAA,MACF;AAEA,UAAI,MAAM,OAAO,GAAG;AAClB,YAAI,MAAM,SAAS,aAAa;AAC9B;AAAA,QACF;AACA,gBAAQ,KAAK,OAAO;AACpB;AAAA,MACF;AAEA,aAAO,KAAK,MAAM,uCAAuC,OAAO,EAAE;AAAA,IACpE;AAAA,EACF;AAEA,QAAM,KAAK,MAAM,EAAE;AACnB,UAAQ,KAAK;AACb,SAAO;AACT;AAEA,SAAS,mBAAmB,SAAsE;AAChG,QAAM,UAAU,oBAAI,IAAY;AAChC,aAAW,SAAS,SAAS;AAC3B,sBAAkB,MAAM,IAAI;AAC5B,QAAI,CAAC,cAAc,IAAI,MAAM,IAAI,GAAG;AAClC,aAAO,KAAK,MAAM,wCAAwC,MAAM,IAAI,EAAE;AAAA,IACxE;AACA,QAAI,MAAM,SAAS,UAAW,MAAM,OAAO,IAAQ;AACjD,cAAQ,IAAI,MAAM,IAAI;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AACT;;;AMpJA,IAAAK,mBAAe;AACf,IAAAC,oBAAiB;AACjB,IAAAC,kBAAe;AACf,IAAAC,kBAAkC;AAKlC,IAAAC,cAAgB;AAIhB,IAAMC,iBAAgB,oBAAI,IAAI,CAAC,QAAQ,WAAW,CAAC;AAS5C,SAAS,oBAAoB,KAAa,WAAmB,KAAsB;AACxF,QAAM,gBAAgB,mBAAmB,GAAG;AAC5C,QAAM,iBAAiB,mBAAmB,SAAS;AACnD,QAAM,UAAU,MACZ,KAAK,UAAU,EAAE,KAAK,eAAe,MAAM,gBAAgB,KAAK,kBAAkB,GAAG,EAAE,CAAC,IACxF,KAAK,UAAU,EAAE,KAAK,eAAe,MAAM,gBAAgB,OAAO,UAAU,CAAC;AACjF,SAAO,kBAAkB;AAC3B;AAEO,SAAS,mBAAmB,OAAyB;AAC1D,MAAI,CAAC,MAAM,WAAW,eAAe,GAAG;AACtC,WAAO,KAAK,iBAAiB,yBAAyB;AAAA,EACxD;AACA,QAAM,MAAM,MAAM,MAAM,gBAAgB,MAAM;AAC9C,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,QAAQ;AACN,WAAO,KAAK,MAAM,+BAA+B;AAAA,EACnD;AACA,MAAI,CAAC,UAAU,OAAO,OAAO,QAAQ,YAAY,OAAO,OAAO,SAAS,UAAU;AAChF,WAAO,KAAK,MAAM,iCAAiC;AAAA,EACrD;AACA,QAAM,aAAa;AAAA,IACjB,KAAK,mBAAmB,OAAO,GAAG;AAAA,IAClC,MAAM,mBAAmB,OAAO,IAAI;AAAA,EACtC;AAEA,MAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,WAAO,EAAE,GAAG,YAAY,KAAK,kBAAkB,OAAO,GAAG,EAAE;AAAA,EAC7D;AAEA,MAAI,OAAO,UAAU,WAAW;AAC9B,WAAO,EAAE,GAAG,YAAY,OAAO,UAAU;AAAA,EAC3C;AAEA,SAAO,KAAK,MAAM,iCAAiC;AACrD;AAEA,eAAsB,kBAAkB,OAAe,WAAkC;AACvF,QAAM,WAAW,mBAAmB,KAAK;AACzC,QAAM,cAAc,SAAS,OAAQ,MAAM,mBAAmB,SAAS,GAAG;AAC1E,QAAM,UAAU,MAAM,iBAAAC,QAAG,QAAQ,kBAAAC,QAAK,KAAK,gBAAAC,QAAG,OAAO,GAAG,kBAAkB,CAAC;AAC3E,QAAM,UAAU,kBAAAD,QAAK,KAAK,SAAS,iBAAiB;AAEpD,MAAI;AACF,UAAM,gBAAgB,SAAS,KAAK,aAAa,OAAO;AAExD,UAAM,UAAU,MAAM,eAAe,OAAO,EAAE,MAAM,MAAM,KAAK,MAAM,6BAA6B,CAAC;AACnG,UAAM,WAAW,eAAe,SAAS,SAAS,IAAI;AAEtD,UAAM,aAAa,kBAAAA,QAAK,KAAK,SAAS,SAAS;AAC/C,UAAM,UAAU,UAAU;AAE1B,UAAM,aAAa,IAAI,SAAS,KAAK,MAAM,GAAG,EAAE;AAChD,UAAM,YAAAE,QAAI,EAAE;AAAA,MACV,MAAM;AAAA,MACN,KAAK;AAAA,MACL,eAAe;AAAA,MACf,SAAS;AAAA,MACT,OAAO;AAAA,MACP,QAAQ,CAAC,GAAG,UAAU;AACpB,cAAM,YAAY,OAAO,QAAQ;AACjC,eAAO,YAAY,WAAW,SAAS,QAAQ,SAAS,IAAI;AAAA,MAC9D;AAAA,IACF,CAAC;AAED,UAAM,2BAA2B,YAAY,SAAS,OAAO;AAC7D,UAAM,UAAU,SAAS;AACzB,UAAM,gBAAgB,YAAY,SAAS;AAAA,EAC7C,UAAE;AACA,UAAM,iBAAAH,QAAG,GAAG,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACvD;AACF;AAEA,eAAe,gBAAgB,SAAiB,KAAa,SAAgC;AAC3F,QAAM,EAAE,OAAO,KAAK,IAAI,eAAe,OAAO;AAC9C,QAAM,MAAM,+BAA+B,KAAK,IAAI,IAAI,WAAW,GAAG;AACtE,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,aAAa,WAAW,MAAM,WAAW,MAAM,GAAG,4BAA4B;AACpF,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,kBAAkB,KAAK,GAAG,YAAY,CAAC,cAAc,qBAAqB,CAAC;AAAA,EACzF,SAAS,KAAK;AACZ,iBAAa,UAAU;AACvB,WAAO,KAAK,WAAW,oBAAoB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,EAC/F;AAEA,MAAI,CAAC,IAAI,IAAI;AACX,iBAAa,UAAU;AACvB,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,WAAO,KAAK,WAAW,oBAAoB,IAAI,MAAM,MAAM,IAAI,EAAE;AAAA,EACnE;AACA,MAAI,CAAC,IAAI,MAAM;AACb,iBAAa,UAAU;AACvB,WAAO,KAAK,WAAW,sCAAsC;AAAA,EAC/D;AAEA,QAAM,iBAAa,mCAAkB,OAAO;AAC5C,MAAI,QAAQ;AACZ,MAAI,QAAQ,OAAO,MAAM,CAAC;AAE1B,MAAI;AACF,qBAAiB,SAAS,IAAI,MAA+B;AAC3D,UAAI,MAAM,SAAS,GAAG;AACpB,cAAM,SAAS,IAAI,MAAM;AACzB,gBAAQ,OAAO,OAAO,CAAC,OAAO,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC;AACxD,YAAI,MAAM,WAAW,GAAG;AACtB,cAAI,MAAM,CAAC,MAAM,MAAQ,MAAM,CAAC,MAAM,KAAM;AAC1C,uBAAW,MAAM;AACjB,uBAAW,MAAM;AACjB,mBAAO,KAAK,MAAM,kCAAkC;AAAA,UACtD;AAAA,QACF;AAAA,MACF;AAEA,eAAS,MAAM;AACf,UAAI,QAAQ,6BAA6B;AACvC,mBAAW,MAAM;AACjB,mBAAW,MAAM;AACjB,eAAO;AAAA,UACL;AAAA,UACA,2BAA2B,KAAK,YAAY,2BAA2B;AAAA,QACzE;AAAA,MACF;AAEA,iBAAW,MAAM,KAAK;AAAA,IACxB;AAAA,EACF,SAAS,KAAK;AACZ,eAAW,MAAM;AACjB,iBAAa,UAAU;AACvB,QAAI,eAAe,aAAa;AAC9B,YAAM;AAAA,IACR;AACA,WAAO,KAAK,WAAW,oBAAoB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,EAC/F,UAAE;AACA,iBAAa,UAAU;AAAA,EACzB;AAEA,MAAI,MAAM,SAAS,GAAG;AACpB,eAAW,MAAM;AACjB,WAAO,KAAK,MAAM,+BAA+B;AAAA,EACnD;AAEA,QAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,eAAW,IAAI,MAAM,QAAQ,CAAC;AAC9B,eAAW,GAAG,SAAS,MAAM;AAAA,EAC/B,CAAC;AACH;AAEA,eAAe,kBACb,KACA,eACA,YACA,cACA,MACmB;AACnB,QAAM,eAAe,WAAW,MAAM,WAAW,MAAM,GAAG,2BAA2B;AAErF,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,GAAG;AAAA,IACH,QAAQ,WAAW;AAAA,IACnB,UAAU;AAAA,EACZ,CAAC;AAED,eAAa,YAAY;AAEzB,MAAI,WAAW,IAAI,MAAM,GAAG;AAC1B,QAAI,iBAAiB,GAAG;AACtB,aAAO,KAAK,WAAW,oBAAoB;AAAA,IAC7C;AACA,UAAM,WAAW,IAAI,QAAQ,IAAI,UAAU;AAC3C,QAAI,CAAC,UAAU;AACb,aAAO,KAAK,WAAW,kCAAkC;AAAA,IAC3D;AACA,UAAM,UAAU,IAAI,IAAI,UAAU,GAAG,EAAE,SAAS;AAChD,UAAM,OAAO,IAAI,IAAI,OAAO,EAAE;AAC9B,QAAI,CAAC,aAAa,SAAS,IAAI,GAAG;AAChC,aAAO,KAAK,WAAW,mCAAmC,IAAI,EAAE;AAAA,IAClE;AACA,WAAO,kBAAkB,SAAS,gBAAgB,GAAG,YAAY,cAAc,IAAI;AAAA,EACrF;AAEA,SAAO;AACT;AAEA,SAAS,WAAW,QAAyB;AAC3C,SAAO,CAAC,KAAK,KAAK,KAAK,KAAK,GAAG,EAAE,SAAS,MAAM;AAClD;AAEA,SAAS,eAAe,SAAkD;AACxE,QAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAM,QAAQ,IAAI,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AACpD,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,KAAK,eAAe,+CAA+C;AAAA,EAC5E;AACA,SAAO,EAAE,OAAO,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,EAAE;AAC3C;AAEA,eAAe,mBAAmB,SAAkC;AAClE,QAAM,EAAE,OAAO,KAAK,IAAI,eAAe,OAAO;AAC9C,QAAM,MAAM,gCAAgC,KAAK,IAAI,IAAI;AACzD,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,aAAa,WAAW,MAAM,WAAW,MAAM,GAAG,4BAA4B;AACpF,MAAI;AACJ,MAAI;AACF,UAAM,MAAM,kBAAkB,KAAK,GAAG,YAAY,CAAC,cAAc,gBAAgB,GAAG;AAAA,MAClF,SAAS;AAAA,QACP,cAAc;AAAA,QACd,QAAQ;AAAA,MACV;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,iBAAa,UAAU;AACvB,WAAO,KAAK,WAAW,iCAAiC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,EAC5G;AAEA,MAAI,CAAC,IAAI,IAAI;AACX,iBAAa,UAAU;AACvB,UAAM,OAAO,MAAM,IAAI,KAAK;AAC5B,WAAO,KAAK,WAAW,iCAAiC,IAAI,MAAM,MAAM,IAAI,EAAE;AAAA,EAChF;AAEA,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,IAAI,KAAK;AAAA,EACxB,QAAQ;AACN,iBAAa,UAAU;AACvB,WAAO,KAAK,WAAW,6CAA6C;AAAA,EACtE;AAEA,eAAa,UAAU;AACvB,MAAI,CAAC,QAAQ,OAAO,KAAK,mBAAmB,YAAY,KAAK,eAAe,WAAW,GAAG;AACxF,WAAO,KAAK,WAAW,kDAAkD;AAAA,EAC3E;AACA,SAAO,KAAK;AACd;AAEA,SAAS,eAAe,SAAyB,eAG/C;AACA,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,KAAK,aAAa,8BAA8B;AAAA,EACzD;AAEA,QAAM,SAAS,QAAQ,CAAC,EAAE,KAAK,MAAM,GAAG,EAAE,CAAC;AAC3C,MAAI,CAAC,QAAQ;AACX,WAAO,KAAK,MAAM,oCAAoC;AAAA,EACxD;AAEA,QAAM,UAAU,oBAAI,IAAY;AAChC,MAAI,aAAa;AACjB,MAAI,YAAY;AAChB,MAAI,UAAU;AAEd,aAAW,SAAS,SAAS;AAC3B,sBAAkB,MAAM,IAAI;AAC5B,QAAI,CAACD,eAAc,IAAI,MAAM,IAAI,GAAG;AAClC,aAAO,KAAK,MAAM,sCAAsC,MAAM,IAAI,EAAE;AAAA,IACtE;AAEA,QAAI,MAAM,SAAS,QAAQ;AACzB;AAAA,IACF;AACA,QAAI,CAAC,MAAM,KAAK,WAAW,GAAG,MAAM,GAAG,GAAG;AACxC,aAAO,KAAK,MAAM,yCAAyC;AAAA,IAC7D;AAEA,UAAM,MAAM,MAAM,KAAK,MAAM,OAAO,SAAS,CAAC;AAC9C,QAAI,CAAC,KAAK;AACR;AAAA,IACF;AAEA,UAAM,WAAW,mBAAmB,KAAK,aAAa;AACtD,QAAI,aAAa,MAAM;AACrB;AAAA,IACF;AAEA,cAAU;AACV,kBAAc;AACd,QAAI,QAAQ,iBAAiB,MAAM,SAAS,QAAQ;AAClD,aAAO,KAAK,gBAAgB,mCAAmC;AAAA,IACjE;AACA,QAAI,MAAM,SAAS,QAAQ;AACzB,mBAAa,MAAM,QAAQ;AAC3B,UAAI,MAAM,OAAO,IAAO;AACtB,gBAAQ,IAAI,QAAQ;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,SAAS;AACZ,WAAO,KAAK,aAAa,qCAAqC;AAAA,EAChE;AACA,MAAI,aAAa,oBAAoB;AACnC,WAAO,KAAK,cAAc,yBAAyB,UAAU,YAAY,kBAAkB,EAAE;AAAA,EAC/F;AACA,MAAI,YAAY,4BAA4B;AAC1C,WAAO,KAAK,cAAc,kBAAkB,SAAS,YAAY,0BAA0B,EAAE;AAAA,EAC/F;AAEA,SAAO,EAAE,QAAQ,QAAQ;AAC3B;AAEA,SAAS,mBAAmB,KAAa,eAAsC;AAC7E,MAAI,QAAQ,eAAe;AACzB,WAAO;AAAA,EACT;AACA,QAAM,SAAS,gBAAgB;AAC/B,MAAI,IAAI,WAAW,MAAM,GAAG;AAC1B,WAAO,IAAI,MAAM,OAAO,MAAM;AAAA,EAChC;AACA,SAAO;AACT;AAEA,SAAS,YAAY,WAAmB,QAAgB,eAAgC;AACtF,MAAI,cAAc,QAAQ;AACxB,WAAO;AAAA,EACT;AACA,MAAI,CAAC,UAAU,WAAW,GAAG,MAAM,GAAG,GAAG;AACvC,WAAO;AAAA,EACT;AACA,QAAM,MAAM,UAAU,MAAM,OAAO,SAAS,CAAC;AAC7C,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,iBAAiB,IAAI,WAAW,gBAAgB,GAAG,GAAG;AAChE,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;AC5VO,SAAS,qBAAqB,OAA+B;AAClE,MAAI,MAAM,WAAW,gBAAgB,EAAG,QAAO;AAC/C,MAAI,MAAM,WAAW,eAAe,EAAG,QAAO;AAC9C,SAAO;AACT;;;ACRA,IAAAK,mBAAe;AACf,0BAAoB;AAiBpB,eAAsB,iBACpB,UACA,MACA,aAAsB,QAAQ,oBAAAC,QAAQ,MAAM,KAAK,GAC7B;AACpB,QAAM,UAAU,OAAO,KAAK,SAAS;AACrC,QAAM,WAAW,OAAO,KAAK,UAAU;AACvC,QAAM,SAAS,OAAO,KAAK,QAAQ;AACnC,QAAM,eAAe,QAAQ,KAAK,OAAO,KAAK,OAAO,KAAK,IAAI;AAC9D,QAAM,SAAS,QAAQ,KAAK,OAAO,KAAK,IAAI;AAC5C,QAAM,gBAAgB,CAAC,SAAS,UAAU,QAAQ,MAAM,EAAE,OAAO,OAAO,EAAE;AAC1E,QAAM,WAAW,CAAC,cAAc,kBAAkB;AAElD,MAAI,gBAAgB,CAAC,QAAQ;AAC3B,WAAO,KAAK,iBAAiB,4CAA4C;AAAA,EAC3E;AAEA,QAAM,UAAU,iBAAiB,WAAW,IAAI;AAChD,MAAI,YAAY,GAAG;AACjB,WAAO,KAAK,iBAAiB,uCAAuC;AAAA,EACtE;AAEA,MAAI,UAAU,aAAa,SAAS;AAClC,WAAO,KAAK,iBAAiB,oCAAoC;AAAA,EACnE;AACA,MAAI,UAAU,aAAa,SAAS;AAClC,WAAO,KAAK,iBAAiB,kDAAkD;AAAA,EACjF;AACA,MAAI,KAAK,WAAW,UAAU,SAAS;AACrC,WAAO,KAAK,iBAAiB,6CAA6C;AAAA,EAC5E;AAEA,MAAI,QAAQ;AACV,UAAM,QAAQ,MAAM,uBAAuB,KAAK,GAAa;AAC7D,WAAO,EAAE,MAAM,aAAa,MAAM;AAAA,EACpC;AAEA,MAAI,QAAQ;AACV,UAAM,QAAQ,oBAAoB,KAAK,KAAe,KAAK,MAAgB,KAAK,GAAyB;AACzG,WAAO,EAAE,MAAM,YAAY,MAAM;AAAA,EACnC;AAEA,MAAI,SAAS;AACX,UAAM,UAAU,MAAM,iBAAAC,QAAG,SAAS,KAAK,MAAgB,MAAM;AAC7D,WAAO,EAAE,MAAM,UAAU,OAAO,QAAQ;AAAA,EAC1C;AAEA,MAAI,UAAU;AACZ,WAAO,EAAE,MAAM,UAAU,OAAO,KAAK,MAAgB;AAAA,EACvD;AAEA,QAAM,QAAQ,MAAM,UAAU;AAC9B,SAAO,EAAE,MAAM,UAAU,OAAO,MAAM;AACxC;AAEA,eAAe,YAA6B;AAC1C,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI,OAAO;AACX,wBAAAD,QAAQ,MAAM,YAAY,MAAM;AAChC,wBAAAA,QAAQ,MAAM,GAAG,QAAQ,CAAC,UAAU;AAClC,cAAQ;AAAA,IACV,CAAC;AACD,wBAAAA,QAAQ,MAAM,GAAG,OAAO,MAAM,QAAQ,IAAI,CAAC;AAC3C,wBAAAA,QAAQ,MAAM,GAAG,SAAS,MAAM;AAAA,EAClC,CAAC;AACH;;;AdrEA,eAAe,OAAsB;AACnC,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,KAAC,EAAE,aAAa,OAAO,QAAI,6BAAU;AAAA,MACnC,MAAM,qBAAAE,QAAQ,KAAK,MAAM,CAAC;AAAA,MAC1B,SAAS;AAAA,QACT,QAAQ,EAAE,MAAM,UAAU;AAAA,QAC1B,SAAS,EAAE,MAAM,WAAW,OAAO,IAAI;AAAA,QACvC,MAAM,EAAE,MAAM,SAAS;AAAA,QACvB,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,KAAK,EAAE,MAAM,SAAS;AAAA,QACtB,KAAK,EAAE,MAAM,SAAS;AAAA,QACtB,KAAK,EAAE,MAAM,SAAS;AAAA,QACtB,MAAM,EAAE,MAAM,SAAS;AAAA,MACvB;AAAA,MACA,kBAAkB;AAAA,IACpB,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,WAAO,KAAK,iBAAiB,eAAe,QAAQ,IAAI,UAAU,mBAAmB;AAAA,EACvF;AAEA,QAAM,CAAC,UAAU,SAAS,QAAQ,GAAG,KAAK,IAAI;AAC9C,MAAI,OAAO,SAAS;AAClB,yBAAAA,QAAQ,OAAO,MAAM,WAAW,IAAI,IAAI;AACxC;AAAA,EACF;AACA,MAAI,CAAC,UAAU;AACb,WAAO,KAAK,iBAAiB,kBAAkB;AAAA,EACjD;AAEA,MAAI,aAAa,QAAQ;AACvB,QAAI,WAAW,UAAU,MAAM,QAAQ;AACrC,aAAO,KAAK,iBAAiB,2CAA2C;AAAA,IAC1E;AACA,UAAM,QAAQ;AACd;AAAA,EACF;AAEA,MAAI,aAAa,QAAQ;AACvB,QAAI,WAAW,UAAU,MAAM,QAAQ;AACrC,aAAO,KAAK,iBAAiB,2CAA2C;AAAA,IAC1E;AACA,UAAM,UAAU,MAAM,iBAAiB;AACvC,QAAI,SAAS;AACX,2BAAAA,QAAQ,OAAO,MAAM,OAAO;AAC5B;AAAA,IACF;AACA,WAAO,KAAK,MAAM,yBAAyB;AAAA,EAC7C;AAEA,MAAI,CAAC,SAAS;AACZ,WAAO,KAAK,iBAAiB,iBAAiB;AAAA,EAChD;AACA,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO,KAAK,iBAAiB,+BAA+B;AAAA,EAC9D;AAEA,QAAM,OAAO;AAAA,IACX,QAAQ,QAAQ,OAAO,MAAM;AAAA,IAC7B,MAAM,OAAO;AAAA,IACb,OAAO,OAAO;AAAA,IACd,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO;AAAA,IACZ,MAAM,OAAO;AAAA,EACf;AAEA,MAAI;AACJ,MAAI;AACF,UAAM,cAAc,MAAM,WAAW;AACrC,YAAQ,YAAY,YAAY,KAAK,YAAY,KAAK;AAAA,EACxD,SAAS,KAAK;AACZ,QAAI,aAAa,WAAW,YAAY,UAAU,WAAW,UAAU;AACrE,YAAM,WAAW,MAAM,iBAAiB;AACxC,UAAI,UAAU;AACZ,6BAAAA,QAAQ,OAAO,MAAM,QAAQ;AAC7B;AAAA,MACF;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAEA,QAAM,OAAO,YAAY,QAAQ;AAEjC,MAAI,YAAY,QAAQ;AACtB,QAAI,QAAQ;AACV,aAAO,KAAK,iBAAiB,4BAA4B;AAAA,IAC3D;AACA,sBAAkB,IAAI;AACtB,UAAM,WAAW,OAAO,UAAU,IAAI;AACtC;AAAA,EACF;AAEA,QAAM,MAAM,MAAM,WAAW,UAAU,MAAM;AAE7C,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,YAAM,WAAW,OAAO,UAAU,MAAM,KAAK,IAAI;AACjD;AAAA,IACF,KAAK;AACH,YAAM,WAAW,OAAO,UAAU,MAAM,KAAK,IAAI;AACjD;AAAA,IACF,KAAK;AACH,YAAM,aAAa,OAAO,UAAU,MAAM,KAAK,IAAI;AACnD;AAAA,IACF;AACE,aAAO,KAAK,iBAAiB,oBAAoB,OAAO,EAAE;AAAA,EAC9D;AACF;AAEA,eAAe,UAAyB;AACtC,QAAM,WAAW,MAAM,OAAO,mBAAwB;AACtD,QAAM,KAAK,SAAS,gBAAgB,EAAE,OAAO,qBAAAA,QAAQ,OAAO,QAAQ,qBAAAA,QAAQ,OAAO,CAAC;AACpF,QAAM,OAAO,MAAM,GAAG,SAAS,oBAAoB,GAAG,KAAK;AAC3D,QAAM,SAAS,MAAM,GAAG,SAAS,sBAAsB,GAAG,KAAK;AAC/D,QAAM,GAAG,MAAM;AAEf,MAAI,CAAC,OAAO,CAAC,OAAO;AAClB,WAAO,KAAK,iBAAiB,iCAAiC;AAAA,EAChE;AAEA,QAAM,YAAY,EAAE,KAAK,MAAM,CAAC;AAClC;AAEA,SAAS,YAAY,UAA6C;AAChE,MAAI,aAAa,SAAS,aAAa,WAAW,aAAa,SAAS;AACtE,WAAO;AAAA,EACT;AACA,SAAO,KAAK,iBAAiB,qBAAqB,QAAQ,EAAE;AAC9D;AAEA,eAAe,WAAW,UAAkB,QAAkC;AAC5E,MAAI,aAAa,OAAO;AACtB,QAAI,OAAQ,QAAO;AACnB,WAAO,YAAY;AAAA,EACrB;AACA,MAAI,CAAC,QAAQ;AACX,WAAO,KAAK,eAAe,iBAAiB;AAAA,EAC9C;AACA,SAAO;AACT;AAEA,eAAe,WACb,OACA,UACA,MACA,KACA,MASe;AACf,oBAAkB,MAAM,MAAM;AAE9B,QAAM,QAAQ,MAAM,MAAM,IAAI,MAAM,GAAG;AACvC,MAAI,UAAU,MAAM;AAClB,QAAI,aAAa,WAAW,QAAQ,UAAU;AAC5C,YAAM,WAAW,MAAM,iBAAiB;AACxC,UAAI,UAAU;AACZ,6BAAAA,QAAQ,OAAO,MAAM,QAAQ;AAC7B;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK,aAAa,gBAAgB,IAAI,IAAI,GAAG,EAAE;AAAA,EACxD;AAEA,MAAI,aAAa,SAAS;AACxB,UAAM,OAAO,qBAAqB,KAAK;AACvC,QAAI,SAAS,UAAU;AACrB,UAAI,KAAK,KAAK;AACZ,eAAO,KAAK,iBAAiB,yCAAyC;AAAA,MACxE;AACA,2BAAAA,QAAQ,OAAO,MAAM,KAAK;AAC1B;AAAA,IACF;AACA,QAAI,CAAC,KAAK,KAAK;AACb,aAAO,KAAK,iBAAiB,+CAA+C;AAAA,IAC9E;AACA,QAAI,SAAS,aAAa;AACxB,YAAM,sBAAsB,OAAO,KAAK,GAAG;AAC3C;AAAA,IACF;AACA,QAAI,SAAS,YAAY;AACvB,YAAM,kBAAkB,OAAO,KAAK,GAAG;AACvC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,KAAK,KAAK;AACZ,WAAO,KAAK,iBAAiB,sCAAsC;AAAA,EACrE;AACA,uBAAAA,QAAQ,OAAO,MAAM,KAAK;AAC5B;AAEA,eAAe,WACb,OACA,UACA,MACA,KACA,MASe;AACf,QAAM,QAAQ,MAAM,iBAAiB,UAAU,IAAI;AAEnD,MAAI,KAAK,QAAQ;AACf,QAAI,MAAM,SAAS,UAAU;AAC3B,aAAO,KAAK,iBAAiB,wCAAwC;AAAA,IACvE;AACA,UAAM,WAAW,MAAM,MAAM,IAAI,MAAM,GAAG;AAC1C,QAAI,aAAa,WAAW,YAAY,qBAAqB,QAAQ,MAAM,UAAU;AACnF,aAAO,KAAK,iBAAiB,4CAA4C;AAAA,IAC3E;AACA,UAAM,SAAS,WAAW,GAAG,QAAQ;AAAA;AAAA,EAAO,MAAM,KAAK,KAAK,MAAM;AAClE,UAAM,MAAM,IAAI,MAAM,KAAK,MAAM;AACjC;AAAA,EACF;AAEA,MAAI,MAAM,SAAS,YAAY,aAAa,SAAS;AACnD,WAAO,KAAK,iBAAiB,4CAA6C;AAAA,EAC5E;AAEA,QAAM,MAAM,IAAI,MAAM,KAAK,MAAM,KAAK;AACxC;AAEA,eAAe,aACb,OACA,UACA,MACA,KACA,MASe;AACf,oBAAkB,MAAM,QAAQ;AAChC,MAAI,KAAK,KAAK;AACZ,WAAO,KAAK,iBAAiB,+BAA+B;AAAA,EAC9D;AACA,QAAM,MAAM,OAAO,MAAM,GAAG;AAC9B;AAEA,eAAe,WACb,OACA,UACA,MACe;AACf,QAAM,UAAU,MAAM,MAAM,KAAK,IAAI;AACrC,MAAI,QAAQ,WAAW,EAAG;AAE1B,QAAM,QAAQ,QAAQ,IAAI,CAAC,EAAE,OAAO,MAAM,MAAM;AAC9C,QAAI,OAAO;AACX,QAAI,aAAa,SAAS;AACxB,YAAM,OAAO,qBAAqB,KAAK;AACvC,UAAI,SAAS,YAAa,QAAO;AACjC,UAAI,SAAS,WAAY,QAAO;AAAA,IAClC;AACA,WAAO,GAAG,KAAK,IAAK,IAAI;AAAA,EAC1B,CAAC;AAED,uBAAAA,QAAQ,OAAO,MAAM,MAAM,KAAK,IAAI,IAAI,IAAI;AAC9C;AAGA,SAAS,kBACP,MASA,SACM;AACN,MAAI,KAAK,UAAU,KAAK,QAAQ,KAAK,SAAS,KAAK,OAAO,KAAK,OAAO,KAAK,MAAM;AAC/E,WAAO,KAAK,iBAAiB,GAAG,OAAO,8BAA8B;AAAA,EACvE;AACF;AAEA,SAAS,kBAAkB,MAQlB;AACP,MAAI,KAAK,UAAU,KAAK,QAAQ,KAAK,SAAS,KAAK,OAAO,KAAK,OAAO,KAAK,OAAO,KAAK,MAAM;AAC3F,WAAO,KAAK,iBAAiB,kCAAkC;AAAA,EACjE;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,QAAQ;AACpB,uBAAAA,QAAQ,OAAO,MAAM,YAAY,GAAG,IAAI,IAAI;AAC5C,uBAAAA,QAAQ,KAAK,CAAC;AAChB,CAAC;AAED,eAAe,mBAA2C;AACxD,MAAI;AACF,UAAM,UAAU,kBAAAC,QAAK,QAAQ,WAAW,UAAU,UAAU,UAAU;AACtE,WAAO,MAAM,iBAAAC,QAAG,SAAS,SAAS,MAAM;AAAA,EAC1C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAqB;AAC5B,MAAI;AACF,UAAM,UAAU,kBAAAD,QAAK,QAAQ,WAAW,MAAM,cAAc;AAC5D,UAAM,UAAM,8BAAa,SAAS,MAAM;AACxC,UAAM,OAAO,KAAK,MAAM,GAAG;AAC3B,QAAI,QAAQ,OAAO,KAAK,YAAY,UAAU;AAC5C,aAAO,KAAK;AAAA,IACd;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;","names":["import_node_util","import_node_process","import_node_path","import_promises","import_node_fs","path","os","fs","import_node_path","path","import_promises","import_node_path","import_node_os","import_tar","import_promises","import_node_path","import_promises","path","fs","fs","path","import_promises","import_node_path","fs","path","import_node_path","path","tar","fs","path","os","tar","zlib","import_promises","import_node_path","import_node_os","import_node_fs","import_tar","ALLOWED_TYPES","fs","path","os","tar","import_promises","process","fs","process","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/errors.ts","../src/config.ts","../src/constants.ts","../src/store.ts","../src/git.ts","../src/skillpack.ts","../src/fs-ops.ts","../src/chmod.ts","../src/perm.ts","../src/validators.ts","../src/tar-utils.ts","../src/skillref.ts","../src/value.ts","../src/input.ts"],"sourcesContent":["import { parseArgs } from \"node:util\";\nimport process from \"node:process\";\nimport path from \"node:path\";\nimport fs from \"node:fs/promises\";\nimport { readFileSync } from \"node:fs\";\nimport { formatError, fail } from \"./errors\";\nimport { loadConfig, writeConfig } from \"./config\";\nimport { createStore } from \"./store\";\nimport { inferCtxKey } from \"./git\";\nimport { extractSkillpackToDir } from \"./skillpack\";\nimport { loadSkillrefToDir } from \"./skillref\";\nimport { detectSkillValueType } from \"./value\";\nimport { resolveSaveInput } from \"./input\";\n\nasync function main(): Promise<void> {\n let positionals: string[];\n let values: Record<string, unknown>;\n try {\n ({ positionals, values } = parseArgs({\n args: process.argv.slice(2),\n options: {\n append: { type: \"boolean\" },\n version: { type: \"boolean\", short: \"v\" },\n file: { type: \"string\" },\n value: { type: \"string\" },\n dir: { type: \"string\" },\n url: { type: \"string\" },\n ref: { type: \"string\" },\n path: { type: \"string\" },\n },\n allowPositionals: true,\n }));\n } catch (err) {\n return fail(\"INVALID_INPUT\", err instanceof Error ? err.message : \"invalid arguments\");\n }\n\n const [resource, command, keyArg, ...extra] = positionals;\n if (values.version) {\n process.stdout.write(getVersion() + \"\\n\");\n return;\n }\n if (!resource) {\n return fail(\"INVALID_INPUT\", \"missing resource\");\n }\n\n if (resource === \"init\") {\n if (command || keyArg || extra.length) {\n return fail(\"INVALID_INPUT\", \"init does not accept additional arguments\");\n }\n await runInit();\n return;\n }\n\n if (resource === \"help\") {\n if (command || keyArg || extra.length) {\n return fail(\"INVALID_INPUT\", \"help does not accept additional arguments\");\n }\n const content = await loadBundledSkill();\n if (content) {\n process.stdout.write(content);\n return;\n }\n return fail(\"IO\", \"bundled skill not found\");\n }\n\n if (!command) {\n return fail(\"INVALID_INPUT\", \"missing command\");\n }\n if (extra.length > 0) {\n return fail(\"INVALID_INPUT\", \"too many positional arguments\");\n }\n\n const opts = {\n append: Boolean(values.append),\n file: values.file as string | undefined,\n value: values.value as string | undefined,\n dir: values.dir as string | undefined,\n url: values.url as string | undefined,\n ref: values.ref as string | undefined,\n path: values.path as string | undefined,\n };\n\n let store: ReturnType<typeof createStore>;\n try {\n const storeConfig = await loadConfig();\n store = createStore(storeConfig.url, storeConfig.token);\n } catch (err) {\n if (resource === \"skill\" && command === \"load\" && keyArg === \"ctxbin\") {\n const fallback = await loadBundledSkill();\n if (fallback) {\n process.stdout.write(fallback);\n return;\n }\n }\n throw err;\n }\n\n const hash = resolveHash(resource);\n\n if (command === \"list\") {\n if (keyArg) {\n return fail(\"INVALID_INPUT\", \"list does not accept a key\");\n }\n ensureNoListFlags(opts);\n await handleList(store, resource, hash);\n return;\n }\n\n const key = await resolveKey(resource, keyArg);\n\n switch (command) {\n case \"load\":\n await handleLoad(store, resource, hash, key, opts);\n return;\n case \"save\":\n await handleSave(store, resource, hash, key, opts);\n return;\n case \"delete\":\n await handleDelete(store, resource, hash, key, opts);\n return;\n default:\n return fail(\"INVALID_INPUT\", `unknown command: ${command}`);\n }\n}\n\nasync function runInit(): Promise<void> {\n const readline = await import(\"node:readline/promises\");\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const url = (await rl.question(\"CTXBIN_STORE_URL: \")).trim();\n const token = (await rl.question(\"CTXBIN_STORE_TOKEN: \")).trim();\n await rl.close();\n\n if (!url || !token) {\n return fail(\"INVALID_INPUT\", \"both URL and token are required\");\n }\n\n await writeConfig({ url, token });\n}\n\nfunction resolveHash(resource: string): \"ctx\" | \"agent\" | \"skill\" {\n if (resource === \"ctx\" || resource === \"agent\" || resource === \"skill\") {\n return resource;\n }\n return fail(\"INVALID_INPUT\", `unknown resource: ${resource}`);\n}\n\nasync function resolveKey(resource: string, keyArg?: string): Promise<string> {\n if (resource === \"ctx\") {\n if (keyArg) return keyArg;\n return inferCtxKey();\n }\n if (!keyArg) {\n return fail(\"MISSING_KEY\", \"key is required\");\n }\n return keyArg;\n}\n\nasync function handleLoad(\n store: ReturnType<typeof createStore>,\n resource: string,\n hash: string,\n key: string,\n opts: {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n }\n): Promise<void> {\n ensureNoSaveInput(opts, \"load\");\n\n const value = await store.get(hash, key);\n if (value === null) {\n if (resource === \"skill\" && key === \"ctxbin\") {\n const fallback = await loadBundledSkill();\n if (fallback) {\n process.stdout.write(fallback);\n return;\n }\n }\n return fail(\"NOT_FOUND\", `no value for ${hash}:${key}`);\n }\n\n if (resource === \"skill\") {\n const kind = detectSkillValueType(value);\n if (kind === \"string\") {\n if (opts.dir) {\n return fail(\"TYPE_MISMATCH\", \"--dir cannot be used with string values\");\n }\n process.stdout.write(value);\n return;\n }\n if (!opts.dir) {\n return fail(\"TYPE_MISMATCH\", \"--dir is required for skillpack/skillref load\");\n }\n if (kind === \"skillpack\") {\n await extractSkillpackToDir(value, opts.dir);\n return;\n }\n if (kind === \"skillref\") {\n await loadSkillrefToDir(value, opts.dir);\n return;\n }\n }\n\n if (opts.dir) {\n return fail(\"TYPE_MISMATCH\", \"--dir is only valid for skill values\");\n }\n process.stdout.write(value);\n}\n\nasync function handleSave(\n store: ReturnType<typeof createStore>,\n resource: string,\n hash: string,\n key: string,\n opts: {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n }\n): Promise<void> {\n const input = await resolveSaveInput(resource, opts);\n\n if (opts.append) {\n if (input.kind !== \"string\") {\n return fail(\"INVALID_INPUT\", \"--append only applies to string inputs\");\n }\n const existing = await store.get(hash, key);\n if (resource === \"skill\" && existing && detectSkillValueType(existing) !== \"string\") {\n return fail(\"TYPE_MISMATCH\", \"cannot append to skillpack/skillref values\");\n }\n const merged = existing ? `${existing}\\n\\n${input.value}` : input.value;\n await store.set(hash, key, merged);\n return;\n }\n\n if (input.kind !== \"string\" && resource !== \"skill\") {\n return fail(\"TYPE_MISMATCH\", \"non-string inputs are only valid for skill\" );\n }\n\n await store.set(hash, key, input.value);\n}\n\nasync function handleDelete(\n store: ReturnType<typeof createStore>,\n resource: string,\n hash: string,\n key: string,\n opts: {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n }\n): Promise<void> {\n ensureNoSaveInput(opts, \"delete\");\n if (opts.dir) {\n return fail(\"INVALID_INPUT\", \"--dir is not valid for delete\");\n }\n await store.delete(hash, key);\n}\n\nasync function handleList(\n store: ReturnType<typeof createStore>,\n resource: string,\n hash: string\n): Promise<void> {\n const entries = await store.list(hash);\n if (entries.length === 0) return;\n\n const lines = entries.map(({ field, value }) => {\n let type = \"--value\";\n if (resource === \"skill\") {\n const kind = detectSkillValueType(value);\n if (kind === \"skillpack\") type = \"--dir\";\n if (kind === \"skillref\") type = \"--url\";\n }\n return `${field}\\t${type}`;\n });\n\n process.stdout.write(lines.join(\"\\n\") + \"\\n\");\n}\n\n\nfunction ensureNoSaveInput(\n opts: {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n },\n command: \"load\" | \"delete\"\n): void {\n if (opts.append || opts.file || opts.value || opts.url || opts.ref || opts.path) {\n return fail(\"INVALID_INPUT\", `${command} does not accept input flags`);\n }\n}\n\nfunction ensureNoListFlags(opts: {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n}): void {\n if (opts.append || opts.file || opts.value || opts.dir || opts.url || opts.ref || opts.path) {\n return fail(\"INVALID_INPUT\", \"list does not accept input flags\");\n }\n}\n\nmain().catch((err) => {\n process.stderr.write(formatError(err) + \"\\n\");\n process.exit(1);\n});\n\nasync function loadBundledSkill(): Promise<string | null> {\n try {\n const bundled = path.resolve(__dirname, \"skills\", \"ctxbin\", \"SKILL.md\");\n return await fs.readFile(bundled, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction getVersion(): string {\n try {\n const pkgPath = path.resolve(__dirname, \"..\", \"package.json\");\n const raw = readFileSync(pkgPath, \"utf8\");\n const data = JSON.parse(raw);\n if (data && typeof data.version === \"string\") {\n return data.version;\n }\n } catch {\n // ignore\n }\n return \"0.0.0\";\n}\n","export type ErrorCode =\n | \"INVALID_INPUT\"\n | \"MISSING_KEY\"\n | \"INVALID_URL\"\n | \"INVALID_REF\"\n | \"INVALID_PATH\"\n | \"NOT_IN_GIT\"\n | \"NOT_FOUND\"\n | \"TYPE_MISMATCH\"\n | \"SIZE_LIMIT\"\n | \"NETWORK\"\n | \"IO\";\n\nexport class CtxbinError extends Error {\n readonly code: ErrorCode;\n\n constructor(code: ErrorCode, message: string) {\n super(message);\n this.code = code;\n }\n}\n\nexport function fail(code: ErrorCode, message: string): never {\n throw new CtxbinError(code, message);\n}\n\nexport function formatError(err: unknown): string {\n if (err instanceof CtxbinError) {\n return `CTXBIN_ERR ${err.code}: ${err.message}`;\n }\n const message = err instanceof Error ? err.message : String(err);\n return `CTXBIN_ERR IO: ${message}`;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { fail } from \"./errors\";\n\nexport interface StoreConfig {\n url: string;\n token: string;\n}\n\nconst ENV_URL = \"CTXBIN_STORE_URL\";\nconst ENV_TOKEN = \"CTXBIN_STORE_TOKEN\";\n\nexport async function loadConfig(): Promise<StoreConfig> {\n const envUrl = process.env[ENV_URL];\n const envToken = process.env[ENV_TOKEN];\n\n if (envUrl || envToken) {\n if (!envUrl || !envToken) {\n return fail(\"INVALID_INPUT\", \"both CTXBIN_STORE_URL and CTXBIN_STORE_TOKEN must be set\");\n }\n return { url: envUrl, token: envToken };\n }\n\n const configPath = path.join(os.homedir(), \".ctxbin\", \"config.json\");\n let raw: string;\n try {\n raw = await fs.readFile(configPath, \"utf8\");\n } catch {\n return fail(\"INVALID_INPUT\", \"missing CTXBIN_STORE_URL/CTXBIN_STORE_TOKEN and no ~/.ctxbin/config.json. Create a Redis database at https://upstash.com and run `npx ctxbin init` to configure.\");\n }\n\n let parsed: any;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return fail(\"INVALID_INPUT\", \"invalid JSON in ~/.ctxbin/config.json\");\n }\n\n const url = parsed.store_url || parsed.storeUrl || parsed.url;\n const token = parsed.store_token || parsed.storeToken || parsed.token;\n if (!url || !token) {\n return fail(\"INVALID_INPUT\", \"config.json must include store_url and store_token\");\n }\n\n return { url, token };\n}\n\nexport async function writeConfig(config: StoreConfig): Promise<void> {\n const dir = path.join(os.homedir(), \".ctxbin\");\n const configPath = path.join(dir, \"config.json\");\n await fs.mkdir(dir, { recursive: true, mode: 0o700 });\n const payload = {\n store_url: config.url,\n store_token: config.token,\n };\n await fs.writeFile(configPath, JSON.stringify(payload, null, 2), \"utf8\");\n}\n","export const SKILLPACK_HEADER = \"ctxbin-skillpack@1\\n\";\nexport const SKILLREF_HEADER = \"ctxbin-skillref@1\\n\";\n\nexport const MAX_SKILLPACK_BYTES = 7 * 1024 * 1024;\nexport const MAX_SKILLREF_DOWNLOAD_BYTES = 20 * 1024 * 1024;\nexport const MAX_SKILLREF_EXTRACT_BYTES = 100 * 1024 * 1024;\nexport const MAX_SKILLREF_FILES = 5000;\n\nexport const SKILLREF_CONNECT_TIMEOUT_MS = 5000;\nexport const SKILLREF_DOWNLOAD_TIMEOUT_MS = 30000;\n\nexport const DEFAULT_EXCLUDES = [\".git\", \"node_modules\", \".DS_Store\"];\n\nexport const STORE_REQUEST_TIMEOUT_MS = 5000;\n","import { fail } from \"./errors\";\nimport { STORE_REQUEST_TIMEOUT_MS } from \"./constants\";\n\nexport interface Store {\n get(hash: string, field: string): Promise<string | null>;\n set(hash: string, field: string, value: string): Promise<void>;\n delete(hash: string, field: string): Promise<void>;\n list(hash: string): Promise<Array<{ field: string; value: string }>>;\n}\n\ninterface UpstashResponse<T> {\n result?: T;\n error?: string;\n}\n\nexport function createStore(url: string, token: string): Store {\n const baseUrl = url.replace(/\\/$/, \"\");\n\n async function command<T>(cmd: string, ...args: string[]): Promise<T> {\n let res: Response;\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), STORE_REQUEST_TIMEOUT_MS);\n try {\n res = await fetch(baseUrl, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify([cmd, ...args]),\n signal: controller.signal,\n });\n } catch (err) {\n if (controller.signal.aborted) {\n return fail(\"NETWORK\", `store request timed out after ${STORE_REQUEST_TIMEOUT_MS}ms`);\n }\n return fail(\"NETWORK\", `store request failed: ${err instanceof Error ? err.message : String(err)}`);\n } finally {\n clearTimeout(timeout);\n }\n\n if (!res.ok) {\n const text = await res.text();\n return fail(\"NETWORK\", `store request failed (${res.status}): ${text}`);\n }\n\n let data: UpstashResponse<T>;\n try {\n data = (await res.json()) as UpstashResponse<T>;\n } catch {\n return fail(\"NETWORK\", \"store response was not valid JSON\");\n }\n\n if (data.error) {\n return fail(\"NETWORK\", data.error);\n }\n\n return data.result as T;\n }\n\n return {\n async get(hash, field) {\n const result = await command<string | null>(\"HGET\", hash, field);\n return result ?? null;\n },\n async set(hash, field, value) {\n await command<number>(\"HSET\", hash, field, value);\n },\n async delete(hash, field) {\n await command<number>(\"HDEL\", hash, field);\n },\n async list(hash) {\n const result = await command<unknown>(\"HGETALL\", hash);\n if (!result) return [];\n if (!Array.isArray(result)) {\n return fail(\"NETWORK\", \"store response for HGETALL was not an array\");\n }\n const pairs: Array<{ field: string; value: string }> = [];\n for (let i = 0; i < result.length; i += 2) {\n const field = result[i];\n const value = result[i + 1];\n if (typeof field !== \"string\" || typeof value !== \"string\") {\n return fail(\"NETWORK\", \"store response for HGETALL contained invalid entries\");\n }\n pairs.push({ field, value });\n }\n pairs.sort((a, b) => a.field.localeCompare(b.field));\n return pairs;\n },\n };\n}\n","import { execFile } from \"node:child_process\";\nimport { readFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { fail } from \"./errors\";\n\nconst execFileAsync = promisify(execFile);\n\nasync function git(args: string[]): Promise<string> {\n try {\n const { stdout } = await execFileAsync(\"git\", args, { encoding: \"utf8\" });\n return stdout.trim();\n } catch {\n return fail(\"NOT_IN_GIT\", \"not inside a git repository\");\n }\n}\n\nasync function getPackageJsonName(root: string): Promise<string | null> {\n try {\n const content = await readFile(path.join(root, \"package.json\"), \"utf8\");\n const pkg = JSON.parse(content);\n return typeof pkg.name === \"string\" ? pkg.name : null;\n } catch {\n return null;\n }\n}\n\nexport async function inferCtxKey(): Promise<string> {\n const root = await git([\"rev-parse\", \"--show-toplevel\"]);\n const branch = await git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n const folderName = path.basename(root);\n\n if (!folderName || !branch) {\n return fail(\"NOT_IN_GIT\", \"unable to infer ctx key from git repository\");\n }\n\n const pkgName = await getPackageJsonName(root);\n\n if (pkgName) {\n if (pkgName !== folderName) {\n process.stderr.write(\n `CTXBIN_WARN: package.json name \"${pkgName}\" differs from folder name \"${folderName}\". Using \"${pkgName}\".\\n`\n );\n }\n return `${pkgName}/${branch}`;\n }\n\n return `${folderName}/${branch}`;\n}\n","import fs from \"node:fs/promises\";\nimport { createWriteStream } from \"node:fs\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport zlib from \"node:zlib\";\nimport { pipeline } from \"node:stream/promises\";\nimport tar from \"tar\";\nimport { DEFAULT_EXCLUDES, MAX_SKILLPACK_BYTES, SKILLPACK_HEADER } from \"./constants\";\nimport { fail } from \"./errors\";\nimport { ensureDir, copyDirContents } from \"./fs-ops\";\nimport { applyNormalizedPermissions } from \"./perm\";\nimport { assertSafeTarPath } from \"./validators\";\nimport { listTarEntries } from \"./tar-utils\";\n\nconst ALLOWED_TYPES = new Set([\"File\", \"Directory\"]);\n\nexport async function createSkillpackFromDir(dirPath: string): Promise<string> {\n const stats = await fs.stat(dirPath).catch(() => null);\n if (!stats || !stats.isDirectory()) {\n return fail(\"INVALID_INPUT\", `--dir is not a directory: ${dirPath}`);\n }\n\n const entries = await collectEntries(dirPath);\n const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), \"ctxbin-skillpack-\"));\n const tarPath = path.join(tmpDir, \"skillpack.tar.gz\");\n\n try {\n const tarStream = tar.c(\n {\n cwd: dirPath,\n portable: true,\n mtime: new Date(0),\n },\n entries\n );\n\n const gzip = zlib.createGzip({ mtime: 0 });\n await pipeline(tarStream, gzip, createWriteStream(tarPath));\n\n const stat = await fs.stat(tarPath);\n if (stat.size > MAX_SKILLPACK_BYTES) {\n return fail(\n \"SIZE_LIMIT\",\n `skillpack tar.gz size ${stat.size} bytes exceeds ${MAX_SKILLPACK_BYTES} bytes`\n );\n }\n\n const data = await fs.readFile(tarPath);\n const b64 = data.toString(\"base64\");\n return SKILLPACK_HEADER + b64;\n } finally {\n await fs.rm(tmpDir, { recursive: true, force: true });\n }\n}\n\nexport async function extractSkillpackToDir(value: string, targetDir: string): Promise<void> {\n const base64 = value.slice(SKILLPACK_HEADER.length);\n let buffer: Buffer;\n try {\n buffer = Buffer.from(base64, \"base64\");\n } catch {\n return fail(\"IO\", \"invalid skillpack base64 data\");\n }\n\n const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"ctxbin-skillpack-\"));\n const tarPath = path.join(tmpRoot, \"skillpack.tar.gz\");\n await fs.writeFile(tarPath, buffer);\n\n try {\n const entries = await listTarEntries(tarPath);\n const execSet = validateTarEntries(entries);\n\n const extractDir = path.join(tmpRoot, \"extract\");\n await ensureDir(extractDir);\n await tar.x({\n file: tarPath,\n cwd: extractDir,\n preserveOwner: false,\n noMtime: true,\n });\n\n await applyNormalizedPermissions(extractDir, execSet);\n await ensureDir(targetDir);\n await copyDirContents(extractDir, targetDir);\n } finally {\n await fs.rm(tmpRoot, { recursive: true, force: true });\n }\n}\n\nasync function collectEntries(root: string): Promise<string[]> {\n const results: string[] = [];\n\n async function walk(absDir: string, relDir: string): Promise<void> {\n const entries = await fs.readdir(absDir, { withFileTypes: true });\n entries.sort((a, b) => a.name.localeCompare(b.name));\n\n for (const entry of entries) {\n if (DEFAULT_EXCLUDES.includes(entry.name)) {\n if (entry.isDirectory()) {\n continue;\n }\n if (entry.isFile() && entry.name === \".DS_Store\") {\n continue;\n }\n }\n\n const absPath = path.join(absDir, entry.name);\n const relPath = relDir ? path.posix.join(relDir, entry.name) : entry.name;\n const stat = await fs.lstat(absPath);\n if (stat.isSymbolicLink()) {\n return fail(\"IO\", `symlink not allowed in skillpack: ${absPath}`);\n }\n\n if (entry.isDirectory()) {\n results.push(relPath);\n await walk(absPath, relPath);\n continue;\n }\n\n if (entry.isFile()) {\n if (entry.name === \".DS_Store\") {\n continue;\n }\n results.push(relPath);\n continue;\n }\n\n return fail(\"IO\", `unsupported file type in skillpack: ${absPath}`);\n }\n }\n\n await walk(root, \"\");\n results.sort();\n return results;\n}\n\nfunction validateTarEntries(entries: { path: string; type: string; mode: number }[]): Set<string> {\n const execSet = new Set<string>();\n for (const entry of entries) {\n assertSafeTarPath(entry.path);\n if (!ALLOWED_TYPES.has(entry.type)) {\n return fail(\"IO\", `unsupported entry type in skillpack: ${entry.path}`);\n }\n if (entry.type === \"File\" && (entry.mode & 0o111)) {\n execSet.add(entry.path);\n }\n }\n return execSet;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fail } from \"./errors\";\nimport { safeChmod } from \"./chmod\";\n\nexport async function ensureDir(dir: string): Promise<void> {\n await fs.mkdir(dir, { recursive: true });\n}\n\nexport function toPosix(p: string): string {\n return p.split(path.sep).join(\"/\");\n}\n\nexport async function copyDirContents(src: string, dest: string): Promise<void> {\n await ensureDir(dest);\n const entries = await fs.readdir(src, { withFileTypes: true });\n for (const entry of entries) {\n const srcPath = path.join(src, entry.name);\n const destPath = path.join(dest, entry.name);\n if (entry.isDirectory()) {\n await copyDirContents(srcPath, destPath);\n const stat = await fs.stat(srcPath);\n await safeChmod(destPath, stat.mode & 0o777);\n continue;\n }\n if (entry.isFile()) {\n await ensureDir(path.dirname(destPath));\n await fs.copyFile(srcPath, destPath);\n const stat = await fs.stat(srcPath);\n await safeChmod(destPath, stat.mode & 0o777);\n continue;\n }\n return fail(\"IO\", `unsupported file type during copy: ${srcPath}`);\n }\n}\n","import fs from \"node:fs/promises\";\n\nexport async function safeChmod(path: string, mode: number): Promise<void> {\n try {\n await fs.chmod(path, mode);\n } catch (err) {\n if (process.platform === \"win32\") {\n return;\n }\n throw err;\n }\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { fail } from \"./errors\";\nimport { toPosix } from \"./fs-ops\";\nimport { safeChmod } from \"./chmod\";\n\nexport async function applyNormalizedPermissions(root: string, execSet: Set<string>): Promise<void> {\n async function walk(absDir: string): Promise<void> {\n const entries = await fs.readdir(absDir, { withFileTypes: true });\n for (const entry of entries) {\n const absPath = path.join(absDir, entry.name);\n if (entry.isDirectory()) {\n await safeChmod(absPath, 0o755);\n await walk(absPath);\n continue;\n }\n if (entry.isFile()) {\n const rel = toPosix(path.relative(root, absPath));\n const mode = execSet.has(rel) ? 0o755 : 0o644;\n await safeChmod(absPath, mode);\n continue;\n }\n return fail(\"IO\", `unsupported file type after extract: ${absPath}`);\n }\n }\n\n await walk(root);\n}\n","import path from \"node:path\";\nimport { fail } from \"./errors\";\n\nexport function normalizeGithubUrl(input: string): string {\n let url: URL;\n try {\n url = new URL(input);\n } catch {\n return fail(\"INVALID_URL\", \"invalid URL\");\n }\n\n if (url.protocol !== \"https:\") {\n return fail(\"INVALID_URL\", \"URL must use https\");\n }\n if (url.hostname !== \"github.com\") {\n return fail(\"INVALID_URL\", \"only github.com is supported\");\n }\n if (url.search || url.hash) {\n return fail(\"INVALID_URL\", \"URL must not include query or hash\");\n }\n\n const parts = url.pathname.split(\"/\").filter(Boolean);\n if (parts.length !== 2) {\n return fail(\"INVALID_URL\", \"URL must be https://github.com/<owner>/<repo>\");\n }\n const owner = parts[0];\n let repo = parts[1];\n if (repo.endsWith(\".git\")) {\n repo = repo.slice(0, -4);\n }\n if (!owner || !repo) {\n return fail(\"INVALID_URL\", \"URL must be https://github.com/<owner>/<repo>\");\n }\n\n return `https://github.com/${owner}/${repo}`;\n}\n\nexport function validateCommitSha(ref: string): string {\n if (!/^[0-9a-f]{40}$/.test(ref)) {\n return fail(\"INVALID_REF\", \"ref must be a 40-hex commit SHA\");\n }\n return ref;\n}\n\nexport function normalizeSkillPath(input: string): string {\n const trimmed = input.trim();\n if (!trimmed) {\n return fail(\"INVALID_PATH\", \"path must be a non-empty directory path\");\n }\n const cleaned = trimmed.replace(/\\\\/g, \"/\");\n if (cleaned.startsWith(\"/\")) {\n return fail(\"INVALID_PATH\", \"path must be relative, not absolute\");\n }\n const normalized = path.posix.normalize(cleaned).replace(/^\\.\\//, \"\");\n if (normalized === \".\" || normalized === \"\") {\n return fail(\"INVALID_PATH\", \"path must be a non-empty directory path\");\n }\n if (normalized.startsWith(\"../\") || normalized.includes(\"/../\") || normalized === \"..\") {\n return fail(\"INVALID_PATH\", \"path must not include .. segments\");\n }\n if (normalized.endsWith(\"/\")) {\n return normalized.slice(0, -1);\n }\n return normalized;\n}\n\nexport function assertSafeTarPath(entryPath: string): void {\n const cleaned = entryPath.replace(/\\\\/g, \"/\");\n if (cleaned.startsWith(\"/\")) {\n return fail(\"INVALID_PATH\", `tar entry path must be relative: ${entryPath}`);\n }\n const normalized = path.posix.normalize(cleaned);\n if (normalized.startsWith(\"../\") || normalized === \"..\" || normalized.includes(\"/../\")) {\n return fail(\"INVALID_PATH\", `tar entry path contains traversal: ${entryPath}`);\n }\n}\n","import tar from \"tar\";\n\nexport interface TarEntryInfo {\n path: string;\n type: string;\n size: number;\n mode: number;\n}\n\nexport async function listTarEntries(file: string): Promise<TarEntryInfo[]> {\n const entries: TarEntryInfo[] = [];\n await tar.t({\n file,\n onentry(entry) {\n entries.push({\n path: entry.path,\n type: entry.type,\n size: entry.size ?? 0,\n mode: entry.mode ?? 0,\n });\n },\n });\n return entries;\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { createWriteStream } from \"node:fs\";\nimport { SKILLREF_HEADER, MAX_SKILLREF_DOWNLOAD_BYTES, MAX_SKILLREF_EXTRACT_BYTES, MAX_SKILLREF_FILES, SKILLREF_CONNECT_TIMEOUT_MS, SKILLREF_DOWNLOAD_TIMEOUT_MS } from \"./constants\";\nimport { fail, CtxbinError } from \"./errors\";\nimport { normalizeGithubUrl, normalizeSkillPath, validateCommitSha, assertSafeTarPath } from \"./validators\";\nimport { listTarEntries, TarEntryInfo } from \"./tar-utils\";\nimport tar from \"tar\";\nimport { ensureDir, copyDirContents } from \"./fs-ops\";\nimport { applyNormalizedPermissions } from \"./perm\";\n\nconst ALLOWED_TYPES = new Set([\"File\", \"Directory\"]);\n\nexport interface Skillref {\n url: string;\n path: string;\n ref?: string;\n track?: \"default\";\n}\n\nexport function createSkillrefValue(url: string, skillPath: string, ref?: string): string {\n const normalizedUrl = normalizeGithubUrl(url);\n const normalizedPath = normalizeSkillPath(skillPath);\n const payload = ref\n ? JSON.stringify({ url: normalizedUrl, path: normalizedPath, ref: validateCommitSha(ref) })\n : JSON.stringify({ url: normalizedUrl, path: normalizedPath, track: \"default\" });\n return SKILLREF_HEADER + payload;\n}\n\nexport function parseSkillrefValue(value: string): Skillref {\n if (!value.startsWith(SKILLREF_HEADER)) {\n return fail(\"TYPE_MISMATCH\", \"value is not a skillref\");\n }\n const raw = value.slice(SKILLREF_HEADER.length);\n let parsed: any;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return fail(\"IO\", \"invalid skillref payload JSON\");\n }\n if (!parsed || typeof parsed.url !== \"string\" || typeof parsed.path !== \"string\") {\n return fail(\"IO\", \"invalid skillref payload fields\");\n }\n const normalized = {\n url: normalizeGithubUrl(parsed.url),\n path: normalizeSkillPath(parsed.path),\n } satisfies Pick<Skillref, \"url\" | \"path\">;\n\n if (typeof parsed.ref === \"string\") {\n return { ...normalized, ref: validateCommitSha(parsed.ref) };\n }\n\n if (parsed.track === \"default\") {\n return { ...normalized, track: \"default\" };\n }\n\n return fail(\"IO\", \"invalid skillref payload fields\");\n}\n\nexport async function loadSkillrefToDir(value: string, targetDir: string): Promise<void> {\n const skillref = parseSkillrefValue(value);\n const resolvedRef = skillref.ref ?? (await fetchDefaultBranch(skillref.url));\n const tmpRoot = await fs.mkdtemp(path.join(os.tmpdir(), \"ctxbin-skillref-\"));\n const tarPath = path.join(tmpRoot, \"skillref.tar.gz\");\n\n try {\n await downloadArchive(skillref.url, resolvedRef, tarPath);\n\n const entries = await listTarEntries(tarPath).catch(() => fail(\"IO\", \"failed to parse tar archive\"));\n const analysis = analyzeEntries(entries, skillref.path);\n\n const extractDir = path.join(tmpRoot, \"extract\");\n await ensureDir(extractDir);\n\n const stripCount = 1 + skillref.path.split(\"/\").length;\n await tar.x({\n file: tarPath,\n cwd: extractDir,\n preserveOwner: false,\n noMtime: true,\n strip: stripCount,\n filter: (p, entry) => {\n const entryPath = entry?.path ?? p;\n return isUnderPath(entryPath, analysis.prefix, skillref.path);\n },\n });\n\n await applyNormalizedPermissions(extractDir, analysis.execSet);\n await ensureDir(targetDir);\n await copyDirContents(extractDir, targetDir);\n } finally {\n await fs.rm(tmpRoot, { recursive: true, force: true });\n }\n}\n\nasync function downloadArchive(repoUrl: string, ref: string, outPath: string): Promise<void> {\n const { owner, repo } = splitGithubUrl(repoUrl);\n const url = `https://codeload.github.com/${owner}/${repo}/tar.gz/${ref}`;\n const controller = new AbortController();\n const totalTimer = setTimeout(() => controller.abort(), SKILLREF_DOWNLOAD_TIMEOUT_MS);\n let res: Response;\n try {\n res = await fetchWithRedirect(url, 1, controller, [\"github.com\", \"codeload.github.com\"]);\n } catch (err) {\n clearTimeout(totalTimer);\n return fail(\"NETWORK\", `download failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n if (!res.ok) {\n clearTimeout(totalTimer);\n const text = await res.text();\n return fail(\"NETWORK\", `download failed (${res.status}): ${text}`);\n }\n if (!res.body) {\n clearTimeout(totalTimer);\n return fail(\"NETWORK\", \"download failed: empty response body\");\n }\n\n const fileStream = createWriteStream(outPath);\n let total = 0;\n let magic = Buffer.alloc(0);\n\n try {\n for await (const chunk of res.body as AsyncIterable<Buffer>) {\n if (magic.length < 2) {\n const needed = 2 - magic.length;\n magic = Buffer.concat([magic, chunk.subarray(0, needed)]);\n if (magic.length === 2) {\n if (magic[0] !== 0x1f || magic[1] !== 0x8b) {\n fileStream.close();\n controller.abort();\n return fail(\"IO\", \"downloaded file is not gzip data\");\n }\n }\n }\n\n total += chunk.length;\n if (total > MAX_SKILLREF_DOWNLOAD_BYTES) {\n fileStream.close();\n controller.abort();\n return fail(\n \"SIZE_LIMIT\",\n `downloaded archive size ${total} exceeds ${MAX_SKILLREF_DOWNLOAD_BYTES} bytes`\n );\n }\n\n fileStream.write(chunk);\n }\n } catch (err) {\n fileStream.close();\n clearTimeout(totalTimer);\n if (err instanceof CtxbinError) {\n throw err;\n }\n return fail(\"NETWORK\", `download failed: ${err instanceof Error ? err.message : String(err)}`);\n } finally {\n clearTimeout(totalTimer);\n }\n\n if (magic.length < 2) {\n fileStream.close();\n return fail(\"IO\", \"downloaded file is incomplete\");\n }\n\n await new Promise<void>((resolve, reject) => {\n fileStream.end(() => resolve());\n fileStream.on(\"error\", reject);\n });\n}\n\nasync function fetchWithRedirect(\n url: string,\n redirectsLeft: number,\n controller: AbortController,\n allowedHosts: string[],\n init?: RequestInit\n): Promise<Response> {\n const connectTimer = setTimeout(() => controller.abort(), SKILLREF_CONNECT_TIMEOUT_MS);\n\n const res = await fetch(url, {\n ...init,\n signal: controller.signal,\n redirect: \"manual\",\n });\n\n clearTimeout(connectTimer);\n\n if (isRedirect(res.status)) {\n if (redirectsLeft <= 0) {\n return fail(\"NETWORK\", \"too many redirects\");\n }\n const location = res.headers.get(\"location\");\n if (!location) {\n return fail(\"NETWORK\", \"redirect without location header\");\n }\n const nextUrl = new URL(location, url).toString();\n const host = new URL(nextUrl).hostname;\n if (!allowedHosts.includes(host)) {\n return fail(\"NETWORK\", `redirected to unsupported host: ${host}`);\n }\n return fetchWithRedirect(nextUrl, redirectsLeft - 1, controller, allowedHosts, init);\n }\n\n return res;\n}\n\nfunction isRedirect(status: number): boolean {\n return [301, 302, 303, 307, 308].includes(status);\n}\n\nfunction splitGithubUrl(repoUrl: string): { owner: string; repo: string } {\n const url = new URL(repoUrl);\n const parts = url.pathname.split(\"/\").filter(Boolean);\n if (parts.length !== 2) {\n return fail(\"INVALID_URL\", \"URL must be https://github.com/<owner>/<repo>\");\n }\n return { owner: parts[0], repo: parts[1] };\n}\n\nasync function fetchDefaultBranch(repoUrl: string): Promise<string> {\n const { owner, repo } = splitGithubUrl(repoUrl);\n const url = `https://api.github.com/repos/${owner}/${repo}`;\n const controller = new AbortController();\n const totalTimer = setTimeout(() => controller.abort(), SKILLREF_DOWNLOAD_TIMEOUT_MS);\n let res: Response;\n try {\n res = await fetchWithRedirect(url, 1, controller, [\"github.com\", \"api.github.com\"], {\n headers: {\n \"User-Agent\": \"ctxbin\",\n Accept: \"application/vnd.github+json\",\n },\n });\n } catch (err) {\n clearTimeout(totalTimer);\n return fail(\"NETWORK\", `default branch lookup failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n if (!res.ok) {\n clearTimeout(totalTimer);\n const text = await res.text();\n return fail(\"NETWORK\", `default branch lookup failed (${res.status}): ${text}`);\n }\n\n let data: any;\n try {\n data = await res.json();\n } catch {\n clearTimeout(totalTimer);\n return fail(\"NETWORK\", \"default branch lookup returned invalid JSON\");\n }\n\n clearTimeout(totalTimer);\n if (!data || typeof data.default_branch !== \"string\" || data.default_branch.length === 0) {\n return fail(\"NETWORK\", \"default branch lookup returned no default_branch\");\n }\n return data.default_branch;\n}\n\nfunction analyzeEntries(entries: TarEntryInfo[], requestedPath: string): {\n prefix: string;\n execSet: Set<string>;\n} {\n if (entries.length === 0) {\n return fail(\"NOT_FOUND\", \"archive contained no entries\");\n }\n\n const prefix = entries[0].path.split(\"/\")[0];\n if (!prefix) {\n return fail(\"IO\", \"unable to determine archive prefix\");\n }\n\n const execSet = new Set<string>();\n let entryCount = 0;\n let totalSize = 0;\n let matched = false;\n\n for (const entry of entries) {\n assertSafeTarPath(entry.path);\n if (!ALLOWED_TYPES.has(entry.type)) {\n return fail(\"IO\", `unsupported entry type in archive: ${entry.path}`);\n }\n\n if (entry.path === prefix) {\n continue;\n }\n if (!entry.path.startsWith(`${prefix}/`)) {\n return fail(\"IO\", \"archive has unexpected top-level layout\");\n }\n\n const rel = entry.path.slice(prefix.length + 1);\n if (!rel) {\n continue;\n }\n\n const relToReq = stripRequestedPath(rel, requestedPath);\n if (relToReq === null) {\n continue;\n }\n\n matched = true;\n entryCount += 1;\n if (rel === requestedPath && entry.type === \"File\") {\n return fail(\"INVALID_PATH\", \"requested path is not a directory\");\n }\n if (entry.type === \"File\") {\n totalSize += entry.size ?? 0;\n if (entry.mode & 0o111) {\n execSet.add(relToReq);\n }\n }\n }\n\n if (!matched) {\n return fail(\"NOT_FOUND\", \"requested path not found in archive\");\n }\n if (entryCount > MAX_SKILLREF_FILES) {\n return fail(\"SIZE_LIMIT\", `extracted entry count ${entryCount} exceeds ${MAX_SKILLREF_FILES}`);\n }\n if (totalSize > MAX_SKILLREF_EXTRACT_BYTES) {\n return fail(\"SIZE_LIMIT\", `extracted size ${totalSize} exceeds ${MAX_SKILLREF_EXTRACT_BYTES}`);\n }\n\n return { prefix, execSet };\n}\n\nfunction stripRequestedPath(rel: string, requestedPath: string): string | null {\n if (rel === requestedPath) {\n return \"\";\n }\n const prefix = requestedPath + \"/\";\n if (rel.startsWith(prefix)) {\n return rel.slice(prefix.length);\n }\n return null;\n}\n\nfunction isUnderPath(entryPath: string, prefix: string, requestedPath: string): boolean {\n if (entryPath === prefix) {\n return false;\n }\n if (!entryPath.startsWith(`${prefix}/`)) {\n return false;\n }\n const rel = entryPath.slice(prefix.length + 1);\n if (!rel) {\n return false;\n }\n if (rel === requestedPath || rel.startsWith(requestedPath + \"/\")) {\n return true;\n }\n return false;\n}\n","import { SKILLPACK_HEADER, SKILLREF_HEADER } from \"./constants\";\n\nexport type SkillValueType = \"skillpack\" | \"skillref\" | \"string\";\n\nexport function detectSkillValueType(value: string): SkillValueType {\n if (value.startsWith(SKILLPACK_HEADER)) return \"skillpack\";\n if (value.startsWith(SKILLREF_HEADER)) return \"skillref\";\n return \"string\";\n}\n","import fs from \"node:fs/promises\";\nimport process from \"node:process\";\nimport { fail } from \"./errors\";\nimport { createSkillpackFromDir } from \"./skillpack\";\nimport { createSkillrefValue } from \"./skillref\";\n\nexport type SaveInput = { kind: \"string\" | \"skillpack\" | \"skillref\"; value: string };\n\nexport interface SaveOptions {\n append: boolean;\n file?: string;\n value?: string;\n dir?: string;\n url?: string;\n ref?: string;\n path?: string;\n}\n\nexport async function resolveSaveInput(\n resource: string,\n opts: SaveOptions,\n stdinIsTTY: boolean = Boolean(process.stdin.isTTY)\n): Promise<SaveInput> {\n const hasFile = typeof opts.file === \"string\";\n const hasValue = typeof opts.value === \"string\";\n const hasDir = typeof opts.dir === \"string\";\n const urlFlagsUsed = Boolean(opts.url || opts.ref || opts.path);\n const hasUrl = Boolean(opts.url && opts.path);\n const explicitCount = [hasFile, hasValue, hasDir, hasUrl].filter(Boolean).length;\n const hasStdin = !stdinIsTTY && explicitCount === 0;\n\n if (urlFlagsUsed && !hasUrl) {\n return fail(\"INVALID_INPUT\", \"--url and --path must be provided together\");\n }\n\n const methods = explicitCount + (hasStdin ? 1 : 0);\n if (methods !== 1) {\n return fail(\"INVALID_INPUT\", \"exactly one input method must be used\");\n }\n\n if (hasDir && resource !== \"skill\") {\n return fail(\"INVALID_INPUT\", \"--dir is only valid for skill save\");\n }\n if (hasUrl && resource !== \"skill\") {\n return fail(\"INVALID_INPUT\", \"--url/--ref/--path are only valid for skill save\");\n }\n if (opts.append && (hasDir || hasUrl)) {\n return fail(\"INVALID_INPUT\", \"--append cannot be used with --dir or --url\");\n }\n\n if (hasDir) {\n const value = await createSkillpackFromDir(opts.dir as string);\n return { kind: \"skillpack\", value };\n }\n\n if (hasUrl) {\n const value = createSkillrefValue(opts.url as string, opts.path as string, opts.ref as string | undefined);\n return { kind: \"skillref\", value };\n }\n\n if (hasFile) {\n const content = await fs.readFile(opts.file as string, \"utf8\");\n return { kind: \"string\", value: content };\n }\n\n if (hasValue) {\n return { kind: \"string\", value: opts.value as string };\n }\n\n const stdin = await readStdin();\n return { kind: \"string\", value: stdin };\n}\n\nasync function readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n let data = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk) => {\n data += chunk;\n });\n process.stdin.on(\"end\", () => resolve(data));\n process.stdin.on(\"error\", reject);\n });\n}\n"],"mappings":"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","names":["import_node_util","import_node_process","import_node_path","import_promises","import_node_fs","path","os","fs","import_promises","import_node_path","path","import_promises","import_node_path","import_node_os","import_tar","import_promises","import_node_path","import_promises","path","fs","fs","path","import_promises","import_node_path","fs","path","import_node_path","path","tar","fs","path","os","tar","zlib","import_promises","import_node_path","import_node_os","import_node_fs","import_tar","ALLOWED_TYPES","fs","path","os","tar","import_promises","process","fs","process","path","fs"]}
|
|
@@ -3,7 +3,7 @@ name: ctxbin
|
|
|
3
3
|
description: Use when working with ctxbin to save and load ctx, agent, and skill context.
|
|
4
4
|
metadata:
|
|
5
5
|
short-description: ctxbin workflow
|
|
6
|
-
version: 1.0
|
|
6
|
+
version: 1.1.0
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# ctxbin Skill
|
|
@@ -17,12 +17,13 @@ Prefer `npx ctxbin ...` when running commands in agent workflows.
|
|
|
17
17
|
|
|
18
18
|
```
|
|
19
19
|
key = {project}/{branch}
|
|
20
|
-
project =
|
|
20
|
+
project = package.json "name" field, or folder name if no package.json
|
|
21
21
|
branch = git rev-parse --abbrev-ref HEAD
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
> **Note:**
|
|
25
|
-
> If the
|
|
24
|
+
> **Note:** If `package.json` exists, the `name` field is used as the project name.
|
|
25
|
+
> If the name differs from the folder name, a warning is printed.
|
|
26
|
+
> Without `package.json`, the folder name is used. Use an explicit key if needed.
|
|
26
27
|
|
|
27
28
|
### Save (most common)
|
|
28
29
|
```bash
|
package/package.json
CHANGED
package/skills/ctxbin/SKILL.md
CHANGED
|
@@ -9,12 +9,13 @@ Prefer `npx ctxbin ...` when running commands in agent workflows.
|
|
|
9
9
|
|
|
10
10
|
```
|
|
11
11
|
key = {project}/{branch}
|
|
12
|
-
project =
|
|
12
|
+
project = package.json "name" field, or folder name if no package.json
|
|
13
13
|
branch = git rev-parse --abbrev-ref HEAD
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
> **Note:**
|
|
17
|
-
> If the
|
|
16
|
+
> **Note:** If `package.json` exists, the `name` field is used as the project name.
|
|
17
|
+
> If the name differs from the folder name, a warning is printed.
|
|
18
|
+
> Without `package.json`, the folder name is used. Use an explicit key if needed.
|
|
18
19
|
|
|
19
20
|
### Save (most common)
|
|
20
21
|
```bash
|