@aipm-registry/cli 0.4.1 → 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 +324 -153
- package/dist/bin.cjs.map +4 -4
- package/package.json +1 -1
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
|
}
|
|
@@ -4372,23 +4377,57 @@ var init_detect_tools = __esm({
|
|
|
4372
4377
|
}
|
|
4373
4378
|
});
|
|
4374
4379
|
|
|
4375
|
-
// ../../packages/adapter-
|
|
4376
|
-
|
|
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;
|
|
4377
4409
|
var init_dist2 = __esm({
|
|
4378
|
-
"../../packages/adapter-
|
|
4410
|
+
"../../packages/adapter-sdk/dist/index.js"() {
|
|
4379
4411
|
"use strict";
|
|
4380
4412
|
import_promises2 = require("node:fs/promises");
|
|
4381
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();
|
|
4382
4424
|
init_dist();
|
|
4383
4425
|
ClaudeSkillAdapter = class {
|
|
4384
4426
|
tool = "claude";
|
|
4385
4427
|
async installSkill(input2) {
|
|
4386
4428
|
const short = shortNameFromScopeName(input2.packageName);
|
|
4387
|
-
const skillDir = (0,
|
|
4388
|
-
|
|
4389
|
-
const filePath = (0, import_node_path3.join)(skillDir, "SKILL.md");
|
|
4390
|
-
await (0, import_promises2.writeFile)(filePath, input2.skillMarkdown, "utf8");
|
|
4391
|
-
return { writtenPaths: [filePath] };
|
|
4429
|
+
const skillDir = (0, import_node_path4.join)(input2.projectRoot, ".claude", "skills", short);
|
|
4430
|
+
return writeSkillDirectory(skillDir, input2);
|
|
4392
4431
|
}
|
|
4393
4432
|
};
|
|
4394
4433
|
claudeSkillAdapter = new ClaudeSkillAdapter();
|
|
@@ -4396,20 +4435,20 @@ var init_dist2 = __esm({
|
|
|
4396
4435
|
});
|
|
4397
4436
|
|
|
4398
4437
|
// ../../packages/adapter-cursor/dist/index.js
|
|
4399
|
-
var import_promises3,
|
|
4400
|
-
var
|
|
4438
|
+
var import_promises3, import_node_path5, CursorSkillAdapter, cursorSkillAdapter;
|
|
4439
|
+
var init_dist4 = __esm({
|
|
4401
4440
|
"../../packages/adapter-cursor/dist/index.js"() {
|
|
4402
4441
|
"use strict";
|
|
4403
4442
|
import_promises3 = require("node:fs/promises");
|
|
4404
|
-
|
|
4443
|
+
import_node_path5 = require("node:path");
|
|
4405
4444
|
init_dist();
|
|
4406
4445
|
CursorSkillAdapter = class {
|
|
4407
4446
|
tool = "cursor";
|
|
4408
4447
|
async installSkill(input2) {
|
|
4409
4448
|
const short = shortNameFromScopeName(input2.packageName);
|
|
4410
|
-
const skillsDir = (0,
|
|
4449
|
+
const skillsDir = (0, import_node_path5.join)(input2.projectRoot, ".cursor", "aipm", "skills");
|
|
4411
4450
|
await (0, import_promises3.mkdir)(skillsDir, { recursive: true });
|
|
4412
|
-
const filePath = (0,
|
|
4451
|
+
const filePath = (0, import_node_path5.join)(skillsDir, `${short}.md`);
|
|
4413
4452
|
await (0, import_promises3.writeFile)(filePath, input2.skillMarkdown, "utf8");
|
|
4414
4453
|
return { writtenPaths: [filePath] };
|
|
4415
4454
|
}
|
|
@@ -4419,22 +4458,19 @@ var init_dist3 = __esm({
|
|
|
4419
4458
|
});
|
|
4420
4459
|
|
|
4421
4460
|
// ../../packages/adapter-codex/dist/index.js
|
|
4422
|
-
var
|
|
4423
|
-
var
|
|
4461
|
+
var import_node_path6, CodexSkillAdapter, codexSkillAdapter;
|
|
4462
|
+
var init_dist5 = __esm({
|
|
4424
4463
|
"../../packages/adapter-codex/dist/index.js"() {
|
|
4425
4464
|
"use strict";
|
|
4426
|
-
|
|
4427
|
-
|
|
4465
|
+
import_node_path6 = require("node:path");
|
|
4466
|
+
init_dist2();
|
|
4428
4467
|
init_dist();
|
|
4429
4468
|
CodexSkillAdapter = class {
|
|
4430
4469
|
tool = "codex";
|
|
4431
4470
|
async installSkill(input2) {
|
|
4432
4471
|
const short = shortNameFromScopeName(input2.packageName);
|
|
4433
|
-
const skillDir = (0,
|
|
4434
|
-
|
|
4435
|
-
const filePath = (0, import_node_path5.join)(skillDir, "SKILL.md");
|
|
4436
|
-
await (0, import_promises4.writeFile)(filePath, input2.skillMarkdown, "utf8");
|
|
4437
|
-
return { writtenPaths: [filePath] };
|
|
4472
|
+
const skillDir = (0, import_node_path6.join)(input2.projectRoot, ".agents", "skills", short);
|
|
4473
|
+
return writeSkillDirectory(skillDir, input2);
|
|
4438
4474
|
}
|
|
4439
4475
|
};
|
|
4440
4476
|
codexSkillAdapter = new CodexSkillAdapter();
|
|
@@ -4459,6 +4495,7 @@ async function installSkillPackage(options) {
|
|
|
4459
4495
|
packageName: options.manifest.name,
|
|
4460
4496
|
version: options.manifest.version,
|
|
4461
4497
|
skillMarkdown: options.skillMarkdown,
|
|
4498
|
+
supportingFiles: options.supportingFiles,
|
|
4462
4499
|
projectRoot: options.projectRoot
|
|
4463
4500
|
});
|
|
4464
4501
|
installed[tool] = result.writtenPaths;
|
|
@@ -4469,9 +4506,9 @@ var adapters;
|
|
|
4469
4506
|
var init_install_skill = __esm({
|
|
4470
4507
|
"../../packages/engine/dist/install-skill.js"() {
|
|
4471
4508
|
"use strict";
|
|
4472
|
-
init_dist2();
|
|
4473
4509
|
init_dist3();
|
|
4474
4510
|
init_dist4();
|
|
4511
|
+
init_dist5();
|
|
4475
4512
|
init_detect_tools();
|
|
4476
4513
|
adapters = {
|
|
4477
4514
|
cursor: cursorSkillAdapter,
|
|
@@ -4488,7 +4525,7 @@ __export(dist_exports, {
|
|
|
4488
4525
|
installSkillPackage: () => installSkillPackage,
|
|
4489
4526
|
resolveInstallTools: () => resolveInstallTools
|
|
4490
4527
|
});
|
|
4491
|
-
var
|
|
4528
|
+
var init_dist6 = __esm({
|
|
4492
4529
|
"../../packages/engine/dist/index.js"() {
|
|
4493
4530
|
"use strict";
|
|
4494
4531
|
init_detect_tools();
|
|
@@ -7869,24 +7906,33 @@ var import_node_crypto3 = require("node:crypto");
|
|
|
7869
7906
|
var import_node_child_process4 = require("node:child_process");
|
|
7870
7907
|
var import_node_http = require("node:http");
|
|
7871
7908
|
var import_promises12 = require("node:fs/promises");
|
|
7872
|
-
var
|
|
7909
|
+
var import_node_path17 = require("node:path");
|
|
7873
7910
|
var import_node_process5 = require("node:process");
|
|
7874
7911
|
init_dist();
|
|
7875
|
-
|
|
7912
|
+
init_dist6();
|
|
7876
7913
|
|
|
7877
7914
|
// src/pack.ts
|
|
7878
7915
|
var import_node_child_process2 = require("node:child_process");
|
|
7879
7916
|
var import_node_util3 = require("node:util");
|
|
7880
|
-
var
|
|
7881
|
-
var
|
|
7917
|
+
var import_promises5 = require("node:fs/promises");
|
|
7918
|
+
var import_node_path8 = require("node:path");
|
|
7882
7919
|
var import_node_os = require("node:os");
|
|
7883
7920
|
|
|
7884
7921
|
// src/publish-state.ts
|
|
7885
7922
|
var import_node_crypto = require("node:crypto");
|
|
7886
|
-
var
|
|
7887
|
-
var
|
|
7923
|
+
var import_promises4 = require("node:fs/promises");
|
|
7924
|
+
var import_node_path7 = require("node:path");
|
|
7888
7925
|
init_dist();
|
|
7889
|
-
|
|
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");
|
|
7890
7936
|
var IGNORE_FILE = ".aipmignore";
|
|
7891
7937
|
var MAX_PACKAGE_BYTES = 50 * 1024 * 1024;
|
|
7892
7938
|
var EXCLUDED_SEGMENTS = /* @__PURE__ */ new Set([".aipm", ".git", "node_modules", "dist", ".next"]);
|
|
@@ -7901,11 +7947,11 @@ var SECRET_PATTERNS = [
|
|
|
7901
7947
|
/<publishData/i
|
|
7902
7948
|
];
|
|
7903
7949
|
function publishStatePath(root) {
|
|
7904
|
-
return (0,
|
|
7950
|
+
return (0, import_node_path7.join)(root, STATE_PATH);
|
|
7905
7951
|
}
|
|
7906
7952
|
function normalizePublishPath(root, filePath) {
|
|
7907
|
-
const abs = (0,
|
|
7908
|
-
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("/");
|
|
7909
7955
|
if (!rel || rel === ".") return ".";
|
|
7910
7956
|
if (rel.startsWith("../") || rel === ".." || rel.startsWith("/")) {
|
|
7911
7957
|
throw new Error(`Path is outside the skill folder: ${filePath}`);
|
|
@@ -7922,7 +7968,7 @@ function isExcludedPublishPath(rel) {
|
|
|
7922
7968
|
}
|
|
7923
7969
|
async function readAipmIgnore(root) {
|
|
7924
7970
|
try {
|
|
7925
|
-
const raw = await (0,
|
|
7971
|
+
const raw = await (0, import_promises4.readFile)((0, import_node_path7.join)(root, IGNORE_FILE), "utf8");
|
|
7926
7972
|
return raw.split(/\r?\n/).map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
|
|
7927
7973
|
} catch {
|
|
7928
7974
|
return [];
|
|
@@ -7943,7 +7989,7 @@ async function isIgnoredByAipmIgnore(root, rel) {
|
|
|
7943
7989
|
return rules.some((rule) => matchesIgnoreRule(rel, rule));
|
|
7944
7990
|
}
|
|
7945
7991
|
async function assertNoObviousSecrets(path2, rel) {
|
|
7946
|
-
const data = await (0,
|
|
7992
|
+
const data = await (0, import_promises4.readFile)(path2);
|
|
7947
7993
|
if (data.includes(0)) return;
|
|
7948
7994
|
const text = data.toString("utf8");
|
|
7949
7995
|
if (SECRET_PATTERNS.some((pattern) => pattern.test(text))) {
|
|
@@ -7951,7 +7997,7 @@ async function assertNoObviousSecrets(path2, rel) {
|
|
|
7951
7997
|
}
|
|
7952
7998
|
}
|
|
7953
7999
|
async function fileHash(path2) {
|
|
7954
|
-
const data = await (0,
|
|
8000
|
+
const data = await (0, import_promises4.readFile)(path2);
|
|
7955
8001
|
return {
|
|
7956
8002
|
hash: (0, import_node_crypto.createHash)("sha256").update(data).digest("hex"),
|
|
7957
8003
|
size: data.length
|
|
@@ -7959,7 +8005,7 @@ async function fileHash(path2) {
|
|
|
7959
8005
|
}
|
|
7960
8006
|
async function readPublishState(root) {
|
|
7961
8007
|
try {
|
|
7962
|
-
const raw = await (0,
|
|
8008
|
+
const raw = await (0, import_promises4.readFile)(publishStatePath(root), "utf8");
|
|
7963
8009
|
const parsed = JSON.parse(raw);
|
|
7964
8010
|
return {
|
|
7965
8011
|
schemaVersion: "0.1",
|
|
@@ -7971,18 +8017,18 @@ async function readPublishState(root) {
|
|
|
7971
8017
|
}
|
|
7972
8018
|
async function writePublishState(root, state) {
|
|
7973
8019
|
const path2 = publishStatePath(root);
|
|
7974
|
-
await (0,
|
|
8020
|
+
await (0, import_promises4.mkdir)((0, import_node_path7.dirname)(path2), { recursive: true });
|
|
7975
8021
|
const files = [...state.files].sort((a, b) => a.path.localeCompare(b.path));
|
|
7976
|
-
await (0,
|
|
8022
|
+
await (0, import_promises4.writeFile)(path2, JSON.stringify({ schemaVersion: "0.1", files }, null, 2) + "\n", "utf8");
|
|
7977
8023
|
}
|
|
7978
8024
|
async function expandPublishPath(root, rel) {
|
|
7979
8025
|
if (isExcludedPublishPath(rel)) return [];
|
|
7980
8026
|
if (await isIgnoredByAipmIgnore(root, rel)) return [];
|
|
7981
|
-
const abs = (0,
|
|
7982
|
-
const info = await (0,
|
|
8027
|
+
const abs = (0, import_node_path7.join)(root, rel);
|
|
8028
|
+
const info = await (0, import_promises4.stat)(abs);
|
|
7983
8029
|
if (info.isFile()) return [rel];
|
|
7984
8030
|
if (!info.isDirectory()) return [];
|
|
7985
|
-
const entries = await (0,
|
|
8031
|
+
const entries = await (0, import_promises4.readdir)(abs);
|
|
7986
8032
|
const nested = await Promise.all(
|
|
7987
8033
|
entries.map((entry) => expandPublishPath(root, `${rel === "." ? "" : `${rel}/`}${entry}`))
|
|
7988
8034
|
);
|
|
@@ -7998,7 +8044,7 @@ async function addPublishFiles(root, paths) {
|
|
|
7998
8044
|
for (const rel of files) {
|
|
7999
8045
|
if (isExcludedPublishPath(rel)) continue;
|
|
8000
8046
|
if (await isIgnoredByAipmIgnore(root, rel)) continue;
|
|
8001
|
-
const hashed = await fileHash((0,
|
|
8047
|
+
const hashed = await fileHash((0, import_node_path7.join)(root, rel));
|
|
8002
8048
|
byPath.set(rel, { path: rel, ...hashed });
|
|
8003
8049
|
}
|
|
8004
8050
|
}
|
|
@@ -8017,15 +8063,17 @@ async function removePublishFiles(root, paths) {
|
|
|
8017
8063
|
return next;
|
|
8018
8064
|
}
|
|
8019
8065
|
async function resetPublishState(root) {
|
|
8020
|
-
await (0,
|
|
8066
|
+
await (0, import_promises4.rm)(publishStatePath(root), { force: true });
|
|
8021
8067
|
}
|
|
8022
8068
|
async function readManifest(root) {
|
|
8023
8069
|
try {
|
|
8024
|
-
const raw = await (0,
|
|
8070
|
+
const raw = await (0, import_promises4.readFile)((0, import_node_path7.join)(root, "aipm.manifest.json"), "utf8");
|
|
8025
8071
|
return PackageManifestSchema.parse(JSON.parse(raw));
|
|
8026
8072
|
} catch (error) {
|
|
8027
8073
|
if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
|
|
8028
|
-
throw new Error(
|
|
8074
|
+
throw new Error(
|
|
8075
|
+
`No aipm.manifest.json found. Run ${recommendCmd("aipm publish init --name <@org/skill>")}.`
|
|
8076
|
+
);
|
|
8029
8077
|
}
|
|
8030
8078
|
throw error;
|
|
8031
8079
|
}
|
|
@@ -8041,7 +8089,9 @@ function installReferencedFiles(manifest) {
|
|
|
8041
8089
|
async function validatePublishState(root) {
|
|
8042
8090
|
const manifest = await readManifest(root);
|
|
8043
8091
|
const state = await readPublishState(root);
|
|
8044
|
-
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
|
+
}
|
|
8045
8095
|
const staged = new Set(state.files.map((entry) => entry.path));
|
|
8046
8096
|
if (!staged.has("aipm.manifest.json")) throw new Error("aipm.manifest.json must be staged.");
|
|
8047
8097
|
if (!staged.has(manifest.entry)) throw new Error(`Manifest entry must be staged: ${manifest.entry}`);
|
|
@@ -8054,12 +8104,14 @@ async function validatePublishState(root) {
|
|
|
8054
8104
|
if (await isIgnoredByAipmIgnore(root, entry.path)) {
|
|
8055
8105
|
throw new Error(`Refusing to publish ignored path: ${entry.path}`);
|
|
8056
8106
|
}
|
|
8057
|
-
const abs = (0,
|
|
8058
|
-
const info = await (0,
|
|
8107
|
+
const abs = (0, import_node_path7.join)(root, entry.path);
|
|
8108
|
+
const info = await (0, import_promises4.stat)(abs).catch(() => null);
|
|
8059
8109
|
if (!info?.isFile()) throw new Error(`Staged file is missing: ${entry.path}`);
|
|
8060
8110
|
const hashed = await fileHash(abs);
|
|
8061
8111
|
if (hashed.hash !== entry.hash) {
|
|
8062
|
-
throw new Error(
|
|
8112
|
+
throw new Error(
|
|
8113
|
+
`Staged file changed after add: ${entry.path}. Run ${recommendCmd(`aipm publish add ${entry.path}`)}.`
|
|
8114
|
+
);
|
|
8063
8115
|
}
|
|
8064
8116
|
await assertNoObviousSecrets(abs, entry.path);
|
|
8065
8117
|
size += hashed.size;
|
|
@@ -8071,7 +8123,7 @@ async function statusPublishState(root) {
|
|
|
8071
8123
|
const state = await readPublishState(root);
|
|
8072
8124
|
const rows = [];
|
|
8073
8125
|
for (const entry of state.files) {
|
|
8074
|
-
const current = await fileHash((0,
|
|
8126
|
+
const current = await fileHash((0, import_node_path7.join)(root, entry.path)).catch(() => null);
|
|
8075
8127
|
rows.push({ ...entry, changed: !current || current.hash !== entry.hash });
|
|
8076
8128
|
}
|
|
8077
8129
|
return rows;
|
|
@@ -8079,9 +8131,9 @@ async function statusPublishState(root) {
|
|
|
8079
8131
|
async function copyStagedFiles(root, destination) {
|
|
8080
8132
|
const state = await readPublishState(root);
|
|
8081
8133
|
for (const entry of state.files) {
|
|
8082
|
-
const target = (0,
|
|
8083
|
-
await (0,
|
|
8084
|
-
await (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);
|
|
8085
8137
|
}
|
|
8086
8138
|
}
|
|
8087
8139
|
|
|
@@ -8095,21 +8147,21 @@ async function packDirectory(dir) {
|
|
|
8095
8147
|
return Buffer.isBuffer(stdout) ? stdout : Buffer.from(stdout);
|
|
8096
8148
|
}
|
|
8097
8149
|
async function packStagedFiles(root) {
|
|
8098
|
-
const tempDir = await (0,
|
|
8150
|
+
const tempDir = await (0, import_promises5.mkdtemp)((0, import_node_path8.join)((0, import_node_os.tmpdir)(), "aipm-publish-stage-"));
|
|
8099
8151
|
try {
|
|
8100
8152
|
await copyStagedFiles(root, tempDir);
|
|
8101
8153
|
return await packDirectory(tempDir);
|
|
8102
8154
|
} finally {
|
|
8103
|
-
await (0,
|
|
8155
|
+
await (0, import_promises5.rm)(tempDir, { recursive: true, force: true });
|
|
8104
8156
|
}
|
|
8105
8157
|
}
|
|
8106
8158
|
async function unpackTarballToDirectory(tarball) {
|
|
8107
|
-
const { mkdtemp: mkdtemp2, writeFile:
|
|
8108
|
-
const { join:
|
|
8159
|
+
const { mkdtemp: mkdtemp2, writeFile: writeFile8 } = await import("node:fs/promises");
|
|
8160
|
+
const { join: join16 } = await import("node:path");
|
|
8109
8161
|
const { tmpdir: tmpdir2 } = await import("node:os");
|
|
8110
|
-
const tempDir = await mkdtemp2(
|
|
8111
|
-
const tgzPath =
|
|
8112
|
-
await
|
|
8162
|
+
const tempDir = await mkdtemp2(join16(tmpdir2(), "aipm-install-"));
|
|
8163
|
+
const tgzPath = join16(tempDir, "pkg.tgz");
|
|
8164
|
+
await writeFile8(tgzPath, tarball);
|
|
8113
8165
|
await execFileAsync("tar", ["-xzf", tgzPath, "-C", tempDir]);
|
|
8114
8166
|
return tempDir;
|
|
8115
8167
|
}
|
|
@@ -8122,7 +8174,7 @@ function registryFetchError(registry, cause) {
|
|
|
8122
8174
|
const msg = cause instanceof Error ? cause.message : String(cause);
|
|
8123
8175
|
if (msg === "fetch failed" || msg.includes("ECONNREFUSED") || msg.includes("ENOTFOUND") || msg.includes("timed out") || msg.includes("aborted")) {
|
|
8124
8176
|
return new Error(
|
|
8125
|
-
`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>")}.`
|
|
8126
8178
|
);
|
|
8127
8179
|
}
|
|
8128
8180
|
return new Error(`Registry request failed (${registry}): ${msg}`);
|
|
@@ -8143,13 +8195,13 @@ function privateInstallHint(name, status, token) {
|
|
|
8143
8195
|
if (status !== 404 || !name.startsWith("@") || token) {
|
|
8144
8196
|
return `Package not found: ${name} (${status})`;
|
|
8145
8197
|
}
|
|
8146
|
-
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.`;
|
|
8147
8199
|
}
|
|
8148
8200
|
function publishTokenHint(name, error) {
|
|
8149
8201
|
if (error === "Publish token required") {
|
|
8150
8202
|
return [
|
|
8151
8203
|
`Publish token required for ${name}.`,
|
|
8152
|
-
`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")}.`
|
|
8153
8205
|
].join(" ");
|
|
8154
8206
|
}
|
|
8155
8207
|
if (error === "Invalid publish token") {
|
|
@@ -8305,16 +8357,16 @@ async function publishPrompt(registry, input2, accessToken, sampleImage) {
|
|
|
8305
8357
|
}
|
|
8306
8358
|
|
|
8307
8359
|
// src/auth-store.ts
|
|
8308
|
-
var
|
|
8360
|
+
var import_promises6 = require("node:fs/promises");
|
|
8309
8361
|
var import_node_os2 = require("node:os");
|
|
8310
|
-
var
|
|
8311
|
-
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");
|
|
8312
8364
|
function normalizeRegistry(registry) {
|
|
8313
8365
|
return registry.replace(/\/$/, "");
|
|
8314
8366
|
}
|
|
8315
8367
|
async function readAuthStore() {
|
|
8316
8368
|
try {
|
|
8317
|
-
const raw = await (0,
|
|
8369
|
+
const raw = await (0, import_promises6.readFile)(AUTH_FILE, "utf8");
|
|
8318
8370
|
const parsed = JSON.parse(raw);
|
|
8319
8371
|
return { registries: parsed.registries ?? {} };
|
|
8320
8372
|
} catch {
|
|
@@ -8322,9 +8374,9 @@ async function readAuthStore() {
|
|
|
8322
8374
|
}
|
|
8323
8375
|
}
|
|
8324
8376
|
async function writeAuthStore(store) {
|
|
8325
|
-
await (0,
|
|
8326
|
-
await (0,
|
|
8327
|
-
await (0,
|
|
8377
|
+
await (0, import_promises6.mkdir)((0, import_node_path9.dirname)(AUTH_FILE), { recursive: true });
|
|
8378
|
+
await (0, import_promises6.writeFile)(AUTH_FILE, JSON.stringify(store, null, 2) + "\n", "utf8");
|
|
8379
|
+
await (0, import_promises6.chmod)(AUTH_FILE, 384).catch(() => void 0);
|
|
8328
8380
|
}
|
|
8329
8381
|
async function getStoredRegistryAuth(registry) {
|
|
8330
8382
|
const store = await readAuthStore();
|
|
@@ -8353,41 +8405,41 @@ function isAccessTokenFresh(auth, skewMs = 6e4) {
|
|
|
8353
8405
|
}
|
|
8354
8406
|
|
|
8355
8407
|
// src/install-one.ts
|
|
8356
|
-
|
|
8357
|
-
var
|
|
8358
|
-
var
|
|
8408
|
+
init_dist6();
|
|
8409
|
+
var import_promises8 = require("node:fs/promises");
|
|
8410
|
+
var import_node_path11 = require("node:path");
|
|
8359
8411
|
|
|
8360
8412
|
// src/project-files.ts
|
|
8361
|
-
var
|
|
8362
|
-
var
|
|
8413
|
+
var import_promises7 = require("node:fs/promises");
|
|
8414
|
+
var import_node_path10 = require("node:path");
|
|
8363
8415
|
init_dist();
|
|
8364
8416
|
var PACKAGE_JSON = "aipm.package.json";
|
|
8365
8417
|
var LOCKFILE = "aipm-lock.json";
|
|
8366
8418
|
async function readProjectPackageJson(projectRoot) {
|
|
8367
8419
|
try {
|
|
8368
|
-
const raw = await (0,
|
|
8420
|
+
const raw = await (0, import_promises7.readFile)((0, import_node_path10.join)(projectRoot, PACKAGE_JSON), "utf8");
|
|
8369
8421
|
return ProjectPackageJsonSchema.parse(JSON.parse(raw));
|
|
8370
8422
|
} catch {
|
|
8371
8423
|
return null;
|
|
8372
8424
|
}
|
|
8373
8425
|
}
|
|
8374
8426
|
async function writeProjectPackageJson(projectRoot, data) {
|
|
8375
|
-
await (0,
|
|
8376
|
-
(0,
|
|
8427
|
+
await (0, import_promises7.writeFile)(
|
|
8428
|
+
(0, import_node_path10.join)(projectRoot, PACKAGE_JSON),
|
|
8377
8429
|
JSON.stringify(data, null, 2) + "\n",
|
|
8378
8430
|
"utf8"
|
|
8379
8431
|
);
|
|
8380
8432
|
}
|
|
8381
8433
|
async function readLockfile(projectRoot) {
|
|
8382
8434
|
try {
|
|
8383
|
-
const raw = await (0,
|
|
8435
|
+
const raw = await (0, import_promises7.readFile)((0, import_node_path10.join)(projectRoot, LOCKFILE), "utf8");
|
|
8384
8436
|
return LockfileSchema.parse(JSON.parse(raw));
|
|
8385
8437
|
} catch {
|
|
8386
8438
|
return null;
|
|
8387
8439
|
}
|
|
8388
8440
|
}
|
|
8389
8441
|
async function writeLockfile(projectRoot, data) {
|
|
8390
|
-
await (0,
|
|
8442
|
+
await (0, import_promises7.writeFile)((0, import_node_path10.join)(projectRoot, LOCKFILE), JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
8391
8443
|
}
|
|
8392
8444
|
function upsertLockEntry(lock, name, entry) {
|
|
8393
8445
|
return {
|
|
@@ -8462,7 +8514,7 @@ async function promptForConfirmation(question) {
|
|
|
8462
8514
|
|
|
8463
8515
|
// src/install-one.ts
|
|
8464
8516
|
function normalizeRelativePath(path2) {
|
|
8465
|
-
return (0,
|
|
8517
|
+
return (0, import_node_path11.normalize)(path2).split(import_node_path11.sep).join("/");
|
|
8466
8518
|
}
|
|
8467
8519
|
function assertSafeRelativePath(path2) {
|
|
8468
8520
|
const rel = normalizeRelativePath(path2.trim());
|
|
@@ -8473,8 +8525,8 @@ function assertSafeRelativePath(path2) {
|
|
|
8473
8525
|
}
|
|
8474
8526
|
function safeJoin(root, relPath) {
|
|
8475
8527
|
const rel = assertSafeRelativePath(relPath);
|
|
8476
|
-
const target = (0,
|
|
8477
|
-
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));
|
|
8478
8530
|
if (fromRoot === ".." || fromRoot.startsWith("../") || fromRoot.startsWith("/")) {
|
|
8479
8531
|
throw new Error(`Unsafe install path: ${relPath}`);
|
|
8480
8532
|
}
|
|
@@ -8485,33 +8537,82 @@ function packageHelperSlug(name) {
|
|
|
8485
8537
|
return `${scope}__${pkg}`;
|
|
8486
8538
|
}
|
|
8487
8539
|
function helperRootFor(configRoot, packageName, version) {
|
|
8488
|
-
const base = (0,
|
|
8489
|
-
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);
|
|
8490
8542
|
}
|
|
8491
8543
|
async function assertSourceFile(packageRoot, relPath) {
|
|
8492
8544
|
const source = safeJoin(packageRoot, relPath);
|
|
8493
|
-
const info = await (0,
|
|
8545
|
+
const info = await (0, import_promises8.stat)(source).catch(() => null);
|
|
8494
8546
|
if (!info?.isFile()) throw new Error(`Package install file not found: ${relPath}`);
|
|
8495
8547
|
return source;
|
|
8496
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
|
+
}
|
|
8497
8598
|
async function copyMainFile(input2) {
|
|
8498
8599
|
const source = await assertSourceFile(input2.packageRoot, input2.file.from);
|
|
8499
8600
|
const target = safeJoin(input2.installRoot, input2.file.to);
|
|
8500
8601
|
const overwrite = input2.file.overwrite ?? "fail";
|
|
8501
|
-
const exists = await (0,
|
|
8602
|
+
const exists = await (0, import_promises8.stat)(target).catch(() => null);
|
|
8502
8603
|
if (exists) {
|
|
8503
8604
|
if (overwrite === "skip") return null;
|
|
8504
8605
|
if (overwrite === "fail") throw new Error(`Install target already exists: ${target}`);
|
|
8505
8606
|
}
|
|
8506
|
-
await (0,
|
|
8507
|
-
await (0,
|
|
8607
|
+
await (0, import_promises8.mkdir)((0, import_node_path11.dirname)(target), { recursive: true });
|
|
8608
|
+
await (0, import_promises8.cp)(source, target, { force: overwrite === "replace" });
|
|
8508
8609
|
return target;
|
|
8509
8610
|
}
|
|
8510
8611
|
async function copyHelperFile(input2) {
|
|
8511
8612
|
const source = await assertSourceFile(input2.packageRoot, input2.file.from);
|
|
8512
|
-
const target = safeJoin(input2.helperRoot, input2.file.to ?? (0,
|
|
8513
|
-
await (0,
|
|
8514
|
-
await (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 });
|
|
8615
|
+
await (0, import_promises8.cp)(source, target, { force: true });
|
|
8515
8616
|
return target;
|
|
8516
8617
|
}
|
|
8517
8618
|
async function installPackageAssets(options) {
|
|
@@ -8528,7 +8629,7 @@ async function installPackageAssets(options) {
|
|
|
8528
8629
|
}
|
|
8529
8630
|
const helperRoot = helperRootFor(options.configRoot, options.packageName, options.version);
|
|
8530
8631
|
if ((install.helperFiles ?? []).length > 0) {
|
|
8531
|
-
await (0,
|
|
8632
|
+
await (0, import_promises8.rm)(helperRoot, { recursive: true, force: true });
|
|
8532
8633
|
}
|
|
8533
8634
|
for (const file of install.helperFiles ?? []) {
|
|
8534
8635
|
assets.helper.push(await copyHelperFile({ packageRoot: options.packageRoot, helperRoot, file }));
|
|
@@ -8573,7 +8674,7 @@ async function installOnePackage(options) {
|
|
|
8573
8674
|
}
|
|
8574
8675
|
let explicitTarget = options.explicitTarget;
|
|
8575
8676
|
let preferredTools = options.project.preferredTools;
|
|
8576
|
-
const { resolveInstallTools: resolveInstallTools2 } = await Promise.resolve().then(() => (
|
|
8677
|
+
const { resolveInstallTools: resolveInstallTools2 } = await Promise.resolve().then(() => (init_dist6(), dist_exports));
|
|
8577
8678
|
let tools = await resolveInstallTools2({
|
|
8578
8679
|
projectRoot: installRoot,
|
|
8579
8680
|
manifest,
|
|
@@ -8604,11 +8705,13 @@ async function installOnePackage(options) {
|
|
|
8604
8705
|
);
|
|
8605
8706
|
const packageRoot = await unpackTarballToDirectory(tarball);
|
|
8606
8707
|
try {
|
|
8607
|
-
const skillMarkdown = await (0,
|
|
8708
|
+
const skillMarkdown = await (0, import_promises8.readFile)(safeJoin(packageRoot, manifest.entry), "utf8");
|
|
8709
|
+
const supportingFiles = await collectSkillSupportingFiles(packageRoot, manifest);
|
|
8608
8710
|
const result = await installSkillPackage({
|
|
8609
8711
|
projectRoot: installRoot,
|
|
8610
8712
|
manifest,
|
|
8611
8713
|
skillMarkdown,
|
|
8714
|
+
supportingFiles,
|
|
8612
8715
|
preferredTools,
|
|
8613
8716
|
explicitTarget
|
|
8614
8717
|
});
|
|
@@ -8645,23 +8748,23 @@ async function installOnePackage(options) {
|
|
|
8645
8748
|
console.log(`Installed ${options.name}@${options.version} \u2192 ${result.resolvedTools.join(", ")}`);
|
|
8646
8749
|
printPostInstallNotice(options.name, postInstall);
|
|
8647
8750
|
} finally {
|
|
8648
|
-
await (0,
|
|
8751
|
+
await (0, import_promises8.rm)(packageRoot, { recursive: true, force: true });
|
|
8649
8752
|
}
|
|
8650
8753
|
}
|
|
8651
8754
|
|
|
8652
8755
|
// src/doctor.ts
|
|
8653
8756
|
var import_node_child_process3 = require("node:child_process");
|
|
8654
|
-
var
|
|
8655
|
-
var
|
|
8757
|
+
var import_promises9 = require("node:fs/promises");
|
|
8758
|
+
var import_node_path13 = require("node:path");
|
|
8656
8759
|
var import_node_util4 = require("node:util");
|
|
8657
8760
|
|
|
8658
8761
|
// src/project-root.ts
|
|
8659
8762
|
var import_node_os3 = require("node:os");
|
|
8660
|
-
var
|
|
8763
|
+
var import_node_path12 = require("node:path");
|
|
8661
8764
|
var import_node_process3 = require("node:process");
|
|
8662
8765
|
function globalConfigDir(env2 = process.env) {
|
|
8663
8766
|
const fromEnv = env2.AIPM_HOME?.trim();
|
|
8664
|
-
return fromEnv ? fromEnv.replace(/\/$/, "") : (0,
|
|
8767
|
+
return fromEnv ? fromEnv.replace(/\/$/, "") : (0, import_node_path12.join)((0, import_node_os3.homedir)(), ".aipm");
|
|
8665
8768
|
}
|
|
8666
8769
|
function resolveConfigRoot(options = {}) {
|
|
8667
8770
|
return options.global ? globalConfigDir() : (0, import_node_process3.cwd)();
|
|
@@ -8673,7 +8776,7 @@ function scopeLabel(options) {
|
|
|
8673
8776
|
return options.global ? "global" : "project";
|
|
8674
8777
|
}
|
|
8675
8778
|
function initRequiredMessage(options) {
|
|
8676
|
-
return options.global ?
|
|
8779
|
+
return options.global ? `Run ${recommendCmd("aipm init -g")} first` : `Run ${recommendCmd("aipm init")} first`;
|
|
8677
8780
|
}
|
|
8678
8781
|
|
|
8679
8782
|
// src/doctor.ts
|
|
@@ -8692,11 +8795,11 @@ async function commandOutput(command, args) {
|
|
|
8692
8795
|
}
|
|
8693
8796
|
function npmGlobalBin(prefix) {
|
|
8694
8797
|
if (!prefix) return null;
|
|
8695
|
-
return process.platform === "win32" ? prefix : `${prefix}${
|
|
8798
|
+
return process.platform === "win32" ? prefix : `${prefix}${import_node_path13.sep}bin`;
|
|
8696
8799
|
}
|
|
8697
8800
|
function pathIncludes(pathDir) {
|
|
8698
8801
|
if (!pathDir) return false;
|
|
8699
|
-
return (process.env.PATH ?? "").split(
|
|
8802
|
+
return (process.env.PATH ?? "").split(import_node_path13.delimiter).includes(pathDir);
|
|
8700
8803
|
}
|
|
8701
8804
|
function shellPathHint(binDir) {
|
|
8702
8805
|
if (!binDir) return "Run npm prefix -g and add its bin folder to PATH.";
|
|
@@ -8749,11 +8852,11 @@ async function runDoctor(options) {
|
|
|
8749
8852
|
if (!options.publish) {
|
|
8750
8853
|
const configLabel = options.global ? "Global config" : "Project config";
|
|
8751
8854
|
try {
|
|
8752
|
-
await (0,
|
|
8855
|
+
await (0, import_promises9.access)((0, import_node_path13.join)(configRoot, "aipm.package.json"));
|
|
8753
8856
|
checks.push({
|
|
8754
8857
|
name: configLabel,
|
|
8755
8858
|
ok: true,
|
|
8756
|
-
detail: `${(0,
|
|
8859
|
+
detail: `${(0, import_node_path13.join)(configRoot, "aipm.package.json")} exists (${scopeLabel(scope)}).`
|
|
8757
8860
|
});
|
|
8758
8861
|
} catch {
|
|
8759
8862
|
checks.push({
|
|
@@ -8783,7 +8886,7 @@ async function runDoctor(options) {
|
|
|
8783
8886
|
checks.push({
|
|
8784
8887
|
name: "Publish stage",
|
|
8785
8888
|
ok: rows.length > 0 && changed.length === 0,
|
|
8786
|
-
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.`
|
|
8787
8890
|
});
|
|
8788
8891
|
} catch (error) {
|
|
8789
8892
|
checks.push({
|
|
@@ -8823,8 +8926,8 @@ async function runDoctor(options) {
|
|
|
8823
8926
|
|
|
8824
8927
|
// src/prompt-install.ts
|
|
8825
8928
|
var import_node_crypto2 = require("node:crypto");
|
|
8826
|
-
var
|
|
8827
|
-
var
|
|
8929
|
+
var import_promises10 = require("node:fs/promises");
|
|
8930
|
+
var import_node_path14 = require("node:path");
|
|
8828
8931
|
var PROMPT_SITE_ORIGIN = "https://www.aipm-registry.com";
|
|
8829
8932
|
function parsePromptUrl(value) {
|
|
8830
8933
|
let url;
|
|
@@ -8849,10 +8952,10 @@ function parsePromptUrl(value) {
|
|
|
8849
8952
|
};
|
|
8850
8953
|
}
|
|
8851
8954
|
function promptDirectory(configRoot) {
|
|
8852
|
-
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");
|
|
8853
8956
|
}
|
|
8854
8957
|
function promptSnapshotPath(configRoot, reference) {
|
|
8855
|
-
return (0,
|
|
8958
|
+
return (0, import_node_path14.join)(promptDirectory(configRoot), `${reference.publisher}--${reference.slug}.md`);
|
|
8856
8959
|
}
|
|
8857
8960
|
function canonicalPromptContent(prompt) {
|
|
8858
8961
|
return JSON.stringify({
|
|
@@ -8911,7 +9014,7 @@ function emptyLock() {
|
|
|
8911
9014
|
return { schemaVersion: "0.1", packages: {}, prompts: {} };
|
|
8912
9015
|
}
|
|
8913
9016
|
function installedRelativePath(configRoot, absolutePath) {
|
|
8914
|
-
return (0,
|
|
9017
|
+
return (0, import_node_path14.relative)(configRoot, absolutePath).split("\\").join("/");
|
|
8915
9018
|
}
|
|
8916
9019
|
async function installTrackedPrompt(input2) {
|
|
8917
9020
|
const prompt = await fetchPromptDetail(
|
|
@@ -8929,11 +9032,11 @@ async function installTrackedPrompt(input2) {
|
|
|
8929
9032
|
const contentHash = promptContentHash(prompt);
|
|
8930
9033
|
const lock = await readLockfile(input2.configRoot) ?? emptyLock();
|
|
8931
9034
|
const existing = lock.prompts[input2.reference.alias];
|
|
8932
|
-
const fileExists = Boolean(await (0,
|
|
9035
|
+
const fileExists = Boolean(await (0, import_promises10.stat)(outputPath).catch(() => null));
|
|
8933
9036
|
const changed = !existing || existing.contentHash !== contentHash || !fileExists;
|
|
8934
9037
|
if (!input2.updateOnly || changed) {
|
|
8935
|
-
await (0,
|
|
8936
|
-
await (0,
|
|
9038
|
+
await (0, import_promises10.mkdir)((0, import_node_path14.dirname)(outputPath), { recursive: true });
|
|
9039
|
+
await (0, import_promises10.writeFile)(outputPath, renderPromptMarkdown(prompt, canonicalReference.url), "utf8");
|
|
8937
9040
|
}
|
|
8938
9041
|
if (input2.track) {
|
|
8939
9042
|
const currentUrl = input2.project.prompts[input2.reference.alias];
|
|
@@ -8975,12 +9078,12 @@ function resolveTrackedPrompt(project, value) {
|
|
|
8975
9078
|
return parsed ? { ...parsed, alias: value } : null;
|
|
8976
9079
|
}
|
|
8977
9080
|
async function readInstalledPrompt(configRoot, entry) {
|
|
8978
|
-
return (0,
|
|
9081
|
+
return (0, import_promises10.readFile)((0, import_node_path14.join)(configRoot, entry.installedPath), "utf8");
|
|
8979
9082
|
}
|
|
8980
9083
|
async function removeTrackedPrompt(input2) {
|
|
8981
9084
|
const lock = await readLockfile(input2.configRoot);
|
|
8982
9085
|
const entry = lock?.prompts[input2.reference.alias];
|
|
8983
|
-
if (entry) await (0,
|
|
9086
|
+
if (entry) await (0, import_promises10.rm)((0, import_node_path14.join)(input2.configRoot, entry.installedPath), { force: true });
|
|
8984
9087
|
const prompts = { ...input2.project.prompts };
|
|
8985
9088
|
delete prompts[input2.reference.alias];
|
|
8986
9089
|
await writeProjectPackageJson(input2.configRoot, { ...input2.project, prompts });
|
|
@@ -8991,11 +9094,65 @@ async function removeTrackedPrompt(input2) {
|
|
|
8991
9094
|
}
|
|
8992
9095
|
}
|
|
8993
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
|
+
|
|
8994
9151
|
// src/version.ts
|
|
8995
9152
|
var import_node_fs2 = require("node:fs");
|
|
8996
|
-
var
|
|
9153
|
+
var import_node_path16 = require("node:path");
|
|
8997
9154
|
function getCliVersion() {
|
|
8998
|
-
const pkgPath = (0,
|
|
9155
|
+
const pkgPath = (0, import_node_path16.join)(__dirname, "..", "package.json");
|
|
8999
9156
|
const pkg = JSON.parse((0, import_node_fs2.readFileSync)(pkgPath, "utf8"));
|
|
9000
9157
|
return pkg.version;
|
|
9001
9158
|
}
|
|
@@ -9141,7 +9298,7 @@ async function writeStarterFile(path2, content) {
|
|
|
9141
9298
|
}
|
|
9142
9299
|
async function inferEntryFromSource(source, fallback) {
|
|
9143
9300
|
const sourceInfo = await (0, import_promises12.stat)(source);
|
|
9144
|
-
if (sourceInfo.isFile()) return (0,
|
|
9301
|
+
if (sourceInfo.isFile()) return (0, import_node_path17.basename)(source);
|
|
9145
9302
|
if (!sourceInfo.isDirectory()) return fallback;
|
|
9146
9303
|
const entries = await (0, import_promises12.readdir)(source);
|
|
9147
9304
|
if (entries.includes(fallback)) return fallback;
|
|
@@ -9153,7 +9310,7 @@ async function copySourceIntoSkillRoot(source, root, sourceLabel) {
|
|
|
9153
9310
|
if (sourceInfo.isDirectory()) {
|
|
9154
9311
|
const entries = await (0, import_promises12.readdir)(source);
|
|
9155
9312
|
for (const entry of entries) {
|
|
9156
|
-
await (0, import_promises12.cp)((0,
|
|
9313
|
+
await (0, import_promises12.cp)((0, import_node_path17.join)(source, entry), (0, import_node_path17.join)(root, entry), {
|
|
9157
9314
|
recursive: true,
|
|
9158
9315
|
force: false,
|
|
9159
9316
|
errorOnExist: true
|
|
@@ -9162,7 +9319,7 @@ async function copySourceIntoSkillRoot(source, root, sourceLabel) {
|
|
|
9162
9319
|
return;
|
|
9163
9320
|
}
|
|
9164
9321
|
if (sourceInfo.isFile()) {
|
|
9165
|
-
await (0, import_promises12.cp)(source, (0,
|
|
9322
|
+
await (0, import_promises12.cp)(source, (0, import_node_path17.join)(root, (0, import_node_path17.basename)(source)), { force: false, errorOnExist: true });
|
|
9166
9323
|
return;
|
|
9167
9324
|
}
|
|
9168
9325
|
throw new Error(`Unsupported source path: ${sourceLabel}`);
|
|
@@ -9196,11 +9353,11 @@ function packageDashboardUrl(name) {
|
|
|
9196
9353
|
return `${DASHBOARD_URL}/packages/${name.replace(/^@/, "")}`;
|
|
9197
9354
|
}
|
|
9198
9355
|
function helperRootFromTrackedPath(path2) {
|
|
9199
|
-
const parts = path2.split(
|
|
9356
|
+
const parts = path2.split(import_node_path17.sep).filter(Boolean);
|
|
9200
9357
|
const helpersIndex = parts.lastIndexOf("helpers");
|
|
9201
9358
|
if (helpersIndex === -1 || parts.length <= helpersIndex + 2) return null;
|
|
9202
|
-
const prefix = path2.startsWith(
|
|
9203
|
-
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));
|
|
9204
9361
|
}
|
|
9205
9362
|
async function showInstalledPrompt(configRoot, packageArg) {
|
|
9206
9363
|
const { name } = parsePackageArg(packageArg);
|
|
@@ -9293,7 +9450,7 @@ async function authTokenForRegistry(registry, options = {}) {
|
|
|
9293
9450
|
return refreshed.accessToken;
|
|
9294
9451
|
} catch {
|
|
9295
9452
|
await clearStoredRegistryAuth(registry);
|
|
9296
|
-
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.`;
|
|
9297
9454
|
if (options.throwOnFailure) throw new Error(message);
|
|
9298
9455
|
if (!options.quiet) console.warn(`Warning: ${message}`);
|
|
9299
9456
|
return void 0;
|
|
@@ -9542,9 +9699,9 @@ function buildStarterQualityMetadata(options) {
|
|
|
9542
9699
|
}
|
|
9543
9700
|
async function initSkill(opts) {
|
|
9544
9701
|
if (!isValidScopeName(opts.name)) throw new Error("Invalid @scope/name");
|
|
9545
|
-
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));
|
|
9546
9703
|
const cdTarget = opts.here ? null : opts.dir ?? skillFolderName(opts.name);
|
|
9547
|
-
const source = opts.from ? (0,
|
|
9704
|
+
const source = opts.from ? (0, import_node_path17.resolve)(opts.from) : null;
|
|
9548
9705
|
const entry = source ? await inferEntryFromSource(source, opts.entry) : opts.entry;
|
|
9549
9706
|
const template = parseSkillTemplate(opts.template ?? "blank");
|
|
9550
9707
|
const manifest = PackageManifestSchema.parse({
|
|
@@ -9567,15 +9724,15 @@ async function initSkill(opts) {
|
|
|
9567
9724
|
} else {
|
|
9568
9725
|
await (0, import_promises12.mkdir)(root, { recursive: true });
|
|
9569
9726
|
}
|
|
9570
|
-
await writeStarterFile((0,
|
|
9727
|
+
await writeStarterFile((0, import_node_path17.join)(root, "aipm.manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
9571
9728
|
if (!opts.from) {
|
|
9572
9729
|
await writeStarterFile(
|
|
9573
|
-
(0,
|
|
9730
|
+
(0, import_node_path17.join)(root, entry),
|
|
9574
9731
|
SKILL_TEMPLATES[template](opts.name)
|
|
9575
9732
|
);
|
|
9576
9733
|
}
|
|
9577
9734
|
await writeStarterFile(
|
|
9578
|
-
(0,
|
|
9735
|
+
(0, import_node_path17.join)(root, ".aipmignore"),
|
|
9579
9736
|
[
|
|
9580
9737
|
"# Files that should never be published with this skill",
|
|
9581
9738
|
".env*",
|
|
@@ -9593,7 +9750,7 @@ async function initSkill(opts) {
|
|
|
9593
9750
|
""
|
|
9594
9751
|
].join("\n")
|
|
9595
9752
|
);
|
|
9596
|
-
await (0, import_promises12.mkdir)((0,
|
|
9753
|
+
await (0, import_promises12.mkdir)((0, import_node_path17.join)(root, ".aipm"), { recursive: true });
|
|
9597
9754
|
console.log(`Created ${opts.name} skill folder: ${root}`);
|
|
9598
9755
|
printPublishGuide(
|
|
9599
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.`,
|
|
@@ -9734,7 +9891,7 @@ program2.command("add <package-or-prompt>").description("Add a skill package or
|
|
|
9734
9891
|
const { name, version: requestedVersion } = parsePackageArg(pkgArg);
|
|
9735
9892
|
const token = await tokenForRead(registry, opts.token);
|
|
9736
9893
|
const version = requestedVersion ?? project.packages[name] ?? await latestVersionForPackage(registry, name, token);
|
|
9737
|
-
if (!version) throw new Error(
|
|
9894
|
+
if (!version) throw new Error(`Specify version: ${recommendCmd("aipm add <@scope/pkg>@<version>")}`);
|
|
9738
9895
|
project = {
|
|
9739
9896
|
...project,
|
|
9740
9897
|
packages: { ...project.packages, [name]: version.replace(/^\^/, "") }
|
|
@@ -9826,7 +9983,7 @@ program2.command("show <package-or-prompt>").description("Show an installed prom
|
|
|
9826
9983
|
if (reference && project.prompts[reference.alias] === reference.url) {
|
|
9827
9984
|
const lock2 = await readLockfile(configRoot);
|
|
9828
9985
|
const entry2 = lock2?.prompts[reference.alias];
|
|
9829
|
-
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")}.`);
|
|
9830
9987
|
console.log(await readInstalledPrompt(configRoot, entry2));
|
|
9831
9988
|
return;
|
|
9832
9989
|
}
|
|
@@ -9840,7 +9997,7 @@ program2.command("show-prompt <package>").description("Show the manual setup pro
|
|
|
9840
9997
|
await showInstalledPrompt(resolveConfigRoot({ global: opts.global }), pkgArg);
|
|
9841
9998
|
});
|
|
9842
9999
|
function promptImageContentType(path2) {
|
|
9843
|
-
const extension = (0,
|
|
10000
|
+
const extension = (0, import_node_path17.extname)(path2).toLowerCase();
|
|
9844
10001
|
if (extension === ".png") return "image/png";
|
|
9845
10002
|
if (extension === ".jpg" || extension === ".jpeg") return "image/jpeg";
|
|
9846
10003
|
if (extension === ".webp") return "image/webp";
|
|
@@ -9850,8 +10007,8 @@ var promptCommand = program2.command("prompt").description("Publish prompt listi
|
|
|
9850
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) => {
|
|
9851
10008
|
const registry = registryFromEnvOrDefault(opts.registry);
|
|
9852
10009
|
const accessToken = await authTokenForRegistry(registry, { throwOnFailure: true });
|
|
9853
|
-
if (!accessToken) throw new Error(
|
|
9854
|
-
const absoluteFile = (0,
|
|
10010
|
+
if (!accessToken) throw new Error(`Run ${recommendCmd("aipm login")} before publishing prompts.`);
|
|
10011
|
+
const absoluteFile = (0, import_node_path17.resolve)(file);
|
|
9855
10012
|
const parsed = JSON.parse(await (0, import_promises12.readFile)(absoluteFile, "utf8"));
|
|
9856
10013
|
const rows = Array.isArray(parsed) ? parsed : "prompts" in parsed ? parsed.prompts : [parsed];
|
|
9857
10014
|
if (rows.length === 0) throw new Error("Prompt publish file contains no prompts.");
|
|
@@ -9863,10 +10020,10 @@ promptCommand.command("publish <file>").description("Publish one prompt or a bat
|
|
|
9863
10020
|
const { sampleImagePath, ...input2 } = row;
|
|
9864
10021
|
let sampleImage;
|
|
9865
10022
|
if (sampleImagePath) {
|
|
9866
|
-
const imagePath = (0,
|
|
10023
|
+
const imagePath = (0, import_node_path17.resolve)((0, import_node_path17.dirname)(absoluteFile), sampleImagePath);
|
|
9867
10024
|
sampleImage = {
|
|
9868
10025
|
data: await (0, import_promises12.readFile)(imagePath),
|
|
9869
|
-
filename: (0,
|
|
10026
|
+
filename: (0, import_node_path17.basename)(imagePath),
|
|
9870
10027
|
contentType: promptImageContentType(imagePath)
|
|
9871
10028
|
};
|
|
9872
10029
|
}
|
|
@@ -9889,8 +10046,8 @@ var publish = program2.command("publish [dir]").description("Stage, validate, an
|
|
|
9889
10046
|
publish.help();
|
|
9890
10047
|
return;
|
|
9891
10048
|
}
|
|
9892
|
-
const abs = (0,
|
|
9893
|
-
const manifestRaw = await (0, import_promises12.readFile)((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");
|
|
9894
10051
|
const manifest = PackageManifestSchema.parse(JSON.parse(manifestRaw));
|
|
9895
10052
|
const tarball = await packDirectory(abs);
|
|
9896
10053
|
const registry = registryFromEnvOrDefault(opts.registry);
|
|
@@ -10055,6 +10212,7 @@ program2.command("list").description("List installed skills and prompts from aip
|
|
|
10055
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) => {
|
|
10056
10213
|
const scope = { global: opts.global };
|
|
10057
10214
|
const configRoot = resolveConfigRoot(scope);
|
|
10215
|
+
const installRoot = resolveInstallRoot(scope);
|
|
10058
10216
|
const project = await readProjectPackageJson(configRoot);
|
|
10059
10217
|
if (!project) throw new Error(initRequiredMessage(scope));
|
|
10060
10218
|
const promptReference = resolveTrackedPrompt(project, pkgArg);
|
|
@@ -10064,17 +10222,30 @@ program2.command("remove <package-or-prompt>").alias("rm").description("Remove a
|
|
|
10064
10222
|
return;
|
|
10065
10223
|
}
|
|
10066
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
|
+
}
|
|
10067
10240
|
const packages = { ...project.packages };
|
|
10068
10241
|
delete packages[name];
|
|
10069
10242
|
await writeProjectPackageJson(configRoot, { ...project, packages });
|
|
10070
|
-
const lock = await readLockfile(configRoot);
|
|
10071
10243
|
if (lock) {
|
|
10072
10244
|
const lockPackages = { ...lock.packages };
|
|
10073
10245
|
delete lockPackages[name];
|
|
10074
10246
|
await writeLockfile(configRoot, { ...lock, packages: lockPackages });
|
|
10075
10247
|
}
|
|
10076
10248
|
console.log(`Removed ${name} from AIPM ${scopeLabel(scope)} files.`);
|
|
10077
|
-
console.log("Adapter-written files are not deleted yet; review your project before committing.");
|
|
10078
10249
|
});
|
|
10079
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) => {
|
|
10080
10251
|
const scope = { global: opts.global };
|