@hasna/skills 0.10.81 → 0.10.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -0
- package/bin/index.js +278 -57
- package/bin/mcp.js +120 -11
- package/bin/migrate.js +1 -1
- package/bin/server.js +1 -1
- package/bin/worker.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +116 -7
- package/dist/lib/agent-discovery-directories.d.ts +2 -1
- package/dist/lib/private-publication-customer.d.ts +4 -1
- package/dist/lib/remote-auth.d.ts +3 -1
- package/dist/lib/remote-private-publications.d.ts +35 -0
- package/dist/runtime-prerequisites.js +2 -2
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +116 -7
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -36888,7 +36888,7 @@ var package_default;
|
|
|
36888
36888
|
var init_package = __esm(() => {
|
|
36889
36889
|
package_default = {
|
|
36890
36890
|
name: "@hasna/skills",
|
|
36891
|
-
version: "0.10.
|
|
36891
|
+
version: "0.10.82",
|
|
36892
36892
|
description: "Skills library for AI coding agents",
|
|
36893
36893
|
type: "module",
|
|
36894
36894
|
bin: {
|
|
@@ -40624,7 +40624,7 @@ function hashClaudePluginCacheOrphanMarker(path, budget2, changes) {
|
|
|
40624
40624
|
if (!before2)
|
|
40625
40625
|
return null;
|
|
40626
40626
|
const uid = process.getuid?.();
|
|
40627
|
-
if (!before2.isFile() || uid === undefined || before2.uid !== uid || before2.size > 32)
|
|
40627
|
+
if (!before2.isFile() || uid === undefined || before2.uid !== uid || before2.size > 32 || (before2.mode & 73) !== 0)
|
|
40628
40628
|
throw new Error("Invalid Claude orphan marker file or owner");
|
|
40629
40629
|
const fd = openSync3(path, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
|
|
40630
40630
|
try {
|
|
@@ -48216,7 +48216,7 @@ function safe2(path) {
|
|
|
48216
48216
|
function same2(before2, after2) {
|
|
48217
48217
|
return Boolean(after2 && after2.isDirectory() && before2.dev === after2.dev && before2.ino === after2.ino && before2.mtimeMs === after2.mtimeMs && before2.ctimeMs === after2.ctimeMs);
|
|
48218
48218
|
}
|
|
48219
|
-
function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
|
|
48219
|
+
function capture(path, budget2, excludedRoots, omittedRoots = [], rows, claudeMarkers) {
|
|
48220
48220
|
safe2(path);
|
|
48221
48221
|
if (omittedRoots.some((root2) => path === root2 || path.startsWith(root2 + "/")))
|
|
48222
48222
|
return { path, sha256: null };
|
|
@@ -48244,6 +48244,11 @@ function capture(path, budget2, excludedRoots, omittedRoots = [], rows) {
|
|
|
48244
48244
|
need3(child2.length <= AGENT_POLICY_LIMITS.pathCharacters, "Native discovery directory path limit exceeded");
|
|
48245
48245
|
const stat = lstatSync7(child2);
|
|
48246
48246
|
need3(stat.isFile() || stat.isDirectory(), "Refusing symlink or special native discovery directory member");
|
|
48247
|
+
if (claudeMarkers && isClaudePluginCacheOrphanMarker(child2)) {
|
|
48248
|
+
need3(hashClaudePluginCacheOrphanMarker(child2) !== null, "Claude orphan marker changed while reading directory");
|
|
48249
|
+
if (claudeMarkers === "omit")
|
|
48250
|
+
continue;
|
|
48251
|
+
}
|
|
48247
48252
|
const row = JSON.stringify([childRelative, stat.isDirectory() ? "directory" : "file"]) + `
|
|
48248
48253
|
`;
|
|
48249
48254
|
budget2.bytes += Buffer.byteLength(row);
|
|
@@ -48300,25 +48305,33 @@ function verifyDiscoveryDirectoryProjection(directories, omittedRoots, tolerance
|
|
|
48300
48305
|
witnessChanged(new NativeDiscoveryWitnessChange("membership", directories[i].path, "Native discovery directory membership changed outside retired Codex roots"), tolerance, tolerance?.acceptsMembership(directories[i].path) === true);
|
|
48301
48306
|
}
|
|
48302
48307
|
}
|
|
48303
|
-
function
|
|
48308
|
+
function captureOrdinaryDirectories(paths, excludedRoots, claudeMarkers) {
|
|
48304
48309
|
need3(Array.isArray(paths) && paths.length <= AGENT_POLICY_LIMITS.discoveryDirectories && new Set(paths).size === paths.length, "Invalid native discovery directory collection");
|
|
48305
48310
|
const budget2 = { entries: 0, bytes: 0 };
|
|
48306
48311
|
for (const root of excludedRoots)
|
|
48307
48312
|
safe2(root);
|
|
48308
|
-
return paths.map((path) => capture(path, budget2, excludedRoots));
|
|
48313
|
+
return paths.map((path) => capture(path, budget2, excludedRoots, [], undefined, claudeMarkers));
|
|
48314
|
+
}
|
|
48315
|
+
function captureDiscoveryDirectories(paths, excludedRoots = []) {
|
|
48316
|
+
return captureOrdinaryDirectories(paths, excludedRoots, "omit");
|
|
48309
48317
|
}
|
|
48310
48318
|
function verifyDiscoveryDirectories(directories, excludedRoots = [], tolerance) {
|
|
48311
48319
|
need3(Array.isArray(directories) && directories.length <= AGENT_POLICY_LIMITS.discoveryDirectories, "Invalid native discovery directory collection");
|
|
48312
48320
|
for (const directory of directories)
|
|
48313
48321
|
need3(directory && typeof directory === "object" && (directory.sha256 === null || typeof directory.sha256 === "string" && /^[a-f0-9]{64}$/.test(directory.sha256)), "Invalid native discovery directory digest");
|
|
48314
48322
|
const current = captureDiscoveryDirectories(directories.map((directory) => directory.path), excludedRoots);
|
|
48323
|
+
let legacy;
|
|
48315
48324
|
for (let i = 0;i < directories.length; i++)
|
|
48316
48325
|
if (current[i].sha256 !== directories[i].sha256) {
|
|
48326
|
+
legacy ??= captureOrdinaryDirectories(directories.map((directory) => directory.path), excludedRoots, "retain");
|
|
48327
|
+
if (legacy[i].sha256 === directories[i].sha256)
|
|
48328
|
+
continue;
|
|
48317
48329
|
witnessChanged(new NativeDiscoveryWitnessChange("membership", directories[i].path, `Native discovery directory membership changed; run skills hook install with a fresh discovery review: ${directories[i].path}`), tolerance, tolerance?.acceptsMembership(directories[i].path) === true);
|
|
48318
48330
|
}
|
|
48319
48331
|
}
|
|
48320
48332
|
var init_agent_discovery_directories = __esm(() => {
|
|
48321
48333
|
init_agent_policy_limits();
|
|
48334
|
+
init_claude_plugin_cache_marker();
|
|
48322
48335
|
init_native_discovery_witness_change();
|
|
48323
48336
|
});
|
|
48324
48337
|
|
|
@@ -67851,7 +67864,7 @@ function checkedPublicationView(value, skillId, intentId, declaration) {
|
|
|
67851
67864
|
return invalid3();
|
|
67852
67865
|
return Object.freeze({ ...value });
|
|
67853
67866
|
}
|
|
67854
|
-
async function boundedJson(url, init, token, mutation, budget2 = 15000, signal, create3 = false) {
|
|
67867
|
+
async function boundedJson(url, init, token, mutation, budget2 = 15000, signal, create3 = false, readBinding) {
|
|
67855
67868
|
const controller = new AbortController;
|
|
67856
67869
|
let reader;
|
|
67857
67870
|
let response;
|
|
@@ -67867,8 +67880,18 @@ async function boundedJson(url, init, token, mutation, budget2 = 15000, signal,
|
|
|
67867
67880
|
redirect: "error",
|
|
67868
67881
|
credentials: "omit",
|
|
67869
67882
|
signal: controller.signal,
|
|
67870
|
-
headers: {
|
|
67883
|
+
headers: {
|
|
67884
|
+
"Content-Type": "application/json",
|
|
67885
|
+
Authorization: `Bearer ${token}`,
|
|
67886
|
+
...readBinding ? {
|
|
67887
|
+
"x-skills-user-id": readBinding.userId,
|
|
67888
|
+
"x-skills-workspace-id": readBinding.organizationId,
|
|
67889
|
+
"x-skills-membership-id": readBinding.membershipId
|
|
67890
|
+
} : {}
|
|
67891
|
+
}
|
|
67871
67892
|
});
|
|
67893
|
+
if (readBinding && response.ok && response.status !== 200)
|
|
67894
|
+
return invalid3();
|
|
67872
67895
|
const length = response.headers.get("content-length");
|
|
67873
67896
|
if (length !== null && (!/^\d+$/.test(length) || Number(length) > 65536))
|
|
67874
67897
|
return invalid3();
|
|
@@ -67936,6 +67959,81 @@ async function boundedJson(url, init, token, mutation, budget2 = 15000, signal,
|
|
|
67936
67959
|
response?.body?.cancel().catch(() => {});
|
|
67937
67960
|
}
|
|
67938
67961
|
}
|
|
67962
|
+
function historyDate(value) {
|
|
67963
|
+
if (typeof value !== "string")
|
|
67964
|
+
return false;
|
|
67965
|
+
const parts = /^(\d{4})-(\d{2})-(\d{2})(T| )(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,9}))?(Z|[+-](\d{2})(?::(\d{2}))?)$/.exec(value);
|
|
67966
|
+
if (!parts)
|
|
67967
|
+
return false;
|
|
67968
|
+
const [, y, m, d, separator, h, minute, second, fraction, zone, offsetHour, offsetMinute] = parts;
|
|
67969
|
+
if (separator === " " ? zone === "Z" || (fraction?.length ?? 0) > 6 : zone !== "Z" && offsetMinute === undefined)
|
|
67970
|
+
return false;
|
|
67971
|
+
const year = Number(y), month = Number(m), day = Number(d);
|
|
67972
|
+
const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
67973
|
+
const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
67974
|
+
return year > 0 && month >= 1 && month <= 12 && day >= 1 && day <= days[month - 1] && Number(h) <= 23 && Number(minute) <= 59 && Number(second) <= 59 && (zone === "Z" || Number(offsetHour) <= 23 && Number(offsetMinute ?? 0) <= 59);
|
|
67975
|
+
}
|
|
67976
|
+
function privateHistory(value, organizationId, skillId, limit, cursor) {
|
|
67977
|
+
if (!record7(value) || value.organizationId !== organizationId || value.skillId !== skillId || typeof value.slug !== "string" || !/^[a-z0-9-]+$/.test(value.slug) || !(value.currentVersion === null || historyText(value.currentVersion)) || !(value.currentVersionId === null || publicationUuid(value.currentVersionId)) || value.currentVersion === null !== (value.currentVersionId === null) || !(value.nextCursor === null || publicationUuid(value.nextCursor)) || !Array.isArray(value.versions) || value.versions.length > limit)
|
|
67978
|
+
return historyResponse();
|
|
67979
|
+
const seen = new Set;
|
|
67980
|
+
let previous = cursor;
|
|
67981
|
+
const versions = value.versions.map((row) => {
|
|
67982
|
+
if (!record7(row) || !publicationUuid(row.id) || seen.has(row.id) || previous !== undefined && row.id >= previous || !historyText(row.version) || !(row.releasedAt === null || historyDate(row.releasedAt)) || !historyDate(row.createdAt) || row.id === value.currentVersionId !== (row.version === value.currentVersion))
|
|
67983
|
+
return historyResponse();
|
|
67984
|
+
seen.add(row.id);
|
|
67985
|
+
previous = row.id;
|
|
67986
|
+
return Object.freeze({ id: row.id, version: row.version, releasedAt: row.releasedAt, createdAt: row.createdAt });
|
|
67987
|
+
});
|
|
67988
|
+
if (value.nextCursor !== null && (!versions.length || value.nextCursor !== versions.at(-1).id))
|
|
67989
|
+
return historyResponse();
|
|
67990
|
+
return Object.freeze({
|
|
67991
|
+
organizationId,
|
|
67992
|
+
skillId,
|
|
67993
|
+
slug: value.slug,
|
|
67994
|
+
currentVersion: value.currentVersion,
|
|
67995
|
+
currentVersionId: value.currentVersionId,
|
|
67996
|
+
versions: Object.freeze(versions),
|
|
67997
|
+
nextCursor: value.nextCursor
|
|
67998
|
+
});
|
|
67999
|
+
}
|
|
68000
|
+
|
|
68001
|
+
class RemotePrivateSkillHistoryClient {
|
|
68002
|
+
apiOrigin;
|
|
68003
|
+
organizationId;
|
|
68004
|
+
userId;
|
|
68005
|
+
membershipId;
|
|
68006
|
+
#token;
|
|
68007
|
+
constructor(apiUrl, session) {
|
|
68008
|
+
const checked = parseWorkspaceSession(session, { userId: session?.user?.id, membershipId: session?.user?.membershipId });
|
|
68009
|
+
this.apiOrigin = normalizeSkillsApiOrigin(apiUrl);
|
|
68010
|
+
this.#token = checked.token;
|
|
68011
|
+
this.organizationId = checked.organization.id;
|
|
68012
|
+
this.userId = checked.user.id;
|
|
68013
|
+
this.membershipId = checked.user.membershipId;
|
|
68014
|
+
Object.freeze(this);
|
|
68015
|
+
}
|
|
68016
|
+
async listVersions(skillId, options = {}) {
|
|
68017
|
+
if (!publicationUuid(skillId) || options.limit !== undefined && (!Number.isSafeInteger(options.limit) || options.limit < 1 || options.limit > 50) || options.cursor !== undefined && !publicationUuid(options.cursor) || options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 15000))
|
|
68018
|
+
return historyInput();
|
|
68019
|
+
const limit = options.limit ?? 20, cursor = options.cursor;
|
|
68020
|
+
const query = new URLSearchParams;
|
|
68021
|
+
if (options.limit !== undefined)
|
|
68022
|
+
query.set("limit", String(limit));
|
|
68023
|
+
if (cursor !== undefined)
|
|
68024
|
+
query.set("cursor", cursor);
|
|
68025
|
+
const path = `/api/v1/skills/${skillId}/versions${query.size ? `?${query}` : ""}`;
|
|
68026
|
+
let value;
|
|
68027
|
+
try {
|
|
68028
|
+
value = await boundedJson(skillsApiRequestUrl(this.apiOrigin, path), { method: "GET" }, this.#token, false, options.timeoutMs, options.signal, false, this);
|
|
68029
|
+
} catch (error) {
|
|
68030
|
+
if (error instanceof PrivatePublicationError && error.code === "INVALID_PUBLICATION_RESPONSE")
|
|
68031
|
+
return historyResponse();
|
|
68032
|
+
throw new PrivatePublicationError("PRIVATE_HISTORY_UNAVAILABLE", "Unable to read private version history. Check the selected server, current membership and fresh sign-in; no skill or credential was changed.", false, error instanceof PrivatePublicationError ? error.status : undefined);
|
|
68033
|
+
}
|
|
68034
|
+
return privateHistory(value, this.organizationId, skillId, limit, cursor);
|
|
68035
|
+
}
|
|
68036
|
+
}
|
|
67939
68037
|
|
|
67940
68038
|
class RemotePrivatePublicationsClient {
|
|
67941
68039
|
apiOrigin;
|
|
@@ -68109,7 +68207,11 @@ var PRIVATE_PUBLICATION_MAX_BYTES, skillCreateFailures, failures, PrivatePublica
|
|
|
68109
68207
|
throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
|
|
68110
68208
|
}, invalid3 = () => {
|
|
68111
68209
|
throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
|
|
68112
|
-
}, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash4 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record7 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record7(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) => createHash31("sha256").update(bytes).digest("hex")
|
|
68210
|
+
}, publicationUuid = (v) => typeof v === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(v), hash4 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record7 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record7(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date = (v) => typeof v === "string" && /^\d{4}-\d\d-\d\dT[0-9:.]+(?:Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.test(v) && Number.isFinite(Date.parse(v)), publicationSha256 = (bytes) => createHash31("sha256").update(bytes).digest("hex"), historyInput = () => {
|
|
68211
|
+
throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_INPUT", "Provide a private skill UUID, limit from 1 to 50, and an optional UUID cursor; timeoutMs must be from 1 to 15000.");
|
|
68212
|
+
}, historyResponse = () => {
|
|
68213
|
+
throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_RESPONSE", "The server returned invalid private version history.");
|
|
68214
|
+
}, historyText = (value) => typeof value === "string" && value.length > 0 && value.length <= 128 && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value);
|
|
68113
68215
|
var init_remote_private_publications = __esm(() => {
|
|
68114
68216
|
init_fleet_credentials();
|
|
68115
68217
|
init_remote_workspace_selection();
|
|
@@ -89514,6 +89616,10 @@ class RemoteSkillsAuthClient {
|
|
|
89514
89616
|
const origin = this.apiOrigin, captured = workspaceContext(context);
|
|
89515
89617
|
return new RemotePrivatePublicationsClient(origin, await this.switchWorkspace(email4, code, captured));
|
|
89516
89618
|
}
|
|
89619
|
+
async openPrivateSkillHistory(email4, code, context) {
|
|
89620
|
+
const origin = this.apiOrigin, captured = workspaceContext(context);
|
|
89621
|
+
return new RemotePrivateSkillHistoryClient(origin, await this.switchWorkspace(email4, code, captured));
|
|
89622
|
+
}
|
|
89517
89623
|
requestInvitationEmailChallenge(input2) {
|
|
89518
89624
|
return requestInvitationEmail(this.apiOrigin, "challenge", input2);
|
|
89519
89625
|
}
|
|
@@ -116446,7 +116552,7 @@ var init_remote_invitation_tools = __esm(() => {
|
|
|
116446
116552
|
});
|
|
116447
116553
|
|
|
116448
116554
|
// src/lib/private-publication-customer.ts
|
|
116449
|
-
function
|
|
116555
|
+
function preparePrivateSession(requested, action, open2) {
|
|
116450
116556
|
const selectors = [
|
|
116451
116557
|
"HASNA_PROFILE",
|
|
116452
116558
|
"HASNA_HOME",
|
|
@@ -116460,7 +116566,7 @@ function preparePrivatePublicationSession(requested) {
|
|
|
116460
116566
|
"SKILLS_API_KEY"
|
|
116461
116567
|
];
|
|
116462
116568
|
const before2 = new Map(selectors.map((key2) => [key2, process.env[key2]]));
|
|
116463
|
-
const profile = selectedSkillsProfile(process.env), pending = prepareProfileWorkspace(
|
|
116569
|
+
const profile = selectedSkillsProfile(process.env), pending = prepareProfileWorkspace(action);
|
|
116464
116570
|
const captured = requested ? { ...requested } : undefined;
|
|
116465
116571
|
const unchanged3 = () => {
|
|
116466
116572
|
if (selectors.some((key2) => process.env[key2] !== before2.get(key2)) || selectedSkillsProfile(process.env) !== profile)
|
|
@@ -116474,12 +116580,18 @@ function preparePrivatePublicationSession(requested) {
|
|
|
116474
116580
|
throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide the observed user and membership IDs, or select an enrolled workspace profile.");
|
|
116475
116581
|
unchanged3();
|
|
116476
116582
|
target.unchanged();
|
|
116477
|
-
const client2 = await new RemoteSkillsAuthClient(target.origin)
|
|
116583
|
+
const client2 = await open2(new RemoteSkillsAuthClient(target.origin), email5, code2, context2);
|
|
116478
116584
|
unchanged3();
|
|
116479
116585
|
target.unchanged();
|
|
116480
116586
|
return client2;
|
|
116481
116587
|
} };
|
|
116482
116588
|
}
|
|
116589
|
+
function preparePrivatePublicationSession(requested) {
|
|
116590
|
+
return preparePrivateSession(requested, "Manage private publications", (auth, email5, code2, context2) => auth.openPrivatePublications(email5, code2, context2));
|
|
116591
|
+
}
|
|
116592
|
+
function preparePrivateSkillHistorySession(requested) {
|
|
116593
|
+
return preparePrivateSession(requested, "Read private version history", (auth, email5, code2, context2) => auth.openPrivateSkillHistory(email5, code2, context2));
|
|
116594
|
+
}
|
|
116483
116595
|
async function privatePublicationSession(email5, code2, requested) {
|
|
116484
116596
|
return preparePrivatePublicationSession(requested).verify(email5, code2);
|
|
116485
116597
|
}
|
|
@@ -117201,7 +117313,7 @@ var exports_runtime_mcp = {};
|
|
|
117201
117313
|
__export(exports_runtime_mcp, {
|
|
117202
117314
|
handleMcp: () => handleMcp
|
|
117203
117315
|
});
|
|
117204
|
-
import { existsSync as existsSync33, lstatSync as lstatSync40, mkdirSync as mkdirSync26, readFileSync as readFileSync43, renameSync as renameSync14, rmdirSync as rmdirSync4, statSync as statSync22, writeFileSync as writeFileSync23 } from "fs";
|
|
117316
|
+
import { closeSync as closeSync29, constants as constants28, existsSync as existsSync33, fstatSync as fstatSync29, lstatSync as lstatSync40, mkdirSync as mkdirSync26, openSync as openSync29, readFileSync as readFileSync43, readSync as readSync21, renameSync as renameSync14, rmdirSync as rmdirSync4, statSync as statSync22, writeFileSync as writeFileSync23 } from "fs";
|
|
117205
117317
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
117206
117318
|
import { homedir as homedir10 } from "os";
|
|
117207
117319
|
import { dirname as dirname40, isAbsolute as isAbsolute38, join as join66 } from "path";
|
|
@@ -117270,10 +117382,14 @@ async function registerClaudeMcp(command, server2, environment) {
|
|
|
117270
117382
|
const desired = { type: "stdio", ...server2, env: environment };
|
|
117271
117383
|
try {
|
|
117272
117384
|
const path = claudeUserConfigPath();
|
|
117385
|
+
const firstRun = lstatSync40(path, { throwIfNoEntry: false }) === undefined ? claudeFirstRunPathWitness(path) : undefined;
|
|
117273
117386
|
const before2 = withClaudeConfigLock(path, () => {
|
|
117274
117387
|
if (claudeUserConfigPath() !== path)
|
|
117275
117388
|
throw new Error;
|
|
117389
|
+
firstRun?.();
|
|
117276
117390
|
const bytes = readClaudeConfig(path);
|
|
117391
|
+
if (firstRun && bytes !== null)
|
|
117392
|
+
throw new Error;
|
|
117277
117393
|
if (bytes !== null) {
|
|
117278
117394
|
const backup = `${path}.skills-mcp-${randomUUID10()}.backup`;
|
|
117279
117395
|
writeFileSync23(backup, bytes, { flag: "wx", mode: 384 });
|
|
@@ -117308,11 +117424,11 @@ async function registerClaudeMcp(command, server2, environment) {
|
|
|
117308
117424
|
return withClaudeConfigLock(path, () => {
|
|
117309
117425
|
if (claudeUserConfigPath() !== path)
|
|
117310
117426
|
throw new Error;
|
|
117311
|
-
const current = readClaudeConfig(path);
|
|
117427
|
+
const current = firstRun ? readClaudeFirstRunConfig(path, firstRun) : readClaudeConfig(path);
|
|
117312
117428
|
const previous = parseClaudeConfig(before2), data = parseClaudeConfig(current);
|
|
117313
117429
|
if (exitCode === 0) {
|
|
117314
117430
|
const actual = isPlainObject4(data.mcpServers) ? data.mcpServers[MCP_SERVER_NAME] : undefined;
|
|
117315
|
-
if (!claudeNativeConfigPreserved(previous, data) || !isPlainObject4(actual) || !isDeepStrictEqual17({ ...actual, env: actual.env ?? {} }, desired))
|
|
117431
|
+
if (!claudeNativeConfigPreserved(previous, data, firstRun !== undefined && before2 === null) || !isPlainObject4(actual) || !isDeepStrictEqual17({ ...actual, env: actual.env ?? {} }, desired))
|
|
117316
117432
|
throw new Error;
|
|
117317
117433
|
} else {
|
|
117318
117434
|
if (!cliUnavailable && (!duplicateAccepted || !isPlainObject4(previous.mcpServers) || !previous.mcpServers[MCP_SERVER_NAME]))
|
|
@@ -117326,7 +117442,7 @@ async function registerClaudeMcp(command, server2, environment) {
|
|
|
117326
117442
|
writeFileSync23(temporary, next, { flag: "wx", mode: 384 });
|
|
117327
117443
|
if (!readFileSync43(temporary).equals(next))
|
|
117328
117444
|
throw new Error;
|
|
117329
|
-
const latest = readClaudeConfig(path);
|
|
117445
|
+
const latest = firstRun ? readClaudeFirstRunConfig(path, firstRun) : readClaudeConfig(path);
|
|
117330
117446
|
if (claudeUserConfigPath() !== path || (before2 === null ? latest !== null : latest === null || !latest.equals(before2)))
|
|
117331
117447
|
throw new Error;
|
|
117332
117448
|
renameSync14(temporary, path);
|
|
@@ -117360,27 +117476,92 @@ function claudeUserConfigPath() {
|
|
|
117360
117476
|
return modern;
|
|
117361
117477
|
}
|
|
117362
117478
|
function readClaudeConfig(path) {
|
|
117363
|
-
|
|
117479
|
+
const info = lstatSync40(path, { throwIfNoEntry: false });
|
|
117480
|
+
if (info === undefined)
|
|
117364
117481
|
return null;
|
|
117365
|
-
const info = lstatSync40(path);
|
|
117366
117482
|
if (!info.isFile() || info.size > 16777216)
|
|
117367
117483
|
throw new Error;
|
|
117368
117484
|
const bytes = readFileSync43(path);
|
|
117369
117485
|
parseClaudeConfig(bytes);
|
|
117370
117486
|
return bytes;
|
|
117371
117487
|
}
|
|
117488
|
+
function claudeFirstRunPathWitness(path) {
|
|
117489
|
+
if (!process.getuid || constants28.O_NOFOLLOW === undefined)
|
|
117490
|
+
throw new Error;
|
|
117491
|
+
const uid2 = BigInt(process.getuid()), canonical9 = canonicalSystemPath(path);
|
|
117492
|
+
const identity6 = (info) => `${info.dev}:${info.ino}:${info.uid}:${info.gid}:${info.mode}`;
|
|
117493
|
+
const directories = [];
|
|
117494
|
+
for (let cursor2 = dirname40(canonical9);; cursor2 = dirname40(cursor2)) {
|
|
117495
|
+
directories.unshift({ path: cursor2, identity: "" });
|
|
117496
|
+
if (dirname40(cursor2) === cursor2)
|
|
117497
|
+
break;
|
|
117498
|
+
}
|
|
117499
|
+
const verify = () => {
|
|
117500
|
+
if (canonicalSystemPath(path) !== canonical9)
|
|
117501
|
+
throw new Error;
|
|
117502
|
+
for (const directory3 of directories) {
|
|
117503
|
+
const info = lstatSync40(directory3.path, { bigint: true });
|
|
117504
|
+
if (!info.isDirectory() || identity6(info) !== directory3.identity)
|
|
117505
|
+
throw new Error;
|
|
117506
|
+
}
|
|
117507
|
+
};
|
|
117508
|
+
for (const directory3 of directories) {
|
|
117509
|
+
let info = lstatSync40(directory3.path, { bigint: true, throwIfNoEntry: false });
|
|
117510
|
+
if (!info) {
|
|
117511
|
+
mkdirSync26(directory3.path, { mode: 448 });
|
|
117512
|
+
info = lstatSync40(directory3.path, { bigint: true });
|
|
117513
|
+
}
|
|
117514
|
+
if (!info.isDirectory() || info.uid !== 0n && info.uid !== uid2 || (info.mode & 0o022n) !== 0n && !(info.uid === 0n && (info.mode & 0o1000n) !== 0n))
|
|
117515
|
+
throw new Error;
|
|
117516
|
+
directory3.identity = identity6(info);
|
|
117517
|
+
}
|
|
117518
|
+
verify();
|
|
117519
|
+
if (lstatSync40(path, { throwIfNoEntry: false }) !== undefined)
|
|
117520
|
+
throw new Error;
|
|
117521
|
+
return verify;
|
|
117522
|
+
}
|
|
117523
|
+
function readClaudeFirstRunConfig(path, verifyPath) {
|
|
117524
|
+
verifyPath();
|
|
117525
|
+
const before2 = lstatSync40(path, { bigint: true, throwIfNoEntry: false });
|
|
117526
|
+
if (!before2)
|
|
117527
|
+
return null;
|
|
117528
|
+
const identity6 = (info) => `${info.dev}:${info.ino}:${info.uid}:${info.gid}:${info.mode}:${info.nlink}:${info.size}:${info.mtimeNs}:${info.ctimeNs}`;
|
|
117529
|
+
if (!before2.isFile() || before2.nlink !== 1n || before2.uid !== BigInt(process.getuid()) || (before2.mode & 0o022n) !== 0n || before2.size > 16n * 1024n * 1024n)
|
|
117530
|
+
throw new Error;
|
|
117531
|
+
const fd = openSync29(path, constants28.O_RDONLY | constants28.O_NOFOLLOW | constants28.O_NONBLOCK);
|
|
117532
|
+
try {
|
|
117533
|
+
if (identity6(fstatSync29(fd, { bigint: true })) !== identity6(before2))
|
|
117534
|
+
throw new Error;
|
|
117535
|
+
const bytes = Buffer.alloc(Number(before2.size) + 1);
|
|
117536
|
+
let length = 0;
|
|
117537
|
+
while (length < bytes.length) {
|
|
117538
|
+
const count = readSync21(fd, bytes, length, bytes.length - length, null);
|
|
117539
|
+
if (!count)
|
|
117540
|
+
break;
|
|
117541
|
+
length += count;
|
|
117542
|
+
}
|
|
117543
|
+
if (BigInt(length) !== before2.size || identity6(fstatSync29(fd, { bigint: true })) !== identity6(before2) || identity6(lstatSync40(path, { bigint: true })) !== identity6(before2))
|
|
117544
|
+
throw new Error;
|
|
117545
|
+
const content = bytes.subarray(0, length);
|
|
117546
|
+
verifyPath();
|
|
117547
|
+
parseClaudeConfig(content);
|
|
117548
|
+
return content;
|
|
117549
|
+
} finally {
|
|
117550
|
+
closeSync29(fd);
|
|
117551
|
+
}
|
|
117552
|
+
}
|
|
117372
117553
|
function parseClaudeConfig(bytes) {
|
|
117373
117554
|
const data = bytes === null ? {} : JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
117374
117555
|
if (!isPlainObject4(data) || data.mcpServers !== undefined && !isPlainObject4(data.mcpServers))
|
|
117375
117556
|
throw new Error;
|
|
117376
117557
|
return data;
|
|
117377
117558
|
}
|
|
117378
|
-
function claudeNativeConfigPreserved(before2, after2) {
|
|
117559
|
+
function claudeNativeConfigPreserved(before2, after2, firstRun = false) {
|
|
117379
117560
|
const previous = withoutClaudeSkills(before2), current = withoutClaudeSkills(after2);
|
|
117380
117561
|
for (const key2 of Object.keys(current)) {
|
|
117381
117562
|
if (Object.hasOwn(previous, key2))
|
|
117382
117563
|
continue;
|
|
117383
|
-
if (!isClaudeBootstrapAddition(key2, current[key2]))
|
|
117564
|
+
if (!(firstRun && key2 === "userID" && typeof current[key2] === "string" && /^[0-9a-f]{64}$/i.test(current[key2])) && !isClaudeBootstrapAddition(key2, current[key2]))
|
|
117384
117565
|
return false;
|
|
117385
117566
|
delete current[key2];
|
|
117386
117567
|
}
|
|
@@ -117562,6 +117743,7 @@ var MCP_SERVER_NAME = "skills", MCP_COMMAND_NAME = "skills-mcp";
|
|
|
117562
117743
|
var init_runtime_mcp = __esm(() => {
|
|
117563
117744
|
init_source();
|
|
117564
117745
|
init_installer();
|
|
117746
|
+
init_agent_integration();
|
|
117565
117747
|
init_credential_profile_command();
|
|
117566
117748
|
init_mcp_registration_environment();
|
|
117567
117749
|
});
|
|
@@ -120456,30 +120638,30 @@ var exports_recurring = {};
|
|
|
120456
120638
|
__export(exports_recurring, {
|
|
120457
120639
|
registerRecurringCommands: () => registerRecurringCommands
|
|
120458
120640
|
});
|
|
120459
|
-
import { constants as
|
|
120641
|
+
import { constants as constants29, closeSync as closeSync30, fstatSync as fstatSync30, lstatSync as lstatSync43, openSync as openSync30, readSync as readSync22 } from "fs";
|
|
120460
120642
|
import { createInterface as createInterface2 } from "readline";
|
|
120461
120643
|
function readRequest(path) {
|
|
120462
|
-
const fd =
|
|
120644
|
+
const fd = openSync30(path, constants29.O_RDONLY | constants29.O_NOFOLLOW | constants29.O_NONBLOCK);
|
|
120463
120645
|
try {
|
|
120464
|
-
const before2 =
|
|
120646
|
+
const before2 = fstatSync30(fd);
|
|
120465
120647
|
if (!before2.isFile() || before2.size > 1048576 || before2.size < 1)
|
|
120466
120648
|
throw new RecurringInputError;
|
|
120467
120649
|
const bytes = Buffer.alloc(before2.size + 1);
|
|
120468
120650
|
let length = 0;
|
|
120469
120651
|
while (length < bytes.length) {
|
|
120470
|
-
const n2 =
|
|
120652
|
+
const n2 = readSync22(fd, bytes, length, bytes.length - length, length);
|
|
120471
120653
|
if (!n2)
|
|
120472
120654
|
break;
|
|
120473
120655
|
length += n2;
|
|
120474
120656
|
}
|
|
120475
|
-
const after2 =
|
|
120657
|
+
const after2 = fstatSync30(fd), current = lstatSync43(path);
|
|
120476
120658
|
if (length !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || current.dev !== before2.dev || current.ino !== before2.ino || !current.isFile() || current.isSymbolicLink())
|
|
120477
120659
|
throw new RecurringInputError;
|
|
120478
120660
|
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
|
|
120479
120661
|
} catch {
|
|
120480
120662
|
throw new RecurringInputError;
|
|
120481
120663
|
} finally {
|
|
120482
|
-
|
|
120664
|
+
closeSync30(fd);
|
|
120483
120665
|
}
|
|
120484
120666
|
}
|
|
120485
120667
|
async function acceptAtTerminal(draft) {
|
|
@@ -123119,7 +123301,7 @@ var init_claude_installer_binding = __esm(() => {
|
|
|
123119
123301
|
});
|
|
123120
123302
|
|
|
123121
123303
|
// src/cli/commands/claude-installer-capture.ts
|
|
123122
|
-
import { closeSync as
|
|
123304
|
+
import { closeSync as closeSync31, constants as constants30, fstatSync as fstatSync31, lstatSync as lstatSync48, openSync as openSync31, readSync as readSync23 } from "fs";
|
|
123123
123305
|
import { isAbsolute as isAbsolute46, resolve as resolve44 } from "path";
|
|
123124
123306
|
function need11(condition, code2) {
|
|
123125
123307
|
if (!condition)
|
|
@@ -123141,19 +123323,19 @@ function readRequest2(path) {
|
|
|
123141
123323
|
const before2 = lstatSync48(path, { throwIfNoEntry: false });
|
|
123142
123324
|
if (!before2?.isFile() || before2.isSymbolicLink() || before2.size > MAX_REQUEST_BYTES)
|
|
123143
123325
|
throw new CaptureRefusal("INVALID_REQUEST_FILE: --request must name a regular non-symlink JSON file no larger than 64 KiB");
|
|
123144
|
-
const fd =
|
|
123326
|
+
const fd = openSync31(path, constants30.O_RDONLY | (constants30.O_NOFOLLOW ?? 0) | constants30.O_NONBLOCK);
|
|
123145
123327
|
try {
|
|
123146
|
-
const opened =
|
|
123328
|
+
const opened = fstatSync31(fd);
|
|
123147
123329
|
need11(opened.isFile() && opened.dev === before2.dev && opened.ino === before2.ino && opened.size === before2.size, "INVALID_REQUEST_FILE: --request must remain the same regular file while read");
|
|
123148
123330
|
const bytes = Buffer.alloc(MAX_REQUEST_BYTES + 1);
|
|
123149
123331
|
let length = 0;
|
|
123150
123332
|
while (length < bytes.length) {
|
|
123151
|
-
const count =
|
|
123333
|
+
const count = readSync23(fd, bytes, length, bytes.length - length, null);
|
|
123152
123334
|
if (!count)
|
|
123153
123335
|
break;
|
|
123154
123336
|
length += count;
|
|
123155
123337
|
}
|
|
123156
|
-
const after2 =
|
|
123338
|
+
const after2 = fstatSync31(fd), current = lstatSync48(path);
|
|
123157
123339
|
need11(length <= MAX_REQUEST_BYTES && length === opened.size && after2.size === opened.size && after2.mtimeMs === opened.mtimeMs && after2.ctimeMs === opened.ctimeMs && current.dev === opened.dev && current.ino === opened.ino && current.mtimeMs === opened.mtimeMs && current.ctimeMs === opened.ctimeMs, "INVALID_REQUEST_FILE: --request must remain unchanged while read");
|
|
123158
123340
|
try {
|
|
123159
123341
|
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
|
|
@@ -123161,7 +123343,7 @@ function readRequest2(path) {
|
|
|
123161
123343
|
throw new CaptureRefusal("INVALID_REQUEST_JSON: --request must contain one valid UTF-8 JSON object");
|
|
123162
123344
|
}
|
|
123163
123345
|
} finally {
|
|
123164
|
-
|
|
123346
|
+
closeSync31(fd);
|
|
123165
123347
|
}
|
|
123166
123348
|
}
|
|
123167
123349
|
function paths(value) {
|
|
@@ -123305,7 +123487,7 @@ var exports_agent_integration = {};
|
|
|
123305
123487
|
__export(exports_agent_integration, {
|
|
123306
123488
|
registerAgentIntegration: () => registerAgentIntegration
|
|
123307
123489
|
});
|
|
123308
|
-
import { existsSync as existsSync36, lstatSync as lstatSync49, readFileSync as readFileSync50, readSync as
|
|
123490
|
+
import { existsSync as existsSync36, lstatSync as lstatSync49, readFileSync as readFileSync50, readSync as readSync24, writeFileSync as writeFileSync27 } from "fs";
|
|
123309
123491
|
import { createHash as createHash48 } from "crypto";
|
|
123310
123492
|
import { homedir as homedir14 } from "os";
|
|
123311
123493
|
import { basename as basename25, isAbsolute as isAbsolute47, resolve as resolve45 } from "path";
|
|
@@ -123420,7 +123602,7 @@ function registerAgentIntegration(parent) {
|
|
|
123420
123602
|
const bytes = Buffer.alloc(1024 * 1024 + 1);
|
|
123421
123603
|
let length = 0;
|
|
123422
123604
|
while (length < bytes.length) {
|
|
123423
|
-
const count =
|
|
123605
|
+
const count = readSync24(0, bytes, length, bytes.length - length, null);
|
|
123424
123606
|
if (!count)
|
|
123425
123607
|
break;
|
|
123426
123608
|
length += count;
|
|
@@ -123976,17 +124158,17 @@ var exports_profiles = {};
|
|
|
123976
124158
|
__export(exports_profiles, {
|
|
123977
124159
|
registerProfiles: () => registerProfiles
|
|
123978
124160
|
});
|
|
123979
|
-
import { closeSync as
|
|
124161
|
+
import { closeSync as closeSync32, constants as constants31, fstatSync as fstatSync32, openSync as openSync32, readSync as readSync25, writeFileSync as writeFileSync28 } from "fs";
|
|
123980
124162
|
function readProfileInput(path) {
|
|
123981
|
-
const fd =
|
|
124163
|
+
const fd = openSync32(path, constants31.O_RDONLY | constants31.O_NONBLOCK);
|
|
123982
124164
|
try {
|
|
123983
|
-
const stat3 =
|
|
124165
|
+
const stat3 = fstatSync32(fd);
|
|
123984
124166
|
if (!stat3.isFile() || stat3.size > MAX_PROFILE_DOCUMENT_BYTES)
|
|
123985
124167
|
throw new Error("Profile input exceeds the size limit or is not a regular file");
|
|
123986
124168
|
const bytes = Buffer.alloc(MAX_PROFILE_DOCUMENT_BYTES + 1);
|
|
123987
124169
|
let size2 = 0;
|
|
123988
124170
|
while (size2 < bytes.length) {
|
|
123989
|
-
const read3 =
|
|
124171
|
+
const read3 = readSync25(fd, bytes, size2, bytes.length - size2, null);
|
|
123990
124172
|
if (!read3)
|
|
123991
124173
|
break;
|
|
123992
124174
|
size2 += read3;
|
|
@@ -123995,7 +124177,7 @@ function readProfileInput(path) {
|
|
|
123995
124177
|
throw new Error("Profile input exceeds the size limit");
|
|
123996
124178
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
|
|
123997
124179
|
} finally {
|
|
123998
|
-
|
|
124180
|
+
closeSync32(fd);
|
|
123999
124181
|
}
|
|
124000
124182
|
}
|
|
124001
124183
|
function registerProfiles(parent) {
|
|
@@ -124409,23 +124591,23 @@ __export(exports_grants, {
|
|
|
124409
124591
|
registerGrants: () => registerGrants
|
|
124410
124592
|
});
|
|
124411
124593
|
import {
|
|
124412
|
-
constants as
|
|
124413
|
-
closeSync as
|
|
124414
|
-
fstatSync as
|
|
124415
|
-
openSync as
|
|
124416
|
-
readSync as
|
|
124594
|
+
constants as constants32,
|
|
124595
|
+
closeSync as closeSync33,
|
|
124596
|
+
fstatSync as fstatSync33,
|
|
124597
|
+
openSync as openSync33,
|
|
124598
|
+
readSync as readSync26,
|
|
124417
124599
|
writeFileSync as writeFileSync29
|
|
124418
124600
|
} from "fs";
|
|
124419
124601
|
function readInput(path) {
|
|
124420
|
-
const fd =
|
|
124602
|
+
const fd = openSync33(path, constants32.O_RDONLY | constants32.O_NONBLOCK);
|
|
124421
124603
|
try {
|
|
124422
|
-
const stat3 =
|
|
124604
|
+
const stat3 = fstatSync33(fd);
|
|
124423
124605
|
if (!stat3.isFile() || stat3.size > MAX_EXECUTION_GRANT_BYTES)
|
|
124424
124606
|
throw new Error("Grant input must be a regular file within the policy size limit.");
|
|
124425
124607
|
const bytes = Buffer.alloc(MAX_EXECUTION_GRANT_BYTES + 1);
|
|
124426
124608
|
let size2 = 0;
|
|
124427
124609
|
while (size2 < bytes.length) {
|
|
124428
|
-
const count =
|
|
124610
|
+
const count = readSync26(fd, bytes, size2, bytes.length - size2, null);
|
|
124429
124611
|
if (!count)
|
|
124430
124612
|
break;
|
|
124431
124613
|
size2 += count;
|
|
@@ -124438,7 +124620,7 @@ function readInput(path) {
|
|
|
124438
124620
|
throw new Error("Grant input must be a JSON document containing a grants array.");
|
|
124439
124621
|
}
|
|
124440
124622
|
} finally {
|
|
124441
|
-
|
|
124623
|
+
closeSync33(fd);
|
|
124442
124624
|
}
|
|
124443
124625
|
}
|
|
124444
124626
|
function registerGrants(parent) {
|
|
@@ -125221,17 +125403,17 @@ var exports_metadata = {};
|
|
|
125221
125403
|
__export(exports_metadata, {
|
|
125222
125404
|
registerMetadata: () => registerMetadata
|
|
125223
125405
|
});
|
|
125224
|
-
import { closeSync as
|
|
125406
|
+
import { closeSync as closeSync34, constants as constants33, fstatSync as fstatSync34, openSync as openSync34, readFileSync as readFileSync53, readSync as readSync27, writeFileSync as writeFileSync32 } from "fs";
|
|
125225
125407
|
function readPlan(path) {
|
|
125226
|
-
const fd =
|
|
125408
|
+
const fd = openSync34(path, constants33.O_RDONLY | constants33.O_NONBLOCK | constants33.O_NOFOLLOW);
|
|
125227
125409
|
try {
|
|
125228
|
-
const stat3 =
|
|
125410
|
+
const stat3 = fstatSync34(fd);
|
|
125229
125411
|
if (!stat3.isFile() || stat3.size > 8 * 1024 * 1024)
|
|
125230
125412
|
throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
|
|
125231
125413
|
const bytes = Buffer.alloc(stat3.size + 1);
|
|
125232
125414
|
let size2 = 0;
|
|
125233
125415
|
while (size2 < bytes.length) {
|
|
125234
|
-
const count =
|
|
125416
|
+
const count = readSync27(fd, bytes, size2, bytes.length - size2, null);
|
|
125235
125417
|
if (!count)
|
|
125236
125418
|
break;
|
|
125237
125419
|
size2 += count;
|
|
@@ -125240,7 +125422,7 @@ function readPlan(path) {
|
|
|
125240
125422
|
throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
|
|
125241
125423
|
return metadataPlan(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2))));
|
|
125242
125424
|
} finally {
|
|
125243
|
-
|
|
125425
|
+
closeSync34(fd);
|
|
125244
125426
|
}
|
|
125245
125427
|
}
|
|
125246
125428
|
function failure(error61) {
|
|
@@ -125606,7 +125788,7 @@ var init_registry_sync = __esm(() => {
|
|
|
125606
125788
|
});
|
|
125607
125789
|
|
|
125608
125790
|
// src/lib/review-export.ts
|
|
125609
|
-
import { constants as
|
|
125791
|
+
import { constants as constants34, closeSync as closeSync35, existsSync as existsSync38, fstatSync as fstatSync35, fsyncSync as fsyncSync10, lstatSync as lstatSync51, openSync as openSync35, realpathSync as realpathSync25, statSync as statSync27, writeFileSync as writeFileSync34 } from "fs";
|
|
125610
125792
|
import { basename as basename26, dirname as dirname52, isAbsolute as isAbsolute49, join as join80, parse as parse13, resolve as resolve48, sep as sep25 } from "path";
|
|
125611
125793
|
function exactVersion(spec) {
|
|
125612
125794
|
const at2 = spec.indexOf("@");
|
|
@@ -125670,16 +125852,16 @@ async function exportSkillVersionForReview(spec, output2, client2) {
|
|
|
125670
125852
|
if (bytes.byteLength !== metadata2.bundleByteSize || sha256Hex(bytes) !== metadata2.bundleSha256.toLowerCase()) {
|
|
125671
125853
|
throw new Error("Published bundle bytes do not match the exact version metadata.");
|
|
125672
125854
|
}
|
|
125673
|
-
const fd =
|
|
125855
|
+
const fd = openSync35(target, constants34.O_WRONLY | constants34.O_CREAT | constants34.O_EXCL | constants34.O_NOFOLLOW, 384);
|
|
125674
125856
|
try {
|
|
125675
125857
|
writeFileSync34(fd, bytes);
|
|
125676
125858
|
fsyncSync10(fd);
|
|
125677
|
-
if (
|
|
125859
|
+
if (fstatSync35(fd).size !== bytes.byteLength)
|
|
125678
125860
|
throw new Error("Incomplete review output write.");
|
|
125679
125861
|
} catch (error61) {
|
|
125680
125862
|
throw new Error(`Review output write failed. A private partial file may remain at ${target}; use Trash to remove it before reusing this path.`, { cause: error61 });
|
|
125681
125863
|
} finally {
|
|
125682
|
-
|
|
125864
|
+
closeSync35(fd);
|
|
125683
125865
|
}
|
|
125684
125866
|
return { slug: slug2, version: version2, bundleSha256: metadata2.bundleSha256.toLowerCase(), bundleByteSize: bytes.byteLength, output: target };
|
|
125685
125867
|
}
|
|
@@ -126217,7 +126399,7 @@ function verifySessionOptions(options) {
|
|
|
126217
126399
|
if (options.userId === undefined !== (options.membershipId === undefined) || options.userId !== undefined && (!publicationUuid(options.userId) || !publicationUuid(options.membershipId)))
|
|
126218
126400
|
throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide both observed --user-id and --membership-id UUIDs.");
|
|
126219
126401
|
if (!options.codeStdin && (options.json || !process.stdin.isTTY || !process.stderr.isTTY))
|
|
126220
|
-
throw new PrivatePublicationError("PUBLICATION_CODE_REQUIRED", "Use --code-stdin with a fresh code for noninteractive
|
|
126402
|
+
throw new PrivatePublicationError("PUBLICATION_CODE_REQUIRED", "Use --code-stdin with a fresh code for noninteractive private-skill commands.");
|
|
126221
126403
|
}
|
|
126222
126404
|
function verifyOptions(options, action) {
|
|
126223
126405
|
verifySessionOptions(options);
|
|
@@ -126273,6 +126455,45 @@ function registerPrivatePublications(parent) {
|
|
|
126273
126455
|
process.exitCode = 1;
|
|
126274
126456
|
}
|
|
126275
126457
|
});
|
|
126458
|
+
group.command("versions").allowExcessArguments(false).description("Read one page of a private skill's versions and current version using fresh interactive sign-in").argument("<skill-id>", "Private or team skill UUID from the workspace catalog or create result").requiredOption("--email <email>", "Account email for fresh interactive verification").option("--user-id <uuid>", "Observed account UUID (required without an enrolled named profile)").option("--membership-id <uuid>", "Observed workspace membership UUID").option("--code-stdin", "Read a fresh six-digit verification code from stdin").option("--limit <count>", "Page size from 1 to 50", "20").option("--cursor <uuid>", "Read the next page using its returned cursor").option("--json", "Output validated history metadata without credentials or source content").action(async (skillId, options) => {
|
|
126459
|
+
try {
|
|
126460
|
+
if (!publicationUuid(skillId) || !/^[1-9]\d?$/.test(options.limit) || Number(options.limit) > 50 || options.cursor !== undefined && !publicationUuid(options.cursor))
|
|
126461
|
+
throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_INPUT", "Provide a private skill UUID, --limit from 1 to 50, and an optional UUID --cursor.");
|
|
126462
|
+
verifySessionOptions(options);
|
|
126463
|
+
const context2 = options.userId ? { userId: options.userId, membershipId: options.membershipId } : undefined;
|
|
126464
|
+
const pending = preparePrivateSkillHistorySession(context2);
|
|
126465
|
+
let code2;
|
|
126466
|
+
if (options.codeStdin)
|
|
126467
|
+
code2 = await readCode();
|
|
126468
|
+
else {
|
|
126469
|
+
await new RemoteSkillsAuthClient(pending.origin).requestCode(options.email);
|
|
126470
|
+
code2 = await promptCode();
|
|
126471
|
+
}
|
|
126472
|
+
if (code2 === null)
|
|
126473
|
+
return;
|
|
126474
|
+
const client2 = await pending.verify(options.email, code2);
|
|
126475
|
+
const history = await client2.listVersions(skillId, { limit: Number(options.limit), cursor: options.cursor });
|
|
126476
|
+
if (options.json)
|
|
126477
|
+
console.log(JSON.stringify(history));
|
|
126478
|
+
else {
|
|
126479
|
+
console.log(`Private versions of ${history.slug} (${history.skillId})`);
|
|
126480
|
+
console.log(`Current version: ${history.currentVersion ?? "Not published yet"}`);
|
|
126481
|
+
if (!history.versions.length)
|
|
126482
|
+
console.log("No versions on this page.");
|
|
126483
|
+
for (const version2 of history.versions)
|
|
126484
|
+
console.log(` ${version2.version}${version2.id === history.currentVersionId ? " (current)" : ""} published: ${version2.releasedAt ?? "Not released"} created: ${version2.createdAt}`);
|
|
126485
|
+
if (history.nextCursor)
|
|
126486
|
+
console.log(`More versions: repeat this command with --cursor ${history.nextCursor} and fresh verification.`);
|
|
126487
|
+
}
|
|
126488
|
+
} catch (error61) {
|
|
126489
|
+
const result2 = error61 instanceof PrivatePublicationError ? privatePublicationCustomerError(error61) : { error: "Unable to read private version history. Check the selected account, workspace and fresh verification; no skill or credential was changed.", code: "PRIVATE_HISTORY_UNAVAILABLE", uncertain: false };
|
|
126490
|
+
if (options.json)
|
|
126491
|
+
console.log(JSON.stringify(result2));
|
|
126492
|
+
else
|
|
126493
|
+
console.error(result2.error);
|
|
126494
|
+
process.exitCode = 1;
|
|
126495
|
+
}
|
|
126496
|
+
});
|
|
126276
126497
|
const publishCommand = group.command("publish").allowExcessArguments(false).description("Publish private source with explicit current-version comparison").requiredOption("--recovery-dir <directory>", "New recovery directory for publish; existing directory for other actions").requiredOption("--email <email>", "Account email for fresh interactive verification").option("--user-id <uuid>", "Observed account UUID (required without an enrolled named profile)").option("--membership-id <uuid>", "Observed workspace membership UUID").option("--code-stdin", "Read a fresh six-digit verification code from stdin").option("--json", "Output a safe result without session credentials or upload URLs").option("--confirm", "Explicitly approve this action").argument("<directory>", "Validated local skill directory").requiredOption("--skill-id <uuid>", "Existing private/team skill UUID").option("--expected-current-version <uuid>", "Compare against the observed current version UUID").option("--expect-empty", "Require the skill to have no current version").option("--idempotency-key <uuid>", "Stable intent key; generated and saved before begin when omitted").option("--wait-seconds <seconds>", "Bounded status wait from 0 to 300", "60");
|
|
126277
126498
|
const statusCommand = group.command("status").allowExcessArguments(false).description("Inspect the exact saved publication").requiredOption("--recovery-dir <directory>", "New recovery directory for publish; existing directory for other actions").requiredOption("--email <email>", "Account email for fresh interactive verification").option("--user-id <uuid>", "Observed account UUID (required without an enrolled named profile)").option("--membership-id <uuid>", "Observed workspace membership UUID").option("--code-stdin", "Read a fresh six-digit verification code from stdin").option("--json", "Output a safe result without session credentials or upload URLs");
|
|
126278
126499
|
const resumeCommand = group.command("resume").allowExcessArguments(false).description("Reconcile the saved intent without creating a replacement").requiredOption("--recovery-dir <directory>", "New recovery directory for publish; existing directory for other actions").requiredOption("--email <email>", "Account email for fresh interactive verification").option("--user-id <uuid>", "Observed account UUID (required without an enrolled named profile)").option("--membership-id <uuid>", "Observed workspace membership UUID").option("--code-stdin", "Read a fresh six-digit verification code from stdin").option("--json", "Output a safe result without session credentials or upload URLs").option("--confirm", "Explicitly approve this action").option("--wait-seconds <seconds>", "Bounded status wait from 0 to 300", "60");
|