skillvault-publisher 0.11.2 → 0.13.1
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/index.js +905 -300
- package/package.json +6 -2
- package/dist/commands/analytics.js +0 -75
- package/dist/commands/audit.js +0 -96
- package/dist/commands/changelog.js +0 -78
- package/dist/commands/check-session.js +0 -117
- package/dist/commands/customers.js +0 -53
- package/dist/commands/grants.js +0 -69
- package/dist/commands/info.js +0 -30
- package/dist/commands/init.js +0 -83
- package/dist/commands/investigate.js +0 -455
- package/dist/commands/invite.js +0 -198
- package/dist/commands/licenses.js +0 -65
- package/dist/commands/link.js +0 -112
- package/dist/commands/list.js +0 -80
- package/dist/commands/login.js +0 -137
- package/dist/commands/logout.js +0 -11
- package/dist/commands/publish-all.js +0 -336
- package/dist/commands/publish.js +0 -341
- package/dist/commands/register.js +0 -118
- package/dist/commands/report.js +0 -45
- package/dist/commands/revoke-grant.js +0 -49
- package/dist/commands/scan-output.js +0 -201
- package/dist/commands/search.js +0 -89
- package/dist/commands/session-cleanup.js +0 -108
- package/dist/commands/session-common.js +0 -180
- package/dist/commands/session-keepalive.js +0 -215
- package/dist/commands/skill-delete.js +0 -58
- package/dist/commands/skill-status.js +0 -63
- package/dist/commands/skill-unarchive.js +0 -51
- package/dist/commands/unlink.js +0 -67
- package/dist/commands/update.js +0 -221
- package/dist/commands/watchtower.js +0 -109
- package/dist/commands/watermark-decode.js +0 -105
- package/dist/commands/webhook.js +0 -77
- package/dist/commands/whoami.js +0 -118
- package/dist/commands/workspaces.js +0 -108
- package/dist/credentials.js +0 -185
- package/dist/fingerprint.js +0 -51
- package/dist/grant-cache.js +0 -112
- package/dist/hooks-manager.js +0 -202
- package/dist/pdf-report.js +0 -265
- package/dist/projects-registry.js +0 -192
- package/dist/publisher-workspace.js +0 -165
- package/dist/publisher-workspaces-registry.js +0 -133
- package/dist/scope.js +0 -100
- package/dist/session.js +0 -103
package/dist/index.js
CHANGED
|
@@ -237,10 +237,10 @@ var require_utils = __commonJS({
|
|
|
237
237
|
sum += a.length;
|
|
238
238
|
}
|
|
239
239
|
const res = new Uint8Array(sum);
|
|
240
|
-
for (let i = 0,
|
|
240
|
+
for (let i = 0, pad4 = 0; i < arrays.length; i++) {
|
|
241
241
|
const a = arrays[i];
|
|
242
|
-
res.set(a,
|
|
243
|
-
|
|
242
|
+
res.set(a, pad4);
|
|
243
|
+
pad4 += a.length;
|
|
244
244
|
}
|
|
245
245
|
return res;
|
|
246
246
|
}
|
|
@@ -1769,10 +1769,10 @@ var require_utils2 = __commonJS({
|
|
|
1769
1769
|
sum += a.length;
|
|
1770
1770
|
}
|
|
1771
1771
|
const res = new Uint8Array(sum);
|
|
1772
|
-
for (let i = 0,
|
|
1772
|
+
for (let i = 0, pad4 = 0; i < arrays.length; i++) {
|
|
1773
1773
|
const a = arrays[i];
|
|
1774
|
-
res.set(a,
|
|
1775
|
-
|
|
1774
|
+
res.set(a, pad4);
|
|
1775
|
+
pad4 += a.length;
|
|
1776
1776
|
}
|
|
1777
1777
|
return res;
|
|
1778
1778
|
}
|
|
@@ -3891,11 +3891,11 @@ function __metadata(metadataKey, metadataValue) {
|
|
|
3891
3891
|
}
|
|
3892
3892
|
function __awaiter(thisArg, _arguments, P, generator) {
|
|
3893
3893
|
function adopt(value) {
|
|
3894
|
-
return value instanceof P ? value : new P(function(
|
|
3895
|
-
|
|
3894
|
+
return value instanceof P ? value : new P(function(resolve12) {
|
|
3895
|
+
resolve12(value);
|
|
3896
3896
|
});
|
|
3897
3897
|
}
|
|
3898
|
-
return new (P || (P = Promise))(function(
|
|
3898
|
+
return new (P || (P = Promise))(function(resolve12, reject) {
|
|
3899
3899
|
function fulfilled(value) {
|
|
3900
3900
|
try {
|
|
3901
3901
|
step(generator.next(value));
|
|
@@ -3911,7 +3911,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
3911
3911
|
}
|
|
3912
3912
|
}
|
|
3913
3913
|
function step(result) {
|
|
3914
|
-
result.done ?
|
|
3914
|
+
result.done ? resolve12(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
3915
3915
|
}
|
|
3916
3916
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
3917
3917
|
});
|
|
@@ -4102,14 +4102,14 @@ function __asyncValues(o) {
|
|
|
4102
4102
|
}, i);
|
|
4103
4103
|
function verb(n) {
|
|
4104
4104
|
i[n] = o[n] && function(v) {
|
|
4105
|
-
return new Promise(function(
|
|
4106
|
-
v = o[n](v), settle(
|
|
4105
|
+
return new Promise(function(resolve12, reject) {
|
|
4106
|
+
v = o[n](v), settle(resolve12, reject, v.done, v.value);
|
|
4107
4107
|
});
|
|
4108
4108
|
};
|
|
4109
4109
|
}
|
|
4110
|
-
function settle(
|
|
4110
|
+
function settle(resolve12, reject, d, v) {
|
|
4111
4111
|
Promise.resolve(v).then(function(v2) {
|
|
4112
|
-
|
|
4112
|
+
resolve12({ value: v2, done: d });
|
|
4113
4113
|
}, reject);
|
|
4114
4114
|
}
|
|
4115
4115
|
}
|
|
@@ -5054,9 +5054,9 @@ var require_clone = __commonJS({
|
|
|
5054
5054
|
} else if (_instanceof(parent2, nativeSet)) {
|
|
5055
5055
|
child = new nativeSet();
|
|
5056
5056
|
} else if (_instanceof(parent2, nativePromise)) {
|
|
5057
|
-
child = new nativePromise(function(
|
|
5057
|
+
child = new nativePromise(function(resolve12, reject) {
|
|
5058
5058
|
parent2.then(function(value) {
|
|
5059
|
-
|
|
5059
|
+
resolve12(_clone(value, depth2 - 1));
|
|
5060
5060
|
}, function(err) {
|
|
5061
5061
|
reject(_clone(err, depth2 - 1));
|
|
5062
5062
|
});
|
|
@@ -145431,7 +145431,7 @@ var require_pdfkit = __commonJS({
|
|
|
145431
145431
|
return `${this.ref.id} 0 R`;
|
|
145432
145432
|
}
|
|
145433
145433
|
};
|
|
145434
|
-
var
|
|
145434
|
+
var pad4 = (str, length) => (Array(length + 1).join("0") + str).slice(-length);
|
|
145435
145435
|
var escapableRe = /[\n\r\t\b\f()\\]/g;
|
|
145436
145436
|
var escapable = {
|
|
145437
145437
|
"\n": "\\n",
|
|
@@ -145487,7 +145487,7 @@ var require_pdfkit = __commonJS({
|
|
|
145487
145487
|
} else if (object instanceof PDFAbstractReference || object instanceof PDFTree || object instanceof SpotColor) {
|
|
145488
145488
|
return object.toString();
|
|
145489
145489
|
} else if (object instanceof Date) {
|
|
145490
|
-
let string = `D:${
|
|
145490
|
+
let string = `D:${pad4(object.getUTCFullYear(), 4)}` + pad4(object.getUTCMonth() + 1, 2) + pad4(object.getUTCDate(), 2) + pad4(object.getUTCHours(), 2) + pad4(object.getUTCMinutes(), 2) + pad4(object.getUTCSeconds(), 2) + "Z";
|
|
145491
145491
|
if (encryptFn) {
|
|
145492
145492
|
string = encryptFn(Buffer.from(string, "ascii")).toString("binary");
|
|
145493
145493
|
string = string.replace(escapableRe, (c) => escapable[c]);
|
|
@@ -151595,7 +151595,7 @@ function confColor(c) {
|
|
|
151595
151595
|
return SV.sirenRed500;
|
|
151596
151596
|
}
|
|
151597
151597
|
async function generatePdfReport(data, outputPath) {
|
|
151598
|
-
return new Promise((
|
|
151598
|
+
return new Promise((resolve12, reject) => {
|
|
151599
151599
|
const doc = new import_pdfkit.default({
|
|
151600
151600
|
size: "A4",
|
|
151601
151601
|
margins: { top: 72, bottom: 0, left: 56, right: 56 },
|
|
@@ -151742,7 +151742,7 @@ async function generatePdfReport(data, outputPath) {
|
|
|
151742
151742
|
yPos += 72;
|
|
151743
151743
|
drawPageFooter(doc, leftMargin, contentWidth, pageWidth, pageNum);
|
|
151744
151744
|
doc.end();
|
|
151745
|
-
stream.on("finish",
|
|
151745
|
+
stream.on("finish", resolve12);
|
|
151746
151746
|
stream.on("error", reject);
|
|
151747
151747
|
});
|
|
151748
151748
|
}
|
|
@@ -151804,7 +151804,7 @@ var init_pdf_report = __esm({
|
|
|
151804
151804
|
});
|
|
151805
151805
|
|
|
151806
151806
|
// dist/index.js
|
|
151807
|
-
import { Command as
|
|
151807
|
+
import { Command as Command37 } from "commander";
|
|
151808
151808
|
import { readFileSync as readFileSync18 } from "node:fs";
|
|
151809
151809
|
import { fileURLToPath } from "node:url";
|
|
151810
151810
|
import { dirname as dirname5, join as join17 } from "node:path";
|
|
@@ -151813,6 +151813,7 @@ import { dirname as dirname5, join as join17 } from "node:path";
|
|
|
151813
151813
|
import { Command } from "commander";
|
|
151814
151814
|
import chalk from "chalk";
|
|
151815
151815
|
import { randomBytes } from "node:crypto";
|
|
151816
|
+
import { createInterface } from "node:readline/promises";
|
|
151816
151817
|
|
|
151817
151818
|
// dist/credentials.js
|
|
151818
151819
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, rmSync, existsSync as existsSync2, openSync as openSync2, closeSync as closeSync2, unlinkSync as unlinkSync2 } from "node:fs";
|
|
@@ -151861,7 +151862,43 @@ function removeKeypair() {
|
|
|
151861
151862
|
}
|
|
151862
151863
|
|
|
151863
151864
|
// dist/commands/login.js
|
|
151864
|
-
|
|
151865
|
+
async function chooseFromMultiple(available, publisherFlag) {
|
|
151866
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
151867
|
+
if (publisherFlag) {
|
|
151868
|
+
const match = available.find((p) => p.publisher_id === publisherFlag);
|
|
151869
|
+
if (match)
|
|
151870
|
+
return match;
|
|
151871
|
+
console.error(chalk.red(`Publisher ${publisherFlag} not in your accessible list.`));
|
|
151872
|
+
}
|
|
151873
|
+
console.error(chalk.red("Multiple publishers available for this email. Pass --publisher <id> to choose:"));
|
|
151874
|
+
for (const p of available) {
|
|
151875
|
+
console.error(chalk.dim(` --publisher ${p.publisher_id} (${p.publisher_name || "unnamed"}, role: ${p.role})`));
|
|
151876
|
+
}
|
|
151877
|
+
process.exit(1);
|
|
151878
|
+
}
|
|
151879
|
+
console.log();
|
|
151880
|
+
console.log(chalk.bold(" This email has access to multiple publishers:"));
|
|
151881
|
+
console.log();
|
|
151882
|
+
available.forEach((p, idx) => {
|
|
151883
|
+
const roleColor = p.role === "owner" ? chalk.green : p.role === "admin" ? chalk.cyan : chalk.dim;
|
|
151884
|
+
console.log(` ${chalk.bold(`[${idx + 1}]`)} ${p.publisher_name || p.publisher_id} ${chalk.dim(`(${p.publisher_id})`)} ${roleColor(p.role)}`);
|
|
151885
|
+
});
|
|
151886
|
+
console.log();
|
|
151887
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
151888
|
+
try {
|
|
151889
|
+
while (true) {
|
|
151890
|
+
const answer = (await rl.question(` Pick a publisher [1-${available.length}]: `)).trim();
|
|
151891
|
+
const idx = parseInt(answer, 10);
|
|
151892
|
+
if (Number.isInteger(idx) && idx >= 1 && idx <= available.length) {
|
|
151893
|
+
return available[idx - 1];
|
|
151894
|
+
}
|
|
151895
|
+
console.log(chalk.red(` Invalid choice \u2014 enter a number between 1 and ${available.length}`));
|
|
151896
|
+
}
|
|
151897
|
+
} finally {
|
|
151898
|
+
rl.close();
|
|
151899
|
+
}
|
|
151900
|
+
}
|
|
151901
|
+
var loginCommand = new Command("login").description("Authenticate with the Skill Vault server").option("--email <email>", "Your publisher account email").option("--token <token>", "Authenticate with a publisher session JWT (Bearer token from dashboard)").option("--license-key <key>", "Authenticate with a license key (customer)").option("--code <code>", "Redeem an invite code after login").option("--publisher <id>", "Disambiguate when your email has access to multiple publisher accounts").option("--server <url>", "Server URL", "https://api.getskillvault.com").action(async (options) => {
|
|
151865
151902
|
try {
|
|
151866
151903
|
const serverUrl = options.server;
|
|
151867
151904
|
const publisherToken = options.token || process.env.SKILLVAULT_TOKEN || null;
|
|
@@ -151881,22 +151918,52 @@ var loginCommand = new Command("login").description("Authenticate with the Skill
|
|
|
151881
151918
|
publisherIdentity = { publisher_id: me.publisher_id, email: me.email, name: me.name };
|
|
151882
151919
|
} else if (options.email) {
|
|
151883
151920
|
console.log(chalk.dim(`Authenticating as ${options.email}...`));
|
|
151921
|
+
const body2 = { email: options.email };
|
|
151922
|
+
if (options.publisher)
|
|
151923
|
+
body2.publisher_id = options.publisher;
|
|
151884
151924
|
const loginRes = await fetch(`${serverUrl}/auth/login`, {
|
|
151885
151925
|
method: "POST",
|
|
151886
151926
|
headers: { "Content-Type": "application/json" },
|
|
151887
|
-
body: JSON.stringify(
|
|
151927
|
+
body: JSON.stringify(body2)
|
|
151888
151928
|
});
|
|
151889
151929
|
if (!loginRes.ok) {
|
|
151890
|
-
const err = await loginRes.json().catch(() =>
|
|
151891
|
-
|
|
151930
|
+
const err = await loginRes.json().catch(() => null);
|
|
151931
|
+
const reason = err?.message || err?.error || loginRes.statusText || `HTTP ${loginRes.status}`;
|
|
151932
|
+
console.error(chalk.red(`Login failed: ${reason}`));
|
|
151892
151933
|
if (loginRes.status === 404) {
|
|
151893
151934
|
console.error(chalk.dim("No account found. Create one at https://app.getskillvault.com/login"));
|
|
151935
|
+
console.error(chalk.dim("Or ask a team owner to add your email via `skillvault-publisher team add`."));
|
|
151894
151936
|
}
|
|
151895
151937
|
process.exit(1);
|
|
151896
151938
|
}
|
|
151897
151939
|
const loginData = await loginRes.json();
|
|
151898
|
-
|
|
151899
|
-
|
|
151940
|
+
if ("multiple_choice" in loginData && loginData.multiple_choice) {
|
|
151941
|
+
const chosen = await chooseFromMultiple(loginData.available_publishers, options.publisher);
|
|
151942
|
+
const retryRes = await fetch(`${serverUrl}/auth/login`, {
|
|
151943
|
+
method: "POST",
|
|
151944
|
+
headers: { "Content-Type": "application/json" },
|
|
151945
|
+
body: JSON.stringify({ email: options.email, publisher_id: chosen.publisher_id })
|
|
151946
|
+
});
|
|
151947
|
+
if (!retryRes.ok) {
|
|
151948
|
+
const err = await retryRes.json().catch(() => null);
|
|
151949
|
+
const reason = err?.message || err?.error || retryRes.statusText;
|
|
151950
|
+
console.error(chalk.red(`Login retry failed: ${reason}`));
|
|
151951
|
+
process.exit(1);
|
|
151952
|
+
}
|
|
151953
|
+
const retryData = await retryRes.json();
|
|
151954
|
+
sessionToken = retryData.session_token;
|
|
151955
|
+
publisherIdentity = { publisher_id: retryData.publisher_id, email: retryData.email, name: retryData.name };
|
|
151956
|
+
if (retryData.role && retryData.role !== "owner") {
|
|
151957
|
+
console.log(chalk.dim(` Logged in as ${chalk.bold(retryData.role)} of ${chosen.publisher_name || retryData.publisher_id}`));
|
|
151958
|
+
}
|
|
151959
|
+
} else {
|
|
151960
|
+
const single = loginData;
|
|
151961
|
+
sessionToken = single.session_token;
|
|
151962
|
+
publisherIdentity = { publisher_id: single.publisher_id, email: single.email, name: single.name };
|
|
151963
|
+
if (single.role && single.role !== "owner") {
|
|
151964
|
+
console.log(chalk.dim(` Logged in as ${chalk.bold(single.role)} of ${single.publisher_id}`));
|
|
151965
|
+
}
|
|
151966
|
+
}
|
|
151900
151967
|
} else if (!options.licenseKey) {
|
|
151901
151968
|
console.error(chalk.red("Publisher identity required."));
|
|
151902
151969
|
console.error("");
|
|
@@ -152003,7 +152070,7 @@ var registerCommand = new Command2("register").description("Create a new publish
|
|
|
152003
152070
|
let verified = false;
|
|
152004
152071
|
const maxAttempts = 120;
|
|
152005
152072
|
for (let i = 0; i < maxAttempts; i++) {
|
|
152006
|
-
await new Promise((
|
|
152073
|
+
await new Promise((resolve12) => setTimeout(resolve12, 3e3));
|
|
152007
152074
|
try {
|
|
152008
152075
|
const statusRes = await fetch(`${serverUrl}/publishers/${publisher_id}/verification-status`);
|
|
152009
152076
|
if (statusRes.ok) {
|
|
@@ -152094,7 +152161,7 @@ var logoutCommand = new Command3("logout").description("Remove stored credential
|
|
|
152094
152161
|
import { Command as Command4 } from "commander";
|
|
152095
152162
|
import chalk5 from "chalk";
|
|
152096
152163
|
import { readFileSync as readFileSync6, existsSync as existsSync6, statSync as statSync3 } from "node:fs";
|
|
152097
|
-
import { resolve as
|
|
152164
|
+
import { resolve as resolve5, join as join6 } from "node:path";
|
|
152098
152165
|
import { createHash as createHash3 } from "node:crypto";
|
|
152099
152166
|
|
|
152100
152167
|
// ../shared/dist/crypto.js
|
|
@@ -152212,7 +152279,7 @@ function readVaultMetadata(data) {
|
|
|
152212
152279
|
// ../shared/dist/packer.js
|
|
152213
152280
|
import { readFileSync as readFileSync3, readdirSync, existsSync as existsSync3 } from "node:fs";
|
|
152214
152281
|
import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
|
|
152215
|
-
import { join as join3, relative } from "node:path";
|
|
152282
|
+
import { join as join3, relative, resolve as resolve2, isAbsolute, sep } from "node:path";
|
|
152216
152283
|
import { createHash as createHash2 } from "node:crypto";
|
|
152217
152284
|
var DEFAULT_IGNORE = /* @__PURE__ */ new Set([
|
|
152218
152285
|
"node_modules",
|
|
@@ -152245,10 +152312,12 @@ function collectFiles(dir, base, ignoreSet) {
|
|
|
152245
152312
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
152246
152313
|
if (ignoreSet.has(entry.name))
|
|
152247
152314
|
continue;
|
|
152315
|
+
if (entry.isSymbolicLink())
|
|
152316
|
+
continue;
|
|
152248
152317
|
const fullPath = join3(dir, entry.name);
|
|
152249
152318
|
if (entry.isDirectory()) {
|
|
152250
152319
|
entries.push(...collectFiles(fullPath, base, ignoreSet));
|
|
152251
|
-
} else {
|
|
152320
|
+
} else if (entry.isFile()) {
|
|
152252
152321
|
entries.push({
|
|
152253
152322
|
path: relative(base, fullPath),
|
|
152254
152323
|
content: readFileSync3(fullPath)
|
|
@@ -152529,17 +152598,57 @@ function extractPotentialHeartbeats(content) {
|
|
|
152529
152598
|
return values;
|
|
152530
152599
|
}
|
|
152531
152600
|
|
|
152601
|
+
// ../shared/dist/skill-name.js
|
|
152602
|
+
var MAX_SKILL_NAME_LENGTH = 64;
|
|
152603
|
+
var ALLOWED_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9_-]*$/;
|
|
152604
|
+
var InvalidSkillNameError = class extends Error {
|
|
152605
|
+
reason;
|
|
152606
|
+
name;
|
|
152607
|
+
constructor(reason, name) {
|
|
152608
|
+
super(`invalid skill name: ${reason}`);
|
|
152609
|
+
this.reason = reason;
|
|
152610
|
+
this.name = name;
|
|
152611
|
+
this.name = "InvalidSkillNameError";
|
|
152612
|
+
}
|
|
152613
|
+
};
|
|
152614
|
+
function validateSkillName(name) {
|
|
152615
|
+
if (typeof name !== "string") {
|
|
152616
|
+
throw new InvalidSkillNameError("must be a string", String(name));
|
|
152617
|
+
}
|
|
152618
|
+
if (name.length === 0) {
|
|
152619
|
+
throw new InvalidSkillNameError("must not be empty", name);
|
|
152620
|
+
}
|
|
152621
|
+
if (name.length > MAX_SKILL_NAME_LENGTH) {
|
|
152622
|
+
throw new InvalidSkillNameError(`exceeds ${MAX_SKILL_NAME_LENGTH} characters`, name);
|
|
152623
|
+
}
|
|
152624
|
+
for (let i = 0; i < name.length; i++) {
|
|
152625
|
+
const code = name.charCodeAt(i);
|
|
152626
|
+
if (code < 32 || code === 127) {
|
|
152627
|
+
throw new InvalidSkillNameError(`contains control character (0x${code.toString(16).padStart(2, "0")})`, name);
|
|
152628
|
+
}
|
|
152629
|
+
}
|
|
152630
|
+
if (name.includes("..")) {
|
|
152631
|
+
throw new InvalidSkillNameError('contains parent-directory segment "..", which is not allowed in path components', name);
|
|
152632
|
+
}
|
|
152633
|
+
if (name.includes("/") || name.includes("\\")) {
|
|
152634
|
+
throw new InvalidSkillNameError("contains a path separator, which is not allowed in skill names", name);
|
|
152635
|
+
}
|
|
152636
|
+
if (!ALLOWED_PATTERN.test(name)) {
|
|
152637
|
+
throw new InvalidSkillNameError(`must match ${ALLOWED_PATTERN.source} (ASCII letters, digits, dashes, underscores; must start with a letter or digit)`, name);
|
|
152638
|
+
}
|
|
152639
|
+
}
|
|
152640
|
+
|
|
152532
152641
|
// dist/session.js
|
|
152533
152642
|
import chalk4 from "chalk";
|
|
152534
152643
|
|
|
152535
152644
|
// dist/publisher-workspace.js
|
|
152536
152645
|
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync4 } from "node:fs";
|
|
152537
|
-
import { join as join4, dirname as dirname3, resolve as
|
|
152646
|
+
import { join as join4, dirname as dirname3, resolve as resolve3 } from "node:path";
|
|
152538
152647
|
import { homedir as homedir3 } from "node:os";
|
|
152539
152648
|
var MANIFEST_DIRNAME = ".skillvault-publisher";
|
|
152540
152649
|
var MANIFEST_FILENAME = "workspace.json";
|
|
152541
152650
|
function workspaceRootsFor(dir) {
|
|
152542
|
-
const abs =
|
|
152651
|
+
const abs = resolve3(dir);
|
|
152543
152652
|
const manifestPath = join4(abs, MANIFEST_DIRNAME, MANIFEST_FILENAME);
|
|
152544
152653
|
return {
|
|
152545
152654
|
dir: abs,
|
|
@@ -152586,7 +152695,7 @@ function saveWorkspace(dir, manifest) {
|
|
|
152586
152695
|
writeFileSync4(manifestPath, JSON.stringify(manifest, null, 2), { mode: 420 });
|
|
152587
152696
|
}
|
|
152588
152697
|
function findWorkspace(cwd) {
|
|
152589
|
-
const start =
|
|
152698
|
+
const start = resolve3(cwd ?? process.cwd());
|
|
152590
152699
|
const home = homedir3();
|
|
152591
152700
|
let dir = start;
|
|
152592
152701
|
while (true) {
|
|
@@ -152658,8 +152767,9 @@ async function sessionFetch(ctx, path, options) {
|
|
|
152658
152767
|
process.exit(1);
|
|
152659
152768
|
}
|
|
152660
152769
|
if (!res.ok) {
|
|
152661
|
-
const err = await res.json().catch(() =>
|
|
152662
|
-
|
|
152770
|
+
const err = await res.json().catch(() => null);
|
|
152771
|
+
const reason = err?.message || err?.error || res.statusText || `HTTP ${res.status}`;
|
|
152772
|
+
process.stderr.write(chalk4.red(`Error: ${reason}
|
|
152663
152773
|
`));
|
|
152664
152774
|
process.exit(1);
|
|
152665
152775
|
}
|
|
@@ -152696,7 +152806,7 @@ function requireCommandContext(opts = {}) {
|
|
|
152696
152806
|
|
|
152697
152807
|
// dist/publisher-workspaces-registry.js
|
|
152698
152808
|
import { mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5, existsSync as existsSync5, statSync as statSync2 } from "node:fs";
|
|
152699
|
-
import { dirname as dirname4, join as join5, resolve as
|
|
152809
|
+
import { dirname as dirname4, join as join5, resolve as resolve4 } from "node:path";
|
|
152700
152810
|
import { homedir as homedir4 } from "node:os";
|
|
152701
152811
|
var REGISTRY_VERSION = 1;
|
|
152702
152812
|
var MANIFEST_DIRNAME2 = ".skillvault-publisher";
|
|
@@ -152730,7 +152840,7 @@ function listWorkspaces() {
|
|
|
152730
152840
|
const live = [];
|
|
152731
152841
|
let pruned = false;
|
|
152732
152842
|
for (const entry of reg.workspaces) {
|
|
152733
|
-
const path =
|
|
152843
|
+
const path = resolve4(entry.path);
|
|
152734
152844
|
let stillThere = false;
|
|
152735
152845
|
try {
|
|
152736
152846
|
const st = statSync2(path);
|
|
@@ -152755,8 +152865,8 @@ function listWorkspaces() {
|
|
|
152755
152865
|
}
|
|
152756
152866
|
function registerWorkspace(entry) {
|
|
152757
152867
|
const reg = readRegistry();
|
|
152758
|
-
const normalized = { ...entry, path:
|
|
152759
|
-
const idx = reg.workspaces.findIndex((w) =>
|
|
152868
|
+
const normalized = { ...entry, path: resolve4(entry.path) };
|
|
152869
|
+
const idx = reg.workspaces.findIndex((w) => resolve4(w.path) === normalized.path);
|
|
152760
152870
|
if (idx >= 0) {
|
|
152761
152871
|
reg.workspaces[idx] = normalized;
|
|
152762
152872
|
} else {
|
|
@@ -152766,9 +152876,9 @@ function registerWorkspace(entry) {
|
|
|
152766
152876
|
}
|
|
152767
152877
|
function unregisterWorkspace(path) {
|
|
152768
152878
|
const reg = readRegistry();
|
|
152769
|
-
const target =
|
|
152879
|
+
const target = resolve4(path);
|
|
152770
152880
|
const before = reg.workspaces.length;
|
|
152771
|
-
reg.workspaces = reg.workspaces.filter((w) =>
|
|
152881
|
+
reg.workspaces = reg.workspaces.filter((w) => resolve4(w.path) !== target);
|
|
152772
152882
|
if (reg.workspaces.length !== before)
|
|
152773
152883
|
writeRegistry(reg);
|
|
152774
152884
|
}
|
|
@@ -152798,9 +152908,9 @@ var publishCommand = new Command4("publish").description("Encrypt and publish a
|
|
|
152798
152908
|
const config = ctx.config;
|
|
152799
152909
|
const workspaceCtx = resolveWorkspaceContext({
|
|
152800
152910
|
workspaceFlag: options.workspace,
|
|
152801
|
-
cwd: directory ?
|
|
152911
|
+
cwd: directory ? resolve5(directory) : process.cwd()
|
|
152802
152912
|
});
|
|
152803
|
-
const dirPath = options.workspace ?
|
|
152913
|
+
const dirPath = options.workspace ? resolve5(options.workspace) : directory ? resolve5(directory) : workspaceCtx?.dir ?? process.cwd();
|
|
152804
152914
|
if (!existsSync6(dirPath) || !statSync3(dirPath).isDirectory()) {
|
|
152805
152915
|
process.stderr.write(chalk5.red(`Error: "${dirPath}" is not a valid directory
|
|
152806
152916
|
`));
|
|
@@ -152821,6 +152931,17 @@ var publishCommand = new Command4("publish").description("Encrypt and publish a
|
|
|
152821
152931
|
process.stderr.write(chalk5.red("Error: Skill name required \u2014 set in SKILL.md frontmatter or use --name\n"));
|
|
152822
152932
|
process.exit(1);
|
|
152823
152933
|
}
|
|
152934
|
+
try {
|
|
152935
|
+
validateSkillName(skillName);
|
|
152936
|
+
} catch (err) {
|
|
152937
|
+
if (err instanceof InvalidSkillNameError) {
|
|
152938
|
+
process.stderr.write(chalk5.red(`Error: ${err.message}
|
|
152939
|
+
`));
|
|
152940
|
+
process.stderr.write(chalk5.dim("Skill names must be ASCII letters, digits, dashes, or underscores (1-64 chars).\n"));
|
|
152941
|
+
process.exit(1);
|
|
152942
|
+
}
|
|
152943
|
+
throw err;
|
|
152944
|
+
}
|
|
152824
152945
|
if (!description) {
|
|
152825
152946
|
process.stderr.write(chalk5.red("Error: Description required \u2014 set in SKILL.md frontmatter or use --description\n"));
|
|
152826
152947
|
process.exit(1);
|
|
@@ -153031,7 +153152,8 @@ The server will clean up automatically. If the problem persists, re-run with --f
|
|
|
153031
153152
|
}
|
|
153032
153153
|
const publishResult = await publishRes.json().catch(() => ({}));
|
|
153033
153154
|
const wasUnlinked = existingManifest === null;
|
|
153034
|
-
|
|
153155
|
+
const publishAccepted = publishResult.status !== "rejected";
|
|
153156
|
+
if (publishAccepted && !options.noLink && sessionPublisherId) {
|
|
153035
153157
|
const linkedAt = existingManifest?.linked_at ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
153036
153158
|
const newManifest = {
|
|
153037
153159
|
...existingManifest ?? {},
|
|
@@ -153065,6 +153187,26 @@ The server will clean up automatically. If the problem persists, re-run with --f
|
|
|
153065
153187
|
if (publishResult.status === "unchanged") {
|
|
153066
153188
|
console.log(chalk5.yellow(`Content unchanged for ${skillName} v${version}. No new version created.`));
|
|
153067
153189
|
console.log(chalk5.dim(` Use --force to publish anyway.`));
|
|
153190
|
+
} else if (publishResult.status === "rejected") {
|
|
153191
|
+
const reasonMessage = publishResult.public_reason?.message || "Skill rejected by the security review pipeline.";
|
|
153192
|
+
process.stderr.write(chalk5.red(`
|
|
153193
|
+
Publish rejected: ${reasonMessage}
|
|
153194
|
+
`));
|
|
153195
|
+
process.stderr.write(chalk5.dim(` Run \`skillvault-publisher skill-status ${skillName}\` for more details.
|
|
153196
|
+
`));
|
|
153197
|
+
process.stderr.write(chalk5.dim(` Download a rejection report with \`skillvault-publisher skill-status ${skillName} --review-report <file>\`.
|
|
153198
|
+
`));
|
|
153199
|
+
process.exit(1);
|
|
153200
|
+
} else if (publishResult.status === "under_review") {
|
|
153201
|
+
console.log(chalk5.yellow(`
|
|
153202
|
+
Skill queued for review: ${skillName} v${version}`));
|
|
153203
|
+
if (publishResult.review_id) {
|
|
153204
|
+
console.log(chalk5.dim(` Review ID: ${publishResult.review_id}`));
|
|
153205
|
+
}
|
|
153206
|
+
console.log(chalk5.dim(` Skill ID: ${publishResult.skill_id || "n/a"}`));
|
|
153207
|
+
console.log(chalk5.dim(` Capability: ${capabilityName}`));
|
|
153208
|
+
console.log(chalk5.dim(" Reviews usually complete within a few minutes."));
|
|
153209
|
+
console.log(chalk5.dim(` Check status with \`skillvault-publisher skill-status ${skillName}\` (or listen on your webhook).`));
|
|
153068
153210
|
} else {
|
|
153069
153211
|
console.log(chalk5.green(`Published ${skillName} v${version}`));
|
|
153070
153212
|
console.log(chalk5.dim(` Skill ID: ${publishResult.skill_id || "n/a"}`));
|
|
@@ -153092,7 +153234,7 @@ import chalk6 from "chalk";
|
|
|
153092
153234
|
var searchCommand = new Command5("search").description("Search for skills in the registry").argument("<query>", "Search query").option("--type <type>", "Filter by capability type").option("--publisher <publisher>", "Filter by publisher name or ID").option("--mine", "Show only your own published skills").option("--json", "Output results as JSON").action(async (query, options) => {
|
|
153093
153235
|
try {
|
|
153094
153236
|
const config = getConfig();
|
|
153095
|
-
const serverUrl = config?.server_url ?? "
|
|
153237
|
+
const serverUrl = config?.server_url ?? "https://api.getskillvault.com";
|
|
153096
153238
|
let publisherFilter = options.publisher;
|
|
153097
153239
|
if (options.mine) {
|
|
153098
153240
|
if (!config) {
|
|
@@ -153253,7 +153395,7 @@ var licensesCommand = new Command7("licenses").description("List your active ski
|
|
|
153253
153395
|
import { Command as Command8 } from "commander";
|
|
153254
153396
|
import chalk9 from "chalk";
|
|
153255
153397
|
import { readFileSync as readFileSync8, existsSync as existsSync7, statSync as statSync4 } from "node:fs";
|
|
153256
|
-
import { resolve as
|
|
153398
|
+
import { resolve as resolve6, join as join7 } from "node:path";
|
|
153257
153399
|
import { createHash as createHash4 } from "node:crypto";
|
|
153258
153400
|
function parseFrontmatter2(content) {
|
|
153259
153401
|
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
@@ -153304,7 +153446,7 @@ var updateCommand = new Command8("update").description("Push a new version of an
|
|
|
153304
153446
|
try {
|
|
153305
153447
|
const ctx = requireSession();
|
|
153306
153448
|
const config = ctx.config;
|
|
153307
|
-
const dirPath =
|
|
153449
|
+
const dirPath = resolve6(directory);
|
|
153308
153450
|
if (!existsSync7(dirPath) || !statSync4(dirPath).isDirectory()) {
|
|
153309
153451
|
process.stderr.write(chalk9.red(`Error: "${dirPath}" is not a valid directory
|
|
153310
153452
|
`));
|
|
@@ -153487,6 +153629,14 @@ var whoamiCommand = new Command9("whoami").description("Show current user, activ
|
|
|
153487
153629
|
const ctx = requireSession();
|
|
153488
153630
|
const config = ctx.config;
|
|
153489
153631
|
const fingerprint = getDeviceFingerprint();
|
|
153632
|
+
let authMe = null;
|
|
153633
|
+
try {
|
|
153634
|
+
const meRes = await fetch(`${config.server_url}/auth/me`, { headers: ctx.headers });
|
|
153635
|
+
if (meRes.ok) {
|
|
153636
|
+
authMe = await meRes.json();
|
|
153637
|
+
}
|
|
153638
|
+
} catch {
|
|
153639
|
+
}
|
|
153490
153640
|
const response = await fetch(`${config.server_url}/agent/status?agent_id=${encodeURIComponent(config.agent_id)}`, {
|
|
153491
153641
|
headers: ctx.headers
|
|
153492
153642
|
});
|
|
@@ -153495,29 +153645,48 @@ var whoamiCommand = new Command9("whoami").description("Show current user, activ
|
|
|
153495
153645
|
console.log(JSON.stringify({
|
|
153496
153646
|
host_id: config.host_id,
|
|
153497
153647
|
agent_id: config.agent_id,
|
|
153498
|
-
...
|
|
153499
|
-
|
|
153648
|
+
...authMe ? {
|
|
153649
|
+
publisher_id: authMe.publisher_id,
|
|
153650
|
+
publisher_name: authMe.publisher_name,
|
|
153651
|
+
email: authMe.email,
|
|
153652
|
+
role: authMe.role,
|
|
153653
|
+
is_owner: authMe.is_owner
|
|
153654
|
+
} : {
|
|
153655
|
+
...config.publisher_id ? { publisher_id: config.publisher_id } : {},
|
|
153656
|
+
...config.email ? { email: config.email } : {}
|
|
153657
|
+
},
|
|
153500
153658
|
device_fingerprint: fingerprint,
|
|
153501
153659
|
server_url: config.server_url,
|
|
153502
|
-
server_status: "
|
|
153660
|
+
server_status: "agent_status_unreachable"
|
|
153503
153661
|
}, null, 2));
|
|
153504
153662
|
return;
|
|
153505
153663
|
}
|
|
153506
153664
|
console.log();
|
|
153507
153665
|
console.log(chalk10.bold(" Skill Vault Identity"));
|
|
153508
153666
|
console.log();
|
|
153509
|
-
if (
|
|
153510
|
-
|
|
153511
|
-
|
|
153512
|
-
|
|
153513
|
-
|
|
153667
|
+
if (authMe) {
|
|
153668
|
+
const roleColor = authMe.role === "owner" ? chalk10.green : authMe.role === "admin" ? chalk10.cyan : chalk10.dim;
|
|
153669
|
+
const roleLabel = authMe.role || (authMe.is_owner ? "owner" : "member");
|
|
153670
|
+
console.log(` ${"You:".padEnd(22)} ${authMe.email} ${roleColor(`(${roleLabel})`)}`);
|
|
153671
|
+
const publisherDisplay = authMe.publisher_name ? `${authMe.publisher_name} ${chalk10.dim(`(${authMe.publisher_id})`)}` : authMe.publisher_id;
|
|
153672
|
+
console.log(` ${"Publisher:".padEnd(22)} ${publisherDisplay}`);
|
|
153673
|
+
if (!authMe.is_owner) {
|
|
153674
|
+
console.log(` ${chalk10.dim(" (you are a team member of this publisher)".padEnd(22))}`);
|
|
153675
|
+
}
|
|
153676
|
+
} else {
|
|
153677
|
+
if (config.publisher_id) {
|
|
153678
|
+
console.log(` ${"Publisher ID:".padEnd(22)} ${config.publisher_id}`);
|
|
153679
|
+
}
|
|
153680
|
+
if (config.email) {
|
|
153681
|
+
console.log(` ${"Email:".padEnd(22)} ${config.email}`);
|
|
153682
|
+
}
|
|
153514
153683
|
}
|
|
153515
153684
|
console.log(` ${"Host ID:".padEnd(22)} ${config.host_id}`);
|
|
153516
153685
|
console.log(` ${"Agent ID:".padEnd(22)} ${config.agent_id}`);
|
|
153517
153686
|
console.log(` ${"Device Fingerprint:".padEnd(22)} ${fingerprint}`);
|
|
153518
153687
|
console.log(` ${"Server:".padEnd(22)} ${config.server_url}`);
|
|
153519
153688
|
console.log();
|
|
153520
|
-
console.log(chalk10.yellow(`
|
|
153689
|
+
console.log(chalk10.yellow(` Status endpoint unreachable (${response.status}); skipped grants list.`));
|
|
153521
153690
|
console.log();
|
|
153522
153691
|
return;
|
|
153523
153692
|
}
|
|
@@ -153526,8 +153695,17 @@ var whoamiCommand = new Command9("whoami").description("Show current user, activ
|
|
|
153526
153695
|
console.log(JSON.stringify({
|
|
153527
153696
|
host_id: data.host_id ?? config.host_id,
|
|
153528
153697
|
agent_id: data.agent_id ?? config.agent_id,
|
|
153529
|
-
...
|
|
153530
|
-
|
|
153698
|
+
...authMe ? {
|
|
153699
|
+
publisher_id: authMe.publisher_id,
|
|
153700
|
+
publisher_name: authMe.publisher_name,
|
|
153701
|
+
email: authMe.email,
|
|
153702
|
+
role: authMe.role,
|
|
153703
|
+
is_owner: authMe.is_owner,
|
|
153704
|
+
...authMe.skill_acls ? { skill_acls: authMe.skill_acls } : {}
|
|
153705
|
+
} : {
|
|
153706
|
+
...config.publisher_id ? { publisher_id: config.publisher_id } : {},
|
|
153707
|
+
...config.email ? { email: config.email } : {}
|
|
153708
|
+
},
|
|
153531
153709
|
device_fingerprint: fingerprint,
|
|
153532
153710
|
server_url: config.server_url,
|
|
153533
153711
|
status: data.status,
|
|
@@ -153535,14 +153713,51 @@ var whoamiCommand = new Command9("whoami").description("Show current user, activ
|
|
|
153535
153713
|
}, null, 2));
|
|
153536
153714
|
return;
|
|
153537
153715
|
}
|
|
153716
|
+
let skillsById = /* @__PURE__ */ new Map();
|
|
153717
|
+
if (authMe?.role === "member" && authMe.skill_acls && authMe.skill_acls.length > 0) {
|
|
153718
|
+
try {
|
|
153719
|
+
const skillsRes = await fetch(`${config.server_url}/skills`, { headers: ctx.headers });
|
|
153720
|
+
if (skillsRes.ok) {
|
|
153721
|
+
const sd = await skillsRes.json();
|
|
153722
|
+
for (const s of sd.skills)
|
|
153723
|
+
skillsById.set(s.id, s);
|
|
153724
|
+
}
|
|
153725
|
+
} catch {
|
|
153726
|
+
}
|
|
153727
|
+
}
|
|
153538
153728
|
console.log();
|
|
153539
153729
|
console.log(chalk10.bold(" Skill Vault Identity"));
|
|
153540
153730
|
console.log();
|
|
153541
|
-
if (
|
|
153542
|
-
|
|
153543
|
-
|
|
153544
|
-
|
|
153545
|
-
|
|
153731
|
+
if (authMe) {
|
|
153732
|
+
const roleColor = authMe.role === "owner" ? chalk10.green : authMe.role === "admin" ? chalk10.cyan : chalk10.dim;
|
|
153733
|
+
const roleLabel = authMe.role || (authMe.is_owner ? "owner" : "member");
|
|
153734
|
+
console.log(` ${"You:".padEnd(22)} ${authMe.email} ${roleColor(`(${roleLabel})`)}`);
|
|
153735
|
+
const publisherDisplay = authMe.publisher_name ? `${authMe.publisher_name} ${chalk10.dim(`(${authMe.publisher_id})`)}` : authMe.publisher_id;
|
|
153736
|
+
console.log(` ${"Publisher:".padEnd(22)} ${publisherDisplay}`);
|
|
153737
|
+
if (!authMe.is_owner) {
|
|
153738
|
+
console.log(` ${chalk10.dim(" (you are a team member of this publisher)".padEnd(22))}`);
|
|
153739
|
+
}
|
|
153740
|
+
if (authMe.role === "member" && authMe.skill_acls) {
|
|
153741
|
+
if (authMe.skill_acls.length === 0) {
|
|
153742
|
+
console.log(` ${chalk10.dim("Skill access:".padEnd(22))} ${chalk10.dim("(none yet \u2014 publish a new skill to auto-own it)")}`);
|
|
153743
|
+
} else {
|
|
153744
|
+
console.log(` ${"Skill access:".padEnd(22)}`);
|
|
153745
|
+
for (const a of authMe.skill_acls) {
|
|
153746
|
+
const sk = skillsById.get(a.skill_id);
|
|
153747
|
+
const label = sk?.name || a.skill_id;
|
|
153748
|
+
const roleColor2 = a.role === "owner" ? chalk10.green : a.role === "write" ? chalk10.cyan : chalk10.dim;
|
|
153749
|
+
const action = a.role === "owner" ? "publish + delete" : a.role === "write" ? "publish new versions" : "view only";
|
|
153750
|
+
console.log(` ${chalk10.cyan(label.padEnd(20))} ${roleColor2(a.role.padEnd(8))} ${chalk10.dim(action)}`);
|
|
153751
|
+
}
|
|
153752
|
+
}
|
|
153753
|
+
}
|
|
153754
|
+
} else {
|
|
153755
|
+
if (config.publisher_id) {
|
|
153756
|
+
console.log(` ${"Publisher ID:".padEnd(22)} ${config.publisher_id}`);
|
|
153757
|
+
}
|
|
153758
|
+
if (config.email) {
|
|
153759
|
+
console.log(` ${"Email:".padEnd(22)} ${config.email}`);
|
|
153760
|
+
}
|
|
153546
153761
|
}
|
|
153547
153762
|
console.log(` ${"Host ID:".padEnd(22)} ${data.host_id ?? config.host_id}`);
|
|
153548
153763
|
console.log(` ${"Agent ID:".padEnd(22)} ${data.agent_id ?? config.agent_id}`);
|
|
@@ -153627,7 +153842,7 @@ var reportCommand = new Command10("report").description("Report a telemetry even
|
|
|
153627
153842
|
import { Command as Command11 } from "commander";
|
|
153628
153843
|
import chalk12 from "chalk";
|
|
153629
153844
|
import { existsSync as existsSync8, mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "node:fs";
|
|
153630
|
-
import { resolve as
|
|
153845
|
+
import { resolve as resolve7, join as join8 } from "node:path";
|
|
153631
153846
|
function toTitleCase(name) {
|
|
153632
153847
|
return name.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
153633
153848
|
}
|
|
@@ -153664,7 +153879,7 @@ var initCommand = new Command11("init").description("Scaffold a new skill direct
|
|
|
153664
153879
|
process.stderr.write(chalk12.dim(" skillvault-publisher init my-awesome-skill\n"));
|
|
153665
153880
|
process.exit(1);
|
|
153666
153881
|
}
|
|
153667
|
-
const dirPath =
|
|
153882
|
+
const dirPath = resolve7(name);
|
|
153668
153883
|
if (existsSync8(dirPath)) {
|
|
153669
153884
|
process.stderr.write(chalk12.red(`Error: Directory "${name}" already exists.
|
|
153670
153885
|
`));
|
|
@@ -153779,11 +153994,9 @@ var listCommand = new Command13("list").description("List your published skills"
|
|
|
153779
153994
|
headers: ctx.headers
|
|
153780
153995
|
});
|
|
153781
153996
|
if (!response.ok) {
|
|
153782
|
-
const err = await response.json().catch(() =>
|
|
153783
|
-
|
|
153784
|
-
|
|
153785
|
-
}));
|
|
153786
|
-
process.stderr.write(chalk14.red(`Failed to list skills: ${err.message}
|
|
153997
|
+
const err = await response.json().catch(() => null);
|
|
153998
|
+
const reason = err?.message || err?.error || response.statusText || `HTTP ${response.status}`;
|
|
153999
|
+
process.stderr.write(chalk14.red(`Failed to list skills: ${reason}
|
|
153787
154000
|
`));
|
|
153788
154001
|
process.exit(1);
|
|
153789
154002
|
}
|
|
@@ -153804,11 +154017,13 @@ var listCommand = new Command13("list").description("List your published skills"
|
|
|
153804
154017
|
const nameWidth = Math.max(20, ...skills.map((s) => s.name.length + 2));
|
|
153805
154018
|
const verWidth = 10;
|
|
153806
154019
|
const statusWidth = 10;
|
|
154020
|
+
const reviewWidth = 8;
|
|
153807
154021
|
const capWidth = Math.max(24, ...skills.map((s) => s.capability_name.length + 2));
|
|
153808
154022
|
const header = [
|
|
153809
154023
|
chalk14.dim("Name".padEnd(nameWidth)),
|
|
153810
154024
|
chalk14.dim("Version".padEnd(verWidth)),
|
|
153811
154025
|
chalk14.dim("Status".padEnd(statusWidth)),
|
|
154026
|
+
chalk14.dim("Review".padEnd(reviewWidth)),
|
|
153812
154027
|
chalk14.dim("Capability".padEnd(capWidth)),
|
|
153813
154028
|
chalk14.dim("Created")
|
|
153814
154029
|
].join(" ");
|
|
@@ -153820,10 +154035,29 @@ var listCommand = new Command13("list").description("List your published skills"
|
|
|
153820
154035
|
year: "numeric"
|
|
153821
154036
|
});
|
|
153822
154037
|
const statusColor = skill.status === "active" ? chalk14.green : chalk14.dim;
|
|
154038
|
+
let reviewCell;
|
|
154039
|
+
switch (skill.review_state) {
|
|
154040
|
+
case "approved":
|
|
154041
|
+
reviewCell = chalk14.green("ok".padEnd(reviewWidth));
|
|
154042
|
+
break;
|
|
154043
|
+
case "queued":
|
|
154044
|
+
case "running":
|
|
154045
|
+
reviewCell = chalk14.yellow("review".padEnd(reviewWidth));
|
|
154046
|
+
break;
|
|
154047
|
+
case "rejected":
|
|
154048
|
+
reviewCell = chalk14.red("reject".padEnd(reviewWidth));
|
|
154049
|
+
break;
|
|
154050
|
+
case "needs_human_review":
|
|
154051
|
+
reviewCell = chalk14.yellow("human".padEnd(reviewWidth));
|
|
154052
|
+
break;
|
|
154053
|
+
default:
|
|
154054
|
+
reviewCell = chalk14.dim("-".padEnd(reviewWidth));
|
|
154055
|
+
}
|
|
153823
154056
|
const row = [
|
|
153824
154057
|
chalk14.cyan(skill.name.padEnd(nameWidth)),
|
|
153825
154058
|
chalk14.green(("v" + skill.latest_version).padEnd(verWidth)),
|
|
153826
154059
|
statusColor(skill.status.padEnd(statusWidth)),
|
|
154060
|
+
reviewCell,
|
|
153827
154061
|
chalk14.dim(skill.capability_name.padEnd(capWidth)),
|
|
153828
154062
|
chalk14.dim(createdDate)
|
|
153829
154063
|
].join(" ");
|
|
@@ -153842,7 +154076,7 @@ var listCommand = new Command13("list").description("List your published skills"
|
|
|
153842
154076
|
import { Command as Command14 } from "commander";
|
|
153843
154077
|
import chalk15 from "chalk";
|
|
153844
154078
|
import { readFileSync as readFileSync9, existsSync as existsSync9, statSync as statSync5, readdirSync as readdirSync2 } from "node:fs";
|
|
153845
|
-
import { resolve as
|
|
154079
|
+
import { resolve as resolve8, join as join9, basename } from "node:path";
|
|
153846
154080
|
import { createHash as createHash6 } from "node:crypto";
|
|
153847
154081
|
function parseFrontmatter3(content) {
|
|
153848
154082
|
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
@@ -153990,7 +154224,7 @@ var publishAllCommand = new Command14("publish-all").description("Discover and p
|
|
|
153990
154224
|
skillDirs = entries.map((e) => e.path);
|
|
153991
154225
|
console.log(chalk15.dim(`Iterating ${skillDirs.length} registered workspace${skillDirs.length === 1 ? "" : "s"}` + (options.current ? " (current account only)" : "") + "..."));
|
|
153992
154226
|
} else {
|
|
153993
|
-
const rootDir =
|
|
154227
|
+
const rootDir = resolve8(directory);
|
|
153994
154228
|
if (!existsSync9(rootDir) || !statSync5(rootDir).isDirectory()) {
|
|
153995
154229
|
process.stderr.write(chalk15.red(`Error: "${rootDir}" is not a valid directory
|
|
153996
154230
|
`));
|
|
@@ -154270,12 +154504,12 @@ var inviteListCommand = new Command15("list").description("List all invites").op
|
|
|
154270
154504
|
}
|
|
154271
154505
|
console.log(`Invites (${invites.length}):
|
|
154272
154506
|
`);
|
|
154273
|
-
const
|
|
154274
|
-
console.log(chalk16.dim(`${
|
|
154507
|
+
const pad4 = (s, n) => s.padEnd(n).slice(0, n);
|
|
154508
|
+
console.log(chalk16.dim(`${pad4("Code", 14)} ${pad4("Email", 30)} ${pad4("Status", 10)} ${pad4("Skills", 25)} ${pad4("Created", 12)}`));
|
|
154275
154509
|
console.log(chalk16.dim("\u2500".repeat(95)));
|
|
154276
154510
|
for (const inv of invites) {
|
|
154277
154511
|
const statusColor = inv.status === "redeemed" ? chalk16.green : inv.status === "expired" ? chalk16.dim : chalk16.yellow;
|
|
154278
|
-
console.log(`${
|
|
154512
|
+
console.log(`${pad4(inv.code, 14)} ${pad4(inv.customer_email || "(open)", 30)} ${statusColor(pad4(inv.status, 10))} ${pad4(inv.capabilities.join(", ") || "(none)", 25)} ${pad4(new Date(inv.created_at).toLocaleDateString(), 12)}`);
|
|
154279
154513
|
}
|
|
154280
154514
|
} catch (err) {
|
|
154281
154515
|
process.stderr.write(chalk16.red(`Error: ${err instanceof Error ? err.message : String(err)}
|
|
@@ -154898,7 +155132,9 @@ var skillDeleteCommand = new Command20("skill-delete").description("Permanently
|
|
|
154898
155132
|
// dist/commands/skill-status.js
|
|
154899
155133
|
import { Command as Command21 } from "commander";
|
|
154900
155134
|
import chalk18 from "chalk";
|
|
154901
|
-
|
|
155135
|
+
import { writeFileSync as writeFileSync10 } from "node:fs";
|
|
155136
|
+
import { resolve as resolve9 } from "node:path";
|
|
155137
|
+
var skillStatusCommand = new Command21("skill-status").description("Show detailed status for a skill").argument("[skill-name]", "Name of the skill to inspect (defaults to workspace skill)").option("--json", "Output as JSON").option("--workspace <path>", "Use workspace at <path> to default skill-name").option("--quiet", 'Suppress the "(using workspace \u2026)" stderr note').option("--review-report <file>", "Write a public review report (JSON) to <file>").action(async (skillNameArg, options) => {
|
|
154902
155138
|
try {
|
|
154903
155139
|
const ctx = requireCommandContext({ workspaceFlag: options.workspace, quiet: options.quiet });
|
|
154904
155140
|
const skillName = skillNameArg ?? ctx.defaultSkillName ?? void 0;
|
|
@@ -154920,17 +155156,56 @@ var skillStatusCommand = new Command21("skill-status").description("Show detaile
|
|
|
154920
155156
|
sessionFetch(ctx, "/grants")
|
|
154921
155157
|
]);
|
|
154922
155158
|
const activeGrants = grantsData.grants.filter((g) => g.capability === detail.capability_name && g.status === "active");
|
|
155159
|
+
if (options.reviewReport) {
|
|
155160
|
+
const report = {
|
|
155161
|
+
skill_id: detail.id,
|
|
155162
|
+
capability_name: detail.capability_name,
|
|
155163
|
+
version: detail.latest_version,
|
|
155164
|
+
review_state: detail.review_state ?? null,
|
|
155165
|
+
public_reason_code: detail.latest_review?.public_reason_code ?? null,
|
|
155166
|
+
public_reason_message: detail.latest_review?.public_reason_message ?? null,
|
|
155167
|
+
last_review_at: detail.latest_review?.last_review_at ?? null
|
|
155168
|
+
};
|
|
155169
|
+
const reportPath = resolve9(options.reviewReport);
|
|
155170
|
+
writeFileSync10(reportPath, JSON.stringify(report, null, 2) + "\n");
|
|
155171
|
+
process.stderr.write(chalk18.green(`Wrote review report to ${reportPath}
|
|
155172
|
+
`));
|
|
155173
|
+
}
|
|
154923
155174
|
if (options.json) {
|
|
154924
155175
|
console.log(JSON.stringify({ ...detail, active_grants: activeGrants.length }, null, 2));
|
|
154925
155176
|
return;
|
|
154926
155177
|
}
|
|
154927
155178
|
const statusColor = detail.status === "active" ? chalk18.green : detail.status === "archived" ? chalk18.yellow : chalk18.dim;
|
|
154928
155179
|
const createdDate = new Date(detail.created_at).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
|
|
155180
|
+
const reviewState = detail.review_state ?? "approved";
|
|
155181
|
+
let reviewLabel;
|
|
155182
|
+
switch (reviewState) {
|
|
155183
|
+
case "approved":
|
|
155184
|
+
reviewLabel = chalk18.green("Approved");
|
|
155185
|
+
break;
|
|
155186
|
+
case "queued":
|
|
155187
|
+
case "running":
|
|
155188
|
+
reviewLabel = chalk18.yellow("Under review");
|
|
155189
|
+
break;
|
|
155190
|
+
case "rejected":
|
|
155191
|
+
reviewLabel = chalk18.red("Rejected");
|
|
155192
|
+
break;
|
|
155193
|
+
case "needs_human_review":
|
|
155194
|
+
reviewLabel = chalk18.yellow("Awaiting review");
|
|
155195
|
+
break;
|
|
155196
|
+
default:
|
|
155197
|
+
reviewLabel = chalk18.dim(reviewState);
|
|
155198
|
+
}
|
|
155199
|
+
const lastReviewAt = detail.latest_review?.last_review_at ? new Date(detail.latest_review.last_review_at).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }) : null;
|
|
154929
155200
|
console.log();
|
|
154930
155201
|
console.log(chalk18.bold(` ${detail.name}`));
|
|
154931
155202
|
console.log();
|
|
154932
155203
|
console.log(` Capability: ${detail.capability_name}`);
|
|
154933
155204
|
console.log(` Status: ${statusColor(detail.status)}`);
|
|
155205
|
+
console.log(` Review: ${reviewLabel}${lastReviewAt ? chalk18.dim(` (${lastReviewAt})`) : ""}`);
|
|
155206
|
+
if (reviewState === "rejected" && detail.latest_review?.public_reason_message) {
|
|
155207
|
+
console.log(` Reason: ${chalk18.red(detail.latest_review.public_reason_message)}`);
|
|
155208
|
+
}
|
|
154934
155209
|
console.log(` Version: ${chalk18.green("v" + detail.latest_version)}`);
|
|
154935
155210
|
console.log(` Created: ${chalk18.dim(createdDate)}`);
|
|
154936
155211
|
console.log(` ID: ${chalk18.dim(detail.id)}`);
|
|
@@ -154987,10 +155262,199 @@ var skillUnarchiveCommand = new Command22("skill-unarchive").description("Restor
|
|
|
154987
155262
|
}
|
|
154988
155263
|
});
|
|
154989
155264
|
|
|
154990
|
-
// dist/commands/
|
|
155265
|
+
// dist/commands/skill-acl.js
|
|
154991
155266
|
import { Command as Command23 } from "commander";
|
|
154992
155267
|
import chalk20 from "chalk";
|
|
154993
|
-
var
|
|
155268
|
+
var VALID_ROLES = /* @__PURE__ */ new Set(["read", "write", "owner"]);
|
|
155269
|
+
async function resolveSkill(ctx, skillName) {
|
|
155270
|
+
const data = await sessionFetch(ctx, "/skills");
|
|
155271
|
+
const skill = data.skills.find((s) => s.name.toLowerCase() === skillName.toLowerCase() || s.capability_name.toLowerCase() === skillName.toLowerCase());
|
|
155272
|
+
if (!skill) {
|
|
155273
|
+
process.stderr.write(chalk20.red(`Skill not found: ${skillName}
|
|
155274
|
+
`));
|
|
155275
|
+
process.stderr.write(chalk20.dim("Run `skillvault-publisher list` to see your skills.\n"));
|
|
155276
|
+
process.exit(1);
|
|
155277
|
+
}
|
|
155278
|
+
return skill;
|
|
155279
|
+
}
|
|
155280
|
+
async function runList(ctx, skill, options) {
|
|
155281
|
+
const data = await sessionFetch(ctx, `/skills/${skill.id}/acls`);
|
|
155282
|
+
const acls = data.acls || [];
|
|
155283
|
+
if (options.json) {
|
|
155284
|
+
console.log(JSON.stringify({ skill: skill.name, skill_id: skill.id, acls }, null, 2));
|
|
155285
|
+
return;
|
|
155286
|
+
}
|
|
155287
|
+
console.log();
|
|
155288
|
+
console.log(chalk20.bold(` ACL grants on ${chalk20.cyan(skill.name)}`));
|
|
155289
|
+
console.log();
|
|
155290
|
+
if (acls.length === 0) {
|
|
155291
|
+
console.log(chalk20.dim(" No ACL grants. Account owners and admins always have full access."));
|
|
155292
|
+
console.log(chalk20.dim(` Add a member: skillvault-publisher skill-acl ${skill.name} add <email> --role read|write|owner`));
|
|
155293
|
+
console.log();
|
|
155294
|
+
return;
|
|
155295
|
+
}
|
|
155296
|
+
const emailWidth = Math.max(20, ...acls.map((a) => a.email.length + 2));
|
|
155297
|
+
const roleWidth = 8;
|
|
155298
|
+
const header = [
|
|
155299
|
+
chalk20.dim("Email".padEnd(emailWidth)),
|
|
155300
|
+
chalk20.dim("Role".padEnd(roleWidth)),
|
|
155301
|
+
chalk20.dim("Granted by")
|
|
155302
|
+
].join(" ");
|
|
155303
|
+
console.log(` ${header}`);
|
|
155304
|
+
console.log(` ${chalk20.dim("-".repeat(emailWidth + roleWidth + 24))}`);
|
|
155305
|
+
for (const a of acls) {
|
|
155306
|
+
const roleColor = a.role === "owner" ? chalk20.green : a.role === "write" ? chalk20.cyan : chalk20.dim;
|
|
155307
|
+
const row = [
|
|
155308
|
+
a.email.padEnd(emailWidth),
|
|
155309
|
+
roleColor(a.role.padEnd(roleWidth)),
|
|
155310
|
+
chalk20.dim(a.granted_by || "(self)")
|
|
155311
|
+
].join(" ");
|
|
155312
|
+
console.log(` ${row}`);
|
|
155313
|
+
}
|
|
155314
|
+
console.log();
|
|
155315
|
+
}
|
|
155316
|
+
async function runAdd(ctx, skill, email, options) {
|
|
155317
|
+
if (!options.role) {
|
|
155318
|
+
process.stderr.write(chalk20.red("Error: --role is required (read|write|owner)\n"));
|
|
155319
|
+
process.exit(1);
|
|
155320
|
+
}
|
|
155321
|
+
const role = options.role.toLowerCase();
|
|
155322
|
+
if (!VALID_ROLES.has(role)) {
|
|
155323
|
+
process.stderr.write(chalk20.red(`Invalid --role value: ${options.role}
|
|
155324
|
+
`));
|
|
155325
|
+
process.stderr.write(chalk20.dim(" Must be one of: read, write, owner\n"));
|
|
155326
|
+
process.exit(1);
|
|
155327
|
+
}
|
|
155328
|
+
const res = await fetch(`${ctx.serverUrl}/skills/${skill.id}/acls`, {
|
|
155329
|
+
method: "POST",
|
|
155330
|
+
headers: ctx.headers,
|
|
155331
|
+
body: JSON.stringify({ email, role })
|
|
155332
|
+
});
|
|
155333
|
+
const body = await res.json().catch(() => ({}));
|
|
155334
|
+
if (!res.ok) {
|
|
155335
|
+
if (body.error === "not_a_team_member") {
|
|
155336
|
+
process.stderr.write(chalk20.red(`${email} is not a member of this team.
|
|
155337
|
+
`));
|
|
155338
|
+
process.stderr.write(chalk20.dim(`Add them first: skillvault-publisher team add ${email} --role member
|
|
155339
|
+
`));
|
|
155340
|
+
process.exit(1);
|
|
155341
|
+
}
|
|
155342
|
+
process.stderr.write(chalk20.red(`Failed to grant: ${body.message || body.error || res.statusText}
|
|
155343
|
+
`));
|
|
155344
|
+
process.exit(1);
|
|
155345
|
+
}
|
|
155346
|
+
if (options.json) {
|
|
155347
|
+
console.log(JSON.stringify(body, null, 2));
|
|
155348
|
+
return;
|
|
155349
|
+
}
|
|
155350
|
+
if (body.note) {
|
|
155351
|
+
console.log(chalk20.yellow(` ${body.note}`));
|
|
155352
|
+
return;
|
|
155353
|
+
}
|
|
155354
|
+
const acl = body.acl;
|
|
155355
|
+
console.log(chalk20.green(`Granted ${acl.email} ${chalk20.bold(acl.role)} on ${skill.name}`));
|
|
155356
|
+
}
|
|
155357
|
+
async function runRemove(ctx, skill, target, options) {
|
|
155358
|
+
const data = await sessionFetch(ctx, `/skills/${skill.id}/acls`);
|
|
155359
|
+
const acls = data.acls || [];
|
|
155360
|
+
let acl;
|
|
155361
|
+
if (target.startsWith("acl_")) {
|
|
155362
|
+
acl = acls.find((a) => a.id === target);
|
|
155363
|
+
} else {
|
|
155364
|
+
acl = acls.find((a) => a.email.toLowerCase() === target.toLowerCase());
|
|
155365
|
+
}
|
|
155366
|
+
if (!acl) {
|
|
155367
|
+
process.stderr.write(chalk20.red(`No ACL row matches: ${target}
|
|
155368
|
+
`));
|
|
155369
|
+
process.exit(1);
|
|
155370
|
+
}
|
|
155371
|
+
if (!options.yes) {
|
|
155372
|
+
console.log();
|
|
155373
|
+
console.log(chalk20.yellow.bold(" Warning: ") + `This revokes ${acl.role} access on ${chalk20.cyan(skill.name)} for ${chalk20.cyan(acl.email)}.`);
|
|
155374
|
+
console.log(chalk20.dim(" Add --yes to confirm."));
|
|
155375
|
+
console.log();
|
|
155376
|
+
process.exit(0);
|
|
155377
|
+
}
|
|
155378
|
+
const res = await fetch(`${ctx.serverUrl}/skills/${skill.id}/acls/${acl.id}`, {
|
|
155379
|
+
method: "DELETE",
|
|
155380
|
+
headers: ctx.headers
|
|
155381
|
+
});
|
|
155382
|
+
const body = await res.json().catch(() => ({}));
|
|
155383
|
+
if (!res.ok) {
|
|
155384
|
+
if (body.error === "last_owner") {
|
|
155385
|
+
process.stderr.write(chalk20.red("Cannot remove the last owner ACL on this skill.\n"));
|
|
155386
|
+
process.stderr.write(chalk20.dim(" Grant another member owner access first, or have an account admin manage it.\n"));
|
|
155387
|
+
process.exit(1);
|
|
155388
|
+
}
|
|
155389
|
+
process.stderr.write(chalk20.red(`Failed to remove: ${body.message || body.error || res.statusText}
|
|
155390
|
+
`));
|
|
155391
|
+
process.exit(1);
|
|
155392
|
+
}
|
|
155393
|
+
if (options.json) {
|
|
155394
|
+
console.log(JSON.stringify({ removed: true, acl_id: acl.id, email: acl.email, role: acl.role }, null, 2));
|
|
155395
|
+
return;
|
|
155396
|
+
}
|
|
155397
|
+
console.log(chalk20.green(`Removed ${acl.email} (${acl.role}) from ${skill.name}`));
|
|
155398
|
+
}
|
|
155399
|
+
var skillAclCommand = new Command23("skill-acl").description("Manage per-skill ACL grants for team members").argument("<skill-name>", 'Skill to manage (or "list"/"add"/"remove" if using a workspace default)').argument("<action>", "Action: list | add | remove").argument("[target]", "Email (for add/remove) \u2014 not used by list").option("--role <role>", "Role for add: read | write | owner").option("--yes", "Skip confirmation on remove").option("--workspace <path>", "Use workspace at <path> to default skill-name").option("--quiet", 'Suppress the "(using workspace \u2026)" stderr note').option("--json", "Output as JSON").action(async (skillNameArg, actionArg, targetArg, options) => {
|
|
155400
|
+
try {
|
|
155401
|
+
let skillName = skillNameArg;
|
|
155402
|
+
let action = actionArg;
|
|
155403
|
+
let target = targetArg;
|
|
155404
|
+
const isActionVerb = (s) => s === "list" || s === "add" || s === "remove";
|
|
155405
|
+
if (isActionVerb(skillNameArg) && !isActionVerb(actionArg)) {
|
|
155406
|
+
action = skillNameArg;
|
|
155407
|
+
target = actionArg;
|
|
155408
|
+
skillName = "";
|
|
155409
|
+
}
|
|
155410
|
+
const ctx = requireCommandContext({ workspaceFlag: options.workspace, quiet: options.quiet });
|
|
155411
|
+
if (!skillName) {
|
|
155412
|
+
if (!ctx.defaultSkillName) {
|
|
155413
|
+
process.stderr.write(chalk20.red("Error: No skill name provided and no workspace context.\n"));
|
|
155414
|
+
process.stderr.write(chalk20.dim(" Pass <skill-name> or run from a linked workspace directory.\n"));
|
|
155415
|
+
process.exit(1);
|
|
155416
|
+
}
|
|
155417
|
+
skillName = ctx.defaultSkillName;
|
|
155418
|
+
}
|
|
155419
|
+
if (!isActionVerb(action)) {
|
|
155420
|
+
process.stderr.write(chalk20.red(`Unknown action: ${action}
|
|
155421
|
+
`));
|
|
155422
|
+
process.stderr.write(chalk20.dim(" Must be one of: list, add, remove\n"));
|
|
155423
|
+
process.exit(1);
|
|
155424
|
+
}
|
|
155425
|
+
const skill = await resolveSkill(ctx, skillName);
|
|
155426
|
+
if (action === "list") {
|
|
155427
|
+
await runList(ctx, skill, options);
|
|
155428
|
+
return;
|
|
155429
|
+
}
|
|
155430
|
+
if (action === "add") {
|
|
155431
|
+
if (!target) {
|
|
155432
|
+
process.stderr.write(chalk20.red("Error: add requires <email>\n"));
|
|
155433
|
+
process.exit(1);
|
|
155434
|
+
}
|
|
155435
|
+
await runAdd(ctx, skill, target, options);
|
|
155436
|
+
return;
|
|
155437
|
+
}
|
|
155438
|
+
if (action === "remove") {
|
|
155439
|
+
if (!target) {
|
|
155440
|
+
process.stderr.write(chalk20.red("Error: remove requires <email-or-id>\n"));
|
|
155441
|
+
process.exit(1);
|
|
155442
|
+
}
|
|
155443
|
+
await runRemove(ctx, skill, target, options);
|
|
155444
|
+
return;
|
|
155445
|
+
}
|
|
155446
|
+
} catch (err) {
|
|
155447
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
155448
|
+
process.stderr.write(chalk20.red(`skill-acl failed: ${message}
|
|
155449
|
+
`));
|
|
155450
|
+
process.exit(1);
|
|
155451
|
+
}
|
|
155452
|
+
});
|
|
155453
|
+
|
|
155454
|
+
// dist/commands/grants.js
|
|
155455
|
+
import { Command as Command24 } from "commander";
|
|
155456
|
+
import chalk21 from "chalk";
|
|
155457
|
+
var grantsCommand = new Command24("grants").description("List capability grants issued to customers").option("--status <status>", "Filter by status: active, revoked, expired").option("--skill <name>", "Filter to grants for a specific skill (capability)").option("--json", "Output as JSON").option("--workspace <path>", "Use workspace at <path> to default --skill").option("--quiet", 'Suppress the "(using workspace \u2026)" stderr note').option("--all", "Disable workspace --skill default; show grants for all skills").action(async (options) => {
|
|
154994
155458
|
try {
|
|
154995
155459
|
const ctx = requireCommandContext({ workspaceFlag: options.workspace, quiet: options.quiet });
|
|
154996
155460
|
const data = await sessionFetch(ctx, "/grants");
|
|
@@ -155008,43 +155472,43 @@ var grantsCommand = new Command23("grants").description("List capability grants
|
|
|
155008
155472
|
return;
|
|
155009
155473
|
}
|
|
155010
155474
|
if (grants.length === 0) {
|
|
155011
|
-
console.log(
|
|
155475
|
+
console.log(chalk21.dim("No grants found."));
|
|
155012
155476
|
return;
|
|
155013
155477
|
}
|
|
155014
155478
|
console.log();
|
|
155015
|
-
console.log(
|
|
155479
|
+
console.log(chalk21.bold(" Capability Grants"));
|
|
155016
155480
|
console.log();
|
|
155017
|
-
const
|
|
155018
|
-
const header = `${
|
|
155019
|
-
console.log(` ${
|
|
155020
|
-
console.log(` ${
|
|
155481
|
+
const pad4 = (s, n) => s.padEnd(n).slice(0, n);
|
|
155482
|
+
const header = `${pad4("Grant ID", 22)} ${pad4("Skill", 24)} ${pad4("Customer", 22)} ${pad4("Status", 10)} ${pad4("Granted", 12)} ${"Expires"}`;
|
|
155483
|
+
console.log(` ${chalk21.dim(header)}`);
|
|
155484
|
+
console.log(` ${chalk21.dim("\u2500".repeat(header.length))}`);
|
|
155021
155485
|
for (const grant of grants) {
|
|
155022
|
-
const statusColor = grant.status === "active" ?
|
|
155486
|
+
const statusColor = grant.status === "active" ? chalk21.green : grant.status === "revoked" ? chalk21.red : grant.status === "expired" ? chalk21.yellow : chalk21.white;
|
|
155023
155487
|
const row = [
|
|
155024
|
-
|
|
155025
|
-
|
|
155026
|
-
|
|
155027
|
-
statusColor(
|
|
155028
|
-
|
|
155488
|
+
pad4(grant.id, 22),
|
|
155489
|
+
pad4(grant.capability, 24),
|
|
155490
|
+
pad4(grant.customer_id || "-", 22),
|
|
155491
|
+
statusColor(pad4(grant.status, 10)),
|
|
155492
|
+
pad4(new Date(grant.created_at).toLocaleDateString(), 12),
|
|
155029
155493
|
grant.expires_at ? new Date(grant.expires_at).toLocaleDateString() : "never"
|
|
155030
155494
|
].join(" ");
|
|
155031
155495
|
console.log(` ${row}`);
|
|
155032
155496
|
}
|
|
155033
155497
|
console.log();
|
|
155034
|
-
console.log(
|
|
155498
|
+
console.log(chalk21.dim(` ${grants.length} grant${grants.length !== 1 ? "s" : ""} total`));
|
|
155035
155499
|
console.log();
|
|
155036
155500
|
} catch (err) {
|
|
155037
155501
|
const message = err instanceof Error ? err.message : String(err);
|
|
155038
|
-
process.stderr.write(
|
|
155502
|
+
process.stderr.write(chalk21.red(`Error: ${message}
|
|
155039
155503
|
`));
|
|
155040
155504
|
process.exit(1);
|
|
155041
155505
|
}
|
|
155042
155506
|
});
|
|
155043
155507
|
|
|
155044
155508
|
// dist/commands/revoke-grant.js
|
|
155045
|
-
import { Command as
|
|
155046
|
-
import
|
|
155047
|
-
var revokeGrantCommand = new
|
|
155509
|
+
import { Command as Command25 } from "commander";
|
|
155510
|
+
import chalk22 from "chalk";
|
|
155511
|
+
var revokeGrantCommand = new Command25("revoke-grant").description("Revoke a capability grant by ID").argument("<grant-id>", "Grant ID to revoke (e.g., gnt_xxx)").option("--yes", "Skip confirmation and revoke immediately").option("--json", "Output as JSON").option("--workspace <path>", "Resolve workspace context (informational only \u2014 grant ID is authoritative)").option("--quiet", 'Suppress the "(using workspace \u2026)" stderr note').action(async (grantId, options) => {
|
|
155048
155512
|
try {
|
|
155049
155513
|
const ctx = requireCommandContext({ workspaceFlag: options.workspace, quiet: options.quiet });
|
|
155050
155514
|
if (!options.yes) {
|
|
@@ -155055,7 +155519,7 @@ var revokeGrantCommand = new Command24("revoke-grant").description("Revoke a cap
|
|
|
155055
155519
|
return;
|
|
155056
155520
|
}
|
|
155057
155521
|
console.log();
|
|
155058
|
-
console.log(
|
|
155522
|
+
console.log(chalk22.bold(" Grant details"));
|
|
155059
155523
|
console.log();
|
|
155060
155524
|
console.log(` ID: ${grant.id}`);
|
|
155061
155525
|
console.log(` Skill: ${grant.skill}`);
|
|
@@ -155064,7 +155528,7 @@ var revokeGrantCommand = new Command24("revoke-grant").description("Revoke a cap
|
|
|
155064
155528
|
console.log(` Granted: ${new Date(grant.granted_at).toLocaleDateString()}`);
|
|
155065
155529
|
console.log(` Expires: ${grant.expires_at ? new Date(grant.expires_at).toLocaleDateString() : "never"}`);
|
|
155066
155530
|
console.log();
|
|
155067
|
-
console.log(
|
|
155531
|
+
console.log(chalk22.yellow(" Add --yes to confirm revocation."));
|
|
155068
155532
|
console.log();
|
|
155069
155533
|
return;
|
|
155070
155534
|
}
|
|
@@ -155073,19 +155537,19 @@ var revokeGrantCommand = new Command24("revoke-grant").description("Revoke a cap
|
|
|
155073
155537
|
console.log(JSON.stringify(result.grant, null, 2));
|
|
155074
155538
|
return;
|
|
155075
155539
|
}
|
|
155076
|
-
console.log(
|
|
155540
|
+
console.log(chalk22.green(`Revoked grant ${result.grant.id} for ${result.grant.skill}`));
|
|
155077
155541
|
} catch (err) {
|
|
155078
155542
|
const message = err instanceof Error ? err.message : String(err);
|
|
155079
|
-
process.stderr.write(
|
|
155543
|
+
process.stderr.write(chalk22.red(`Error: ${message}
|
|
155080
155544
|
`));
|
|
155081
155545
|
process.exit(1);
|
|
155082
155546
|
}
|
|
155083
155547
|
});
|
|
155084
155548
|
|
|
155085
155549
|
// dist/commands/customers.js
|
|
155086
|
-
import { Command as
|
|
155087
|
-
import
|
|
155088
|
-
var customersCommand = new
|
|
155550
|
+
import { Command as Command26 } from "commander";
|
|
155551
|
+
import chalk23 from "chalk";
|
|
155552
|
+
var customersCommand = new Command26("customers").description("List your customers").option("--json", "Output as JSON").option("--workspace <path>", "Resolve workspace context (defaults from CWD)").option("--quiet", 'Suppress the "(using workspace \u2026)" stderr note').action(async (options) => {
|
|
155089
155553
|
const ctx = requireCommandContext({ workspaceFlag: options.workspace, quiet: options.quiet });
|
|
155090
155554
|
try {
|
|
155091
155555
|
const data = await sessionFetch(ctx, "/customers");
|
|
@@ -155095,48 +155559,48 @@ var customersCommand = new Command25("customers").description("List your custome
|
|
|
155095
155559
|
return;
|
|
155096
155560
|
}
|
|
155097
155561
|
if (customers.length === 0) {
|
|
155098
|
-
console.log(
|
|
155562
|
+
console.log(chalk23.dim("No customers found."));
|
|
155099
155563
|
return;
|
|
155100
155564
|
}
|
|
155101
155565
|
console.log();
|
|
155102
|
-
console.log(
|
|
155566
|
+
console.log(chalk23.bold(" Customers"));
|
|
155103
155567
|
console.log();
|
|
155104
|
-
const
|
|
155105
|
-
const header = `${
|
|
155106
|
-
console.log(` ${
|
|
155107
|
-
console.log(` ${
|
|
155568
|
+
const pad4 = (s, n) => s.padEnd(n).slice(0, n);
|
|
155569
|
+
const header = `${pad4("Email", 32)} ${pad4("Skills", 8)} ${pad4("Loads", 8)} ${pad4("Status", 10)} Last Active`;
|
|
155570
|
+
console.log(` ${chalk23.dim(header)}`);
|
|
155571
|
+
console.log(` ${chalk23.dim("\u2500".repeat(header.length))}`);
|
|
155108
155572
|
for (const c of customers) {
|
|
155109
|
-
const statusColor = c.status === "active" ?
|
|
155110
|
-
const lastActive = c.last_active_at ? new Date(c.last_active_at).toLocaleDateString() :
|
|
155573
|
+
const statusColor = c.status === "active" ? chalk23.green : chalk23.dim;
|
|
155574
|
+
const lastActive = c.last_active_at ? new Date(c.last_active_at).toLocaleDateString() : chalk23.dim("never");
|
|
155111
155575
|
const row = [
|
|
155112
|
-
|
|
155113
|
-
|
|
155114
|
-
|
|
155115
|
-
statusColor(
|
|
155576
|
+
pad4(c.email, 32),
|
|
155577
|
+
pad4(String(c.skills_count), 8),
|
|
155578
|
+
pad4(String(c.total_loads), 8),
|
|
155579
|
+
statusColor(pad4(c.status, 10)),
|
|
155116
155580
|
lastActive
|
|
155117
155581
|
].join(" ");
|
|
155118
155582
|
console.log(` ${row}`);
|
|
155119
155583
|
}
|
|
155120
155584
|
console.log();
|
|
155121
|
-
console.log(
|
|
155585
|
+
console.log(chalk23.dim(` ${customers.length} customer${customers.length !== 1 ? "s" : ""} total`));
|
|
155122
155586
|
console.log();
|
|
155123
155587
|
} catch (err) {
|
|
155124
155588
|
const message = err instanceof Error ? err.message : String(err);
|
|
155125
|
-
process.stderr.write(
|
|
155589
|
+
process.stderr.write(chalk23.red(`Error: ${message}
|
|
155126
155590
|
`));
|
|
155127
155591
|
process.exit(1);
|
|
155128
155592
|
}
|
|
155129
155593
|
});
|
|
155130
155594
|
|
|
155131
155595
|
// dist/commands/analytics.js
|
|
155132
|
-
import { Command as
|
|
155133
|
-
import
|
|
155134
|
-
var analyticsCommand = new
|
|
155596
|
+
import { Command as Command27 } from "commander";
|
|
155597
|
+
import chalk24 from "chalk";
|
|
155598
|
+
var analyticsCommand = new Command27("analytics").description("View publisher analytics").option("--days <n>", "Number of days to look back", "30").option("--skill <name>", "Filter top skills/stats to a specific skill").option("--json", "Output as JSON").option("--workspace <path>", "Use workspace at <path> to default --skill").option("--quiet", 'Suppress the "(using workspace \u2026)" stderr note').option("--all", "Disable workspace --skill default; show analytics for all skills").action(async (options) => {
|
|
155135
155599
|
const ctx = requireCommandContext({ workspaceFlag: options.workspace, quiet: options.quiet });
|
|
155136
155600
|
try {
|
|
155137
155601
|
const days = parseInt(options.days, 10);
|
|
155138
155602
|
if (isNaN(days) || days < 1) {
|
|
155139
|
-
process.stderr.write(
|
|
155603
|
+
process.stderr.write(chalk24.red("--days must be a positive number.\n"));
|
|
155140
155604
|
process.exit(1);
|
|
155141
155605
|
}
|
|
155142
155606
|
const end = /* @__PURE__ */ new Date();
|
|
@@ -155149,11 +155613,11 @@ var analyticsCommand = new Command26("analytics").description("View publisher an
|
|
|
155149
155613
|
return;
|
|
155150
155614
|
}
|
|
155151
155615
|
console.log();
|
|
155152
|
-
console.log(
|
|
155616
|
+
console.log(chalk24.bold(" Publisher Analytics"));
|
|
155153
155617
|
console.log();
|
|
155154
|
-
console.log(` ${
|
|
155155
|
-
console.log(` ${
|
|
155156
|
-
console.log(` ${
|
|
155618
|
+
console.log(` ${chalk24.bold("Active Licenses:")} ${data.active_licenses}`);
|
|
155619
|
+
console.log(` ${chalk24.bold("Total Decryptions:")} ${data.total_decryptions}`);
|
|
155620
|
+
console.log(` ${chalk24.bold("Period:")} Last ${days} day${days !== 1 ? "s" : ""} (${start.toLocaleDateString()} \u2013 ${end.toLocaleDateString()})`);
|
|
155157
155621
|
const effectiveSkill = options.skill ?? (options.all ? void 0 : ctx.defaultSkillName ?? void 0);
|
|
155158
155622
|
const filterSkill = (skillName) => !effectiveSkill || skillName.toLowerCase() === effectiveSkill.toLowerCase();
|
|
155159
155623
|
const statsMap = new Map((data.skill_stats || []).map((s) => [s.skill_name, s]));
|
|
@@ -155162,44 +155626,44 @@ var analyticsCommand = new Command26("analytics").description("View publisher an
|
|
|
155162
155626
|
}
|
|
155163
155627
|
if (data.top_skills && data.top_skills.length > 0) {
|
|
155164
155628
|
console.log();
|
|
155165
|
-
console.log(
|
|
155629
|
+
console.log(chalk24.bold(" Top Skills"));
|
|
155166
155630
|
console.log();
|
|
155167
|
-
const
|
|
155168
|
-
const header = `${
|
|
155169
|
-
console.log(` ${
|
|
155170
|
-
console.log(` ${
|
|
155631
|
+
const pad4 = (s, n) => s.padEnd(n).slice(0, n);
|
|
155632
|
+
const header = `${pad4("Skill", 28)} ${pad4("Decryptions", 14)} Active Licenses`;
|
|
155633
|
+
console.log(` ${chalk24.dim(header)}`);
|
|
155634
|
+
console.log(` ${chalk24.dim("\u2500".repeat(header.length))}`);
|
|
155171
155635
|
for (const skill of data.top_skills) {
|
|
155172
155636
|
const stats = statsMap.get(skill.name);
|
|
155173
155637
|
const row = [
|
|
155174
|
-
|
|
155175
|
-
|
|
155638
|
+
pad4(skill.name, 28),
|
|
155639
|
+
pad4(String(skill.decryptions), 14),
|
|
155176
155640
|
String(stats?.active_licenses ?? "-")
|
|
155177
155641
|
].join(" ");
|
|
155178
155642
|
console.log(` ${row}`);
|
|
155179
155643
|
}
|
|
155180
155644
|
} else {
|
|
155181
155645
|
console.log();
|
|
155182
|
-
console.log(
|
|
155646
|
+
console.log(chalk24.dim(" No skill activity in this period."));
|
|
155183
155647
|
}
|
|
155184
155648
|
console.log();
|
|
155185
155649
|
} catch (err) {
|
|
155186
155650
|
const message = err instanceof Error ? err.message : String(err);
|
|
155187
|
-
process.stderr.write(
|
|
155651
|
+
process.stderr.write(chalk24.red(`Error: ${message}
|
|
155188
155652
|
`));
|
|
155189
155653
|
process.exit(1);
|
|
155190
155654
|
}
|
|
155191
155655
|
});
|
|
155192
155656
|
|
|
155193
155657
|
// dist/commands/webhook.js
|
|
155194
|
-
import { Command as
|
|
155195
|
-
import
|
|
155196
|
-
var webhookCommand = new
|
|
155658
|
+
import { Command as Command28 } from "commander";
|
|
155659
|
+
import chalk25 from "chalk";
|
|
155660
|
+
var webhookCommand = new Command28("webhook").description("Manage publisher webhook (set, test, status)").argument("<action>", "Action: set, test, or status").option("--url <url>", "Webhook URL (required for set)").option("--json", "Output as JSON").action(async (action, options) => {
|
|
155197
155661
|
try {
|
|
155198
155662
|
const ctx = requireSession();
|
|
155199
155663
|
switch (action) {
|
|
155200
155664
|
case "set": {
|
|
155201
155665
|
if (!options.url) {
|
|
155202
|
-
process.stderr.write(
|
|
155666
|
+
process.stderr.write(chalk25.red("Missing --url option. Usage: skillvault-publisher webhook set --url <url>\n"));
|
|
155203
155667
|
process.exit(1);
|
|
155204
155668
|
}
|
|
155205
155669
|
const data = await sessionFetch(ctx, `/publishers/${ctx.publisherId}/webhook`, { method: "POST", body: { url: options.url } });
|
|
@@ -155208,12 +155672,12 @@ var webhookCommand = new Command27("webhook").description("Manage publisher webh
|
|
|
155208
155672
|
return;
|
|
155209
155673
|
}
|
|
155210
155674
|
console.log();
|
|
155211
|
-
console.log(
|
|
155675
|
+
console.log(chalk25.green(" Webhook configured"));
|
|
155212
155676
|
console.log();
|
|
155213
155677
|
console.log(` ${"URL:".padEnd(18)} ${data.webhook_url}`);
|
|
155214
|
-
console.log(` ${"Signing Secret:".padEnd(18)} ${
|
|
155678
|
+
console.log(` ${"Signing Secret:".padEnd(18)} ${chalk25.yellow(data.signing_secret)}`);
|
|
155215
155679
|
console.log();
|
|
155216
|
-
console.log(
|
|
155680
|
+
console.log(chalk25.dim(" Store the signing secret securely. It will not be shown again."));
|
|
155217
155681
|
console.log();
|
|
155218
155682
|
break;
|
|
155219
155683
|
}
|
|
@@ -155224,7 +155688,7 @@ var webhookCommand = new Command27("webhook").description("Manage publisher webh
|
|
|
155224
155688
|
return;
|
|
155225
155689
|
}
|
|
155226
155690
|
console.log();
|
|
155227
|
-
console.log(
|
|
155691
|
+
console.log(chalk25.green(" Test event sent to webhook URL"));
|
|
155228
155692
|
console.log();
|
|
155229
155693
|
break;
|
|
155230
155694
|
}
|
|
@@ -155236,36 +155700,36 @@ var webhookCommand = new Command27("webhook").description("Manage publisher webh
|
|
|
155236
155700
|
}
|
|
155237
155701
|
console.log();
|
|
155238
155702
|
if (data.webhook_url) {
|
|
155239
|
-
console.log(
|
|
155703
|
+
console.log(chalk25.bold(" Webhook Status"));
|
|
155240
155704
|
console.log();
|
|
155241
155705
|
console.log(` ${"URL:".padEnd(12)} ${data.webhook_url}`);
|
|
155242
|
-
console.log(` ${"Status:".padEnd(12)} ${
|
|
155706
|
+
console.log(` ${"Status:".padEnd(12)} ${chalk25.green("configured")}`);
|
|
155243
155707
|
} else {
|
|
155244
|
-
console.log(
|
|
155708
|
+
console.log(chalk25.dim(" No webhook configured."));
|
|
155245
155709
|
console.log();
|
|
155246
|
-
console.log(
|
|
155710
|
+
console.log(chalk25.dim(" Set one with: skillvault-publisher webhook set --url <url>"));
|
|
155247
155711
|
}
|
|
155248
155712
|
console.log();
|
|
155249
155713
|
break;
|
|
155250
155714
|
}
|
|
155251
155715
|
default:
|
|
155252
|
-
process.stderr.write(
|
|
155716
|
+
process.stderr.write(chalk25.red(`Unknown action: ${action}
|
|
155253
155717
|
`));
|
|
155254
|
-
process.stderr.write(
|
|
155718
|
+
process.stderr.write(chalk25.dim("Valid actions: set, test, status\n"));
|
|
155255
155719
|
process.exit(1);
|
|
155256
155720
|
}
|
|
155257
155721
|
} catch (err) {
|
|
155258
155722
|
const message = err instanceof Error ? err.message : String(err);
|
|
155259
|
-
process.stderr.write(
|
|
155723
|
+
process.stderr.write(chalk25.red(`Error: ${message}
|
|
155260
155724
|
`));
|
|
155261
155725
|
process.exit(1);
|
|
155262
155726
|
}
|
|
155263
155727
|
});
|
|
155264
155728
|
|
|
155265
155729
|
// dist/commands/audit.js
|
|
155266
|
-
import { Command as
|
|
155267
|
-
import
|
|
155268
|
-
var auditCommand = new
|
|
155730
|
+
import { Command as Command29 } from "commander";
|
|
155731
|
+
import chalk26 from "chalk";
|
|
155732
|
+
var auditCommand = new Command29("audit").description("View audit log events").option("--type <event_type>", "Filter by event type").option("--skill <name>", "Filter by capability/skill name").option("--since <date>", "Filter events since ISO date").option("--limit <n>", "Number of events to return", "20").option("--export <format>", "Export as csv or json").option("--json", "Output as JSON").option("--workspace <path>", "Use workspace at <path> to default --skill").option("--quiet", 'Suppress the "(using workspace \u2026)" stderr note').option("--all", "Disable workspace --skill default; show events for all skills").action(async (options) => {
|
|
155269
155733
|
try {
|
|
155270
155734
|
const ctx = requireCommandContext({ workspaceFlag: options.workspace, quiet: options.quiet });
|
|
155271
155735
|
const effectiveSkill = options.skill ?? (options.all ? void 0 : ctx.defaultSkillName ?? void 0);
|
|
@@ -155280,7 +155744,7 @@ var auditCommand = new Command28("audit").description("View audit log events").o
|
|
|
155280
155744
|
if (options.export) {
|
|
155281
155745
|
const format = options.export.toLowerCase();
|
|
155282
155746
|
if (format !== "csv" && format !== "json") {
|
|
155283
|
-
process.stderr.write(
|
|
155747
|
+
process.stderr.write(chalk26.red('Export format must be "csv" or "json".\n'));
|
|
155284
155748
|
process.exit(1);
|
|
155285
155749
|
}
|
|
155286
155750
|
params.set("format", format);
|
|
@@ -155299,68 +155763,68 @@ var auditCommand = new Command28("audit").description("View audit log events").o
|
|
|
155299
155763
|
return;
|
|
155300
155764
|
}
|
|
155301
155765
|
if (events.length === 0) {
|
|
155302
|
-
console.log(
|
|
155766
|
+
console.log(chalk26.dim("No audit events found."));
|
|
155303
155767
|
return;
|
|
155304
155768
|
}
|
|
155305
155769
|
console.log();
|
|
155306
|
-
console.log(
|
|
155770
|
+
console.log(chalk26.bold(" Audit Log"));
|
|
155307
155771
|
console.log();
|
|
155308
|
-
const
|
|
155309
|
-
const header = `${
|
|
155310
|
-
console.log(` ${
|
|
155311
|
-
console.log(` ${
|
|
155772
|
+
const pad4 = (s, n) => s.padEnd(n).slice(0, n);
|
|
155773
|
+
const header = `${pad4("Event Type", 22)} ${pad4("Skill", 24)} ${pad4("Agent", 20)} ${"Time"}`;
|
|
155774
|
+
console.log(` ${chalk26.dim(header)}`);
|
|
155775
|
+
console.log(` ${chalk26.dim("\u2500".repeat(header.length))}`);
|
|
155312
155776
|
for (const event of events) {
|
|
155313
155777
|
const skill = event.capability ? event.capability.replace(/^skill\//, "") : "-";
|
|
155314
155778
|
const agent = event.agent_id ? event.agent_id.slice(0, 18) : "-";
|
|
155315
155779
|
const time = new Date(event.created_at).toLocaleString();
|
|
155316
155780
|
const row = [
|
|
155317
|
-
|
|
155318
|
-
|
|
155319
|
-
|
|
155781
|
+
pad4(event.event_type, 22),
|
|
155782
|
+
pad4(skill, 24),
|
|
155783
|
+
pad4(agent, 20),
|
|
155320
155784
|
time
|
|
155321
155785
|
].join(" ");
|
|
155322
155786
|
console.log(` ${row}`);
|
|
155323
155787
|
}
|
|
155324
155788
|
console.log();
|
|
155325
|
-
console.log(
|
|
155789
|
+
console.log(chalk26.dim(` Showing ${events.length} event${events.length !== 1 ? "s" : ""}`));
|
|
155326
155790
|
if (data.has_more) {
|
|
155327
|
-
console.log(
|
|
155791
|
+
console.log(chalk26.dim(` More results available`));
|
|
155328
155792
|
}
|
|
155329
155793
|
console.log();
|
|
155330
155794
|
} catch (err) {
|
|
155331
155795
|
const message = err instanceof Error ? err.message : String(err);
|
|
155332
|
-
process.stderr.write(
|
|
155796
|
+
process.stderr.write(chalk26.red(`Error: ${message}
|
|
155333
155797
|
`));
|
|
155334
155798
|
process.exit(1);
|
|
155335
155799
|
}
|
|
155336
155800
|
});
|
|
155337
155801
|
|
|
155338
155802
|
// dist/commands/investigate.js
|
|
155339
|
-
import { Command as
|
|
155340
|
-
import
|
|
155341
|
-
import { readFileSync as readFileSync15, mkdirSync as mkdirSync9, writeFileSync as
|
|
155803
|
+
import { Command as Command30 } from "commander";
|
|
155804
|
+
import chalk27 from "chalk";
|
|
155805
|
+
import { readFileSync as readFileSync15, mkdirSync as mkdirSync9, writeFileSync as writeFileSync11 } from "node:fs";
|
|
155342
155806
|
import { join as join14 } from "node:path";
|
|
155343
|
-
var orange =
|
|
155807
|
+
var orange = chalk27.hex("#f97316");
|
|
155344
155808
|
function riskColor2(level) {
|
|
155345
155809
|
switch (level.toLowerCase()) {
|
|
155346
155810
|
case "low":
|
|
155347
|
-
return
|
|
155811
|
+
return chalk27.green;
|
|
155348
155812
|
case "watch":
|
|
155349
|
-
return
|
|
155813
|
+
return chalk27.yellow;
|
|
155350
155814
|
case "alert":
|
|
155351
155815
|
return orange;
|
|
155352
155816
|
case "critical":
|
|
155353
|
-
return
|
|
155817
|
+
return chalk27.red;
|
|
155354
155818
|
default:
|
|
155355
|
-
return
|
|
155819
|
+
return chalk27.white;
|
|
155356
155820
|
}
|
|
155357
155821
|
}
|
|
155358
155822
|
function confidenceColor(c) {
|
|
155359
155823
|
if (c >= 0.9)
|
|
155360
|
-
return
|
|
155824
|
+
return chalk27.green;
|
|
155361
155825
|
if (c >= 0.5)
|
|
155362
|
-
return
|
|
155363
|
-
return
|
|
155826
|
+
return chalk27.yellow;
|
|
155827
|
+
return chalk27.red;
|
|
155364
155828
|
}
|
|
155365
155829
|
function pad(s, n) {
|
|
155366
155830
|
return s.padEnd(n).slice(0, n);
|
|
@@ -155376,30 +155840,30 @@ function toRawGitHubUrl(url) {
|
|
|
155376
155840
|
}
|
|
155377
155841
|
function displayResults(report) {
|
|
155378
155842
|
console.log();
|
|
155379
|
-
console.log(
|
|
155843
|
+
console.log(chalk27.bold(" Investigation Results"));
|
|
155380
155844
|
console.log();
|
|
155381
|
-
console.log(` ${
|
|
155382
|
-
console.log(` ${
|
|
155383
|
-
console.log(` ${
|
|
155384
|
-
console.log(` ${
|
|
155845
|
+
console.log(` ${chalk27.bold("Investigation ID:")} ${report.investigation_id}`);
|
|
155846
|
+
console.log(` ${chalk27.bold("Skill:")} ${report.skill_name}`);
|
|
155847
|
+
console.log(` ${chalk27.bold("Total Licensees:")} ${report.total_licensees}`);
|
|
155848
|
+
console.log(` ${chalk27.bold("Timestamp:")} ${new Date(report.created_at).toLocaleString()}`);
|
|
155385
155849
|
if (report.heartbeat_matches.length > 0) {
|
|
155386
155850
|
console.log();
|
|
155387
155851
|
const maxConf = Math.max(...report.heartbeat_matches.map((m) => m.confidence));
|
|
155388
155852
|
const confStr = (maxConf * 100).toFixed(0) + "%";
|
|
155389
155853
|
const confFn = confidenceColor(maxConf);
|
|
155390
|
-
console.log(` ${
|
|
155854
|
+
console.log(` ${chalk27.bold("Forensic Match:")} ${confFn(confStr + " confidence")} (${report.heartbeat_matches.length} match${report.heartbeat_matches.length !== 1 ? "es" : ""})`);
|
|
155391
155855
|
}
|
|
155392
155856
|
console.log();
|
|
155393
155857
|
if (report.suspects.length === 0) {
|
|
155394
|
-
console.log(
|
|
155858
|
+
console.log(chalk27.dim(" No suspects identified."));
|
|
155395
155859
|
console.log();
|
|
155396
155860
|
return;
|
|
155397
155861
|
}
|
|
155398
|
-
console.log(
|
|
155862
|
+
console.log(chalk27.bold(" Suspect Ranking"));
|
|
155399
155863
|
console.log();
|
|
155400
155864
|
const header = `${pad("Suspect", 24)} ${pad("Risk Level", 12)} ${pad("Confidence", 12)} ${pad("Anomalies", 10)} ${"Strikes"}`;
|
|
155401
|
-
console.log(` ${
|
|
155402
|
-
console.log(` ${
|
|
155865
|
+
console.log(` ${chalk27.dim(header)}`);
|
|
155866
|
+
console.log(` ${chalk27.dim("\u2500".repeat(header.length))}`);
|
|
155403
155867
|
for (const s of report.suspects) {
|
|
155404
155868
|
const colorFn = riskColor2(s.risk_level);
|
|
155405
155869
|
const label = s.customer_email || s.licensee_id.slice(0, 22);
|
|
@@ -155413,8 +155877,8 @@ function displayResults(report) {
|
|
|
155413
155877
|
console.log(` ${row}`);
|
|
155414
155878
|
}
|
|
155415
155879
|
console.log();
|
|
155416
|
-
console.log(
|
|
155417
|
-
console.log(
|
|
155880
|
+
console.log(chalk27.dim(` Full evidence retained server-side (ID: ${report.investigation_id})`));
|
|
155881
|
+
console.log(chalk27.dim(" Contact investigations@getskillvault.com for the complete evidence package."));
|
|
155418
155882
|
console.log();
|
|
155419
155883
|
}
|
|
155420
155884
|
function buildHtmlReport(report, _auditEvents, metadata) {
|
|
@@ -155659,7 +156123,7 @@ ${report.suspects.length > 0 ? `<table>
|
|
|
155659
156123
|
</body>
|
|
155660
156124
|
</html>`;
|
|
155661
156125
|
}
|
|
155662
|
-
var investigateCommand = new
|
|
156126
|
+
var investigateCommand = new Command30("investigate").description("Investigate a suspected skill leak").argument("<skill-name>", "Name of the skill to investigate").option("--url <url>", "Fetch leaked content from a URL (GitHub raw, gist, etc.)").option("--file <path>", "Read leaked content from a local file").option("--report <dir>", "Generate full investigation report package to directory").option("--json", "Output as JSON").action(async (skillName, options) => {
|
|
155663
156127
|
try {
|
|
155664
156128
|
const ctx = requireSession();
|
|
155665
156129
|
let leakedContent;
|
|
@@ -155667,12 +156131,12 @@ var investigateCommand = new Command29("investigate").description("Investigate a
|
|
|
155667
156131
|
if (options.url) {
|
|
155668
156132
|
const rawUrl = toRawGitHubUrl(options.url);
|
|
155669
156133
|
if (rawUrl !== options.url) {
|
|
155670
|
-
console.log(
|
|
156134
|
+
console.log(chalk27.dim(` Auto-converted GitHub blob URL to raw URL`));
|
|
155671
156135
|
}
|
|
155672
|
-
console.log(
|
|
156136
|
+
console.log(chalk27.dim(` Fetching leaked content from ${rawUrl}...`));
|
|
155673
156137
|
const resp = await fetch(rawUrl);
|
|
155674
156138
|
if (!resp.ok) {
|
|
155675
|
-
process.stderr.write(
|
|
156139
|
+
process.stderr.write(chalk27.red(`Failed to fetch URL: ${resp.status} ${resp.statusText}
|
|
155676
156140
|
`));
|
|
155677
156141
|
process.exit(1);
|
|
155678
156142
|
}
|
|
@@ -155683,24 +156147,24 @@ var investigateCommand = new Command29("investigate").description("Investigate a
|
|
|
155683
156147
|
leakedContent = readFileSync15(options.file, "utf-8");
|
|
155684
156148
|
} catch (err) {
|
|
155685
156149
|
const msg = err instanceof Error ? err.message : String(err);
|
|
155686
|
-
process.stderr.write(
|
|
156150
|
+
process.stderr.write(chalk27.red(`Failed to read file: ${msg}
|
|
155687
156151
|
`));
|
|
155688
156152
|
process.exit(1);
|
|
155689
156153
|
}
|
|
155690
156154
|
sourceLabel = options.file;
|
|
155691
156155
|
} else {
|
|
155692
|
-
process.stderr.write(
|
|
156156
|
+
process.stderr.write(chalk27.red("Provide leaked content with --url <url> or --file <path>.\n"));
|
|
155693
156157
|
process.exit(1);
|
|
155694
156158
|
}
|
|
155695
|
-
console.log(
|
|
156159
|
+
console.log(chalk27.dim(` Loaded ${leakedContent.length.toLocaleString()} chars of leaked content`));
|
|
155696
156160
|
const skillsData = await sessionFetch(ctx, "/skills");
|
|
155697
156161
|
const skill = skillsData.skills.find((s) => s.name.toLowerCase() === skillName.toLowerCase());
|
|
155698
156162
|
if (!skill) {
|
|
155699
|
-
process.stderr.write(
|
|
156163
|
+
process.stderr.write(chalk27.red(`Skill "${skillName}" not found. Use \`skillvault-publisher list\` to see your skills.
|
|
155700
156164
|
`));
|
|
155701
156165
|
process.exit(1);
|
|
155702
156166
|
}
|
|
155703
|
-
console.log(
|
|
156167
|
+
console.log(chalk27.dim(` Running investigation on "${skill.name}"...`));
|
|
155704
156168
|
const report = await sessionFetch(ctx, `/publishers/${ctx.publisherId}/investigate`, {
|
|
155705
156169
|
method: "POST",
|
|
155706
156170
|
body: { skill_id: skill.id, leaked_content: leakedContent }
|
|
@@ -155726,13 +156190,13 @@ var investigateCommand = new Command29("investigate").description("Investigate a
|
|
|
155726
156190
|
source: sourceLabel,
|
|
155727
156191
|
notice: "This is an executive summary. Full evidence is retained server-side. Contact investigations@getskillvault.com for the complete evidence package."
|
|
155728
156192
|
};
|
|
155729
|
-
|
|
155730
|
-
|
|
156193
|
+
writeFileSync11(join14(dir, "metadata.json"), JSON.stringify(metadata, null, 2) + "\n");
|
|
156194
|
+
writeFileSync11(join14(dir, "summary.json"), JSON.stringify({
|
|
155731
156195
|
_generated_by: "SkillVault (https://getskillvault.com)",
|
|
155732
156196
|
...report
|
|
155733
156197
|
}, null, 2) + "\n");
|
|
155734
156198
|
const html = buildHtmlReport(report, [], metadata);
|
|
155735
|
-
|
|
156199
|
+
writeFileSync11(join14(dir, "report.html"), html);
|
|
155736
156200
|
const pdfPath = join14(dir, "report.pdf");
|
|
155737
156201
|
const { generatePdfReport: generatePdfReport2 } = await Promise.resolve().then(() => (init_pdf_report(), pdf_report_exports));
|
|
155738
156202
|
await generatePdfReport2({
|
|
@@ -155746,23 +156210,23 @@ var investigateCommand = new Command29("investigate").description("Investigate a
|
|
|
155746
156210
|
heartbeat_matches: report.heartbeat_matches,
|
|
155747
156211
|
audit_events: []
|
|
155748
156212
|
}, pdfPath);
|
|
155749
|
-
console.log(
|
|
155750
|
-
console.log(
|
|
155751
|
-
console.log(
|
|
156213
|
+
console.log(chalk27.green(` Report saved to ${dir}/`) + chalk27.dim(" (4 files)"));
|
|
156214
|
+
console.log(chalk27.dim(` PDF: report.pdf`));
|
|
156215
|
+
console.log(chalk27.dim(` Full evidence retained server-side (ID: ${report.investigation_id})`));
|
|
155752
156216
|
console.log();
|
|
155753
156217
|
}
|
|
155754
156218
|
} catch (err) {
|
|
155755
156219
|
const message = err instanceof Error ? err.message : String(err);
|
|
155756
|
-
process.stderr.write(
|
|
156220
|
+
process.stderr.write(chalk27.red(`Error: ${message}
|
|
155757
156221
|
`));
|
|
155758
156222
|
process.exit(1);
|
|
155759
156223
|
}
|
|
155760
156224
|
});
|
|
155761
156225
|
|
|
155762
156226
|
// dist/commands/watchtower.js
|
|
155763
|
-
import { Command as
|
|
155764
|
-
import
|
|
155765
|
-
var watchtowerCommand = new
|
|
156227
|
+
import { Command as Command31 } from "commander";
|
|
156228
|
+
import chalk28 from "chalk";
|
|
156229
|
+
var watchtowerCommand = new Command31("watchtower").description("Watchtower security dashboard").option("--json", "Output as JSON").option("--workspace <path>", "Resolve workspace context (defaults from CWD)").option("--quiet", 'Suppress the "(using workspace \u2026)" stderr note').action(async (options) => {
|
|
155766
156230
|
const ctx = requireCommandContext({ workspaceFlag: options.workspace, quiet: options.quiet });
|
|
155767
156231
|
try {
|
|
155768
156232
|
const data = await sessionFetch(ctx, `/publishers/${ctx.publisherId}/watchtower`);
|
|
@@ -155771,37 +156235,37 @@ var watchtowerCommand = new Command30("watchtower").description("Watchtower secu
|
|
|
155771
156235
|
return;
|
|
155772
156236
|
}
|
|
155773
156237
|
const { summary } = data;
|
|
155774
|
-
const
|
|
156238
|
+
const pad4 = (s, n) => s.padEnd(n).slice(0, n);
|
|
155775
156239
|
console.log();
|
|
155776
|
-
console.log(
|
|
156240
|
+
console.log(chalk28.bold(" Watchtower \u2014 Security Overview"));
|
|
155777
156241
|
console.log();
|
|
155778
|
-
console.log(` ${
|
|
156242
|
+
console.log(` ${chalk28.bold("Skills")} ${summary.total_skills} ${chalk28.dim("|")} ${chalk28.bold("Licenses")} ${summary.total_licenses} ${chalk28.dim("|")} ${chalk28.bold("Alerts (7d)")} ${summary.active_alerts > 0 ? chalk28.yellow(String(summary.active_alerts)) : "0"} ${chalk28.dim("|")} ${chalk28.bold("Flagged")} ${summary.flagged_customers > 0 ? chalk28.red(String(summary.flagged_customers)) : "0"} ${chalk28.dim("|")} ${chalk28.bold("Suspended")} ${summary.suspended_grants > 0 ? chalk28.red(String(summary.suspended_grants)) : "0"}`);
|
|
155779
156243
|
if (data.flagged_customers && data.flagged_customers.length > 0) {
|
|
155780
156244
|
console.log();
|
|
155781
|
-
console.log(
|
|
156245
|
+
console.log(chalk28.bold(" Flagged Customers"));
|
|
155782
156246
|
console.log();
|
|
155783
|
-
const header = `${
|
|
155784
|
-
console.log(` ${
|
|
155785
|
-
console.log(` ${
|
|
156247
|
+
const header = `${pad4("Agent ID", 20)} ${pad4("Risk Score", 12)} ${pad4("Level", 10)} ${pad4("Strikes", 9)} ${pad4("Status", 12)} Skills`;
|
|
156248
|
+
console.log(` ${chalk28.dim(header)}`);
|
|
156249
|
+
console.log(` ${chalk28.dim("\u2500".repeat(header.length))}`);
|
|
155786
156250
|
for (const c of data.flagged_customers) {
|
|
155787
156251
|
const agentShort = c.agent_id.length > 18 ? c.agent_id.slice(0, 18) + "\u2026" : c.agent_id;
|
|
155788
156252
|
let levelColored;
|
|
155789
156253
|
if (c.risk_level === "critical") {
|
|
155790
|
-
levelColored =
|
|
156254
|
+
levelColored = chalk28.red.bold(pad4(c.risk_level, 10));
|
|
155791
156255
|
} else if (c.risk_level === "high") {
|
|
155792
|
-
levelColored =
|
|
156256
|
+
levelColored = chalk28.red(pad4(c.risk_level, 10));
|
|
155793
156257
|
} else if (c.risk_level === "medium") {
|
|
155794
|
-
levelColored =
|
|
156258
|
+
levelColored = chalk28.yellow(pad4(c.risk_level, 10));
|
|
155795
156259
|
} else {
|
|
155796
|
-
levelColored =
|
|
156260
|
+
levelColored = chalk28.dim(pad4(c.risk_level, 10));
|
|
155797
156261
|
}
|
|
155798
|
-
const statusColored = c.status === "suspended" ?
|
|
155799
|
-
const skills = c.capabilities.length > 0 ? c.capabilities.join(", ") :
|
|
156262
|
+
const statusColored = c.status === "suspended" ? chalk28.red(pad4(c.status, 12)) : pad4(c.status, 12);
|
|
156263
|
+
const skills = c.capabilities.length > 0 ? c.capabilities.join(", ") : chalk28.dim("none");
|
|
155800
156264
|
const row = [
|
|
155801
|
-
|
|
155802
|
-
|
|
156265
|
+
pad4(agentShort, 20),
|
|
156266
|
+
pad4(String(c.risk_score), 12),
|
|
155803
156267
|
levelColored,
|
|
155804
|
-
|
|
156268
|
+
pad4(String(c.strike_count), 9),
|
|
155805
156269
|
statusColored,
|
|
155806
156270
|
skills
|
|
155807
156271
|
].join(" ");
|
|
@@ -155810,20 +156274,20 @@ var watchtowerCommand = new Command30("watchtower").description("Watchtower secu
|
|
|
155810
156274
|
}
|
|
155811
156275
|
if (data.recent_events && data.recent_events.length > 0) {
|
|
155812
156276
|
console.log();
|
|
155813
|
-
console.log(
|
|
156277
|
+
console.log(chalk28.bold(" Recent Security Events"));
|
|
155814
156278
|
console.log();
|
|
155815
|
-
const header = `${
|
|
155816
|
-
console.log(` ${
|
|
155817
|
-
console.log(` ${
|
|
156279
|
+
const header = `${pad4("Event Type", 28)} ${pad4("Skill", 24)} ${pad4("Agent", 20)} Time`;
|
|
156280
|
+
console.log(` ${chalk28.dim(header)}`);
|
|
156281
|
+
console.log(` ${chalk28.dim("\u2500".repeat(header.length))}`);
|
|
155818
156282
|
const events = data.recent_events.slice(0, 10);
|
|
155819
156283
|
for (const e of events) {
|
|
155820
|
-
const skill = e.capability ? e.capability.replace(/^skill\//, "") :
|
|
155821
|
-
const agent = e.agent_id ? e.agent_id.slice(0, 18) :
|
|
156284
|
+
const skill = e.capability ? e.capability.replace(/^skill\//, "") : chalk28.dim("-");
|
|
156285
|
+
const agent = e.agent_id ? e.agent_id.slice(0, 18) : chalk28.dim("-");
|
|
155822
156286
|
const time = new Date(e.created_at).toLocaleString();
|
|
155823
156287
|
const row = [
|
|
155824
|
-
|
|
155825
|
-
|
|
155826
|
-
|
|
156288
|
+
pad4(e.event_type, 28),
|
|
156289
|
+
pad4(skill, 24),
|
|
156290
|
+
pad4(agent, 20),
|
|
155827
156291
|
time
|
|
155828
156292
|
].join(" ");
|
|
155829
156293
|
console.log(` ${row}`);
|
|
@@ -155831,25 +156295,25 @@ var watchtowerCommand = new Command30("watchtower").description("Watchtower secu
|
|
|
155831
156295
|
}
|
|
155832
156296
|
if ((!data.flagged_customers || data.flagged_customers.length === 0) && (!data.recent_events || data.recent_events.length === 0)) {
|
|
155833
156297
|
console.log();
|
|
155834
|
-
console.log(
|
|
156298
|
+
console.log(chalk28.green(" All clear \u2014 no security alerts in the last 7 days."));
|
|
155835
156299
|
}
|
|
155836
156300
|
console.log();
|
|
155837
156301
|
} catch (err) {
|
|
155838
156302
|
const message = err instanceof Error ? err.message : String(err);
|
|
155839
|
-
process.stderr.write(
|
|
156303
|
+
process.stderr.write(chalk28.red(`Error: ${message}
|
|
155840
156304
|
`));
|
|
155841
156305
|
process.exit(1);
|
|
155842
156306
|
}
|
|
155843
156307
|
});
|
|
155844
156308
|
|
|
155845
156309
|
// dist/commands/watermark-decode.js
|
|
155846
|
-
import { Command as
|
|
155847
|
-
import
|
|
156310
|
+
import { Command as Command32 } from "commander";
|
|
156311
|
+
import chalk29 from "chalk";
|
|
155848
156312
|
import { readFileSync as readFileSync16 } from "node:fs";
|
|
155849
|
-
var watermarkDecodeCommand = new
|
|
156313
|
+
var watermarkDecodeCommand = new Command32("watermark-decode").description("Analyze leaked content for forensic watermarks (local-only)").option("--file <path>", "Path to file with leaked content").option("--json", "Output as JSON").action(async (options) => {
|
|
155850
156314
|
try {
|
|
155851
156315
|
if (!options.file) {
|
|
155852
|
-
process.stderr.write(
|
|
156316
|
+
process.stderr.write(chalk29.red("Provide --file <path> with the leaked content\n"));
|
|
155853
156317
|
process.exit(1);
|
|
155854
156318
|
}
|
|
155855
156319
|
let content;
|
|
@@ -155857,7 +156321,7 @@ var watermarkDecodeCommand = new Command31("watermark-decode").description("Anal
|
|
|
155857
156321
|
content = readFileSync16(options.file, "utf8");
|
|
155858
156322
|
} catch (err) {
|
|
155859
156323
|
const msg = err instanceof Error ? err.message : String(err);
|
|
155860
|
-
process.stderr.write(
|
|
156324
|
+
process.stderr.write(chalk29.red(`Cannot read file: ${msg}
|
|
155861
156325
|
`));
|
|
155862
156326
|
process.exit(1);
|
|
155863
156327
|
}
|
|
@@ -155887,56 +156351,56 @@ var watermarkDecodeCommand = new Command31("watermark-decode").description("Anal
|
|
|
155887
156351
|
return;
|
|
155888
156352
|
}
|
|
155889
156353
|
console.log();
|
|
155890
|
-
console.log(
|
|
156354
|
+
console.log(chalk29.bold(" Watermark Analysis"));
|
|
155891
156355
|
console.log();
|
|
155892
|
-
console.log(
|
|
156356
|
+
console.log(chalk29.bold(" Zero-Width Watermark"));
|
|
155893
156357
|
if (watermark.found) {
|
|
155894
|
-
console.log(` Licensee ID: ${
|
|
156358
|
+
console.log(` Licensee ID: ${chalk29.green.bold(watermark.licenseeId)}`);
|
|
155895
156359
|
} else {
|
|
155896
|
-
console.log(` ${
|
|
156360
|
+
console.log(` ${chalk29.dim("Not found")}`);
|
|
155897
156361
|
}
|
|
155898
156362
|
console.log();
|
|
155899
|
-
console.log(
|
|
156363
|
+
console.log(chalk29.bold(" Heartbeat Markers"));
|
|
155900
156364
|
if (heartbeats.hb1) {
|
|
155901
|
-
console.log(` HB1: ${
|
|
156365
|
+
console.log(` HB1: ${chalk29.green(heartbeats.hb1)}`);
|
|
155902
156366
|
} else {
|
|
155903
|
-
console.log(` HB1: ${
|
|
156367
|
+
console.log(` HB1: ${chalk29.dim("Not found")}`);
|
|
155904
156368
|
}
|
|
155905
156369
|
if (heartbeats.hb2) {
|
|
155906
|
-
console.log(` HB2: ${
|
|
156370
|
+
console.log(` HB2: ${chalk29.green(heartbeats.hb2)}`);
|
|
155907
156371
|
} else {
|
|
155908
|
-
console.log(` HB2: ${
|
|
156372
|
+
console.log(` HB2: ${chalk29.dim("Not found")}`);
|
|
155909
156373
|
}
|
|
155910
156374
|
if (candidates.length > 0) {
|
|
155911
|
-
console.log(` ${
|
|
156375
|
+
console.log(` ${chalk29.dim(`${candidates.length} potential heartbeat candidate${candidates.length !== 1 ? "s" : ""} found`)}`);
|
|
155912
156376
|
}
|
|
155913
156377
|
console.log();
|
|
155914
|
-
console.log(
|
|
156378
|
+
console.log(chalk29.bold(" Semantic Fingerprint"));
|
|
155915
156379
|
if (hasFingerprint) {
|
|
155916
156380
|
const binaryStr = fingerprint.map((v) => v === 1 ? "1" : v === -1 ? "X" : "0").join("");
|
|
155917
156381
|
const variationPoints = fingerprint.filter((v) => v !== 0).length;
|
|
155918
|
-
console.log(` Pattern: ${
|
|
155919
|
-
console.log(` ${
|
|
156382
|
+
console.log(` Pattern: ${chalk29.cyan(binaryStr)}`);
|
|
156383
|
+
console.log(` ${chalk29.dim(`${variationPoints} variation point${variationPoints !== 1 ? "s" : ""} detected`)}`);
|
|
155920
156384
|
} else {
|
|
155921
|
-
console.log(` ${
|
|
156385
|
+
console.log(` ${chalk29.dim("No variation points detected")}`);
|
|
155922
156386
|
}
|
|
155923
156387
|
console.log();
|
|
155924
|
-
const countColor = signalsDetected > 0 ?
|
|
156388
|
+
const countColor = signalsDetected > 0 ? chalk29.green.bold : chalk29.dim;
|
|
155925
156389
|
console.log(` ${countColor(`${signalsDetected} of 4`)} forensic signals detected`);
|
|
155926
156390
|
console.log();
|
|
155927
156391
|
} catch (err) {
|
|
155928
156392
|
const message = err instanceof Error ? err.message : String(err);
|
|
155929
|
-
process.stderr.write(
|
|
156393
|
+
process.stderr.write(chalk29.red(`Error: ${message}
|
|
155930
156394
|
`));
|
|
155931
156395
|
process.exit(1);
|
|
155932
156396
|
}
|
|
155933
156397
|
});
|
|
155934
156398
|
|
|
155935
156399
|
// dist/commands/link.js
|
|
155936
|
-
import { Command as
|
|
155937
|
-
import
|
|
156400
|
+
import { Command as Command33 } from "commander";
|
|
156401
|
+
import chalk30 from "chalk";
|
|
155938
156402
|
import { existsSync as existsSync14, readFileSync as readFileSync17, statSync as statSync6 } from "node:fs";
|
|
155939
|
-
import { resolve as
|
|
156403
|
+
import { resolve as resolve10, join as join15 } from "node:path";
|
|
155940
156404
|
function parseFrontmatter4(content) {
|
|
155941
156405
|
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
155942
156406
|
if (!match)
|
|
@@ -155955,12 +156419,12 @@ function parseFrontmatter4(content) {
|
|
|
155955
156419
|
}
|
|
155956
156420
|
return result;
|
|
155957
156421
|
}
|
|
155958
|
-
var linkCommand = new
|
|
156422
|
+
var linkCommand = new Command33("link").description("Link a skill source directory to your publisher account").argument("[directory]", "Skill directory to link (defaults to CWD)").option("--workspace <path>", "Explicit workspace directory (precedence over positional)").option("--force", "Overwrite an existing link to a different publisher_id").option("--name <name>", "Override skill name (defaults to SKILL.md frontmatter name)").option("--capability <cap>", "Override capability_name (advanced \u2014 usually matches skill name)").action(async (directory, options) => {
|
|
155959
156423
|
try {
|
|
155960
156424
|
const ctx = requireSession();
|
|
155961
|
-
const dirPath = options.workspace ?
|
|
156425
|
+
const dirPath = options.workspace ? resolve10(options.workspace) : directory ? resolve10(directory) : process.cwd();
|
|
155962
156426
|
if (!existsSync14(dirPath) || !statSync6(dirPath).isDirectory()) {
|
|
155963
|
-
process.stderr.write(
|
|
156427
|
+
process.stderr.write(chalk30.red(`Error: "${dirPath}" is not a valid directory
|
|
155964
156428
|
`));
|
|
155965
156429
|
process.exit(1);
|
|
155966
156430
|
}
|
|
@@ -155970,17 +156434,17 @@ var linkCommand = new Command32("link").description("Link a skill source directo
|
|
|
155970
156434
|
const existing = loadWorkspace(dirPath);
|
|
155971
156435
|
const skillName = options.name || existing?.skill_name || frontmatter.name;
|
|
155972
156436
|
if (!skillName) {
|
|
155973
|
-
process.stderr.write(
|
|
155974
|
-
process.stderr.write(
|
|
156437
|
+
process.stderr.write(chalk30.red("Error: Cannot determine skill name.\n"));
|
|
156438
|
+
process.stderr.write(chalk30.dim(" Pass --name <name> or set `name:` in SKILL.md frontmatter.\n"));
|
|
155975
156439
|
process.exit(1);
|
|
155976
156440
|
}
|
|
155977
156441
|
const capabilityName = options.capability || existing?.capability_name || `skill/${skillName.toLowerCase()}`;
|
|
155978
156442
|
if (existing && existing.publisher_id !== ctx.publisherId && !options.force) {
|
|
155979
|
-
process.stderr.write(
|
|
156443
|
+
process.stderr.write(chalk30.red(`Error: This directory is already linked to publisher ${existing.publisher_id}.
|
|
155980
156444
|
`));
|
|
155981
|
-
process.stderr.write(
|
|
156445
|
+
process.stderr.write(chalk30.dim(` You are logged in as ${ctx.publisherId}.
|
|
155982
156446
|
`));
|
|
155983
|
-
process.stderr.write(
|
|
156447
|
+
process.stderr.write(chalk30.cyan(" Use --force to re-link to your account.\n"));
|
|
155984
156448
|
process.exit(1);
|
|
155985
156449
|
}
|
|
155986
156450
|
const linkedAt = existing?.linked_at ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -156002,41 +156466,41 @@ var linkCommand = new Command32("link").description("Link a skill source directo
|
|
|
156002
156466
|
last_published_at: manifest.last_published_at
|
|
156003
156467
|
});
|
|
156004
156468
|
const action = existing ? "Re-linked" : "Linked";
|
|
156005
|
-
console.log(
|
|
156006
|
-
console.log(
|
|
156007
|
-
console.log(
|
|
156008
|
-
console.log(
|
|
156469
|
+
console.log(chalk30.green(`${action} "${skillName}" \u2192 ${capabilityName}`));
|
|
156470
|
+
console.log(chalk30.dim(` Directory: ${dirPath}`));
|
|
156471
|
+
console.log(chalk30.dim(` Publisher: ${ctx.publisherId}`));
|
|
156472
|
+
console.log(chalk30.dim(` Manifest: .skillvault-publisher/workspace.json`));
|
|
156009
156473
|
if (!existing) {
|
|
156010
156474
|
console.log();
|
|
156011
|
-
console.log(
|
|
156475
|
+
console.log(chalk30.cyan(" Tip: commit .skillvault-publisher/workspace.json so teammates and CI can find this skill."));
|
|
156012
156476
|
}
|
|
156013
156477
|
} catch (err) {
|
|
156014
156478
|
const message = err instanceof Error ? err.message : String(err);
|
|
156015
|
-
process.stderr.write(
|
|
156479
|
+
process.stderr.write(chalk30.red(`Link failed: ${message}
|
|
156016
156480
|
`));
|
|
156017
156481
|
process.exit(1);
|
|
156018
156482
|
}
|
|
156019
156483
|
});
|
|
156020
156484
|
|
|
156021
156485
|
// dist/commands/unlink.js
|
|
156022
|
-
import { Command as
|
|
156023
|
-
import
|
|
156486
|
+
import { Command as Command34 } from "commander";
|
|
156487
|
+
import chalk31 from "chalk";
|
|
156024
156488
|
import { existsSync as existsSync15, rmSync as rmSync2, statSync as statSync7 } from "node:fs";
|
|
156025
|
-
import { resolve as
|
|
156026
|
-
var unlinkCommand = new
|
|
156489
|
+
import { resolve as resolve11, join as join16 } from "node:path";
|
|
156490
|
+
var unlinkCommand = new Command34("unlink").description("Remove the workspace link from a skill source directory").argument("[directory]", "Skill directory to unlink (defaults to CWD)").option("--workspace <path>", "Explicit workspace directory (precedence over positional)").option("--keep-registry", "Remove the manifest file but leave the registry entry").action(async (directory, options) => {
|
|
156027
156491
|
try {
|
|
156028
|
-
const dirPath = options.workspace ?
|
|
156492
|
+
const dirPath = options.workspace ? resolve11(options.workspace) : directory ? resolve11(directory) : process.cwd();
|
|
156029
156493
|
if (!existsSync15(dirPath) || !statSync7(dirPath).isDirectory()) {
|
|
156030
|
-
process.stderr.write(
|
|
156494
|
+
process.stderr.write(chalk31.red(`Error: "${dirPath}" is not a valid directory
|
|
156031
156495
|
`));
|
|
156032
156496
|
process.exit(1);
|
|
156033
156497
|
}
|
|
156034
156498
|
const manifest = loadWorkspace(dirPath);
|
|
156035
156499
|
if (!manifest) {
|
|
156036
|
-
process.stderr.write(
|
|
156037
|
-
process.stderr.write(
|
|
156500
|
+
process.stderr.write(chalk31.red("Error: No workspace manifest found at this directory.\n"));
|
|
156501
|
+
process.stderr.write(chalk31.dim(` Looked for: ${join16(dirPath, ".skillvault-publisher", "workspace.json")}
|
|
156038
156502
|
`));
|
|
156039
|
-
process.stderr.write(
|
|
156503
|
+
process.stderr.write(chalk31.dim(" Run `skillvault-publisher link` first to create one.\n"));
|
|
156040
156504
|
process.exit(1);
|
|
156041
156505
|
}
|
|
156042
156506
|
const { manifestPath } = workspaceRootsFor(dirPath);
|
|
@@ -156044,7 +156508,7 @@ var unlinkCommand = new Command33("unlink").description("Remove the workspace li
|
|
|
156044
156508
|
rmSync2(manifestPath);
|
|
156045
156509
|
} catch (err) {
|
|
156046
156510
|
const message = err instanceof Error ? err.message : String(err);
|
|
156047
|
-
process.stderr.write(
|
|
156511
|
+
process.stderr.write(chalk31.red(`Failed to remove manifest: ${message}
|
|
156048
156512
|
`));
|
|
156049
156513
|
process.exit(1);
|
|
156050
156514
|
}
|
|
@@ -156056,25 +156520,25 @@ var unlinkCommand = new Command33("unlink").description("Remove the workspace li
|
|
|
156056
156520
|
if (!options.keepRegistry) {
|
|
156057
156521
|
unregisterWorkspace(dirPath);
|
|
156058
156522
|
}
|
|
156059
|
-
console.log(
|
|
156060
|
-
console.log(
|
|
156523
|
+
console.log(chalk31.green(`Unlinked "${manifest.skill_name}" (${manifest.capability_name})`));
|
|
156524
|
+
console.log(chalk31.dim(` Directory: ${dirPath}`));
|
|
156061
156525
|
if (options.keepRegistry) {
|
|
156062
|
-
console.log(
|
|
156526
|
+
console.log(chalk31.dim(" Registry entry kept (--keep-registry)"));
|
|
156063
156527
|
}
|
|
156064
156528
|
console.log();
|
|
156065
|
-
console.log(
|
|
156066
|
-
console.log(
|
|
156529
|
+
console.log(chalk31.dim(" Note: SKILL.md and source files are untouched."));
|
|
156530
|
+
console.log(chalk31.dim(" Note: The skill on the server is NOT deleted. Use `skill-delete` for that."));
|
|
156067
156531
|
} catch (err) {
|
|
156068
156532
|
const message = err instanceof Error ? err.message : String(err);
|
|
156069
|
-
process.stderr.write(
|
|
156533
|
+
process.stderr.write(chalk31.red(`Unlink failed: ${message}
|
|
156070
156534
|
`));
|
|
156071
156535
|
process.exit(1);
|
|
156072
156536
|
}
|
|
156073
156537
|
});
|
|
156074
156538
|
|
|
156075
156539
|
// dist/commands/workspaces.js
|
|
156076
|
-
import { Command as
|
|
156077
|
-
import
|
|
156540
|
+
import { Command as Command35 } from "commander";
|
|
156541
|
+
import chalk32 from "chalk";
|
|
156078
156542
|
function formatDate(iso) {
|
|
156079
156543
|
if (!iso)
|
|
156080
156544
|
return "-";
|
|
@@ -156109,8 +156573,8 @@ function listAction(options) {
|
|
|
156109
156573
|
return;
|
|
156110
156574
|
}
|
|
156111
156575
|
if (filtered.length === 0) {
|
|
156112
|
-
console.log(
|
|
156113
|
-
console.log(
|
|
156576
|
+
console.log(chalk32.dim("No workspaces linked."));
|
|
156577
|
+
console.log(chalk32.dim(" Run `skillvault-publisher link` from a skill source directory to create one."));
|
|
156114
156578
|
return;
|
|
156115
156579
|
}
|
|
156116
156580
|
const pathWidth = Math.min(Math.max(20, ...filtered.map((w) => w.path.length)), 50);
|
|
@@ -156118,27 +156582,27 @@ function listAction(options) {
|
|
|
156118
156582
|
const pubWidth = Math.max(10, ...filtered.map((w) => w.publisher_id.length));
|
|
156119
156583
|
console.log();
|
|
156120
156584
|
const header = `${pad2("PATH", pathWidth)} ${pad2("PUBLISHER", pubWidth)} ${pad2("SKILL", skillWidth)} ${pad2("VERSION", 10)} ${pad2("LAST PUBLISHED", 14)} SOURCE`;
|
|
156121
|
-
console.log(` ${
|
|
156122
|
-
console.log(` ${
|
|
156585
|
+
console.log(` ${chalk32.dim(header)}`);
|
|
156586
|
+
console.log(` ${chalk32.dim("\u2500".repeat(header.length))}`);
|
|
156123
156587
|
for (const w of filtered) {
|
|
156124
156588
|
const isOther = currentAccount !== null && w.publisher_id !== currentAccount;
|
|
156125
156589
|
const path = w.path.length > pathWidth ? "\u2026" + w.path.slice(-(pathWidth - 1)) : w.path;
|
|
156126
156590
|
const row = `${pad2(path, pathWidth)} ${pad2(w.publisher_id, pubWidth)} ${pad2(w.skill_name, skillWidth)} ${pad2(w.last_published_version ?? "-", 10)} ${pad2(formatDate(w.last_published_at), 14)} ${w.source}`;
|
|
156127
156591
|
if (isOther) {
|
|
156128
|
-
console.log(` ${
|
|
156592
|
+
console.log(` ${chalk32.dim(row + " [other account]")}`);
|
|
156129
156593
|
} else {
|
|
156130
156594
|
console.log(` ${row}`);
|
|
156131
156595
|
}
|
|
156132
156596
|
}
|
|
156133
156597
|
console.log();
|
|
156134
|
-
console.log(
|
|
156598
|
+
console.log(chalk32.dim(` ${filtered.length} workspace${filtered.length === 1 ? "" : "s"}` + (options.current ? " (filtered to current account)" : "")));
|
|
156135
156599
|
}
|
|
156136
|
-
var workspacesCommand = new
|
|
156600
|
+
var workspacesCommand = new Command35("workspaces").description("List linked skill source directories (workspaces)").option("--json", "Output as JSON").option("--current", "Only show workspaces matching the current logged-in publisher").action((options) => {
|
|
156137
156601
|
try {
|
|
156138
156602
|
listAction(options);
|
|
156139
156603
|
} catch (err) {
|
|
156140
156604
|
const message = err instanceof Error ? err.message : String(err);
|
|
156141
|
-
process.stderr.write(
|
|
156605
|
+
process.stderr.write(chalk32.red(`Error: ${message}
|
|
156142
156606
|
`));
|
|
156143
156607
|
process.exit(1);
|
|
156144
156608
|
}
|
|
@@ -156154,7 +156618,146 @@ workspacesCommand.command("find").description("Print the absolute path of a work
|
|
|
156154
156618
|
console.log(match.path);
|
|
156155
156619
|
} catch (err) {
|
|
156156
156620
|
const message = err instanceof Error ? err.message : String(err);
|
|
156157
|
-
process.stderr.write(
|
|
156621
|
+
process.stderr.write(chalk32.red(`Error: ${message}
|
|
156622
|
+
`));
|
|
156623
|
+
process.exit(1);
|
|
156624
|
+
}
|
|
156625
|
+
});
|
|
156626
|
+
|
|
156627
|
+
// dist/commands/team.js
|
|
156628
|
+
import { Command as Command36 } from "commander";
|
|
156629
|
+
import chalk33 from "chalk";
|
|
156630
|
+
function formatRole(role) {
|
|
156631
|
+
if (role === "owner")
|
|
156632
|
+
return chalk33.green("owner");
|
|
156633
|
+
if (role === "admin")
|
|
156634
|
+
return chalk33.cyan("admin");
|
|
156635
|
+
return chalk33.dim("member");
|
|
156636
|
+
}
|
|
156637
|
+
function formatStatus(status) {
|
|
156638
|
+
if (status === "active")
|
|
156639
|
+
return chalk33.green("active");
|
|
156640
|
+
if (status === "pending")
|
|
156641
|
+
return chalk33.yellow("pending");
|
|
156642
|
+
return chalk33.dim(status);
|
|
156643
|
+
}
|
|
156644
|
+
function pad3(s, n) {
|
|
156645
|
+
const visible = s.replace(/\x1b\[[0-9;]*m/g, "");
|
|
156646
|
+
if (visible.length >= n)
|
|
156647
|
+
return s;
|
|
156648
|
+
return s + " ".repeat(n - visible.length);
|
|
156649
|
+
}
|
|
156650
|
+
var teamCommand = new Command36("team").description("Manage your publisher team members").option("--json", "Output as JSON").action(async (options) => {
|
|
156651
|
+
try {
|
|
156652
|
+
const ctx = requireSession();
|
|
156653
|
+
const data = await sessionFetch(ctx, `/publishers/${ctx.publisherId}/team`);
|
|
156654
|
+
const members = data.members || [];
|
|
156655
|
+
if (options.json) {
|
|
156656
|
+
console.log(JSON.stringify(members, null, 2));
|
|
156657
|
+
return;
|
|
156658
|
+
}
|
|
156659
|
+
if (members.length === 0) {
|
|
156660
|
+
console.log();
|
|
156661
|
+
console.log(chalk33.dim(" No team members yet. Invite someone:"));
|
|
156662
|
+
console.log(chalk33.cyan(" skillvault-publisher team add <email> [--role member|admin]"));
|
|
156663
|
+
console.log();
|
|
156664
|
+
return;
|
|
156665
|
+
}
|
|
156666
|
+
console.log();
|
|
156667
|
+
console.log(chalk33.bold(` Team members (${members.length})`));
|
|
156668
|
+
console.log();
|
|
156669
|
+
const header = `${pad3(chalk33.dim("Email"), 36)} ${pad3(chalk33.dim("Role"), 14)} ${pad3(chalk33.dim("Status"), 14)} ${chalk33.dim("Member ID")}`;
|
|
156670
|
+
console.log(` ${header}`);
|
|
156671
|
+
console.log(` ${chalk33.dim("\u2500".repeat(80))}`);
|
|
156672
|
+
for (const m of members) {
|
|
156673
|
+
const row = `${pad3(m.email, 36)} ${pad3(formatRole(m.role), 14)} ${pad3(formatStatus(m.status), 14)} ${chalk33.dim(m.id)}`;
|
|
156674
|
+
console.log(` ${row}`);
|
|
156675
|
+
}
|
|
156676
|
+
console.log();
|
|
156677
|
+
console.log(chalk33.dim(` Logged in as publisher ${ctx.publisherId}`));
|
|
156678
|
+
console.log();
|
|
156679
|
+
} catch (err) {
|
|
156680
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
156681
|
+
process.stderr.write(chalk33.red(`team list failed: ${message}
|
|
156682
|
+
`));
|
|
156683
|
+
process.exit(1);
|
|
156684
|
+
}
|
|
156685
|
+
});
|
|
156686
|
+
teamCommand.command("add").description("Invite someone to your publisher team. Sends a magic-link email.").argument("<email>", "The email address to invite").option("--role <role>", "Role: member (default) or admin", "member").option("--name <name>", "Display name for the invitee (optional)").option("--json", "Output as JSON").action(async (email, options) => {
|
|
156687
|
+
try {
|
|
156688
|
+
if (!["member", "admin"].includes(options.role)) {
|
|
156689
|
+
process.stderr.write(chalk33.red(`Invalid role "${options.role}". Use --role member or --role admin.
|
|
156690
|
+
`));
|
|
156691
|
+
process.exit(1);
|
|
156692
|
+
}
|
|
156693
|
+
const ctx = requireSession();
|
|
156694
|
+
const member = await sessionFetch(ctx, `/publishers/${ctx.publisherId}/team`, {
|
|
156695
|
+
method: "POST",
|
|
156696
|
+
body: { email, role: options.role, name: options.name || null }
|
|
156697
|
+
});
|
|
156698
|
+
if (options.json) {
|
|
156699
|
+
console.log(JSON.stringify(member, null, 2));
|
|
156700
|
+
return;
|
|
156701
|
+
}
|
|
156702
|
+
console.log();
|
|
156703
|
+
console.log(chalk33.green(` \u2713 Invited ${email} as ${formatRole(options.role)}`));
|
|
156704
|
+
console.log(chalk33.dim(` Member ID: ${member.id}`));
|
|
156705
|
+
console.log(chalk33.dim(` Status: ${formatStatus(member.status)}`));
|
|
156706
|
+
console.log();
|
|
156707
|
+
console.log(chalk33.dim(" A magic-link invitation email has been sent. The new member can"));
|
|
156708
|
+
console.log(chalk33.dim(" click the link to activate, then run:"));
|
|
156709
|
+
console.log(chalk33.cyan(` skillvault-publisher login --email ${email}`));
|
|
156710
|
+
console.log();
|
|
156711
|
+
} catch (err) {
|
|
156712
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
156713
|
+
process.stderr.write(chalk33.red(`team add failed: ${message}
|
|
156714
|
+
`));
|
|
156715
|
+
process.exit(1);
|
|
156716
|
+
}
|
|
156717
|
+
});
|
|
156718
|
+
teamCommand.command("remove").description("Remove a team member by email or member ID").argument("<email-or-id>", "The member email address or member ID (tm_xxx)").option("--yes", "Skip confirmation").option("--json", "Output as JSON").action(async (target, options) => {
|
|
156719
|
+
try {
|
|
156720
|
+
const ctx = requireSession();
|
|
156721
|
+
const listData = await sessionFetch(ctx, `/publishers/${ctx.publisherId}/team`);
|
|
156722
|
+
const members = listData.members || [];
|
|
156723
|
+
const member = members.find((m) => m.id === target || m.email === target);
|
|
156724
|
+
if (!member) {
|
|
156725
|
+
process.stderr.write(chalk33.red(`No team member found matching "${target}".
|
|
156726
|
+
`));
|
|
156727
|
+
process.stderr.write(chalk33.dim("Run `skillvault-publisher team` to see the current list.\n"));
|
|
156728
|
+
process.exit(1);
|
|
156729
|
+
}
|
|
156730
|
+
if (member.role === "owner") {
|
|
156731
|
+
process.stderr.write(chalk33.red("Cannot remove the owner of a publisher account.\n"));
|
|
156732
|
+
process.exit(1);
|
|
156733
|
+
}
|
|
156734
|
+
if (member.status === "removed") {
|
|
156735
|
+
process.stderr.write(chalk33.yellow(`${member.email} is already removed.
|
|
156736
|
+
`));
|
|
156737
|
+
process.exit(0);
|
|
156738
|
+
}
|
|
156739
|
+
if (!options.yes) {
|
|
156740
|
+
console.log();
|
|
156741
|
+
console.log(chalk33.yellow.bold(" Warning: ") + "This will revoke " + chalk33.bold(member.email) + `'s access to publisher ${ctx.publisherId}.`);
|
|
156742
|
+
console.log();
|
|
156743
|
+
console.log(` Email: ${chalk33.cyan(member.email)}`);
|
|
156744
|
+
console.log(` Role: ${formatRole(member.role)}`);
|
|
156745
|
+
console.log(` Status: ${formatStatus(member.status)}`);
|
|
156746
|
+
console.log(` Added: ${chalk33.dim(new Date(member.created_at).toLocaleDateString())}`);
|
|
156747
|
+
console.log();
|
|
156748
|
+
console.log(chalk33.dim(" Add --yes to confirm."));
|
|
156749
|
+
console.log();
|
|
156750
|
+
process.exit(0);
|
|
156751
|
+
}
|
|
156752
|
+
await sessionFetch(ctx, `/publishers/${ctx.publisherId}/team/${member.id}`, { method: "DELETE" });
|
|
156753
|
+
if (options.json) {
|
|
156754
|
+
console.log(JSON.stringify({ removed: true, member_id: member.id, email: member.email }, null, 2));
|
|
156755
|
+
return;
|
|
156756
|
+
}
|
|
156757
|
+
console.log(chalk33.green(` \u2713 Removed ${member.email} from the team`));
|
|
156758
|
+
} catch (err) {
|
|
156759
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
156760
|
+
process.stderr.write(chalk33.red(`team remove failed: ${message}
|
|
156158
156761
|
`));
|
|
156159
156762
|
process.exit(1);
|
|
156160
156763
|
}
|
|
@@ -156163,7 +156766,7 @@ workspacesCommand.command("find").description("Print the absolute path of a work
|
|
|
156163
156766
|
// dist/index.js
|
|
156164
156767
|
var __dirname2 = dirname5(fileURLToPath(import.meta.url));
|
|
156165
156768
|
var pkg = JSON.parse(readFileSync18(join17(__dirname2, "..", "package.json"), "utf8"));
|
|
156166
|
-
var program = new
|
|
156769
|
+
var program = new Command37();
|
|
156167
156770
|
program.name("skillvault-publisher").description("SkillVault publisher CLI \u2014 publish, manage, and distribute encrypted skills").version(pkg.version).addHelpText("after", `
|
|
156168
156771
|
|
|
156169
156772
|
Getting Started:
|
|
@@ -156196,6 +156799,7 @@ program.addCommand(sessionCleanupCommand);
|
|
|
156196
156799
|
program.addCommand(skillDeleteCommand);
|
|
156197
156800
|
program.addCommand(skillStatusCommand);
|
|
156198
156801
|
program.addCommand(skillUnarchiveCommand);
|
|
156802
|
+
program.addCommand(skillAclCommand);
|
|
156199
156803
|
program.addCommand(grantsCommand);
|
|
156200
156804
|
program.addCommand(revokeGrantCommand);
|
|
156201
156805
|
program.addCommand(customersCommand);
|
|
@@ -156208,6 +156812,7 @@ program.addCommand(watermarkDecodeCommand);
|
|
|
156208
156812
|
program.addCommand(linkCommand);
|
|
156209
156813
|
program.addCommand(unlinkCommand);
|
|
156210
156814
|
program.addCommand(workspacesCommand);
|
|
156815
|
+
program.addCommand(teamCommand);
|
|
156211
156816
|
program.parse();
|
|
156212
156817
|
/*! Bundled license information:
|
|
156213
156818
|
|