@aipm-registry/cli 0.4.0 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +343 -143
- package/dist/bin.cjs.map +4 -4
- package/package.json +3 -3
package/dist/bin.cjs
CHANGED
|
@@ -6,8 +6,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __esm = (fn, res) => function __init() {
|
|
10
|
-
|
|
9
|
+
var __esm = (fn, res, err) => function __init() {
|
|
10
|
+
if (err) throw err[0];
|
|
11
|
+
try {
|
|
12
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
13
|
+
} catch (e) {
|
|
14
|
+
throw err = [e], e;
|
|
15
|
+
}
|
|
11
16
|
};
|
|
12
17
|
var __export = (target, all) => {
|
|
13
18
|
for (var name in all)
|
|
@@ -3837,7 +3842,7 @@ var init_types = __esm({
|
|
|
3837
3842
|
...processCreateParams(params)
|
|
3838
3843
|
});
|
|
3839
3844
|
};
|
|
3840
|
-
BRAND = Symbol("zod_brand");
|
|
3845
|
+
BRAND = /* @__PURE__ */ Symbol("zod_brand");
|
|
3841
3846
|
ZodBranded = class extends ZodType {
|
|
3842
3847
|
_parse(input2) {
|
|
3843
3848
|
const { ctx } = this._processInputParams(input2);
|
|
@@ -4011,14 +4016,14 @@ var init_types = __esm({
|
|
|
4011
4016
|
onumber = () => numberType().optional();
|
|
4012
4017
|
oboolean = () => booleanType().optional();
|
|
4013
4018
|
coerce = {
|
|
4014
|
-
string: (arg) => ZodString.create({ ...arg, coerce: true }),
|
|
4015
|
-
number: (arg) => ZodNumber.create({ ...arg, coerce: true }),
|
|
4016
|
-
boolean: (arg) => ZodBoolean.create({
|
|
4019
|
+
string: ((arg) => ZodString.create({ ...arg, coerce: true })),
|
|
4020
|
+
number: ((arg) => ZodNumber.create({ ...arg, coerce: true })),
|
|
4021
|
+
boolean: ((arg) => ZodBoolean.create({
|
|
4017
4022
|
...arg,
|
|
4018
4023
|
coerce: true
|
|
4019
|
-
}),
|
|
4020
|
-
bigint: (arg) => ZodBigInt.create({ ...arg, coerce: true }),
|
|
4021
|
-
date: (arg) => ZodDate.create({ ...arg, coerce: true })
|
|
4024
|
+
})),
|
|
4025
|
+
bigint: ((arg) => ZodBigInt.create({ ...arg, coerce: true })),
|
|
4026
|
+
date: ((arg) => ZodDate.create({ ...arg, coerce: true }))
|
|
4022
4027
|
};
|
|
4023
4028
|
NEVER = INVALID;
|
|
4024
4029
|
}
|
|
@@ -4178,8 +4183,8 @@ var init_manifest = __esm({
|
|
|
4178
4183
|
"use strict";
|
|
4179
4184
|
init_zod();
|
|
4180
4185
|
init_scope_name();
|
|
4181
|
-
AiToolSchema = external_exports.enum(["cursor", "claude", "*"]);
|
|
4182
|
-
ALL_TOOLS = ["cursor", "claude"];
|
|
4186
|
+
AiToolSchema = external_exports.enum(["cursor", "claude", "codex", "*"]);
|
|
4187
|
+
ALL_TOOLS = ["cursor", "claude", "codex"];
|
|
4183
4188
|
PackageExampleSchema = external_exports.object({
|
|
4184
4189
|
title: external_exports.string().trim().min(1).max(80),
|
|
4185
4190
|
description: external_exports.string().trim().min(1).max(240).optional(),
|
|
@@ -4326,6 +4331,8 @@ async function detectToolsInProject(projectRoot) {
|
|
|
4326
4331
|
detected.push("cursor");
|
|
4327
4332
|
if (await pathExists((0, import_node_path2.join)(projectRoot, ".claude")))
|
|
4328
4333
|
detected.push("claude");
|
|
4334
|
+
if (await pathExists((0, import_node_path2.join)(projectRoot, ".codex")))
|
|
4335
|
+
detected.push("codex");
|
|
4329
4336
|
return detected;
|
|
4330
4337
|
}
|
|
4331
4338
|
function manifestAllowsTool(manifest, tool) {
|
|
@@ -4370,23 +4377,57 @@ var init_detect_tools = __esm({
|
|
|
4370
4377
|
}
|
|
4371
4378
|
});
|
|
4372
4379
|
|
|
4373
|
-
// ../../packages/adapter-
|
|
4374
|
-
|
|
4380
|
+
// ../../packages/adapter-sdk/dist/index.js
|
|
4381
|
+
async function writeSkillDirectory(skillDir, input2) {
|
|
4382
|
+
const entryPath = (0, import_node_path3.join)(skillDir, "SKILL.md");
|
|
4383
|
+
const seen = /* @__PURE__ */ new Set(["skill.md"]);
|
|
4384
|
+
const files = (input2.supportingFiles ?? []).map((file) => {
|
|
4385
|
+
const normalized = (0, import_node_path3.normalize)(file.path);
|
|
4386
|
+
const target = (0, import_node_path3.resolve)(skillDir, normalized);
|
|
4387
|
+
const fromSkillDir = (0, import_node_path3.relative)(skillDir, target);
|
|
4388
|
+
return { file, normalized, target, fromSkillDir, key: fromSkillDir.toLowerCase() };
|
|
4389
|
+
});
|
|
4390
|
+
for (const { file, normalized, fromSkillDir, key } of files) {
|
|
4391
|
+
if (!normalized || normalized === "." || (0, import_node_path3.isAbsolute)(normalized) || fromSkillDir === ".." || fromSkillDir.startsWith(`..${import_node_path3.sep}`) || (0, import_node_path3.isAbsolute)(fromSkillDir) || seen.has(key)) {
|
|
4392
|
+
throw new Error(`Unsafe or duplicate skill supporting file path: ${file.path}`);
|
|
4393
|
+
}
|
|
4394
|
+
seen.add(key);
|
|
4395
|
+
}
|
|
4396
|
+
await (0, import_promises2.mkdir)(skillDir, { recursive: true });
|
|
4397
|
+
await (0, import_promises2.writeFile)(entryPath, input2.skillMarkdown, "utf8");
|
|
4398
|
+
const writtenPaths = [entryPath];
|
|
4399
|
+
for (const { file, target } of files) {
|
|
4400
|
+
await (0, import_promises2.mkdir)((0, import_node_path3.dirname)(target), { recursive: true });
|
|
4401
|
+
await (0, import_promises2.writeFile)(target, file.content);
|
|
4402
|
+
if (file.mode !== void 0)
|
|
4403
|
+
await (0, import_promises2.chmod)(target, file.mode & 511);
|
|
4404
|
+
writtenPaths.push(target);
|
|
4405
|
+
}
|
|
4406
|
+
return { writtenPaths };
|
|
4407
|
+
}
|
|
4408
|
+
var import_promises2, import_node_path3;
|
|
4375
4409
|
var init_dist2 = __esm({
|
|
4376
|
-
"../../packages/adapter-
|
|
4410
|
+
"../../packages/adapter-sdk/dist/index.js"() {
|
|
4377
4411
|
"use strict";
|
|
4378
4412
|
import_promises2 = require("node:fs/promises");
|
|
4379
4413
|
import_node_path3 = require("node:path");
|
|
4414
|
+
}
|
|
4415
|
+
});
|
|
4416
|
+
|
|
4417
|
+
// ../../packages/adapter-claude/dist/index.js
|
|
4418
|
+
var import_node_path4, ClaudeSkillAdapter, claudeSkillAdapter;
|
|
4419
|
+
var init_dist3 = __esm({
|
|
4420
|
+
"../../packages/adapter-claude/dist/index.js"() {
|
|
4421
|
+
"use strict";
|
|
4422
|
+
import_node_path4 = require("node:path");
|
|
4423
|
+
init_dist2();
|
|
4380
4424
|
init_dist();
|
|
4381
4425
|
ClaudeSkillAdapter = class {
|
|
4382
4426
|
tool = "claude";
|
|
4383
4427
|
async installSkill(input2) {
|
|
4384
4428
|
const short = shortNameFromScopeName(input2.packageName);
|
|
4385
|
-
const skillDir = (0,
|
|
4386
|
-
|
|
4387
|
-
const filePath = (0, import_node_path3.join)(skillDir, "SKILL.md");
|
|
4388
|
-
await (0, import_promises2.writeFile)(filePath, input2.skillMarkdown, "utf8");
|
|
4389
|
-
return { writtenPaths: [filePath] };
|
|
4429
|
+
const skillDir = (0, import_node_path4.join)(input2.projectRoot, ".claude", "skills", short);
|
|
4430
|
+
return writeSkillDirectory(skillDir, input2);
|
|
4390
4431
|
}
|
|
4391
4432
|
};
|
|
4392
4433
|
claudeSkillAdapter = new ClaudeSkillAdapter();
|
|
@@ -4394,20 +4435,20 @@ var init_dist2 = __esm({
|
|
|
4394
4435
|
});
|
|
4395
4436
|
|
|
4396
4437
|
// ../../packages/adapter-cursor/dist/index.js
|
|
4397
|
-
var import_promises3,
|
|
4398
|
-
var
|
|
4438
|
+
var import_promises3, import_node_path5, CursorSkillAdapter, cursorSkillAdapter;
|
|
4439
|
+
var init_dist4 = __esm({
|
|
4399
4440
|
"../../packages/adapter-cursor/dist/index.js"() {
|
|
4400
4441
|
"use strict";
|
|
4401
4442
|
import_promises3 = require("node:fs/promises");
|
|
4402
|
-
|
|
4443
|
+
import_node_path5 = require("node:path");
|
|
4403
4444
|
init_dist();
|
|
4404
4445
|
CursorSkillAdapter = class {
|
|
4405
4446
|
tool = "cursor";
|
|
4406
4447
|
async installSkill(input2) {
|
|
4407
4448
|
const short = shortNameFromScopeName(input2.packageName);
|
|
4408
|
-
const skillsDir = (0,
|
|
4449
|
+
const skillsDir = (0, import_node_path5.join)(input2.projectRoot, ".cursor", "aipm", "skills");
|
|
4409
4450
|
await (0, import_promises3.mkdir)(skillsDir, { recursive: true });
|
|
4410
|
-
const filePath = (0,
|
|
4451
|
+
const filePath = (0, import_node_path5.join)(skillsDir, `${short}.md`);
|
|
4411
4452
|
await (0, import_promises3.writeFile)(filePath, input2.skillMarkdown, "utf8");
|
|
4412
4453
|
return { writtenPaths: [filePath] };
|
|
4413
4454
|
}
|
|
@@ -4416,6 +4457,26 @@ var init_dist3 = __esm({
|
|
|
4416
4457
|
}
|
|
4417
4458
|
});
|
|
4418
4459
|
|
|
4460
|
+
// ../../packages/adapter-codex/dist/index.js
|
|
4461
|
+
var import_node_path6, CodexSkillAdapter, codexSkillAdapter;
|
|
4462
|
+
var init_dist5 = __esm({
|
|
4463
|
+
"../../packages/adapter-codex/dist/index.js"() {
|
|
4464
|
+
"use strict";
|
|
4465
|
+
import_node_path6 = require("node:path");
|
|
4466
|
+
init_dist2();
|
|
4467
|
+
init_dist();
|
|
4468
|
+
CodexSkillAdapter = class {
|
|
4469
|
+
tool = "codex";
|
|
4470
|
+
async installSkill(input2) {
|
|
4471
|
+
const short = shortNameFromScopeName(input2.packageName);
|
|
4472
|
+
const skillDir = (0, import_node_path6.join)(input2.projectRoot, ".agents", "skills", short);
|
|
4473
|
+
return writeSkillDirectory(skillDir, input2);
|
|
4474
|
+
}
|
|
4475
|
+
};
|
|
4476
|
+
codexSkillAdapter = new CodexSkillAdapter();
|
|
4477
|
+
}
|
|
4478
|
+
});
|
|
4479
|
+
|
|
4419
4480
|
// ../../packages/engine/dist/install-skill.js
|
|
4420
4481
|
async function installSkillPackage(options) {
|
|
4421
4482
|
const tools = await resolveInstallTools({
|
|
@@ -4425,7 +4486,7 @@ async function installSkillPackage(options) {
|
|
|
4425
4486
|
explicitTarget: options.explicitTarget
|
|
4426
4487
|
});
|
|
4427
4488
|
if (tools.length === 0) {
|
|
4428
|
-
throw new Error("No AI tool detected (.cursor
|
|
4489
|
+
throw new Error("No AI tool detected (.cursor/, .claude/, or .codex/). Use --target cursor|claude|codex|* or set preferredTools in aipm.package.json.");
|
|
4429
4490
|
}
|
|
4430
4491
|
const installed = {};
|
|
4431
4492
|
for (const tool of tools) {
|
|
@@ -4434,6 +4495,7 @@ async function installSkillPackage(options) {
|
|
|
4434
4495
|
packageName: options.manifest.name,
|
|
4435
4496
|
version: options.manifest.version,
|
|
4436
4497
|
skillMarkdown: options.skillMarkdown,
|
|
4498
|
+
supportingFiles: options.supportingFiles,
|
|
4437
4499
|
projectRoot: options.projectRoot
|
|
4438
4500
|
});
|
|
4439
4501
|
installed[tool] = result.writtenPaths;
|
|
@@ -4444,12 +4506,14 @@ var adapters;
|
|
|
4444
4506
|
var init_install_skill = __esm({
|
|
4445
4507
|
"../../packages/engine/dist/install-skill.js"() {
|
|
4446
4508
|
"use strict";
|
|
4447
|
-
init_dist2();
|
|
4448
4509
|
init_dist3();
|
|
4510
|
+
init_dist4();
|
|
4511
|
+
init_dist5();
|
|
4449
4512
|
init_detect_tools();
|
|
4450
4513
|
adapters = {
|
|
4451
4514
|
cursor: cursorSkillAdapter,
|
|
4452
|
-
claude: claudeSkillAdapter
|
|
4515
|
+
claude: claudeSkillAdapter,
|
|
4516
|
+
codex: codexSkillAdapter
|
|
4453
4517
|
};
|
|
4454
4518
|
}
|
|
4455
4519
|
});
|
|
@@ -4461,7 +4525,7 @@ __export(dist_exports, {
|
|
|
4461
4525
|
installSkillPackage: () => installSkillPackage,
|
|
4462
4526
|
resolveInstallTools: () => resolveInstallTools
|
|
4463
4527
|
});
|
|
4464
|
-
var
|
|
4528
|
+
var init_dist6 = __esm({
|
|
4465
4529
|
"../../packages/engine/dist/index.js"() {
|
|
4466
4530
|
"use strict";
|
|
4467
4531
|
init_detect_tools();
|
|
@@ -7841,25 +7905,34 @@ var program = new Command();
|
|
|
7841
7905
|
var import_node_crypto3 = require("node:crypto");
|
|
7842
7906
|
var import_node_child_process4 = require("node:child_process");
|
|
7843
7907
|
var import_node_http = require("node:http");
|
|
7844
|
-
var
|
|
7845
|
-
var
|
|
7908
|
+
var import_promises12 = require("node:fs/promises");
|
|
7909
|
+
var import_node_path17 = require("node:path");
|
|
7846
7910
|
var import_node_process5 = require("node:process");
|
|
7847
7911
|
init_dist();
|
|
7848
|
-
|
|
7912
|
+
init_dist6();
|
|
7849
7913
|
|
|
7850
7914
|
// src/pack.ts
|
|
7851
7915
|
var import_node_child_process2 = require("node:child_process");
|
|
7852
7916
|
var import_node_util3 = require("node:util");
|
|
7853
7917
|
var import_promises5 = require("node:fs/promises");
|
|
7854
|
-
var
|
|
7918
|
+
var import_node_path8 = require("node:path");
|
|
7855
7919
|
var import_node_os = require("node:os");
|
|
7856
7920
|
|
|
7857
7921
|
// src/publish-state.ts
|
|
7858
7922
|
var import_node_crypto = require("node:crypto");
|
|
7859
7923
|
var import_promises4 = require("node:fs/promises");
|
|
7860
|
-
var
|
|
7924
|
+
var import_node_path7 = require("node:path");
|
|
7861
7925
|
init_dist();
|
|
7862
|
-
|
|
7926
|
+
|
|
7927
|
+
// src/recommend-cmd.ts
|
|
7928
|
+
function recommendCmd(command, stream = process.stderr) {
|
|
7929
|
+
const quoted = `"${command}"`;
|
|
7930
|
+
if (!stream.isTTY) return quoted;
|
|
7931
|
+
return `\x1B[36m${quoted}\x1B[39m`;
|
|
7932
|
+
}
|
|
7933
|
+
|
|
7934
|
+
// src/publish-state.ts
|
|
7935
|
+
var STATE_PATH = (0, import_node_path7.join)(".aipm", "publish-state.json");
|
|
7863
7936
|
var IGNORE_FILE = ".aipmignore";
|
|
7864
7937
|
var MAX_PACKAGE_BYTES = 50 * 1024 * 1024;
|
|
7865
7938
|
var EXCLUDED_SEGMENTS = /* @__PURE__ */ new Set([".aipm", ".git", "node_modules", "dist", ".next"]);
|
|
@@ -7874,11 +7947,11 @@ var SECRET_PATTERNS = [
|
|
|
7874
7947
|
/<publishData/i
|
|
7875
7948
|
];
|
|
7876
7949
|
function publishStatePath(root) {
|
|
7877
|
-
return (0,
|
|
7950
|
+
return (0, import_node_path7.join)(root, STATE_PATH);
|
|
7878
7951
|
}
|
|
7879
7952
|
function normalizePublishPath(root, filePath) {
|
|
7880
|
-
const abs = (0,
|
|
7881
|
-
const rel = (0,
|
|
7953
|
+
const abs = (0, import_node_path7.resolve)(root, filePath);
|
|
7954
|
+
const rel = (0, import_node_path7.normalize)((0, import_node_path7.relative)(root, abs)).split(import_node_path7.sep).join("/");
|
|
7882
7955
|
if (!rel || rel === ".") return ".";
|
|
7883
7956
|
if (rel.startsWith("../") || rel === ".." || rel.startsWith("/")) {
|
|
7884
7957
|
throw new Error(`Path is outside the skill folder: ${filePath}`);
|
|
@@ -7895,7 +7968,7 @@ function isExcludedPublishPath(rel) {
|
|
|
7895
7968
|
}
|
|
7896
7969
|
async function readAipmIgnore(root) {
|
|
7897
7970
|
try {
|
|
7898
|
-
const raw = await (0, import_promises4.readFile)((0,
|
|
7971
|
+
const raw = await (0, import_promises4.readFile)((0, import_node_path7.join)(root, IGNORE_FILE), "utf8");
|
|
7899
7972
|
return raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
7900
7973
|
} catch {
|
|
7901
7974
|
return [];
|
|
@@ -7944,14 +8017,14 @@ async function readPublishState(root) {
|
|
|
7944
8017
|
}
|
|
7945
8018
|
async function writePublishState(root, state) {
|
|
7946
8019
|
const path2 = publishStatePath(root);
|
|
7947
|
-
await (0, import_promises4.mkdir)((0,
|
|
8020
|
+
await (0, import_promises4.mkdir)((0, import_node_path7.dirname)(path2), { recursive: true });
|
|
7948
8021
|
const files = [...state.files].sort((a, b) => a.path.localeCompare(b.path));
|
|
7949
8022
|
await (0, import_promises4.writeFile)(path2, JSON.stringify({ schemaVersion: "0.1", files }, null, 2) + "\n", "utf8");
|
|
7950
8023
|
}
|
|
7951
8024
|
async function expandPublishPath(root, rel) {
|
|
7952
8025
|
if (isExcludedPublishPath(rel)) return [];
|
|
7953
8026
|
if (await isIgnoredByAipmIgnore(root, rel)) return [];
|
|
7954
|
-
const abs = (0,
|
|
8027
|
+
const abs = (0, import_node_path7.join)(root, rel);
|
|
7955
8028
|
const info = await (0, import_promises4.stat)(abs);
|
|
7956
8029
|
if (info.isFile()) return [rel];
|
|
7957
8030
|
if (!info.isDirectory()) return [];
|
|
@@ -7971,7 +8044,7 @@ async function addPublishFiles(root, paths) {
|
|
|
7971
8044
|
for (const rel of files) {
|
|
7972
8045
|
if (isExcludedPublishPath(rel)) continue;
|
|
7973
8046
|
if (await isIgnoredByAipmIgnore(root, rel)) continue;
|
|
7974
|
-
const hashed = await fileHash((0,
|
|
8047
|
+
const hashed = await fileHash((0, import_node_path7.join)(root, rel));
|
|
7975
8048
|
byPath.set(rel, { path: rel, ...hashed });
|
|
7976
8049
|
}
|
|
7977
8050
|
}
|
|
@@ -7994,11 +8067,13 @@ async function resetPublishState(root) {
|
|
|
7994
8067
|
}
|
|
7995
8068
|
async function readManifest(root) {
|
|
7996
8069
|
try {
|
|
7997
|
-
const raw = await (0, import_promises4.readFile)((0,
|
|
8070
|
+
const raw = await (0, import_promises4.readFile)((0, import_node_path7.join)(root, "aipm.manifest.json"), "utf8");
|
|
7998
8071
|
return PackageManifestSchema.parse(JSON.parse(raw));
|
|
7999
8072
|
} catch (error) {
|
|
8000
8073
|
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
8001
|
-
throw new Error(
|
|
8074
|
+
throw new Error(
|
|
8075
|
+
`No aipm.manifest.json found. Run ${recommendCmd("aipm publish init --name <@org/skill>")}.`
|
|
8076
|
+
);
|
|
8002
8077
|
}
|
|
8003
8078
|
throw error;
|
|
8004
8079
|
}
|
|
@@ -8014,7 +8089,9 @@ function installReferencedFiles(manifest) {
|
|
|
8014
8089
|
async function validatePublishState(root) {
|
|
8015
8090
|
const manifest = await readManifest(root);
|
|
8016
8091
|
const state = await readPublishState(root);
|
|
8017
|
-
if (state.files.length === 0)
|
|
8092
|
+
if (state.files.length === 0) {
|
|
8093
|
+
throw new Error(`No files staged. Run ${recommendCmd("aipm publish add <files...>")}.`);
|
|
8094
|
+
}
|
|
8018
8095
|
const staged = new Set(state.files.map((entry) => entry.path));
|
|
8019
8096
|
if (!staged.has("aipm.manifest.json")) throw new Error("aipm.manifest.json must be staged.");
|
|
8020
8097
|
if (!staged.has(manifest.entry)) throw new Error(`Manifest entry must be staged: ${manifest.entry}`);
|
|
@@ -8027,12 +8104,14 @@ async function validatePublishState(root) {
|
|
|
8027
8104
|
if (await isIgnoredByAipmIgnore(root, entry.path)) {
|
|
8028
8105
|
throw new Error(`Refusing to publish ignored path: ${entry.path}`);
|
|
8029
8106
|
}
|
|
8030
|
-
const abs = (0,
|
|
8107
|
+
const abs = (0, import_node_path7.join)(root, entry.path);
|
|
8031
8108
|
const info = await (0, import_promises4.stat)(abs).catch(() => null);
|
|
8032
8109
|
if (!info?.isFile()) throw new Error(`Staged file is missing: ${entry.path}`);
|
|
8033
8110
|
const hashed = await fileHash(abs);
|
|
8034
8111
|
if (hashed.hash !== entry.hash) {
|
|
8035
|
-
throw new Error(
|
|
8112
|
+
throw new Error(
|
|
8113
|
+
`Staged file changed after add: ${entry.path}. Run ${recommendCmd(`aipm publish add ${entry.path}`)}.`
|
|
8114
|
+
);
|
|
8036
8115
|
}
|
|
8037
8116
|
await assertNoObviousSecrets(abs, entry.path);
|
|
8038
8117
|
size += hashed.size;
|
|
@@ -8044,7 +8123,7 @@ async function statusPublishState(root) {
|
|
|
8044
8123
|
const state = await readPublishState(root);
|
|
8045
8124
|
const rows = [];
|
|
8046
8125
|
for (const entry of state.files) {
|
|
8047
|
-
const current = await fileHash((0,
|
|
8126
|
+
const current = await fileHash((0, import_node_path7.join)(root, entry.path)).catch(() => null);
|
|
8048
8127
|
rows.push({ ...entry, changed: !current || current.hash !== entry.hash });
|
|
8049
8128
|
}
|
|
8050
8129
|
return rows;
|
|
@@ -8052,9 +8131,9 @@ async function statusPublishState(root) {
|
|
|
8052
8131
|
async function copyStagedFiles(root, destination) {
|
|
8053
8132
|
const state = await readPublishState(root);
|
|
8054
8133
|
for (const entry of state.files) {
|
|
8055
|
-
const target = (0,
|
|
8056
|
-
await (0, import_promises4.mkdir)((0,
|
|
8057
|
-
await (0, import_promises4.cp)((0,
|
|
8134
|
+
const target = (0, import_node_path7.join)(destination, entry.path);
|
|
8135
|
+
await (0, import_promises4.mkdir)((0, import_node_path7.dirname)(target), { recursive: true });
|
|
8136
|
+
await (0, import_promises4.cp)((0, import_node_path7.join)(root, entry.path), target);
|
|
8058
8137
|
}
|
|
8059
8138
|
}
|
|
8060
8139
|
|
|
@@ -8068,7 +8147,7 @@ async function packDirectory(dir) {
|
|
|
8068
8147
|
return Buffer.isBuffer(stdout) ? stdout : Buffer.from(stdout);
|
|
8069
8148
|
}
|
|
8070
8149
|
async function packStagedFiles(root) {
|
|
8071
|
-
const tempDir = await (0, import_promises5.mkdtemp)((0,
|
|
8150
|
+
const tempDir = await (0, import_promises5.mkdtemp)((0, import_node_path8.join)((0, import_node_os.tmpdir)(), "aipm-publish-stage-"));
|
|
8072
8151
|
try {
|
|
8073
8152
|
await copyStagedFiles(root, tempDir);
|
|
8074
8153
|
return await packDirectory(tempDir);
|
|
@@ -8078,10 +8157,10 @@ async function packStagedFiles(root) {
|
|
|
8078
8157
|
}
|
|
8079
8158
|
async function unpackTarballToDirectory(tarball) {
|
|
8080
8159
|
const { mkdtemp: mkdtemp2, writeFile: writeFile8 } = await import("node:fs/promises");
|
|
8081
|
-
const { join:
|
|
8160
|
+
const { join: join16 } = await import("node:path");
|
|
8082
8161
|
const { tmpdir: tmpdir2 } = await import("node:os");
|
|
8083
|
-
const tempDir = await mkdtemp2(
|
|
8084
|
-
const tgzPath =
|
|
8162
|
+
const tempDir = await mkdtemp2(join16(tmpdir2(), "aipm-install-"));
|
|
8163
|
+
const tgzPath = join16(tempDir, "pkg.tgz");
|
|
8085
8164
|
await writeFile8(tgzPath, tarball);
|
|
8086
8165
|
await execFileAsync("tar", ["-xzf", tgzPath, "-C", tempDir]);
|
|
8087
8166
|
return tempDir;
|
|
@@ -8095,7 +8174,7 @@ function registryFetchError(registry, cause) {
|
|
|
8095
8174
|
const msg = cause instanceof Error ? cause.message : String(cause);
|
|
8096
8175
|
if (msg === "fetch failed" || msg.includes("ECONNREFUSED") || msg.includes("ENOTFOUND") || msg.includes("timed out") || msg.includes("aborted")) {
|
|
8097
8176
|
return new Error(
|
|
8098
|
-
`Cannot reach registry at ${registry}. Check your connection or pass --registry <url
|
|
8177
|
+
`Cannot reach registry at ${registry}. Check your connection or pass ${recommendCmd("--registry <url>")}.`
|
|
8099
8178
|
);
|
|
8100
8179
|
}
|
|
8101
8180
|
return new Error(`Registry request failed (${registry}): ${msg}`);
|
|
@@ -8116,13 +8195,13 @@ function privateInstallHint(name, status, token) {
|
|
|
8116
8195
|
if (status !== 404 || !name.startsWith("@") || token) {
|
|
8117
8196
|
return `Package not found: ${name} (${status})`;
|
|
8118
8197
|
}
|
|
8119
|
-
return `Package not found: ${name} (${status}). If @org/pkg is private, run aipm login, or set AIPM_TOKEN for CI.`;
|
|
8198
|
+
return `Package not found: ${name} (${status}). If @org/pkg is private, run ${recommendCmd("aipm login")}, or set AIPM_TOKEN for CI.`;
|
|
8120
8199
|
}
|
|
8121
8200
|
function publishTokenHint(name, error) {
|
|
8122
8201
|
if (error === "Publish token required") {
|
|
8123
8202
|
return [
|
|
8124
8203
|
`Publish token required for ${name}.`,
|
|
8125
|
-
`Generate a fresh 5-minute publish token for ${name} from the package dashboard, then retry with AIPM_TOKEN=<token> aipm publish push --yes.`
|
|
8204
|
+
`Generate a fresh 5-minute publish token for ${name} from the package dashboard, then retry with ${recommendCmd("AIPM_TOKEN=<token> aipm publish push --yes")}.`
|
|
8126
8205
|
].join(" ");
|
|
8127
8206
|
}
|
|
8128
8207
|
if (error === "Invalid publish token") {
|
|
@@ -8280,8 +8359,8 @@ async function publishPrompt(registry, input2, accessToken, sampleImage) {
|
|
|
8280
8359
|
// src/auth-store.ts
|
|
8281
8360
|
var import_promises6 = require("node:fs/promises");
|
|
8282
8361
|
var import_node_os2 = require("node:os");
|
|
8283
|
-
var
|
|
8284
|
-
var AUTH_FILE = (0,
|
|
8362
|
+
var import_node_path9 = require("node:path");
|
|
8363
|
+
var AUTH_FILE = (0, import_node_path9.join)((0, import_node_os2.homedir)(), ".aipm", "auth.json");
|
|
8285
8364
|
function normalizeRegistry(registry) {
|
|
8286
8365
|
return registry.replace(/\/$/, "");
|
|
8287
8366
|
}
|
|
@@ -8295,7 +8374,7 @@ async function readAuthStore() {
|
|
|
8295
8374
|
}
|
|
8296
8375
|
}
|
|
8297
8376
|
async function writeAuthStore(store) {
|
|
8298
|
-
await (0, import_promises6.mkdir)((0,
|
|
8377
|
+
await (0, import_promises6.mkdir)((0, import_node_path9.dirname)(AUTH_FILE), { recursive: true });
|
|
8299
8378
|
await (0, import_promises6.writeFile)(AUTH_FILE, JSON.stringify(store, null, 2) + "\n", "utf8");
|
|
8300
8379
|
await (0, import_promises6.chmod)(AUTH_FILE, 384).catch(() => void 0);
|
|
8301
8380
|
}
|
|
@@ -8326,19 +8405,19 @@ function isAccessTokenFresh(auth, skewMs = 6e4) {
|
|
|
8326
8405
|
}
|
|
8327
8406
|
|
|
8328
8407
|
// src/install-one.ts
|
|
8329
|
-
|
|
8408
|
+
init_dist6();
|
|
8330
8409
|
var import_promises8 = require("node:fs/promises");
|
|
8331
|
-
var
|
|
8410
|
+
var import_node_path11 = require("node:path");
|
|
8332
8411
|
|
|
8333
8412
|
// src/project-files.ts
|
|
8334
8413
|
var import_promises7 = require("node:fs/promises");
|
|
8335
|
-
var
|
|
8414
|
+
var import_node_path10 = require("node:path");
|
|
8336
8415
|
init_dist();
|
|
8337
8416
|
var PACKAGE_JSON = "aipm.package.json";
|
|
8338
8417
|
var LOCKFILE = "aipm-lock.json";
|
|
8339
8418
|
async function readProjectPackageJson(projectRoot) {
|
|
8340
8419
|
try {
|
|
8341
|
-
const raw = await (0, import_promises7.readFile)((0,
|
|
8420
|
+
const raw = await (0, import_promises7.readFile)((0, import_node_path10.join)(projectRoot, PACKAGE_JSON), "utf8");
|
|
8342
8421
|
return ProjectPackageJsonSchema.parse(JSON.parse(raw));
|
|
8343
8422
|
} catch {
|
|
8344
8423
|
return null;
|
|
@@ -8346,21 +8425,21 @@ async function readProjectPackageJson(projectRoot) {
|
|
|
8346
8425
|
}
|
|
8347
8426
|
async function writeProjectPackageJson(projectRoot, data) {
|
|
8348
8427
|
await (0, import_promises7.writeFile)(
|
|
8349
|
-
(0,
|
|
8428
|
+
(0, import_node_path10.join)(projectRoot, PACKAGE_JSON),
|
|
8350
8429
|
JSON.stringify(data, null, 2) + "\n",
|
|
8351
8430
|
"utf8"
|
|
8352
8431
|
);
|
|
8353
8432
|
}
|
|
8354
8433
|
async function readLockfile(projectRoot) {
|
|
8355
8434
|
try {
|
|
8356
|
-
const raw = await (0, import_promises7.readFile)((0,
|
|
8435
|
+
const raw = await (0, import_promises7.readFile)((0, import_node_path10.join)(projectRoot, LOCKFILE), "utf8");
|
|
8357
8436
|
return LockfileSchema.parse(JSON.parse(raw));
|
|
8358
8437
|
} catch {
|
|
8359
8438
|
return null;
|
|
8360
8439
|
}
|
|
8361
8440
|
}
|
|
8362
8441
|
async function writeLockfile(projectRoot, data) {
|
|
8363
|
-
await (0, import_promises7.writeFile)((0,
|
|
8442
|
+
await (0, import_promises7.writeFile)((0, import_node_path10.join)(projectRoot, LOCKFILE), JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
8364
8443
|
}
|
|
8365
8444
|
function upsertLockEntry(lock, name, entry) {
|
|
8366
8445
|
return {
|
|
@@ -8384,15 +8463,17 @@ function resolveRegistryUrl(project, flag, fallback) {
|
|
|
8384
8463
|
}
|
|
8385
8464
|
function parseTargetFlag(target) {
|
|
8386
8465
|
if (!target) return void 0;
|
|
8387
|
-
if (target === "cursor" || target === "claude" || target === "*")
|
|
8388
|
-
|
|
8466
|
+
if (target === "cursor" || target === "claude" || target === "codex" || target === "*") {
|
|
8467
|
+
return target;
|
|
8468
|
+
}
|
|
8469
|
+
throw new Error('--target must be "cursor", "claude", "codex", or "*"');
|
|
8389
8470
|
}
|
|
8390
8471
|
function parseTargetsFlag(value) {
|
|
8391
8472
|
const targets = value.split(",").map((target) => target.trim()).filter(Boolean);
|
|
8392
8473
|
if (targets.length === 0) throw new Error("At least one target is required.");
|
|
8393
8474
|
for (const target of targets) {
|
|
8394
|
-
if (target !== "cursor" && target !== "claude" && target !== "*") {
|
|
8395
|
-
throw new Error('--targets must contain only "cursor", "claude", and/or "*"');
|
|
8475
|
+
if (target !== "cursor" && target !== "claude" && target !== "codex" && target !== "*") {
|
|
8476
|
+
throw new Error('--targets must contain only "cursor", "claude", "codex", and/or "*"');
|
|
8396
8477
|
}
|
|
8397
8478
|
}
|
|
8398
8479
|
const unique = [...new Set(targets)];
|
|
@@ -8408,13 +8489,13 @@ async function promptForTool() {
|
|
|
8408
8489
|
try {
|
|
8409
8490
|
while (true) {
|
|
8410
8491
|
const answer = await rl.question(
|
|
8411
|
-
"Which AI tool should this skill be installed for? (cursor/claude): "
|
|
8492
|
+
"Which AI tool should this skill be installed for? (cursor/claude/codex): "
|
|
8412
8493
|
);
|
|
8413
8494
|
const normalized = answer.trim().toLowerCase();
|
|
8414
|
-
if (normalized === "cursor" || normalized === "claude") {
|
|
8495
|
+
if (normalized === "cursor" || normalized === "claude" || normalized === "codex") {
|
|
8415
8496
|
return normalized;
|
|
8416
8497
|
}
|
|
8417
|
-
console.log('Please enter "cursor" or "
|
|
8498
|
+
console.log('Please enter "cursor", "claude", or "codex".');
|
|
8418
8499
|
}
|
|
8419
8500
|
} finally {
|
|
8420
8501
|
rl.close();
|
|
@@ -8433,7 +8514,7 @@ async function promptForConfirmation(question) {
|
|
|
8433
8514
|
|
|
8434
8515
|
// src/install-one.ts
|
|
8435
8516
|
function normalizeRelativePath(path2) {
|
|
8436
|
-
return (0,
|
|
8517
|
+
return (0, import_node_path11.normalize)(path2).split(import_node_path11.sep).join("/");
|
|
8437
8518
|
}
|
|
8438
8519
|
function assertSafeRelativePath(path2) {
|
|
8439
8520
|
const rel = normalizeRelativePath(path2.trim());
|
|
@@ -8444,8 +8525,8 @@ function assertSafeRelativePath(path2) {
|
|
|
8444
8525
|
}
|
|
8445
8526
|
function safeJoin(root, relPath) {
|
|
8446
8527
|
const rel = assertSafeRelativePath(relPath);
|
|
8447
|
-
const target = (0,
|
|
8448
|
-
const fromRoot = normalizeRelativePath((0,
|
|
8528
|
+
const target = (0, import_node_path11.resolve)(root, rel);
|
|
8529
|
+
const fromRoot = normalizeRelativePath((0, import_node_path11.relative)(root, target));
|
|
8449
8530
|
if (fromRoot === ".." || fromRoot.startsWith("../") || fromRoot.startsWith("/")) {
|
|
8450
8531
|
throw new Error(`Unsafe install path: ${relPath}`);
|
|
8451
8532
|
}
|
|
@@ -8456,8 +8537,8 @@ function packageHelperSlug(name) {
|
|
|
8456
8537
|
return `${scope}__${pkg}`;
|
|
8457
8538
|
}
|
|
8458
8539
|
function helperRootFor(configRoot, packageName, version) {
|
|
8459
|
-
const base = (0,
|
|
8460
|
-
return (0,
|
|
8540
|
+
const base = (0, import_node_path11.basename)(configRoot) === ".aipm" ? (0, import_node_path11.join)(configRoot, "helpers") : (0, import_node_path11.join)(configRoot, ".aipm", "helpers");
|
|
8541
|
+
return (0, import_node_path11.join)(base, packageHelperSlug(packageName), version);
|
|
8461
8542
|
}
|
|
8462
8543
|
async function assertSourceFile(packageRoot, relPath) {
|
|
8463
8544
|
const source = safeJoin(packageRoot, relPath);
|
|
@@ -8465,6 +8546,55 @@ async function assertSourceFile(packageRoot, relPath) {
|
|
|
8465
8546
|
if (!info?.isFile()) throw new Error(`Package install file not found: ${relPath}`);
|
|
8466
8547
|
return source;
|
|
8467
8548
|
}
|
|
8549
|
+
function installReferencedFiles2(install) {
|
|
8550
|
+
return [
|
|
8551
|
+
...(install?.mainFiles ?? []).map((file) => file.from),
|
|
8552
|
+
...(install?.helperFiles ?? []).map((file) => file.from)
|
|
8553
|
+
];
|
|
8554
|
+
}
|
|
8555
|
+
function isRootLicenseOrNotice(path2) {
|
|
8556
|
+
return !path2.includes("/") && /^(?:licen[cs]e|notice|copying)(?:$|[._-])/i.test(path2);
|
|
8557
|
+
}
|
|
8558
|
+
async function listRegularPackageFiles(root, current = root) {
|
|
8559
|
+
const files = [];
|
|
8560
|
+
for (const entry of await (0, import_promises8.readdir)(current, { withFileTypes: true })) {
|
|
8561
|
+
const absolute = (0, import_node_path11.join)(current, entry.name);
|
|
8562
|
+
if (entry.isDirectory()) {
|
|
8563
|
+
files.push(...await listRegularPackageFiles(root, absolute));
|
|
8564
|
+
} else if (entry.isFile()) {
|
|
8565
|
+
files.push(normalizeRelativePath((0, import_node_path11.relative)(root, absolute)));
|
|
8566
|
+
}
|
|
8567
|
+
}
|
|
8568
|
+
return files;
|
|
8569
|
+
}
|
|
8570
|
+
async function collectSkillSupportingFiles(packageRoot, manifest) {
|
|
8571
|
+
const entry = assertSafeRelativePath(manifest.entry);
|
|
8572
|
+
const entryDirectory = (0, import_node_path11.dirname)(entry);
|
|
8573
|
+
const excluded = /* @__PURE__ */ new Set([
|
|
8574
|
+
entry,
|
|
8575
|
+
"aipm.manifest.json",
|
|
8576
|
+
"pkg.tgz",
|
|
8577
|
+
...installReferencedFiles2(manifest.install).map(assertSafeRelativePath)
|
|
8578
|
+
]);
|
|
8579
|
+
const supportingFiles = [];
|
|
8580
|
+
for (const sourcePath of await listRegularPackageFiles(packageRoot)) {
|
|
8581
|
+
if (excluded.has(sourcePath)) continue;
|
|
8582
|
+
const fromEntryDirectory = normalizeRelativePath((0, import_node_path11.relative)(entryDirectory, sourcePath));
|
|
8583
|
+
const isEntrySibling = fromEntryDirectory !== ".." && !fromEntryDirectory.startsWith("../") && !fromEntryDirectory.startsWith("/");
|
|
8584
|
+
if (!isEntrySibling && !isRootLicenseOrNotice(sourcePath)) continue;
|
|
8585
|
+
const destinationPath = isEntrySibling ? fromEntryDirectory : (0, import_node_path11.basename)(sourcePath);
|
|
8586
|
+
if (destinationPath.toLowerCase() === "skill.md") {
|
|
8587
|
+
throw new Error(`Package supporting file conflicts with installed SKILL.md: ${sourcePath}`);
|
|
8588
|
+
}
|
|
8589
|
+
const source = safeJoin(packageRoot, sourcePath);
|
|
8590
|
+
supportingFiles.push({
|
|
8591
|
+
path: destinationPath,
|
|
8592
|
+
content: await (0, import_promises8.readFile)(source),
|
|
8593
|
+
mode: (await (0, import_promises8.stat)(source)).mode
|
|
8594
|
+
});
|
|
8595
|
+
}
|
|
8596
|
+
return supportingFiles.sort((a, b) => a.path.localeCompare(b.path));
|
|
8597
|
+
}
|
|
8468
8598
|
async function copyMainFile(input2) {
|
|
8469
8599
|
const source = await assertSourceFile(input2.packageRoot, input2.file.from);
|
|
8470
8600
|
const target = safeJoin(input2.installRoot, input2.file.to);
|
|
@@ -8474,14 +8604,14 @@ async function copyMainFile(input2) {
|
|
|
8474
8604
|
if (overwrite === "skip") return null;
|
|
8475
8605
|
if (overwrite === "fail") throw new Error(`Install target already exists: ${target}`);
|
|
8476
8606
|
}
|
|
8477
|
-
await (0, import_promises8.mkdir)((0,
|
|
8607
|
+
await (0, import_promises8.mkdir)((0, import_node_path11.dirname)(target), { recursive: true });
|
|
8478
8608
|
await (0, import_promises8.cp)(source, target, { force: overwrite === "replace" });
|
|
8479
8609
|
return target;
|
|
8480
8610
|
}
|
|
8481
8611
|
async function copyHelperFile(input2) {
|
|
8482
8612
|
const source = await assertSourceFile(input2.packageRoot, input2.file.from);
|
|
8483
|
-
const target = safeJoin(input2.helperRoot, input2.file.to ?? (0,
|
|
8484
|
-
await (0, import_promises8.mkdir)((0,
|
|
8613
|
+
const target = safeJoin(input2.helperRoot, input2.file.to ?? (0, import_node_path11.basename)(input2.file.from));
|
|
8614
|
+
await (0, import_promises8.mkdir)((0, import_node_path11.dirname)(target), { recursive: true });
|
|
8485
8615
|
await (0, import_promises8.cp)(source, target, { force: true });
|
|
8486
8616
|
return target;
|
|
8487
8617
|
}
|
|
@@ -8544,7 +8674,7 @@ async function installOnePackage(options) {
|
|
|
8544
8674
|
}
|
|
8545
8675
|
let explicitTarget = options.explicitTarget;
|
|
8546
8676
|
let preferredTools = options.project.preferredTools;
|
|
8547
|
-
const { resolveInstallTools: resolveInstallTools2 } = await Promise.resolve().then(() => (
|
|
8677
|
+
const { resolveInstallTools: resolveInstallTools2 } = await Promise.resolve().then(() => (init_dist6(), dist_exports));
|
|
8548
8678
|
let tools = await resolveInstallTools2({
|
|
8549
8679
|
projectRoot: installRoot,
|
|
8550
8680
|
manifest,
|
|
@@ -8554,7 +8684,7 @@ async function installOnePackage(options) {
|
|
|
8554
8684
|
if (tools.length === 0) {
|
|
8555
8685
|
if (options.ci) {
|
|
8556
8686
|
throw new Error(
|
|
8557
|
-
"No tool detected. Use --target cursor|claude|* in CI mode."
|
|
8687
|
+
"No tool detected. Use --target cursor|claude|codex|* in CI mode."
|
|
8558
8688
|
);
|
|
8559
8689
|
}
|
|
8560
8690
|
const choice = await promptForTool();
|
|
@@ -8576,10 +8706,12 @@ async function installOnePackage(options) {
|
|
|
8576
8706
|
const packageRoot = await unpackTarballToDirectory(tarball);
|
|
8577
8707
|
try {
|
|
8578
8708
|
const skillMarkdown = await (0, import_promises8.readFile)(safeJoin(packageRoot, manifest.entry), "utf8");
|
|
8709
|
+
const supportingFiles = await collectSkillSupportingFiles(packageRoot, manifest);
|
|
8579
8710
|
const result = await installSkillPackage({
|
|
8580
8711
|
projectRoot: installRoot,
|
|
8581
8712
|
manifest,
|
|
8582
8713
|
skillMarkdown,
|
|
8714
|
+
supportingFiles,
|
|
8583
8715
|
preferredTools,
|
|
8584
8716
|
explicitTarget
|
|
8585
8717
|
});
|
|
@@ -8623,16 +8755,16 @@ async function installOnePackage(options) {
|
|
|
8623
8755
|
// src/doctor.ts
|
|
8624
8756
|
var import_node_child_process3 = require("node:child_process");
|
|
8625
8757
|
var import_promises9 = require("node:fs/promises");
|
|
8626
|
-
var
|
|
8758
|
+
var import_node_path13 = require("node:path");
|
|
8627
8759
|
var import_node_util4 = require("node:util");
|
|
8628
8760
|
|
|
8629
8761
|
// src/project-root.ts
|
|
8630
8762
|
var import_node_os3 = require("node:os");
|
|
8631
|
-
var
|
|
8763
|
+
var import_node_path12 = require("node:path");
|
|
8632
8764
|
var import_node_process3 = require("node:process");
|
|
8633
8765
|
function globalConfigDir(env2 = process.env) {
|
|
8634
8766
|
const fromEnv = env2.AIPM_HOME?.trim();
|
|
8635
|
-
return fromEnv ? fromEnv.replace(/\/$/, "") : (0,
|
|
8767
|
+
return fromEnv ? fromEnv.replace(/\/$/, "") : (0, import_node_path12.join)((0, import_node_os3.homedir)(), ".aipm");
|
|
8636
8768
|
}
|
|
8637
8769
|
function resolveConfigRoot(options = {}) {
|
|
8638
8770
|
return options.global ? globalConfigDir() : (0, import_node_process3.cwd)();
|
|
@@ -8644,7 +8776,7 @@ function scopeLabel(options) {
|
|
|
8644
8776
|
return options.global ? "global" : "project";
|
|
8645
8777
|
}
|
|
8646
8778
|
function initRequiredMessage(options) {
|
|
8647
|
-
return options.global ?
|
|
8779
|
+
return options.global ? `Run ${recommendCmd("aipm init -g")} first` : `Run ${recommendCmd("aipm init")} first`;
|
|
8648
8780
|
}
|
|
8649
8781
|
|
|
8650
8782
|
// src/doctor.ts
|
|
@@ -8663,11 +8795,11 @@ async function commandOutput(command, args) {
|
|
|
8663
8795
|
}
|
|
8664
8796
|
function npmGlobalBin(prefix) {
|
|
8665
8797
|
if (!prefix) return null;
|
|
8666
|
-
return process.platform === "win32" ? prefix : `${prefix}${
|
|
8798
|
+
return process.platform === "win32" ? prefix : `${prefix}${import_node_path13.sep}bin`;
|
|
8667
8799
|
}
|
|
8668
8800
|
function pathIncludes(pathDir) {
|
|
8669
8801
|
if (!pathDir) return false;
|
|
8670
|
-
return (process.env.PATH ?? "").split(
|
|
8802
|
+
return (process.env.PATH ?? "").split(import_node_path13.delimiter).includes(pathDir);
|
|
8671
8803
|
}
|
|
8672
8804
|
function shellPathHint(binDir) {
|
|
8673
8805
|
if (!binDir) return "Run npm prefix -g and add its bin folder to PATH.";
|
|
@@ -8720,11 +8852,11 @@ async function runDoctor(options) {
|
|
|
8720
8852
|
if (!options.publish) {
|
|
8721
8853
|
const configLabel = options.global ? "Global config" : "Project config";
|
|
8722
8854
|
try {
|
|
8723
|
-
await (0, import_promises9.access)((0,
|
|
8855
|
+
await (0, import_promises9.access)((0, import_node_path13.join)(configRoot, "aipm.package.json"));
|
|
8724
8856
|
checks.push({
|
|
8725
8857
|
name: configLabel,
|
|
8726
8858
|
ok: true,
|
|
8727
|
-
detail: `${(0,
|
|
8859
|
+
detail: `${(0, import_node_path13.join)(configRoot, "aipm.package.json")} exists (${scopeLabel(scope)}).`
|
|
8728
8860
|
});
|
|
8729
8861
|
} catch {
|
|
8730
8862
|
checks.push({
|
|
@@ -8754,7 +8886,7 @@ async function runDoctor(options) {
|
|
|
8754
8886
|
checks.push({
|
|
8755
8887
|
name: "Publish stage",
|
|
8756
8888
|
ok: rows.length > 0 && changed.length === 0,
|
|
8757
|
-
detail: rows.length === 0 ?
|
|
8889
|
+
detail: rows.length === 0 ? `No files staged. Run ${recommendCmd("aipm publish add .")}` : changed.length > 0 ? `${changed.length} staged file(s) changed after add. Run ${recommendCmd("aipm publish add .")} again.` : `${rows.length} file(s) staged.`
|
|
8758
8890
|
});
|
|
8759
8891
|
} catch (error) {
|
|
8760
8892
|
checks.push({
|
|
@@ -8795,7 +8927,7 @@ async function runDoctor(options) {
|
|
|
8795
8927
|
// src/prompt-install.ts
|
|
8796
8928
|
var import_node_crypto2 = require("node:crypto");
|
|
8797
8929
|
var import_promises10 = require("node:fs/promises");
|
|
8798
|
-
var
|
|
8930
|
+
var import_node_path14 = require("node:path");
|
|
8799
8931
|
var PROMPT_SITE_ORIGIN = "https://www.aipm-registry.com";
|
|
8800
8932
|
function parsePromptUrl(value) {
|
|
8801
8933
|
let url;
|
|
@@ -8820,10 +8952,10 @@ function parsePromptUrl(value) {
|
|
|
8820
8952
|
};
|
|
8821
8953
|
}
|
|
8822
8954
|
function promptDirectory(configRoot) {
|
|
8823
|
-
return (0,
|
|
8955
|
+
return (0, import_node_path14.basename)(configRoot) === ".aipm" ? (0, import_node_path14.join)(configRoot, "prompts") : (0, import_node_path14.join)(configRoot, ".aipm", "prompts");
|
|
8824
8956
|
}
|
|
8825
8957
|
function promptSnapshotPath(configRoot, reference) {
|
|
8826
|
-
return (0,
|
|
8958
|
+
return (0, import_node_path14.join)(promptDirectory(configRoot), `${reference.publisher}--${reference.slug}.md`);
|
|
8827
8959
|
}
|
|
8828
8960
|
function canonicalPromptContent(prompt) {
|
|
8829
8961
|
return JSON.stringify({
|
|
@@ -8882,7 +9014,7 @@ function emptyLock() {
|
|
|
8882
9014
|
return { schemaVersion: "0.1", packages: {}, prompts: {} };
|
|
8883
9015
|
}
|
|
8884
9016
|
function installedRelativePath(configRoot, absolutePath) {
|
|
8885
|
-
return (0,
|
|
9017
|
+
return (0, import_node_path14.relative)(configRoot, absolutePath).split("\\").join("/");
|
|
8886
9018
|
}
|
|
8887
9019
|
async function installTrackedPrompt(input2) {
|
|
8888
9020
|
const prompt = await fetchPromptDetail(
|
|
@@ -8903,7 +9035,7 @@ async function installTrackedPrompt(input2) {
|
|
|
8903
9035
|
const fileExists = Boolean(await (0, import_promises10.stat)(outputPath).catch(() => null));
|
|
8904
9036
|
const changed = !existing || existing.contentHash !== contentHash || !fileExists;
|
|
8905
9037
|
if (!input2.updateOnly || changed) {
|
|
8906
|
-
await (0, import_promises10.mkdir)((0,
|
|
9038
|
+
await (0, import_promises10.mkdir)((0, import_node_path14.dirname)(outputPath), { recursive: true });
|
|
8907
9039
|
await (0, import_promises10.writeFile)(outputPath, renderPromptMarkdown(prompt, canonicalReference.url), "utf8");
|
|
8908
9040
|
}
|
|
8909
9041
|
if (input2.track) {
|
|
@@ -8946,12 +9078,12 @@ function resolveTrackedPrompt(project, value) {
|
|
|
8946
9078
|
return parsed ? { ...parsed, alias: value } : null;
|
|
8947
9079
|
}
|
|
8948
9080
|
async function readInstalledPrompt(configRoot, entry) {
|
|
8949
|
-
return (0, import_promises10.readFile)((0,
|
|
9081
|
+
return (0, import_promises10.readFile)((0, import_node_path14.join)(configRoot, entry.installedPath), "utf8");
|
|
8950
9082
|
}
|
|
8951
9083
|
async function removeTrackedPrompt(input2) {
|
|
8952
9084
|
const lock = await readLockfile(input2.configRoot);
|
|
8953
9085
|
const entry = lock?.prompts[input2.reference.alias];
|
|
8954
|
-
if (entry) await (0, import_promises10.rm)((0,
|
|
9086
|
+
if (entry) await (0, import_promises10.rm)((0, import_node_path14.join)(input2.configRoot, entry.installedPath), { force: true });
|
|
8955
9087
|
const prompts = { ...input2.project.prompts };
|
|
8956
9088
|
delete prompts[input2.reference.alias];
|
|
8957
9089
|
await writeProjectPackageJson(input2.configRoot, { ...input2.project, prompts });
|
|
@@ -8962,11 +9094,65 @@ async function removeTrackedPrompt(input2) {
|
|
|
8962
9094
|
}
|
|
8963
9095
|
}
|
|
8964
9096
|
|
|
9097
|
+
// src/remove-package.ts
|
|
9098
|
+
var import_promises11 = require("node:fs/promises");
|
|
9099
|
+
var import_node_path15 = require("node:path");
|
|
9100
|
+
function within(root, path2) {
|
|
9101
|
+
const rel = (0, import_node_path15.relative)((0, import_node_path15.resolve)(root), (0, import_node_path15.resolve)(path2));
|
|
9102
|
+
return rel === "" || !rel.startsWith("..") && !(0, import_node_path15.isAbsolute)(rel);
|
|
9103
|
+
}
|
|
9104
|
+
function trackedInstalledPackagePaths(entry) {
|
|
9105
|
+
return [
|
|
9106
|
+
...Object.values(entry.installed).flat(),
|
|
9107
|
+
...entry.installedAssets?.main ?? [],
|
|
9108
|
+
...entry.installedAssets?.helper ?? []
|
|
9109
|
+
];
|
|
9110
|
+
}
|
|
9111
|
+
async function pruneEmptyParents(path2, roots) {
|
|
9112
|
+
let current = (0, import_node_path15.dirname)(path2);
|
|
9113
|
+
while (roots.some((root) => within(root, current)) && !roots.some((root) => (0, import_node_path15.resolve)(root) === current)) {
|
|
9114
|
+
try {
|
|
9115
|
+
await (0, import_promises11.rmdir)(current);
|
|
9116
|
+
} catch {
|
|
9117
|
+
return;
|
|
9118
|
+
}
|
|
9119
|
+
current = (0, import_node_path15.dirname)(current);
|
|
9120
|
+
}
|
|
9121
|
+
}
|
|
9122
|
+
async function removeInstalledPackageFiles(input2) {
|
|
9123
|
+
const roots = [.../* @__PURE__ */ new Set([(0, import_node_path15.resolve)(input2.configRoot), (0, import_node_path15.resolve)(input2.installRoot)])];
|
|
9124
|
+
const realRoots = await Promise.all(roots.map((root) => (0, import_promises11.realpath)(root).catch(() => root)));
|
|
9125
|
+
const requestedPaths = [...new Set(trackedInstalledPackagePaths(input2.entry).map((path2) => (0, import_node_path15.resolve)(path2)))];
|
|
9126
|
+
const protectedPaths = new Set(
|
|
9127
|
+
(input2.otherEntries ?? []).flatMap(trackedInstalledPackagePaths).map((path2) => (0, import_node_path15.resolve)(path2))
|
|
9128
|
+
);
|
|
9129
|
+
const paths = requestedPaths.filter((path2) => !protectedPaths.has(path2));
|
|
9130
|
+
const unsafe = paths.find((path2) => !roots.some((root) => within(root, path2)));
|
|
9131
|
+
if (unsafe) throw new Error(`Refusing to remove an untrusted path from the lockfile: ${unsafe}`);
|
|
9132
|
+
for (const path2 of paths) {
|
|
9133
|
+
const stat5 = await (0, import_promises11.lstat)(path2).catch(() => null);
|
|
9134
|
+
if (!stat5 || stat5.isSymbolicLink()) continue;
|
|
9135
|
+
const canonicalPath = await (0, import_promises11.realpath)(path2);
|
|
9136
|
+
if (!realRoots.some((root) => within(root, canonicalPath))) {
|
|
9137
|
+
throw new Error(`Refusing to remove a path that resolves outside the install roots: ${path2}`);
|
|
9138
|
+
}
|
|
9139
|
+
}
|
|
9140
|
+
let removed = 0;
|
|
9141
|
+
for (const path2 of paths) {
|
|
9142
|
+
if (await (0, import_promises11.lstat)(path2).catch(() => null)) removed += 1;
|
|
9143
|
+
await (0, import_promises11.rm)(path2, { force: true });
|
|
9144
|
+
}
|
|
9145
|
+
for (const path2 of paths.sort((a, b) => b.length - a.length)) {
|
|
9146
|
+
await pruneEmptyParents(path2, roots);
|
|
9147
|
+
}
|
|
9148
|
+
return { removed, retainedShared: requestedPaths.length - paths.length };
|
|
9149
|
+
}
|
|
9150
|
+
|
|
8965
9151
|
// src/version.ts
|
|
8966
9152
|
var import_node_fs2 = require("node:fs");
|
|
8967
|
-
var
|
|
9153
|
+
var import_node_path16 = require("node:path");
|
|
8968
9154
|
function getCliVersion() {
|
|
8969
|
-
const pkgPath = (0,
|
|
9155
|
+
const pkgPath = (0, import_node_path16.join)(__dirname, "..", "package.json");
|
|
8970
9156
|
const pkg = JSON.parse((0, import_node_fs2.readFileSync)(pkgPath, "utf8"));
|
|
8971
9157
|
return pkg.version;
|
|
8972
9158
|
}
|
|
@@ -9108,23 +9294,23 @@ function skillFolderName(name) {
|
|
|
9108
9294
|
return folder;
|
|
9109
9295
|
}
|
|
9110
9296
|
async function writeStarterFile(path2, content) {
|
|
9111
|
-
await (0,
|
|
9297
|
+
await (0, import_promises12.writeFile)(path2, content, { encoding: "utf8", flag: "wx" });
|
|
9112
9298
|
}
|
|
9113
9299
|
async function inferEntryFromSource(source, fallback) {
|
|
9114
|
-
const sourceInfo = await (0,
|
|
9115
|
-
if (sourceInfo.isFile()) return (0,
|
|
9300
|
+
const sourceInfo = await (0, import_promises12.stat)(source);
|
|
9301
|
+
if (sourceInfo.isFile()) return (0, import_node_path17.basename)(source);
|
|
9116
9302
|
if (!sourceInfo.isDirectory()) return fallback;
|
|
9117
|
-
const entries = await (0,
|
|
9303
|
+
const entries = await (0, import_promises12.readdir)(source);
|
|
9118
9304
|
if (entries.includes(fallback)) return fallback;
|
|
9119
9305
|
return entries.find((entry) => entry.endsWith(".md")) ?? entries.find((entry) => entry.endsWith(".mdc")) ?? fallback;
|
|
9120
9306
|
}
|
|
9121
9307
|
async function copySourceIntoSkillRoot(source, root, sourceLabel) {
|
|
9122
|
-
const sourceInfo = await (0,
|
|
9123
|
-
await (0,
|
|
9308
|
+
const sourceInfo = await (0, import_promises12.stat)(source);
|
|
9309
|
+
await (0, import_promises12.mkdir)(root, { recursive: true });
|
|
9124
9310
|
if (sourceInfo.isDirectory()) {
|
|
9125
|
-
const entries = await (0,
|
|
9311
|
+
const entries = await (0, import_promises12.readdir)(source);
|
|
9126
9312
|
for (const entry of entries) {
|
|
9127
|
-
await (0,
|
|
9313
|
+
await (0, import_promises12.cp)((0, import_node_path17.join)(source, entry), (0, import_node_path17.join)(root, entry), {
|
|
9128
9314
|
recursive: true,
|
|
9129
9315
|
force: false,
|
|
9130
9316
|
errorOnExist: true
|
|
@@ -9133,7 +9319,7 @@ async function copySourceIntoSkillRoot(source, root, sourceLabel) {
|
|
|
9133
9319
|
return;
|
|
9134
9320
|
}
|
|
9135
9321
|
if (sourceInfo.isFile()) {
|
|
9136
|
-
await (0,
|
|
9322
|
+
await (0, import_promises12.cp)(source, (0, import_node_path17.join)(root, (0, import_node_path17.basename)(source)), { force: false, errorOnExist: true });
|
|
9137
9323
|
return;
|
|
9138
9324
|
}
|
|
9139
9325
|
throw new Error(`Unsupported source path: ${sourceLabel}`);
|
|
@@ -9167,11 +9353,11 @@ function packageDashboardUrl(name) {
|
|
|
9167
9353
|
return `${DASHBOARD_URL}/packages/${name.replace(/^@/, "")}`;
|
|
9168
9354
|
}
|
|
9169
9355
|
function helperRootFromTrackedPath(path2) {
|
|
9170
|
-
const parts = path2.split(
|
|
9356
|
+
const parts = path2.split(import_node_path17.sep).filter(Boolean);
|
|
9171
9357
|
const helpersIndex = parts.lastIndexOf("helpers");
|
|
9172
9358
|
if (helpersIndex === -1 || parts.length <= helpersIndex + 2) return null;
|
|
9173
|
-
const prefix = path2.startsWith(
|
|
9174
|
-
return (0,
|
|
9359
|
+
const prefix = path2.startsWith(import_node_path17.sep) ? import_node_path17.sep : "";
|
|
9360
|
+
return (0, import_node_path17.join)(prefix, ...parts.slice(0, helpersIndex + 3));
|
|
9175
9361
|
}
|
|
9176
9362
|
async function showInstalledPrompt(configRoot, packageArg) {
|
|
9177
9363
|
const { name } = parsePackageArg(packageArg);
|
|
@@ -9184,7 +9370,7 @@ async function showInstalledPrompt(configRoot, packageArg) {
|
|
|
9184
9370
|
if (entry.postInstall.status === "cleaned") {
|
|
9185
9371
|
throw new Error(`Setup helper files were cleaned for ${name}. Reinstall the package to restore them.`);
|
|
9186
9372
|
}
|
|
9187
|
-
const content = await (0,
|
|
9373
|
+
const content = await (0, import_promises12.readFile)(entry.postInstall.promptFile, "utf8").catch(() => {
|
|
9188
9374
|
throw new Error(`Setup prompt file is missing: ${entry.postInstall?.promptFile}`);
|
|
9189
9375
|
});
|
|
9190
9376
|
console.log(`Prompt file: ${entry.postInstall.promptFile}`);
|
|
@@ -9217,9 +9403,9 @@ async function cleanupInstalledHelpers(options) {
|
|
|
9217
9403
|
entry.installedAssets.helper.map((path2) => helperRootFromTrackedPath(path2)).filter((path2) => Boolean(path2))
|
|
9218
9404
|
);
|
|
9219
9405
|
if (roots.size > 0) {
|
|
9220
|
-
for (const root of roots) await (0,
|
|
9406
|
+
for (const root of roots) await (0, import_promises12.rm)(root, { recursive: true, force: true });
|
|
9221
9407
|
} else {
|
|
9222
|
-
for (const helperPath of entry.installedAssets.helper) await (0,
|
|
9408
|
+
for (const helperPath of entry.installedAssets.helper) await (0, import_promises12.rm)(helperPath, { force: true });
|
|
9223
9409
|
}
|
|
9224
9410
|
await writeLockfile(options.configRoot, {
|
|
9225
9411
|
...lock,
|
|
@@ -9264,7 +9450,7 @@ async function authTokenForRegistry(registry, options = {}) {
|
|
|
9264
9450
|
return refreshed.accessToken;
|
|
9265
9451
|
} catch {
|
|
9266
9452
|
await clearStoredRegistryAuth(registry);
|
|
9267
|
-
const message = `CLI login for ${registry} expired or was revoked. Run aipm login to access private packages.`;
|
|
9453
|
+
const message = `CLI login for ${registry} expired or was revoked. Run ${recommendCmd("aipm login")} to access private packages.`;
|
|
9268
9454
|
if (options.throwOnFailure) throw new Error(message);
|
|
9269
9455
|
if (!options.quiet) console.warn(`Warning: ${message}`);
|
|
9270
9456
|
return void 0;
|
|
@@ -9513,9 +9699,9 @@ function buildStarterQualityMetadata(options) {
|
|
|
9513
9699
|
}
|
|
9514
9700
|
async function initSkill(opts) {
|
|
9515
9701
|
if (!isValidScopeName(opts.name)) throw new Error("Invalid @scope/name");
|
|
9516
|
-
const root = opts.here ? (0, import_node_process5.cwd)() : (0,
|
|
9702
|
+
const root = opts.here ? (0, import_node_process5.cwd)() : (0, import_node_path17.resolve)((0, import_node_process5.cwd)(), opts.dir ?? skillFolderName(opts.name));
|
|
9517
9703
|
const cdTarget = opts.here ? null : opts.dir ?? skillFolderName(opts.name);
|
|
9518
|
-
const source = opts.from ? (0,
|
|
9704
|
+
const source = opts.from ? (0, import_node_path17.resolve)(opts.from) : null;
|
|
9519
9705
|
const entry = source ? await inferEntryFromSource(source, opts.entry) : opts.entry;
|
|
9520
9706
|
const template = parseSkillTemplate(opts.template ?? "blank");
|
|
9521
9707
|
const manifest = PackageManifestSchema.parse({
|
|
@@ -9536,17 +9722,17 @@ async function initSkill(opts) {
|
|
|
9536
9722
|
if (source) {
|
|
9537
9723
|
await copySourceIntoSkillRoot(source, root, source);
|
|
9538
9724
|
} else {
|
|
9539
|
-
await (0,
|
|
9725
|
+
await (0, import_promises12.mkdir)(root, { recursive: true });
|
|
9540
9726
|
}
|
|
9541
|
-
await writeStarterFile((0,
|
|
9727
|
+
await writeStarterFile((0, import_node_path17.join)(root, "aipm.manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
9542
9728
|
if (!opts.from) {
|
|
9543
9729
|
await writeStarterFile(
|
|
9544
|
-
(0,
|
|
9730
|
+
(0, import_node_path17.join)(root, entry),
|
|
9545
9731
|
SKILL_TEMPLATES[template](opts.name)
|
|
9546
9732
|
);
|
|
9547
9733
|
}
|
|
9548
9734
|
await writeStarterFile(
|
|
9549
|
-
(0,
|
|
9735
|
+
(0, import_node_path17.join)(root, ".aipmignore"),
|
|
9550
9736
|
[
|
|
9551
9737
|
"# Files that should never be published with this skill",
|
|
9552
9738
|
".env*",
|
|
@@ -9564,14 +9750,14 @@ async function initSkill(opts) {
|
|
|
9564
9750
|
""
|
|
9565
9751
|
].join("\n")
|
|
9566
9752
|
);
|
|
9567
|
-
await (0,
|
|
9753
|
+
await (0, import_promises12.mkdir)((0, import_node_path17.join)(root, ".aipm"), { recursive: true });
|
|
9568
9754
|
console.log(`Created ${opts.name} skill folder: ${root}`);
|
|
9569
9755
|
printPublishGuide(
|
|
9570
9756
|
opts.from ? `Copied ${opts.from} into ${root} and created aipm.manifest.json, .aipmignore, and the local publish state folder.` : `Created ${root} with aipm.manifest.json, ${entry}, .aipmignore, and the local publish state folder.`,
|
|
9571
9757
|
cdTarget ? `Run cd ${cdTarget}, edit/review the files, then run aipm publish add .` : "Edit/review the files, then run aipm publish add ."
|
|
9572
9758
|
);
|
|
9573
9759
|
}
|
|
9574
|
-
program2.command("init").description("Create aipm.package.json in the current project or globally").option(GLOBAL_OPTION, GLOBAL_OPTION_DESC).option("--registry <url>", "Default registry URL").option("--target <tool>", "Preferred install target: cursor, claude, or *").action(async (opts) => {
|
|
9760
|
+
program2.command("init").description("Create aipm.package.json in the current project or globally").option(GLOBAL_OPTION, GLOBAL_OPTION_DESC).option("--registry <url>", "Default registry URL").option("--target <tool>", "Preferred install target: cursor, claude, codex, or *").action(async (opts) => {
|
|
9575
9761
|
const scope = { global: opts.global };
|
|
9576
9762
|
const configRoot = resolveConfigRoot(scope);
|
|
9577
9763
|
const existing = await readProjectPackageJson(configRoot);
|
|
@@ -9579,7 +9765,7 @@ program2.command("init").description("Create aipm.package.json in the current pr
|
|
|
9579
9765
|
console.log(`aipm.package.json already exists (${scopeLabel(scope)}).`);
|
|
9580
9766
|
return;
|
|
9581
9767
|
}
|
|
9582
|
-
if (scope.global) await (0,
|
|
9768
|
+
if (scope.global) await (0, import_promises12.mkdir)(configRoot, { recursive: true });
|
|
9583
9769
|
const installRoot = resolveInstallRoot(scope);
|
|
9584
9770
|
const detected = await detectToolsInProject(installRoot);
|
|
9585
9771
|
const parsedTarget = parseTargetFlag(opts.target);
|
|
@@ -9682,7 +9868,7 @@ program2.command("config").description("Show resolved AIPM CLI and project confi
|
|
|
9682
9868
|
console.log(`Auth file: ${data.authFile}`);
|
|
9683
9869
|
console.log(`Publish guide: ${data.publishDoc}`);
|
|
9684
9870
|
});
|
|
9685
|
-
program2.command("add <package-or-prompt>").description("Add a skill package or an AIPM prompt URL").option(GLOBAL_OPTION, GLOBAL_OPTION_DESC).option("--registry <url>", "Registry base URL").option("--target <tool>", "cursor, claude, or *").option("--token <token>", "Install token for private packages").option("--ci", "Non-interactive; fail if prompt needed").action(async (pkgArg, opts) => {
|
|
9871
|
+
program2.command("add <package-or-prompt>").description("Add a skill package or an AIPM prompt URL").option(GLOBAL_OPTION, GLOBAL_OPTION_DESC).option("--registry <url>", "Registry base URL").option("--target <tool>", "cursor, claude, codex, or *").option("--token <token>", "Install token for private packages").option("--ci", "Non-interactive; fail if prompt needed").action(async (pkgArg, opts) => {
|
|
9686
9872
|
const scope = { global: opts.global };
|
|
9687
9873
|
const configRoot = resolveConfigRoot(scope);
|
|
9688
9874
|
const installRoot = resolveInstallRoot(scope);
|
|
@@ -9705,7 +9891,7 @@ program2.command("add <package-or-prompt>").description("Add a skill package or
|
|
|
9705
9891
|
const { name, version: requestedVersion } = parsePackageArg(pkgArg);
|
|
9706
9892
|
const token = await tokenForRead(registry, opts.token);
|
|
9707
9893
|
const version = requestedVersion ?? project.packages[name] ?? await latestVersionForPackage(registry, name, token);
|
|
9708
|
-
if (!version) throw new Error(
|
|
9894
|
+
if (!version) throw new Error(`Specify version: ${recommendCmd("aipm add <@scope/pkg>@<version>")}`);
|
|
9709
9895
|
project = {
|
|
9710
9896
|
...project,
|
|
9711
9897
|
packages: { ...project.packages, [name]: version.replace(/^\^/, "") }
|
|
@@ -9754,7 +9940,7 @@ program2.command("search [query]").description("Search public registry packages"
|
|
|
9754
9940
|
console.log(` ${meta}`);
|
|
9755
9941
|
}
|
|
9756
9942
|
});
|
|
9757
|
-
program2.command("install").description("Install all packages from aipm.package.json").option(GLOBAL_OPTION, GLOBAL_OPTION_DESC).option("--registry <url>", "Registry base URL").option("--target <tool>", "cursor, claude, or *").option("--token <token>", "Install token for private packages").option("--ci", "Non-interactive").action(async (opts) => {
|
|
9943
|
+
program2.command("install").description("Install all packages from aipm.package.json").option(GLOBAL_OPTION, GLOBAL_OPTION_DESC).option("--registry <url>", "Registry base URL").option("--target <tool>", "cursor, claude, codex, or *").option("--token <token>", "Install token for private packages").option("--ci", "Non-interactive").action(async (opts) => {
|
|
9758
9944
|
const scope = { global: opts.global };
|
|
9759
9945
|
const configRoot = resolveConfigRoot(scope);
|
|
9760
9946
|
const installRoot = resolveInstallRoot(scope);
|
|
@@ -9797,7 +9983,7 @@ program2.command("show <package-or-prompt>").description("Show an installed prom
|
|
|
9797
9983
|
if (reference && project.prompts[reference.alias] === reference.url) {
|
|
9798
9984
|
const lock2 = await readLockfile(configRoot);
|
|
9799
9985
|
const entry2 = lock2?.prompts[reference.alias];
|
|
9800
|
-
if (!entry2) throw new Error(`Prompt is not installed: ${reference.url}. Run aipm install.`);
|
|
9986
|
+
if (!entry2) throw new Error(`Prompt is not installed: ${reference.url}. Run ${recommendCmd("aipm install")}.`);
|
|
9801
9987
|
console.log(await readInstalledPrompt(configRoot, entry2));
|
|
9802
9988
|
return;
|
|
9803
9989
|
}
|
|
@@ -9811,7 +9997,7 @@ program2.command("show-prompt <package>").description("Show the manual setup pro
|
|
|
9811
9997
|
await showInstalledPrompt(resolveConfigRoot({ global: opts.global }), pkgArg);
|
|
9812
9998
|
});
|
|
9813
9999
|
function promptImageContentType(path2) {
|
|
9814
|
-
const extension = (0,
|
|
10000
|
+
const extension = (0, import_node_path17.extname)(path2).toLowerCase();
|
|
9815
10001
|
if (extension === ".png") return "image/png";
|
|
9816
10002
|
if (extension === ".jpg" || extension === ".jpeg") return "image/jpeg";
|
|
9817
10003
|
if (extension === ".webp") return "image/webp";
|
|
@@ -9821,9 +10007,9 @@ var promptCommand = program2.command("prompt").description("Publish prompt listi
|
|
|
9821
10007
|
promptCommand.command("publish <file>").description("Publish one prompt or a batch of prompts from JSON").option("--registry <url>", "Registry API base URL").option("--yes", "Confirm public publishing without an extra reminder").action(async (file, opts) => {
|
|
9822
10008
|
const registry = registryFromEnvOrDefault(opts.registry);
|
|
9823
10009
|
const accessToken = await authTokenForRegistry(registry, { throwOnFailure: true });
|
|
9824
|
-
if (!accessToken) throw new Error(
|
|
9825
|
-
const absoluteFile = (0,
|
|
9826
|
-
const parsed = JSON.parse(await (0,
|
|
10010
|
+
if (!accessToken) throw new Error(`Run ${recommendCmd("aipm login")} before publishing prompts.`);
|
|
10011
|
+
const absoluteFile = (0, import_node_path17.resolve)(file);
|
|
10012
|
+
const parsed = JSON.parse(await (0, import_promises12.readFile)(absoluteFile, "utf8"));
|
|
9827
10013
|
const rows = Array.isArray(parsed) ? parsed : "prompts" in parsed ? parsed.prompts : [parsed];
|
|
9828
10014
|
if (rows.length === 0) throw new Error("Prompt publish file contains no prompts.");
|
|
9829
10015
|
if (!opts.yes) {
|
|
@@ -9834,10 +10020,10 @@ promptCommand.command("publish <file>").description("Publish one prompt or a bat
|
|
|
9834
10020
|
const { sampleImagePath, ...input2 } = row;
|
|
9835
10021
|
let sampleImage;
|
|
9836
10022
|
if (sampleImagePath) {
|
|
9837
|
-
const imagePath = (0,
|
|
10023
|
+
const imagePath = (0, import_node_path17.resolve)((0, import_node_path17.dirname)(absoluteFile), sampleImagePath);
|
|
9838
10024
|
sampleImage = {
|
|
9839
|
-
data: await (0,
|
|
9840
|
-
filename: (0,
|
|
10025
|
+
data: await (0, import_promises12.readFile)(imagePath),
|
|
10026
|
+
filename: (0, import_node_path17.basename)(imagePath),
|
|
9841
10027
|
contentType: promptImageContentType(imagePath)
|
|
9842
10028
|
};
|
|
9843
10029
|
}
|
|
@@ -9860,8 +10046,8 @@ var publish = program2.command("publish [dir]").description("Stage, validate, an
|
|
|
9860
10046
|
publish.help();
|
|
9861
10047
|
return;
|
|
9862
10048
|
}
|
|
9863
|
-
const abs = (0,
|
|
9864
|
-
const manifestRaw = await (0,
|
|
10049
|
+
const abs = (0, import_node_path17.resolve)(dir);
|
|
10050
|
+
const manifestRaw = await (0, import_promises12.readFile)((0, import_node_path17.join)(abs, "aipm.manifest.json"), "utf8");
|
|
9865
10051
|
const manifest = PackageManifestSchema.parse(JSON.parse(manifestRaw));
|
|
9866
10052
|
const tarball = await packDirectory(abs);
|
|
9867
10053
|
const registry = registryFromEnvOrDefault(opts.registry);
|
|
@@ -10026,6 +10212,7 @@ program2.command("list").description("List installed skills and prompts from aip
|
|
|
10026
10212
|
program2.command("remove <package-or-prompt>").alias("rm").description("Remove a tracked skill or prompt and its installed files").option(GLOBAL_OPTION, GLOBAL_OPTION_DESC).action(async (pkgArg, opts) => {
|
|
10027
10213
|
const scope = { global: opts.global };
|
|
10028
10214
|
const configRoot = resolveConfigRoot(scope);
|
|
10215
|
+
const installRoot = resolveInstallRoot(scope);
|
|
10029
10216
|
const project = await readProjectPackageJson(configRoot);
|
|
10030
10217
|
if (!project) throw new Error(initRequiredMessage(scope));
|
|
10031
10218
|
const promptReference = resolveTrackedPrompt(project, pkgArg);
|
|
@@ -10035,19 +10222,32 @@ program2.command("remove <package-or-prompt>").alias("rm").description("Remove a
|
|
|
10035
10222
|
return;
|
|
10036
10223
|
}
|
|
10037
10224
|
const { name } = parsePackageArg(pkgArg);
|
|
10225
|
+
const lock = await readLockfile(configRoot);
|
|
10226
|
+
const lockEntry = lock?.packages[name];
|
|
10227
|
+
if (lockEntry) {
|
|
10228
|
+
const otherEntries = Object.entries(lock.packages).filter(([packageName]) => packageName !== name).map(([, entry]) => entry);
|
|
10229
|
+
const removal = await removeInstalledPackageFiles({
|
|
10230
|
+
configRoot,
|
|
10231
|
+
installRoot,
|
|
10232
|
+
entry: lockEntry,
|
|
10233
|
+
otherEntries
|
|
10234
|
+
});
|
|
10235
|
+
console.log(`Deleted ${removal.removed} tracked installed ${removal.removed === 1 ? "file" : "files"}.`);
|
|
10236
|
+
if (removal.retainedShared > 0) {
|
|
10237
|
+
console.log(`Retained ${removal.retainedShared} ${removal.retainedShared === 1 ? "file" : "files"} shared with another installed package.`);
|
|
10238
|
+
}
|
|
10239
|
+
}
|
|
10038
10240
|
const packages = { ...project.packages };
|
|
10039
10241
|
delete packages[name];
|
|
10040
10242
|
await writeProjectPackageJson(configRoot, { ...project, packages });
|
|
10041
|
-
const lock = await readLockfile(configRoot);
|
|
10042
10243
|
if (lock) {
|
|
10043
10244
|
const lockPackages = { ...lock.packages };
|
|
10044
10245
|
delete lockPackages[name];
|
|
10045
10246
|
await writeLockfile(configRoot, { ...lock, packages: lockPackages });
|
|
10046
10247
|
}
|
|
10047
10248
|
console.log(`Removed ${name} from AIPM ${scopeLabel(scope)} files.`);
|
|
10048
|
-
console.log("Adapter-written files are not deleted yet; review your project before committing.");
|
|
10049
10249
|
});
|
|
10050
|
-
program2.command("update [package]").description("Update one installed package, or all installed packages, to the latest registry version").option(GLOBAL_OPTION, GLOBAL_OPTION_DESC).option("--registry <url>", "Registry base URL").option("--target <tool>", "cursor, claude, or *").option("--token <token>", "Install token for private packages").option("--ci", "Non-interactive").action(async (pkgArg, opts) => {
|
|
10250
|
+
program2.command("update [package]").description("Update one installed package, or all installed packages, to the latest registry version").option(GLOBAL_OPTION, GLOBAL_OPTION_DESC).option("--registry <url>", "Registry base URL").option("--target <tool>", "cursor, claude, codex, or *").option("--token <token>", "Install token for private packages").option("--ci", "Non-interactive").action(async (pkgArg, opts) => {
|
|
10051
10251
|
const scope = { global: opts.global };
|
|
10052
10252
|
const configRoot = resolveConfigRoot(scope);
|
|
10053
10253
|
const installRoot = resolveInstallRoot(scope);
|