@aipm-registry/cli 0.3.1 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/dist/bin.cjs +371 -79
- package/dist/bin.cjs.map +3 -3
- package/package.json +1 -1
package/dist/bin.cjs
CHANGED
|
@@ -4160,7 +4160,19 @@ function expandTargets(targets) {
|
|
|
4160
4160
|
return [...ALL_TOOLS];
|
|
4161
4161
|
return targets.filter((t) => t !== "*");
|
|
4162
4162
|
}
|
|
4163
|
-
|
|
4163
|
+
function isSafeRelativePath(value) {
|
|
4164
|
+
const trimmed = value.trim();
|
|
4165
|
+
if (!trimmed || trimmed.startsWith("/") || trimmed.startsWith("\\") || /^[A-Za-z]:/.test(trimmed)) {
|
|
4166
|
+
return false;
|
|
4167
|
+
}
|
|
4168
|
+
const normalized = trimmed.replace(/\\/g, "/");
|
|
4169
|
+
return normalized.split("/").filter(Boolean).every((segment) => segment !== "." && segment !== "..");
|
|
4170
|
+
}
|
|
4171
|
+
function basename(value) {
|
|
4172
|
+
const parts = value.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
4173
|
+
return parts[parts.length - 1] ?? value;
|
|
4174
|
+
}
|
|
4175
|
+
var AiToolSchema, ALL_TOOLS, PackageExampleSchema, unsafePathMessage, InstallPathSchema, InstallOverwriteSchema, PackageInstallSchema, PackageManifestSchema;
|
|
4164
4176
|
var init_manifest = __esm({
|
|
4165
4177
|
"../../packages/schemas/dist/manifest.js"() {
|
|
4166
4178
|
"use strict";
|
|
@@ -4173,6 +4185,36 @@ var init_manifest = __esm({
|
|
|
4173
4185
|
description: external_exports.string().trim().min(1).max(240).optional(),
|
|
4174
4186
|
prompt: external_exports.string().trim().min(1).max(1e3)
|
|
4175
4187
|
});
|
|
4188
|
+
unsafePathMessage = "path must be relative and must not contain .. segments";
|
|
4189
|
+
InstallPathSchema = external_exports.string().trim().min(1).refine(isSafeRelativePath, unsafePathMessage);
|
|
4190
|
+
InstallOverwriteSchema = external_exports.enum(["fail", "skip", "replace"]);
|
|
4191
|
+
PackageInstallSchema = external_exports.object({
|
|
4192
|
+
mainFiles: external_exports.array(external_exports.object({
|
|
4193
|
+
from: InstallPathSchema,
|
|
4194
|
+
to: InstallPathSchema,
|
|
4195
|
+
overwrite: InstallOverwriteSchema.optional()
|
|
4196
|
+
})).optional(),
|
|
4197
|
+
helperFiles: external_exports.array(external_exports.object({
|
|
4198
|
+
from: InstallPathSchema,
|
|
4199
|
+
to: InstallPathSchema.optional()
|
|
4200
|
+
})).optional(),
|
|
4201
|
+
postInstall: external_exports.object({
|
|
4202
|
+
mode: external_exports.literal("manual_prompt"),
|
|
4203
|
+
promptFile: InstallPathSchema,
|
|
4204
|
+
cleanup: external_exports.enum(["manual", "after_user_confirmation"]).optional()
|
|
4205
|
+
}).optional()
|
|
4206
|
+
}).superRefine((install, ctx) => {
|
|
4207
|
+
if (!install.postInstall)
|
|
4208
|
+
return;
|
|
4209
|
+
const helperTargets = new Set((install.helperFiles ?? []).map((file) => file.to ?? basename(file.from)));
|
|
4210
|
+
if (!helperTargets.has(install.postInstall.promptFile)) {
|
|
4211
|
+
ctx.addIssue({
|
|
4212
|
+
code: external_exports.ZodIssueCode.custom,
|
|
4213
|
+
path: ["postInstall", "promptFile"],
|
|
4214
|
+
message: "postInstall.promptFile must point to an installed helper file"
|
|
4215
|
+
});
|
|
4216
|
+
}
|
|
4217
|
+
});
|
|
4176
4218
|
PackageManifestSchema = external_exports.object({
|
|
4177
4219
|
schemaVersion: external_exports.literal("0.1"),
|
|
4178
4220
|
name: external_exports.string().regex(SCOPE_NAME_REGEX, "name must be @scope/name"),
|
|
@@ -4183,11 +4225,13 @@ var init_manifest = __esm({
|
|
|
4183
4225
|
targets: external_exports.array(AiToolSchema).min(1),
|
|
4184
4226
|
license: external_exports.string().optional(),
|
|
4185
4227
|
usage: external_exports.string().trim().min(1).max(2e3).optional(),
|
|
4228
|
+
agentDescription: external_exports.string().trim().min(1).max(12e3).optional(),
|
|
4186
4229
|
tags: external_exports.array(external_exports.string().trim().min(1).max(40)).max(12).optional(),
|
|
4187
4230
|
categories: external_exports.array(external_exports.string().trim().min(1).max(40)).max(4).optional(),
|
|
4188
4231
|
sourceUrl: external_exports.string().trim().url().max(500).optional(),
|
|
4189
4232
|
examples: external_exports.array(PackageExampleSchema).max(5).optional(),
|
|
4190
|
-
releaseNotes: external_exports.string().trim().min(1).max(2e3).optional()
|
|
4233
|
+
releaseNotes: external_exports.string().trim().min(1).max(2e3).optional(),
|
|
4234
|
+
install: PackageInstallSchema.optional()
|
|
4191
4235
|
});
|
|
4192
4236
|
}
|
|
4193
4237
|
});
|
|
@@ -4225,7 +4269,17 @@ var init_lockfile = __esm({
|
|
|
4225
4269
|
integrity: external_exports.string(),
|
|
4226
4270
|
registry: external_exports.string().url(),
|
|
4227
4271
|
resolvedTools: external_exports.array(AiToolSchema),
|
|
4228
|
-
installed: InstalledPathsSchema
|
|
4272
|
+
installed: InstalledPathsSchema,
|
|
4273
|
+
installedAssets: external_exports.object({
|
|
4274
|
+
main: external_exports.array(external_exports.string()),
|
|
4275
|
+
helper: external_exports.array(external_exports.string())
|
|
4276
|
+
}).optional(),
|
|
4277
|
+
postInstall: external_exports.object({
|
|
4278
|
+
mode: external_exports.literal("manual_prompt"),
|
|
4279
|
+
status: external_exports.enum(["pending", "cleaned"]),
|
|
4280
|
+
promptFile: external_exports.string(),
|
|
4281
|
+
cleanup: external_exports.enum(["manual", "after_user_confirmation"])
|
|
4282
|
+
}).optional()
|
|
4229
4283
|
});
|
|
4230
4284
|
LockfileSchema = external_exports.object({
|
|
4231
4285
|
schemaVersion: external_exports.literal("0.1"),
|
|
@@ -7776,16 +7830,15 @@ var import_node_crypto2 = require("node:crypto");
|
|
|
7776
7830
|
var import_node_child_process4 = require("node:child_process");
|
|
7777
7831
|
var import_node_http = require("node:http");
|
|
7778
7832
|
var import_promises10 = require("node:fs/promises");
|
|
7779
|
-
var
|
|
7833
|
+
var import_node_path13 = require("node:path");
|
|
7780
7834
|
var import_node_process5 = require("node:process");
|
|
7781
7835
|
init_dist();
|
|
7782
7836
|
init_dist4();
|
|
7783
7837
|
|
|
7784
7838
|
// src/pack.ts
|
|
7785
7839
|
var import_node_child_process2 = require("node:child_process");
|
|
7786
|
-
var import_promises5 = require("node:fs/promises");
|
|
7787
7840
|
var import_node_util3 = require("node:util");
|
|
7788
|
-
var
|
|
7841
|
+
var import_promises5 = require("node:fs/promises");
|
|
7789
7842
|
var import_node_path6 = require("node:path");
|
|
7790
7843
|
var import_node_os = require("node:os");
|
|
7791
7844
|
|
|
@@ -7938,6 +7991,14 @@ async function readManifest(root) {
|
|
|
7938
7991
|
throw error;
|
|
7939
7992
|
}
|
|
7940
7993
|
}
|
|
7994
|
+
function installReferencedFiles(manifest) {
|
|
7995
|
+
const install = manifest.install;
|
|
7996
|
+
if (!install) return [];
|
|
7997
|
+
return [
|
|
7998
|
+
...(install.mainFiles ?? []).map((file) => file.from),
|
|
7999
|
+
...(install.helperFiles ?? []).map((file) => file.from)
|
|
8000
|
+
];
|
|
8001
|
+
}
|
|
7941
8002
|
async function validatePublishState(root) {
|
|
7942
8003
|
const manifest = await readManifest(root);
|
|
7943
8004
|
const state = await readPublishState(root);
|
|
@@ -7945,6 +8006,9 @@ async function validatePublishState(root) {
|
|
|
7945
8006
|
const staged = new Set(state.files.map((entry) => entry.path));
|
|
7946
8007
|
if (!staged.has("aipm.manifest.json")) throw new Error("aipm.manifest.json must be staged.");
|
|
7947
8008
|
if (!staged.has(manifest.entry)) throw new Error(`Manifest entry must be staged: ${manifest.entry}`);
|
|
8009
|
+
for (const file of installReferencedFiles(manifest)) {
|
|
8010
|
+
if (!staged.has(file)) throw new Error(`Manifest install file must be staged: ${file}`);
|
|
8011
|
+
}
|
|
7948
8012
|
let size = 0;
|
|
7949
8013
|
for (const entry of state.files) {
|
|
7950
8014
|
if (isExcludedPublishPath(entry.path)) throw new Error(`Refusing to publish excluded path: ${entry.path}`);
|
|
@@ -7992,27 +8056,23 @@ async function packDirectory(dir) {
|
|
|
7992
8056
|
return Buffer.isBuffer(stdout) ? stdout : Buffer.from(stdout);
|
|
7993
8057
|
}
|
|
7994
8058
|
async function packStagedFiles(root) {
|
|
7995
|
-
const tempDir = await (0,
|
|
8059
|
+
const tempDir = await (0, import_promises5.mkdtemp)((0, import_node_path6.join)((0, import_node_os.tmpdir)(), "aipm-publish-stage-"));
|
|
7996
8060
|
try {
|
|
7997
8061
|
await copyStagedFiles(root, tempDir);
|
|
7998
8062
|
return await packDirectory(tempDir);
|
|
7999
8063
|
} finally {
|
|
8000
|
-
await (0,
|
|
8064
|
+
await (0, import_promises5.rm)(tempDir, { recursive: true, force: true });
|
|
8001
8065
|
}
|
|
8002
8066
|
}
|
|
8003
|
-
async function
|
|
8004
|
-
const { mkdtemp: mkdtemp2,
|
|
8005
|
-
const { join:
|
|
8067
|
+
async function unpackTarballToDirectory(tarball) {
|
|
8068
|
+
const { mkdtemp: mkdtemp2, writeFile: writeFile7 } = await import("node:fs/promises");
|
|
8069
|
+
const { join: join13 } = await import("node:path");
|
|
8006
8070
|
const { tmpdir: tmpdir2 } = await import("node:os");
|
|
8007
|
-
const tempDir = await mkdtemp2(
|
|
8008
|
-
const tgzPath =
|
|
8009
|
-
|
|
8010
|
-
|
|
8011
|
-
|
|
8012
|
-
return (0, import_promises5.readFile)(join12(tempDir, entry), "utf8");
|
|
8013
|
-
} finally {
|
|
8014
|
-
await rm3(tempDir, { recursive: true, force: true });
|
|
8015
|
-
}
|
|
8071
|
+
const tempDir = await mkdtemp2(join13(tmpdir2(), "aipm-install-"));
|
|
8072
|
+
const tgzPath = join13(tempDir, "pkg.tgz");
|
|
8073
|
+
await writeFile7(tgzPath, tarball);
|
|
8074
|
+
await execFileAsync("tar", ["-xzf", tgzPath, "-C", tempDir]);
|
|
8075
|
+
return tempDir;
|
|
8016
8076
|
}
|
|
8017
8077
|
|
|
8018
8078
|
// src/registry-client.ts
|
|
@@ -8046,6 +8106,22 @@ function privateInstallHint(name, status, token) {
|
|
|
8046
8106
|
}
|
|
8047
8107
|
return `Package not found: ${name} (${status}). If @org/pkg is private, run aipm login, or set AIPM_TOKEN for CI.`;
|
|
8048
8108
|
}
|
|
8109
|
+
function publishTokenHint(name, error) {
|
|
8110
|
+
if (error === "Publish token required") {
|
|
8111
|
+
return [
|
|
8112
|
+
`Publish token required for ${name}.`,
|
|
8113
|
+
`Generate a fresh 5-minute publish token for ${name} from the package dashboard, then retry with AIPM_TOKEN=<token> aipm publish push --yes.`
|
|
8114
|
+
].join(" ");
|
|
8115
|
+
}
|
|
8116
|
+
if (error === "Invalid publish token") {
|
|
8117
|
+
return [
|
|
8118
|
+
`Publish token was rejected for ${name}.`,
|
|
8119
|
+
`Generate a fresh 5-minute token for this exact package name, make sure aipm.manifest.json still says "${name}", and confirm your account can publish to that reserved package.`,
|
|
8120
|
+
"If you recently renamed the package or generated the token from another package page, create a new token from the matching package dashboard."
|
|
8121
|
+
].join(" ");
|
|
8122
|
+
}
|
|
8123
|
+
return error;
|
|
8124
|
+
}
|
|
8049
8125
|
async function assertRegistryReachable(registry) {
|
|
8050
8126
|
const base = registry.replace(/\/$/, "");
|
|
8051
8127
|
const res = await registryFetch(`${base}/health`, base);
|
|
@@ -8062,7 +8138,7 @@ async function publishPackage(registry, name, tarball, token) {
|
|
|
8062
8138
|
const res = await registryFetch(url, base, { method: "POST", body: form, headers });
|
|
8063
8139
|
if (!res.ok) {
|
|
8064
8140
|
const err = await res.json().catch(() => ({}));
|
|
8065
|
-
throw new Error(err.error
|
|
8141
|
+
throw new Error(err.error ? publishTokenHint(name, err.error) : `Publish failed: ${res.status}`);
|
|
8066
8142
|
}
|
|
8067
8143
|
return res.json();
|
|
8068
8144
|
}
|
|
@@ -8155,7 +8231,7 @@ async function recordPackageInstall(registry, name, token) {
|
|
|
8155
8231
|
}
|
|
8156
8232
|
|
|
8157
8233
|
// src/auth-store.ts
|
|
8158
|
-
var
|
|
8234
|
+
var import_promises6 = require("node:fs/promises");
|
|
8159
8235
|
var import_node_os2 = require("node:os");
|
|
8160
8236
|
var import_node_path7 = require("node:path");
|
|
8161
8237
|
var AUTH_FILE = (0, import_node_path7.join)((0, import_node_os2.homedir)(), ".aipm", "auth.json");
|
|
@@ -8164,7 +8240,7 @@ function normalizeRegistry(registry) {
|
|
|
8164
8240
|
}
|
|
8165
8241
|
async function readAuthStore() {
|
|
8166
8242
|
try {
|
|
8167
|
-
const raw = await (0,
|
|
8243
|
+
const raw = await (0, import_promises6.readFile)(AUTH_FILE, "utf8");
|
|
8168
8244
|
const parsed = JSON.parse(raw);
|
|
8169
8245
|
return { registries: parsed.registries ?? {} };
|
|
8170
8246
|
} catch {
|
|
@@ -8172,9 +8248,9 @@ async function readAuthStore() {
|
|
|
8172
8248
|
}
|
|
8173
8249
|
}
|
|
8174
8250
|
async function writeAuthStore(store) {
|
|
8175
|
-
await (0,
|
|
8176
|
-
await (0,
|
|
8177
|
-
await (0,
|
|
8251
|
+
await (0, import_promises6.mkdir)((0, import_node_path7.dirname)(AUTH_FILE), { recursive: true });
|
|
8252
|
+
await (0, import_promises6.writeFile)(AUTH_FILE, JSON.stringify(store, null, 2) + "\n", "utf8");
|
|
8253
|
+
await (0, import_promises6.chmod)(AUTH_FILE, 384).catch(() => void 0);
|
|
8178
8254
|
}
|
|
8179
8255
|
async function getStoredRegistryAuth(registry) {
|
|
8180
8256
|
const store = await readAuthStore();
|
|
@@ -8204,23 +8280,25 @@ function isAccessTokenFresh(auth, skewMs = 6e4) {
|
|
|
8204
8280
|
|
|
8205
8281
|
// src/install-one.ts
|
|
8206
8282
|
init_dist4();
|
|
8283
|
+
var import_promises8 = require("node:fs/promises");
|
|
8284
|
+
var import_node_path9 = require("node:path");
|
|
8207
8285
|
|
|
8208
8286
|
// src/project-files.ts
|
|
8209
|
-
var
|
|
8287
|
+
var import_promises7 = require("node:fs/promises");
|
|
8210
8288
|
var import_node_path8 = require("node:path");
|
|
8211
8289
|
init_dist();
|
|
8212
8290
|
var PACKAGE_JSON = "aipm.package.json";
|
|
8213
8291
|
var LOCKFILE = "aipm-lock.json";
|
|
8214
8292
|
async function readProjectPackageJson(projectRoot) {
|
|
8215
8293
|
try {
|
|
8216
|
-
const raw = await (0,
|
|
8294
|
+
const raw = await (0, import_promises7.readFile)((0, import_node_path8.join)(projectRoot, PACKAGE_JSON), "utf8");
|
|
8217
8295
|
return ProjectPackageJsonSchema.parse(JSON.parse(raw));
|
|
8218
8296
|
} catch {
|
|
8219
8297
|
return null;
|
|
8220
8298
|
}
|
|
8221
8299
|
}
|
|
8222
8300
|
async function writeProjectPackageJson(projectRoot, data) {
|
|
8223
|
-
await (0,
|
|
8301
|
+
await (0, import_promises7.writeFile)(
|
|
8224
8302
|
(0, import_node_path8.join)(projectRoot, PACKAGE_JSON),
|
|
8225
8303
|
JSON.stringify(data, null, 2) + "\n",
|
|
8226
8304
|
"utf8"
|
|
@@ -8228,14 +8306,14 @@ async function writeProjectPackageJson(projectRoot, data) {
|
|
|
8228
8306
|
}
|
|
8229
8307
|
async function readLockfile(projectRoot) {
|
|
8230
8308
|
try {
|
|
8231
|
-
const raw = await (0,
|
|
8309
|
+
const raw = await (0, import_promises7.readFile)((0, import_node_path8.join)(projectRoot, LOCKFILE), "utf8");
|
|
8232
8310
|
return LockfileSchema.parse(JSON.parse(raw));
|
|
8233
8311
|
} catch {
|
|
8234
8312
|
return null;
|
|
8235
8313
|
}
|
|
8236
8314
|
}
|
|
8237
8315
|
async function writeLockfile(projectRoot, data) {
|
|
8238
|
-
await (0,
|
|
8316
|
+
await (0, import_promises7.writeFile)((0, import_node_path8.join)(projectRoot, LOCKFILE), JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
8239
8317
|
}
|
|
8240
8318
|
function upsertLockEntry(lock, name, entry) {
|
|
8241
8319
|
return {
|
|
@@ -8289,8 +8367,113 @@ async function promptForTool() {
|
|
|
8289
8367
|
rl.close();
|
|
8290
8368
|
}
|
|
8291
8369
|
}
|
|
8370
|
+
async function promptForConfirmation(question) {
|
|
8371
|
+
const rl = readline.createInterface({ input: import_node_process2.stdin, output: import_node_process2.stdout });
|
|
8372
|
+
try {
|
|
8373
|
+
const answer = await rl.question(`${question} (y/N): `);
|
|
8374
|
+
const normalized = answer.trim().toLowerCase();
|
|
8375
|
+
return normalized === "y" || normalized === "yes";
|
|
8376
|
+
} finally {
|
|
8377
|
+
rl.close();
|
|
8378
|
+
}
|
|
8379
|
+
}
|
|
8292
8380
|
|
|
8293
8381
|
// src/install-one.ts
|
|
8382
|
+
function normalizeRelativePath(path2) {
|
|
8383
|
+
return (0, import_node_path9.normalize)(path2).split(import_node_path9.sep).join("/");
|
|
8384
|
+
}
|
|
8385
|
+
function assertSafeRelativePath(path2) {
|
|
8386
|
+
const rel = normalizeRelativePath(path2.trim());
|
|
8387
|
+
if (!rel || rel === "." || rel.startsWith("/") || rel === ".." || rel.startsWith("../") || rel.includes("/../")) {
|
|
8388
|
+
throw new Error(`Unsafe install path: ${path2}`);
|
|
8389
|
+
}
|
|
8390
|
+
return rel;
|
|
8391
|
+
}
|
|
8392
|
+
function safeJoin(root, relPath) {
|
|
8393
|
+
const rel = assertSafeRelativePath(relPath);
|
|
8394
|
+
const target = (0, import_node_path9.resolve)(root, rel);
|
|
8395
|
+
const fromRoot = normalizeRelativePath((0, import_node_path9.relative)(root, target));
|
|
8396
|
+
if (fromRoot === ".." || fromRoot.startsWith("../") || fromRoot.startsWith("/")) {
|
|
8397
|
+
throw new Error(`Unsafe install path: ${relPath}`);
|
|
8398
|
+
}
|
|
8399
|
+
return target;
|
|
8400
|
+
}
|
|
8401
|
+
function packageHelperSlug(name) {
|
|
8402
|
+
const [scope = "", pkg = ""] = name.replace(/^@/, "").split("/");
|
|
8403
|
+
return `${scope}__${pkg}`;
|
|
8404
|
+
}
|
|
8405
|
+
function helperRootFor(configRoot, packageName, version) {
|
|
8406
|
+
const base = (0, import_node_path9.basename)(configRoot) === ".aipm" ? (0, import_node_path9.join)(configRoot, "helpers") : (0, import_node_path9.join)(configRoot, ".aipm", "helpers");
|
|
8407
|
+
return (0, import_node_path9.join)(base, packageHelperSlug(packageName), version);
|
|
8408
|
+
}
|
|
8409
|
+
async function assertSourceFile(packageRoot, relPath) {
|
|
8410
|
+
const source = safeJoin(packageRoot, relPath);
|
|
8411
|
+
const info = await (0, import_promises8.stat)(source).catch(() => null);
|
|
8412
|
+
if (!info?.isFile()) throw new Error(`Package install file not found: ${relPath}`);
|
|
8413
|
+
return source;
|
|
8414
|
+
}
|
|
8415
|
+
async function copyMainFile(input2) {
|
|
8416
|
+
const source = await assertSourceFile(input2.packageRoot, input2.file.from);
|
|
8417
|
+
const target = safeJoin(input2.installRoot, input2.file.to);
|
|
8418
|
+
const overwrite = input2.file.overwrite ?? "fail";
|
|
8419
|
+
const exists = await (0, import_promises8.stat)(target).catch(() => null);
|
|
8420
|
+
if (exists) {
|
|
8421
|
+
if (overwrite === "skip") return null;
|
|
8422
|
+
if (overwrite === "fail") throw new Error(`Install target already exists: ${target}`);
|
|
8423
|
+
}
|
|
8424
|
+
await (0, import_promises8.mkdir)((0, import_node_path9.dirname)(target), { recursive: true });
|
|
8425
|
+
await (0, import_promises8.cp)(source, target, { force: overwrite === "replace" });
|
|
8426
|
+
return target;
|
|
8427
|
+
}
|
|
8428
|
+
async function copyHelperFile(input2) {
|
|
8429
|
+
const source = await assertSourceFile(input2.packageRoot, input2.file.from);
|
|
8430
|
+
const target = safeJoin(input2.helperRoot, input2.file.to ?? (0, import_node_path9.basename)(input2.file.from));
|
|
8431
|
+
await (0, import_promises8.mkdir)((0, import_node_path9.dirname)(target), { recursive: true });
|
|
8432
|
+
await (0, import_promises8.cp)(source, target, { force: true });
|
|
8433
|
+
return target;
|
|
8434
|
+
}
|
|
8435
|
+
async function installPackageAssets(options) {
|
|
8436
|
+
const assets = { main: [], helper: [] };
|
|
8437
|
+
const install = options.install;
|
|
8438
|
+
if (!install) return { assets };
|
|
8439
|
+
for (const file of install.mainFiles ?? []) {
|
|
8440
|
+
const copied = await copyMainFile({
|
|
8441
|
+
packageRoot: options.packageRoot,
|
|
8442
|
+
installRoot: options.installRoot,
|
|
8443
|
+
file
|
|
8444
|
+
});
|
|
8445
|
+
if (copied) assets.main.push(copied);
|
|
8446
|
+
}
|
|
8447
|
+
const helperRoot = helperRootFor(options.configRoot, options.packageName, options.version);
|
|
8448
|
+
if ((install.helperFiles ?? []).length > 0) {
|
|
8449
|
+
await (0, import_promises8.rm)(helperRoot, { recursive: true, force: true });
|
|
8450
|
+
}
|
|
8451
|
+
for (const file of install.helperFiles ?? []) {
|
|
8452
|
+
assets.helper.push(await copyHelperFile({ packageRoot: options.packageRoot, helperRoot, file }));
|
|
8453
|
+
}
|
|
8454
|
+
if (!install.postInstall) return { assets };
|
|
8455
|
+
const promptFile = safeJoin(helperRoot, install.postInstall.promptFile);
|
|
8456
|
+
if (!assets.helper.includes(promptFile)) {
|
|
8457
|
+
throw new Error(`Post-install prompt was not installed: ${install.postInstall.promptFile}`);
|
|
8458
|
+
}
|
|
8459
|
+
return {
|
|
8460
|
+
assets,
|
|
8461
|
+
postInstall: {
|
|
8462
|
+
mode: "manual_prompt",
|
|
8463
|
+
status: "pending",
|
|
8464
|
+
promptFile,
|
|
8465
|
+
cleanup: install.postInstall.cleanup ?? "manual"
|
|
8466
|
+
}
|
|
8467
|
+
};
|
|
8468
|
+
}
|
|
8469
|
+
function printPostInstallNotice(name, postInstall) {
|
|
8470
|
+
if (!postInstall || postInstall.mode !== "manual_prompt") return;
|
|
8471
|
+
console.log("");
|
|
8472
|
+
console.log("This package requires AI-assisted setup.");
|
|
8473
|
+
console.log(`Prompt saved to: ${postInstall.promptFile}`);
|
|
8474
|
+
console.log(`Run: aipm show-prompt ${name}`);
|
|
8475
|
+
console.log(`After setup, run: aipm cleanup ${name}`);
|
|
8476
|
+
}
|
|
8294
8477
|
async function installOnePackage(options) {
|
|
8295
8478
|
const configRoot = options.configRoot;
|
|
8296
8479
|
const installRoot = options.installRoot ?? configRoot;
|
|
@@ -8337,49 +8520,65 @@ async function installOnePackage(options) {
|
|
|
8337
8520
|
options.version,
|
|
8338
8521
|
options.token
|
|
8339
8522
|
);
|
|
8340
|
-
const
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
|
|
8349
|
-
|
|
8350
|
-
|
|
8351
|
-
|
|
8352
|
-
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
if (paths) installed[tool] = paths;
|
|
8356
|
-
}
|
|
8357
|
-
await writeLockfile(
|
|
8358
|
-
configRoot,
|
|
8359
|
-
upsertLockEntry(lock, options.name, {
|
|
8523
|
+
const packageRoot = await unpackTarballToDirectory(tarball);
|
|
8524
|
+
try {
|
|
8525
|
+
const skillMarkdown = await (0, import_promises8.readFile)(safeJoin(packageRoot, manifest.entry), "utf8");
|
|
8526
|
+
const result = await installSkillPackage({
|
|
8527
|
+
projectRoot: installRoot,
|
|
8528
|
+
manifest,
|
|
8529
|
+
skillMarkdown,
|
|
8530
|
+
preferredTools,
|
|
8531
|
+
explicitTarget
|
|
8532
|
+
});
|
|
8533
|
+
const { assets, postInstall } = await installPackageAssets({
|
|
8534
|
+
configRoot,
|
|
8535
|
+
installRoot,
|
|
8536
|
+
packageRoot,
|
|
8537
|
+
packageName: options.name,
|
|
8360
8538
|
version: options.version,
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
|
|
8539
|
+
install: manifest.install
|
|
8540
|
+
});
|
|
8541
|
+
const lock = await readLockfile(configRoot) ?? {
|
|
8542
|
+
schemaVersion: "0.1",
|
|
8543
|
+
packages: {}
|
|
8544
|
+
};
|
|
8545
|
+
const installed = {};
|
|
8546
|
+
for (const tool of result.resolvedTools) {
|
|
8547
|
+
const paths = result.installed[tool];
|
|
8548
|
+
if (paths) installed[tool] = paths;
|
|
8549
|
+
}
|
|
8550
|
+
await writeLockfile(
|
|
8551
|
+
configRoot,
|
|
8552
|
+
upsertLockEntry(lock, options.name, {
|
|
8553
|
+
version: options.version,
|
|
8554
|
+
integrity: remoteIntegrity,
|
|
8555
|
+
registry: options.registry,
|
|
8556
|
+
resolvedTools: result.resolvedTools,
|
|
8557
|
+
installed,
|
|
8558
|
+
...assets.main.length || assets.helper.length ? { installedAssets: assets } : {},
|
|
8559
|
+
...postInstall ? { postInstall } : {}
|
|
8560
|
+
})
|
|
8561
|
+
);
|
|
8562
|
+
console.log(`Installed ${options.name}@${options.version} \u2192 ${result.resolvedTools.join(", ")}`);
|
|
8563
|
+
printPostInstallNotice(options.name, postInstall);
|
|
8564
|
+
} finally {
|
|
8565
|
+
await (0, import_promises8.rm)(packageRoot, { recursive: true, force: true });
|
|
8566
|
+
}
|
|
8368
8567
|
}
|
|
8369
8568
|
|
|
8370
8569
|
// src/doctor.ts
|
|
8371
8570
|
var import_node_child_process3 = require("node:child_process");
|
|
8372
8571
|
var import_promises9 = require("node:fs/promises");
|
|
8373
|
-
var
|
|
8572
|
+
var import_node_path11 = require("node:path");
|
|
8374
8573
|
var import_node_util4 = require("node:util");
|
|
8375
8574
|
|
|
8376
8575
|
// src/project-root.ts
|
|
8377
8576
|
var import_node_os3 = require("node:os");
|
|
8378
|
-
var
|
|
8577
|
+
var import_node_path10 = require("node:path");
|
|
8379
8578
|
var import_node_process3 = require("node:process");
|
|
8380
8579
|
function globalConfigDir(env2 = process.env) {
|
|
8381
8580
|
const fromEnv = env2.AIPM_HOME?.trim();
|
|
8382
|
-
return fromEnv ? fromEnv.replace(/\/$/, "") : (0,
|
|
8581
|
+
return fromEnv ? fromEnv.replace(/\/$/, "") : (0, import_node_path10.join)((0, import_node_os3.homedir)(), ".aipm");
|
|
8383
8582
|
}
|
|
8384
8583
|
function resolveConfigRoot(options = {}) {
|
|
8385
8584
|
return options.global ? globalConfigDir() : (0, import_node_process3.cwd)();
|
|
@@ -8410,11 +8609,11 @@ async function commandOutput(command, args) {
|
|
|
8410
8609
|
}
|
|
8411
8610
|
function npmGlobalBin(prefix) {
|
|
8412
8611
|
if (!prefix) return null;
|
|
8413
|
-
return process.platform === "win32" ? prefix : `${prefix}${
|
|
8612
|
+
return process.platform === "win32" ? prefix : `${prefix}${import_node_path11.sep}bin`;
|
|
8414
8613
|
}
|
|
8415
8614
|
function pathIncludes(pathDir) {
|
|
8416
8615
|
if (!pathDir) return false;
|
|
8417
|
-
return (process.env.PATH ?? "").split(
|
|
8616
|
+
return (process.env.PATH ?? "").split(import_node_path11.delimiter).includes(pathDir);
|
|
8418
8617
|
}
|
|
8419
8618
|
function shellPathHint(binDir) {
|
|
8420
8619
|
if (!binDir) return "Run npm prefix -g and add its bin folder to PATH.";
|
|
@@ -8467,11 +8666,11 @@ async function runDoctor(options) {
|
|
|
8467
8666
|
if (!options.publish) {
|
|
8468
8667
|
const configLabel = options.global ? "Global config" : "Project config";
|
|
8469
8668
|
try {
|
|
8470
|
-
await (0, import_promises9.access)((0,
|
|
8669
|
+
await (0, import_promises9.access)((0, import_node_path11.join)(configRoot, "aipm.package.json"));
|
|
8471
8670
|
checks.push({
|
|
8472
8671
|
name: configLabel,
|
|
8473
8672
|
ok: true,
|
|
8474
|
-
detail: `${(0,
|
|
8673
|
+
detail: `${(0, import_node_path11.join)(configRoot, "aipm.package.json")} exists (${scopeLabel(scope)}).`
|
|
8475
8674
|
});
|
|
8476
8675
|
} catch {
|
|
8477
8676
|
checks.push({
|
|
@@ -8541,9 +8740,9 @@ async function runDoctor(options) {
|
|
|
8541
8740
|
|
|
8542
8741
|
// src/version.ts
|
|
8543
8742
|
var import_node_fs2 = require("node:fs");
|
|
8544
|
-
var
|
|
8743
|
+
var import_node_path12 = require("node:path");
|
|
8545
8744
|
function getCliVersion() {
|
|
8546
|
-
const pkgPath = (0,
|
|
8745
|
+
const pkgPath = (0, import_node_path12.join)(__dirname, "..", "package.json");
|
|
8547
8746
|
const pkg = JSON.parse((0, import_node_fs2.readFileSync)(pkgPath, "utf8"));
|
|
8548
8747
|
return pkg.version;
|
|
8549
8748
|
}
|
|
@@ -8682,7 +8881,7 @@ async function writeStarterFile(path2, content) {
|
|
|
8682
8881
|
}
|
|
8683
8882
|
async function inferEntryFromSource(source, fallback) {
|
|
8684
8883
|
const sourceInfo = await (0, import_promises10.stat)(source);
|
|
8685
|
-
if (sourceInfo.isFile()) return (0,
|
|
8884
|
+
if (sourceInfo.isFile()) return (0, import_node_path13.basename)(source);
|
|
8686
8885
|
if (!sourceInfo.isDirectory()) return fallback;
|
|
8687
8886
|
const entries = await (0, import_promises10.readdir)(source);
|
|
8688
8887
|
if (entries.includes(fallback)) return fallback;
|
|
@@ -8694,7 +8893,7 @@ async function copySourceIntoSkillRoot(source, root, sourceLabel) {
|
|
|
8694
8893
|
if (sourceInfo.isDirectory()) {
|
|
8695
8894
|
const entries = await (0, import_promises10.readdir)(source);
|
|
8696
8895
|
for (const entry of entries) {
|
|
8697
|
-
await (0, import_promises10.cp)((0,
|
|
8896
|
+
await (0, import_promises10.cp)((0, import_node_path13.join)(source, entry), (0, import_node_path13.join)(root, entry), {
|
|
8698
8897
|
recursive: true,
|
|
8699
8898
|
force: false,
|
|
8700
8899
|
errorOnExist: true
|
|
@@ -8703,7 +8902,7 @@ async function copySourceIntoSkillRoot(source, root, sourceLabel) {
|
|
|
8703
8902
|
return;
|
|
8704
8903
|
}
|
|
8705
8904
|
if (sourceInfo.isFile()) {
|
|
8706
|
-
await (0, import_promises10.cp)(source, (0,
|
|
8905
|
+
await (0, import_promises10.cp)(source, (0, import_node_path13.join)(root, (0, import_node_path13.basename)(source)), { force: false, errorOnExist: true });
|
|
8707
8906
|
return;
|
|
8708
8907
|
}
|
|
8709
8908
|
throw new Error(`Unsupported source path: ${sourceLabel}`);
|
|
@@ -8736,6 +8935,73 @@ function packageDashboardUrl(name) {
|
|
|
8736
8935
|
if (!name) return DASHBOARD_URL;
|
|
8737
8936
|
return `${DASHBOARD_URL}/packages/${name.replace(/^@/, "")}`;
|
|
8738
8937
|
}
|
|
8938
|
+
function helperRootFromTrackedPath(path2) {
|
|
8939
|
+
const parts = path2.split(import_node_path13.sep).filter(Boolean);
|
|
8940
|
+
const helpersIndex = parts.lastIndexOf("helpers");
|
|
8941
|
+
if (helpersIndex === -1 || parts.length <= helpersIndex + 2) return null;
|
|
8942
|
+
const prefix = path2.startsWith(import_node_path13.sep) ? import_node_path13.sep : "";
|
|
8943
|
+
return (0, import_node_path13.join)(prefix, ...parts.slice(0, helpersIndex + 3));
|
|
8944
|
+
}
|
|
8945
|
+
async function showInstalledPrompt(configRoot, packageArg) {
|
|
8946
|
+
const { name } = parsePackageArg(packageArg);
|
|
8947
|
+
const lock = await readLockfile(configRoot);
|
|
8948
|
+
const entry = lock?.packages[name];
|
|
8949
|
+
if (!entry) throw new Error(`Package is not installed: ${name}`);
|
|
8950
|
+
if (!entry.postInstall || entry.postInstall.mode !== "manual_prompt") {
|
|
8951
|
+
throw new Error(`Package has no setup prompt: ${name}`);
|
|
8952
|
+
}
|
|
8953
|
+
if (entry.postInstall.status === "cleaned") {
|
|
8954
|
+
throw new Error(`Setup helper files were cleaned for ${name}. Reinstall the package to restore them.`);
|
|
8955
|
+
}
|
|
8956
|
+
const content = await (0, import_promises10.readFile)(entry.postInstall.promptFile, "utf8").catch(() => {
|
|
8957
|
+
throw new Error(`Setup prompt file is missing: ${entry.postInstall?.promptFile}`);
|
|
8958
|
+
});
|
|
8959
|
+
console.log(`Prompt file: ${entry.postInstall.promptFile}`);
|
|
8960
|
+
console.log("");
|
|
8961
|
+
console.log(content.trimEnd());
|
|
8962
|
+
}
|
|
8963
|
+
async function cleanupInstalledHelpers(options) {
|
|
8964
|
+
const { name } = parsePackageArg(options.packageArg);
|
|
8965
|
+
const lock = await readLockfile(options.configRoot);
|
|
8966
|
+
const entry = lock?.packages[name];
|
|
8967
|
+
if (!lock || !entry) throw new Error(`Package is not installed: ${name}`);
|
|
8968
|
+
if (!entry.installedAssets?.helper?.length) {
|
|
8969
|
+
throw new Error(`Package has no helper files to clean: ${name}`);
|
|
8970
|
+
}
|
|
8971
|
+
if (!entry.postInstall) {
|
|
8972
|
+
throw new Error(`Package has no post-install helper state: ${name}`);
|
|
8973
|
+
}
|
|
8974
|
+
if (entry.postInstall.status === "cleaned") {
|
|
8975
|
+
console.log(`Helper files already cleaned for ${name}.`);
|
|
8976
|
+
return;
|
|
8977
|
+
}
|
|
8978
|
+
if (!options.yes) {
|
|
8979
|
+
const confirmed = await promptForConfirmation(`Delete tracked helper files for ${name}?`);
|
|
8980
|
+
if (!confirmed) {
|
|
8981
|
+
console.log("Cleanup cancelled.");
|
|
8982
|
+
return;
|
|
8983
|
+
}
|
|
8984
|
+
}
|
|
8985
|
+
const roots = new Set(
|
|
8986
|
+
entry.installedAssets.helper.map((path2) => helperRootFromTrackedPath(path2)).filter((path2) => Boolean(path2))
|
|
8987
|
+
);
|
|
8988
|
+
if (roots.size > 0) {
|
|
8989
|
+
for (const root of roots) await (0, import_promises10.rm)(root, { recursive: true, force: true });
|
|
8990
|
+
} else {
|
|
8991
|
+
for (const helperPath of entry.installedAssets.helper) await (0, import_promises10.rm)(helperPath, { force: true });
|
|
8992
|
+
}
|
|
8993
|
+
await writeLockfile(options.configRoot, {
|
|
8994
|
+
...lock,
|
|
8995
|
+
packages: {
|
|
8996
|
+
...lock.packages,
|
|
8997
|
+
[name]: {
|
|
8998
|
+
...entry,
|
|
8999
|
+
postInstall: { ...entry.postInstall, status: "cleaned" }
|
|
9000
|
+
}
|
|
9001
|
+
}
|
|
9002
|
+
});
|
|
9003
|
+
console.log(`Cleaned helper files for ${name}.`);
|
|
9004
|
+
}
|
|
8739
9005
|
async function openUrl(url) {
|
|
8740
9006
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open";
|
|
8741
9007
|
const args = process.platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
@@ -8874,6 +9140,11 @@ async function printPublishPreview(root, json) {
|
|
|
8874
9140
|
description: manifest.description,
|
|
8875
9141
|
targets: manifest.targets,
|
|
8876
9142
|
entry: manifest.entry,
|
|
9143
|
+
install: manifest.install ? {
|
|
9144
|
+
mainFiles: manifest.install.mainFiles ?? [],
|
|
9145
|
+
helperFiles: manifest.install.helperFiles ?? [],
|
|
9146
|
+
postInstall: manifest.install.postInstall ?? null
|
|
9147
|
+
} : null,
|
|
8877
9148
|
files: rows.map((row) => ({ path: row.path, size: row.size, changed: row.changed })),
|
|
8878
9149
|
totalBytes: size,
|
|
8879
9150
|
warnings: [
|
|
@@ -8891,6 +9162,13 @@ async function printPublishPreview(root, json) {
|
|
|
8891
9162
|
console.log(`Description: ${preview.description}`);
|
|
8892
9163
|
console.log(`Targets: ${preview.targets.join(", ")}`);
|
|
8893
9164
|
console.log(`Entry: ${preview.entry}`);
|
|
9165
|
+
if (preview.install) {
|
|
9166
|
+
console.log(`Main files: ${preview.install.mainFiles.length}`);
|
|
9167
|
+
console.log(`Helper files: ${preview.install.helperFiles.length}`);
|
|
9168
|
+
if (preview.install.postInstall) {
|
|
9169
|
+
console.log(`Post-install: ${preview.install.postInstall.mode} (${preview.install.postInstall.promptFile})`);
|
|
9170
|
+
}
|
|
9171
|
+
}
|
|
8894
9172
|
console.log(`Total: ${preview.files.length} file${preview.files.length === 1 ? "" : "s"}, ${preview.totalBytes} bytes`);
|
|
8895
9173
|
for (const file of preview.files) {
|
|
8896
9174
|
console.log(`${file.changed ? "modified" : "staged"} ${file.path} (${file.size} bytes)`);
|
|
@@ -9004,9 +9282,9 @@ function buildStarterQualityMetadata(options) {
|
|
|
9004
9282
|
}
|
|
9005
9283
|
async function initSkill(opts) {
|
|
9006
9284
|
if (!isValidScopeName(opts.name)) throw new Error("Invalid @scope/name");
|
|
9007
|
-
const root = opts.here ? (0, import_node_process5.cwd)() : (0,
|
|
9285
|
+
const root = opts.here ? (0, import_node_process5.cwd)() : (0, import_node_path13.resolve)((0, import_node_process5.cwd)(), opts.dir ?? skillFolderName(opts.name));
|
|
9008
9286
|
const cdTarget = opts.here ? null : opts.dir ?? skillFolderName(opts.name);
|
|
9009
|
-
const source = opts.from ? (0,
|
|
9287
|
+
const source = opts.from ? (0, import_node_path13.resolve)(opts.from) : null;
|
|
9010
9288
|
const entry = source ? await inferEntryFromSource(source, opts.entry) : opts.entry;
|
|
9011
9289
|
const template = parseSkillTemplate(opts.template ?? "blank");
|
|
9012
9290
|
const manifest = PackageManifestSchema.parse({
|
|
@@ -9029,15 +9307,15 @@ async function initSkill(opts) {
|
|
|
9029
9307
|
} else {
|
|
9030
9308
|
await (0, import_promises10.mkdir)(root, { recursive: true });
|
|
9031
9309
|
}
|
|
9032
|
-
await writeStarterFile((0,
|
|
9310
|
+
await writeStarterFile((0, import_node_path13.join)(root, "aipm.manifest.json"), JSON.stringify(manifest, null, 2) + "\n");
|
|
9033
9311
|
if (!opts.from) {
|
|
9034
9312
|
await writeStarterFile(
|
|
9035
|
-
(0,
|
|
9313
|
+
(0, import_node_path13.join)(root, entry),
|
|
9036
9314
|
SKILL_TEMPLATES[template](opts.name)
|
|
9037
9315
|
);
|
|
9038
9316
|
}
|
|
9039
9317
|
await writeStarterFile(
|
|
9040
|
-
(0,
|
|
9318
|
+
(0, import_node_path13.join)(root, ".aipmignore"),
|
|
9041
9319
|
[
|
|
9042
9320
|
"# Files that should never be published with this skill",
|
|
9043
9321
|
".env*",
|
|
@@ -9055,7 +9333,7 @@ async function initSkill(opts) {
|
|
|
9055
9333
|
""
|
|
9056
9334
|
].join("\n")
|
|
9057
9335
|
);
|
|
9058
|
-
await (0, import_promises10.mkdir)((0,
|
|
9336
|
+
await (0, import_promises10.mkdir)((0, import_node_path13.join)(root, ".aipm"), { recursive: true });
|
|
9059
9337
|
console.log(`Created ${opts.name} skill folder: ${root}`);
|
|
9060
9338
|
printPublishGuide(
|
|
9061
9339
|
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.`,
|
|
@@ -9254,6 +9532,16 @@ program2.command("install").description("Install all packages from aipm.package.
|
|
|
9254
9532
|
});
|
|
9255
9533
|
}
|
|
9256
9534
|
});
|
|
9535
|
+
program2.command("show-prompt <package>").description("Show the manual setup prompt installed with a package").option(GLOBAL_OPTION, GLOBAL_OPTION_DESC).action(async (pkgArg, opts) => {
|
|
9536
|
+
await showInstalledPrompt(resolveConfigRoot({ global: opts.global }), pkgArg);
|
|
9537
|
+
});
|
|
9538
|
+
program2.command("cleanup <package>").description("Delete temporary helper files installed with a package").option(GLOBAL_OPTION, GLOBAL_OPTION_DESC).option("--yes", "Delete helper files without asking for confirmation").action(async (pkgArg, opts) => {
|
|
9539
|
+
await cleanupInstalledHelpers({
|
|
9540
|
+
configRoot: resolveConfigRoot({ global: opts.global }),
|
|
9541
|
+
packageArg: pkgArg,
|
|
9542
|
+
yes: opts.yes
|
|
9543
|
+
});
|
|
9544
|
+
});
|
|
9257
9545
|
program2.command("skill").description("Create and manage local skill packages").command("init").description("Create aipm.manifest.json and SKILL.md").requiredOption("--name <name>", "Package name, e.g. @org/skill").option("--version <version>", "Initial version", "1.0.0").option("--description <description>", "Skill description", "AIPM skill").option("--targets <targets>", "Comma-separated targets", "cursor").option("--entry <entry>", "Entry file", "SKILL.md").option("--template <template>", "Starter SKILL.md template: blank, code-review, issue-summary, release-notes", "blank").option("--dir <dir>", "Create files in this folder").option("--here", "Create files in the current folder instead of a skill-named folder").option("--from <path>", "Copy an existing AI-tool skill file or folder into the package folder").action(
|
|
9258
9546
|
async (opts) => initSkill(opts)
|
|
9259
9547
|
);
|
|
@@ -9262,8 +9550,8 @@ var publish = program2.command("publish [dir]").description("Stage, validate, an
|
|
|
9262
9550
|
publish.help();
|
|
9263
9551
|
return;
|
|
9264
9552
|
}
|
|
9265
|
-
const abs = (0,
|
|
9266
|
-
const manifestRaw = await (0, import_promises10.readFile)((0,
|
|
9553
|
+
const abs = (0, import_node_path13.resolve)(dir);
|
|
9554
|
+
const manifestRaw = await (0, import_promises10.readFile)((0, import_node_path13.join)(abs, "aipm.manifest.json"), "utf8");
|
|
9267
9555
|
const manifest = PackageManifestSchema.parse(JSON.parse(manifestRaw));
|
|
9268
9556
|
const tarball = await packDirectory(abs);
|
|
9269
9557
|
const registry = registryFromEnvOrDefault(opts.registry);
|
|
@@ -9376,17 +9664,21 @@ publish.command("validate").description("Validate staged files before publish").
|
|
|
9376
9664
|
);
|
|
9377
9665
|
});
|
|
9378
9666
|
publish.command("preview").description("Preview exactly what will be uploaded").option("--json", "Print machine-readable JSON").action((opts) => printPublishPreview((0, import_node_process5.cwd)(), opts.json));
|
|
9379
|
-
publish.command("push").description("Publish staged files").option("--registry <url>", "Registry base URL").option("--token <token>", "Publish token").option("--yes", "Confirm upload without an extra reminder").action(async (opts) => {
|
|
9667
|
+
publish.command("push").description("Publish staged files").option("--registry <url>", "Registry base URL").option("--token <token>", "Publish token").option("--yes", "Confirm upload without an extra reminder").option("--verbose", "Print extra diagnostic output").action(async (opts) => {
|
|
9380
9668
|
const root = (0, import_node_process5.cwd)();
|
|
9381
9669
|
const { manifest } = await validatePublishState(root);
|
|
9382
9670
|
const registry = registryFromEnvOrDefault(opts.registry);
|
|
9383
9671
|
const tarball = await packStagedFiles(root);
|
|
9384
9672
|
const staged = await statusPublishState(root);
|
|
9673
|
+
const verbose = Boolean(opts.verbose || program2.opts().verbose);
|
|
9385
9674
|
if (!opts.yes) {
|
|
9386
9675
|
console.log("Reminder: this publishes an immutable public package version.");
|
|
9387
9676
|
console.log("Use --yes to skip this reminder in automation.");
|
|
9388
9677
|
}
|
|
9389
9678
|
console.log(`Uploading ${staged.length} file${staged.length === 1 ? "" : "s"} to ${registry}.`);
|
|
9679
|
+
if (verbose) {
|
|
9680
|
+
console.log(`Verbose: package ${manifest.name}@${manifest.version}; tarball ${tarball.length} bytes.`);
|
|
9681
|
+
}
|
|
9390
9682
|
for (const entry of staged) console.log(` ${entry.path}`);
|
|
9391
9683
|
const result = await publishPackage(registry, manifest.name, tarball, opts.token ?? import_node_process5.env.AIPM_TOKEN);
|
|
9392
9684
|
console.log(`Published ${manifest.name}@${result.version}`);
|