@hasna/skills 0.10.81 → 0.10.83
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 +279 -57
- package/bin/mcp.js +121 -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 +117 -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 +3 -2
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.js +117 -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.83",
|
|
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
|
|
|
@@ -57442,6 +57455,7 @@ var init_hook_diagnostics = __esm(() => {
|
|
|
57442
57455
|
"CACHED_PROFILE_EXPIRED",
|
|
57443
57456
|
"CACHED_PROFILE_MISSING",
|
|
57444
57457
|
"CACHED_BUNDLE_MISSING",
|
|
57458
|
+
"PROFILE_LOCK_MISMATCH",
|
|
57445
57459
|
"SESSION_RECONCILIATION_REQUIRED",
|
|
57446
57460
|
"SESSION_RENEWAL_TIMEOUT",
|
|
57447
57461
|
"SESSION_WRITE_BUSY",
|
|
@@ -67851,7 +67865,7 @@ function checkedPublicationView(value, skillId, intentId, declaration) {
|
|
|
67851
67865
|
return invalid3();
|
|
67852
67866
|
return Object.freeze({ ...value });
|
|
67853
67867
|
}
|
|
67854
|
-
async function boundedJson(url, init, token, mutation, budget2 = 15000, signal, create3 = false) {
|
|
67868
|
+
async function boundedJson(url, init, token, mutation, budget2 = 15000, signal, create3 = false, readBinding) {
|
|
67855
67869
|
const controller = new AbortController;
|
|
67856
67870
|
let reader;
|
|
67857
67871
|
let response;
|
|
@@ -67867,8 +67881,18 @@ async function boundedJson(url, init, token, mutation, budget2 = 15000, signal,
|
|
|
67867
67881
|
redirect: "error",
|
|
67868
67882
|
credentials: "omit",
|
|
67869
67883
|
signal: controller.signal,
|
|
67870
|
-
headers: {
|
|
67884
|
+
headers: {
|
|
67885
|
+
"Content-Type": "application/json",
|
|
67886
|
+
Authorization: `Bearer ${token}`,
|
|
67887
|
+
...readBinding ? {
|
|
67888
|
+
"x-skills-user-id": readBinding.userId,
|
|
67889
|
+
"x-skills-workspace-id": readBinding.organizationId,
|
|
67890
|
+
"x-skills-membership-id": readBinding.membershipId
|
|
67891
|
+
} : {}
|
|
67892
|
+
}
|
|
67871
67893
|
});
|
|
67894
|
+
if (readBinding && response.ok && response.status !== 200)
|
|
67895
|
+
return invalid3();
|
|
67872
67896
|
const length = response.headers.get("content-length");
|
|
67873
67897
|
if (length !== null && (!/^\d+$/.test(length) || Number(length) > 65536))
|
|
67874
67898
|
return invalid3();
|
|
@@ -67936,6 +67960,81 @@ async function boundedJson(url, init, token, mutation, budget2 = 15000, signal,
|
|
|
67936
67960
|
response?.body?.cancel().catch(() => {});
|
|
67937
67961
|
}
|
|
67938
67962
|
}
|
|
67963
|
+
function historyDate(value) {
|
|
67964
|
+
if (typeof value !== "string")
|
|
67965
|
+
return false;
|
|
67966
|
+
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);
|
|
67967
|
+
if (!parts)
|
|
67968
|
+
return false;
|
|
67969
|
+
const [, y, m, d, separator, h, minute, second, fraction, zone, offsetHour, offsetMinute] = parts;
|
|
67970
|
+
if (separator === " " ? zone === "Z" || (fraction?.length ?? 0) > 6 : zone !== "Z" && offsetMinute === undefined)
|
|
67971
|
+
return false;
|
|
67972
|
+
const year = Number(y), month = Number(m), day = Number(d);
|
|
67973
|
+
const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
67974
|
+
const days = [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
67975
|
+
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);
|
|
67976
|
+
}
|
|
67977
|
+
function privateHistory(value, organizationId, skillId, limit, cursor) {
|
|
67978
|
+
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)
|
|
67979
|
+
return historyResponse();
|
|
67980
|
+
const seen = new Set;
|
|
67981
|
+
let previous = cursor;
|
|
67982
|
+
const versions = value.versions.map((row) => {
|
|
67983
|
+
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))
|
|
67984
|
+
return historyResponse();
|
|
67985
|
+
seen.add(row.id);
|
|
67986
|
+
previous = row.id;
|
|
67987
|
+
return Object.freeze({ id: row.id, version: row.version, releasedAt: row.releasedAt, createdAt: row.createdAt });
|
|
67988
|
+
});
|
|
67989
|
+
if (value.nextCursor !== null && (!versions.length || value.nextCursor !== versions.at(-1).id))
|
|
67990
|
+
return historyResponse();
|
|
67991
|
+
return Object.freeze({
|
|
67992
|
+
organizationId,
|
|
67993
|
+
skillId,
|
|
67994
|
+
slug: value.slug,
|
|
67995
|
+
currentVersion: value.currentVersion,
|
|
67996
|
+
currentVersionId: value.currentVersionId,
|
|
67997
|
+
versions: Object.freeze(versions),
|
|
67998
|
+
nextCursor: value.nextCursor
|
|
67999
|
+
});
|
|
68000
|
+
}
|
|
68001
|
+
|
|
68002
|
+
class RemotePrivateSkillHistoryClient {
|
|
68003
|
+
apiOrigin;
|
|
68004
|
+
organizationId;
|
|
68005
|
+
userId;
|
|
68006
|
+
membershipId;
|
|
68007
|
+
#token;
|
|
68008
|
+
constructor(apiUrl, session) {
|
|
68009
|
+
const checked = parseWorkspaceSession(session, { userId: session?.user?.id, membershipId: session?.user?.membershipId });
|
|
68010
|
+
this.apiOrigin = normalizeSkillsApiOrigin(apiUrl);
|
|
68011
|
+
this.#token = checked.token;
|
|
68012
|
+
this.organizationId = checked.organization.id;
|
|
68013
|
+
this.userId = checked.user.id;
|
|
68014
|
+
this.membershipId = checked.user.membershipId;
|
|
68015
|
+
Object.freeze(this);
|
|
68016
|
+
}
|
|
68017
|
+
async listVersions(skillId, options = {}) {
|
|
68018
|
+
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))
|
|
68019
|
+
return historyInput();
|
|
68020
|
+
const limit = options.limit ?? 20, cursor = options.cursor;
|
|
68021
|
+
const query = new URLSearchParams;
|
|
68022
|
+
if (options.limit !== undefined)
|
|
68023
|
+
query.set("limit", String(limit));
|
|
68024
|
+
if (cursor !== undefined)
|
|
68025
|
+
query.set("cursor", cursor);
|
|
68026
|
+
const path = `/api/v1/skills/${skillId}/versions${query.size ? `?${query}` : ""}`;
|
|
68027
|
+
let value;
|
|
68028
|
+
try {
|
|
68029
|
+
value = await boundedJson(skillsApiRequestUrl(this.apiOrigin, path), { method: "GET" }, this.#token, false, options.timeoutMs, options.signal, false, this);
|
|
68030
|
+
} catch (error) {
|
|
68031
|
+
if (error instanceof PrivatePublicationError && error.code === "INVALID_PUBLICATION_RESPONSE")
|
|
68032
|
+
return historyResponse();
|
|
68033
|
+
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);
|
|
68034
|
+
}
|
|
68035
|
+
return privateHistory(value, this.organizationId, skillId, limit, cursor);
|
|
68036
|
+
}
|
|
68037
|
+
}
|
|
67939
68038
|
|
|
67940
68039
|
class RemotePrivatePublicationsClient {
|
|
67941
68040
|
apiOrigin;
|
|
@@ -68109,7 +68208,11 @@ var PRIVATE_PUBLICATION_MAX_BYTES, skillCreateFailures, failures, PrivatePublica
|
|
|
68109
68208
|
throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
|
|
68110
68209
|
}, invalid3 = () => {
|
|
68111
68210
|
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")
|
|
68211
|
+
}, 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 = () => {
|
|
68212
|
+
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.");
|
|
68213
|
+
}, historyResponse = () => {
|
|
68214
|
+
throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_RESPONSE", "The server returned invalid private version history.");
|
|
68215
|
+
}, historyText = (value) => typeof value === "string" && value.length > 0 && value.length <= 128 && !/[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value);
|
|
68113
68216
|
var init_remote_private_publications = __esm(() => {
|
|
68114
68217
|
init_fleet_credentials();
|
|
68115
68218
|
init_remote_workspace_selection();
|
|
@@ -89514,6 +89617,10 @@ class RemoteSkillsAuthClient {
|
|
|
89514
89617
|
const origin = this.apiOrigin, captured = workspaceContext(context);
|
|
89515
89618
|
return new RemotePrivatePublicationsClient(origin, await this.switchWorkspace(email4, code, captured));
|
|
89516
89619
|
}
|
|
89620
|
+
async openPrivateSkillHistory(email4, code, context) {
|
|
89621
|
+
const origin = this.apiOrigin, captured = workspaceContext(context);
|
|
89622
|
+
return new RemotePrivateSkillHistoryClient(origin, await this.switchWorkspace(email4, code, captured));
|
|
89623
|
+
}
|
|
89517
89624
|
requestInvitationEmailChallenge(input2) {
|
|
89518
89625
|
return requestInvitationEmail(this.apiOrigin, "challenge", input2);
|
|
89519
89626
|
}
|
|
@@ -116446,7 +116553,7 @@ var init_remote_invitation_tools = __esm(() => {
|
|
|
116446
116553
|
});
|
|
116447
116554
|
|
|
116448
116555
|
// src/lib/private-publication-customer.ts
|
|
116449
|
-
function
|
|
116556
|
+
function preparePrivateSession(requested, action, open2) {
|
|
116450
116557
|
const selectors = [
|
|
116451
116558
|
"HASNA_PROFILE",
|
|
116452
116559
|
"HASNA_HOME",
|
|
@@ -116460,7 +116567,7 @@ function preparePrivatePublicationSession(requested) {
|
|
|
116460
116567
|
"SKILLS_API_KEY"
|
|
116461
116568
|
];
|
|
116462
116569
|
const before2 = new Map(selectors.map((key2) => [key2, process.env[key2]]));
|
|
116463
|
-
const profile = selectedSkillsProfile(process.env), pending = prepareProfileWorkspace(
|
|
116570
|
+
const profile = selectedSkillsProfile(process.env), pending = prepareProfileWorkspace(action);
|
|
116464
116571
|
const captured = requested ? { ...requested } : undefined;
|
|
116465
116572
|
const unchanged3 = () => {
|
|
116466
116573
|
if (selectors.some((key2) => process.env[key2] !== before2.get(key2)) || selectedSkillsProfile(process.env) !== profile)
|
|
@@ -116474,12 +116581,18 @@ function preparePrivatePublicationSession(requested) {
|
|
|
116474
116581
|
throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide the observed user and membership IDs, or select an enrolled workspace profile.");
|
|
116475
116582
|
unchanged3();
|
|
116476
116583
|
target.unchanged();
|
|
116477
|
-
const client2 = await new RemoteSkillsAuthClient(target.origin)
|
|
116584
|
+
const client2 = await open2(new RemoteSkillsAuthClient(target.origin), email5, code2, context2);
|
|
116478
116585
|
unchanged3();
|
|
116479
116586
|
target.unchanged();
|
|
116480
116587
|
return client2;
|
|
116481
116588
|
} };
|
|
116482
116589
|
}
|
|
116590
|
+
function preparePrivatePublicationSession(requested) {
|
|
116591
|
+
return preparePrivateSession(requested, "Manage private publications", (auth, email5, code2, context2) => auth.openPrivatePublications(email5, code2, context2));
|
|
116592
|
+
}
|
|
116593
|
+
function preparePrivateSkillHistorySession(requested) {
|
|
116594
|
+
return preparePrivateSession(requested, "Read private version history", (auth, email5, code2, context2) => auth.openPrivateSkillHistory(email5, code2, context2));
|
|
116595
|
+
}
|
|
116483
116596
|
async function privatePublicationSession(email5, code2, requested) {
|
|
116484
116597
|
return preparePrivatePublicationSession(requested).verify(email5, code2);
|
|
116485
116598
|
}
|
|
@@ -117201,7 +117314,7 @@ var exports_runtime_mcp = {};
|
|
|
117201
117314
|
__export(exports_runtime_mcp, {
|
|
117202
117315
|
handleMcp: () => handleMcp
|
|
117203
117316
|
});
|
|
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";
|
|
117317
|
+
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
117318
|
import { randomUUID as randomUUID10 } from "crypto";
|
|
117206
117319
|
import { homedir as homedir10 } from "os";
|
|
117207
117320
|
import { dirname as dirname40, isAbsolute as isAbsolute38, join as join66 } from "path";
|
|
@@ -117270,10 +117383,14 @@ async function registerClaudeMcp(command, server2, environment) {
|
|
|
117270
117383
|
const desired = { type: "stdio", ...server2, env: environment };
|
|
117271
117384
|
try {
|
|
117272
117385
|
const path = claudeUserConfigPath();
|
|
117386
|
+
const firstRun = lstatSync40(path, { throwIfNoEntry: false }) === undefined ? claudeFirstRunPathWitness(path) : undefined;
|
|
117273
117387
|
const before2 = withClaudeConfigLock(path, () => {
|
|
117274
117388
|
if (claudeUserConfigPath() !== path)
|
|
117275
117389
|
throw new Error;
|
|
117390
|
+
firstRun?.();
|
|
117276
117391
|
const bytes = readClaudeConfig(path);
|
|
117392
|
+
if (firstRun && bytes !== null)
|
|
117393
|
+
throw new Error;
|
|
117277
117394
|
if (bytes !== null) {
|
|
117278
117395
|
const backup = `${path}.skills-mcp-${randomUUID10()}.backup`;
|
|
117279
117396
|
writeFileSync23(backup, bytes, { flag: "wx", mode: 384 });
|
|
@@ -117308,11 +117425,11 @@ async function registerClaudeMcp(command, server2, environment) {
|
|
|
117308
117425
|
return withClaudeConfigLock(path, () => {
|
|
117309
117426
|
if (claudeUserConfigPath() !== path)
|
|
117310
117427
|
throw new Error;
|
|
117311
|
-
const current = readClaudeConfig(path);
|
|
117428
|
+
const current = firstRun ? readClaudeFirstRunConfig(path, firstRun) : readClaudeConfig(path);
|
|
117312
117429
|
const previous = parseClaudeConfig(before2), data = parseClaudeConfig(current);
|
|
117313
117430
|
if (exitCode === 0) {
|
|
117314
117431
|
const actual = isPlainObject4(data.mcpServers) ? data.mcpServers[MCP_SERVER_NAME] : undefined;
|
|
117315
|
-
if (!claudeNativeConfigPreserved(previous, data) || !isPlainObject4(actual) || !isDeepStrictEqual17({ ...actual, env: actual.env ?? {} }, desired))
|
|
117432
|
+
if (!claudeNativeConfigPreserved(previous, data, firstRun !== undefined && before2 === null) || !isPlainObject4(actual) || !isDeepStrictEqual17({ ...actual, env: actual.env ?? {} }, desired))
|
|
117316
117433
|
throw new Error;
|
|
117317
117434
|
} else {
|
|
117318
117435
|
if (!cliUnavailable && (!duplicateAccepted || !isPlainObject4(previous.mcpServers) || !previous.mcpServers[MCP_SERVER_NAME]))
|
|
@@ -117326,7 +117443,7 @@ async function registerClaudeMcp(command, server2, environment) {
|
|
|
117326
117443
|
writeFileSync23(temporary, next, { flag: "wx", mode: 384 });
|
|
117327
117444
|
if (!readFileSync43(temporary).equals(next))
|
|
117328
117445
|
throw new Error;
|
|
117329
|
-
const latest = readClaudeConfig(path);
|
|
117446
|
+
const latest = firstRun ? readClaudeFirstRunConfig(path, firstRun) : readClaudeConfig(path);
|
|
117330
117447
|
if (claudeUserConfigPath() !== path || (before2 === null ? latest !== null : latest === null || !latest.equals(before2)))
|
|
117331
117448
|
throw new Error;
|
|
117332
117449
|
renameSync14(temporary, path);
|
|
@@ -117360,27 +117477,92 @@ function claudeUserConfigPath() {
|
|
|
117360
117477
|
return modern;
|
|
117361
117478
|
}
|
|
117362
117479
|
function readClaudeConfig(path) {
|
|
117363
|
-
|
|
117480
|
+
const info = lstatSync40(path, { throwIfNoEntry: false });
|
|
117481
|
+
if (info === undefined)
|
|
117364
117482
|
return null;
|
|
117365
|
-
const info = lstatSync40(path);
|
|
117366
117483
|
if (!info.isFile() || info.size > 16777216)
|
|
117367
117484
|
throw new Error;
|
|
117368
117485
|
const bytes = readFileSync43(path);
|
|
117369
117486
|
parseClaudeConfig(bytes);
|
|
117370
117487
|
return bytes;
|
|
117371
117488
|
}
|
|
117489
|
+
function claudeFirstRunPathWitness(path) {
|
|
117490
|
+
if (!process.getuid || constants28.O_NOFOLLOW === undefined)
|
|
117491
|
+
throw new Error;
|
|
117492
|
+
const uid2 = BigInt(process.getuid()), canonical9 = canonicalSystemPath(path);
|
|
117493
|
+
const identity6 = (info) => `${info.dev}:${info.ino}:${info.uid}:${info.gid}:${info.mode}`;
|
|
117494
|
+
const directories = [];
|
|
117495
|
+
for (let cursor2 = dirname40(canonical9);; cursor2 = dirname40(cursor2)) {
|
|
117496
|
+
directories.unshift({ path: cursor2, identity: "" });
|
|
117497
|
+
if (dirname40(cursor2) === cursor2)
|
|
117498
|
+
break;
|
|
117499
|
+
}
|
|
117500
|
+
const verify = () => {
|
|
117501
|
+
if (canonicalSystemPath(path) !== canonical9)
|
|
117502
|
+
throw new Error;
|
|
117503
|
+
for (const directory3 of directories) {
|
|
117504
|
+
const info = lstatSync40(directory3.path, { bigint: true });
|
|
117505
|
+
if (!info.isDirectory() || identity6(info) !== directory3.identity)
|
|
117506
|
+
throw new Error;
|
|
117507
|
+
}
|
|
117508
|
+
};
|
|
117509
|
+
for (const directory3 of directories) {
|
|
117510
|
+
let info = lstatSync40(directory3.path, { bigint: true, throwIfNoEntry: false });
|
|
117511
|
+
if (!info) {
|
|
117512
|
+
mkdirSync26(directory3.path, { mode: 448 });
|
|
117513
|
+
info = lstatSync40(directory3.path, { bigint: true });
|
|
117514
|
+
}
|
|
117515
|
+
if (!info.isDirectory() || info.uid !== 0n && info.uid !== uid2 || (info.mode & 0o022n) !== 0n && !(info.uid === 0n && (info.mode & 0o1000n) !== 0n))
|
|
117516
|
+
throw new Error;
|
|
117517
|
+
directory3.identity = identity6(info);
|
|
117518
|
+
}
|
|
117519
|
+
verify();
|
|
117520
|
+
if (lstatSync40(path, { throwIfNoEntry: false }) !== undefined)
|
|
117521
|
+
throw new Error;
|
|
117522
|
+
return verify;
|
|
117523
|
+
}
|
|
117524
|
+
function readClaudeFirstRunConfig(path, verifyPath) {
|
|
117525
|
+
verifyPath();
|
|
117526
|
+
const before2 = lstatSync40(path, { bigint: true, throwIfNoEntry: false });
|
|
117527
|
+
if (!before2)
|
|
117528
|
+
return null;
|
|
117529
|
+
const identity6 = (info) => `${info.dev}:${info.ino}:${info.uid}:${info.gid}:${info.mode}:${info.nlink}:${info.size}:${info.mtimeNs}:${info.ctimeNs}`;
|
|
117530
|
+
if (!before2.isFile() || before2.nlink !== 1n || before2.uid !== BigInt(process.getuid()) || (before2.mode & 0o022n) !== 0n || before2.size > 16n * 1024n * 1024n)
|
|
117531
|
+
throw new Error;
|
|
117532
|
+
const fd = openSync29(path, constants28.O_RDONLY | constants28.O_NOFOLLOW | constants28.O_NONBLOCK);
|
|
117533
|
+
try {
|
|
117534
|
+
if (identity6(fstatSync29(fd, { bigint: true })) !== identity6(before2))
|
|
117535
|
+
throw new Error;
|
|
117536
|
+
const bytes = Buffer.alloc(Number(before2.size) + 1);
|
|
117537
|
+
let length = 0;
|
|
117538
|
+
while (length < bytes.length) {
|
|
117539
|
+
const count = readSync21(fd, bytes, length, bytes.length - length, null);
|
|
117540
|
+
if (!count)
|
|
117541
|
+
break;
|
|
117542
|
+
length += count;
|
|
117543
|
+
}
|
|
117544
|
+
if (BigInt(length) !== before2.size || identity6(fstatSync29(fd, { bigint: true })) !== identity6(before2) || identity6(lstatSync40(path, { bigint: true })) !== identity6(before2))
|
|
117545
|
+
throw new Error;
|
|
117546
|
+
const content = bytes.subarray(0, length);
|
|
117547
|
+
verifyPath();
|
|
117548
|
+
parseClaudeConfig(content);
|
|
117549
|
+
return content;
|
|
117550
|
+
} finally {
|
|
117551
|
+
closeSync29(fd);
|
|
117552
|
+
}
|
|
117553
|
+
}
|
|
117372
117554
|
function parseClaudeConfig(bytes) {
|
|
117373
117555
|
const data = bytes === null ? {} : JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
117374
117556
|
if (!isPlainObject4(data) || data.mcpServers !== undefined && !isPlainObject4(data.mcpServers))
|
|
117375
117557
|
throw new Error;
|
|
117376
117558
|
return data;
|
|
117377
117559
|
}
|
|
117378
|
-
function claudeNativeConfigPreserved(before2, after2) {
|
|
117560
|
+
function claudeNativeConfigPreserved(before2, after2, firstRun = false) {
|
|
117379
117561
|
const previous = withoutClaudeSkills(before2), current = withoutClaudeSkills(after2);
|
|
117380
117562
|
for (const key2 of Object.keys(current)) {
|
|
117381
117563
|
if (Object.hasOwn(previous, key2))
|
|
117382
117564
|
continue;
|
|
117383
|
-
if (!isClaudeBootstrapAddition(key2, current[key2]))
|
|
117565
|
+
if (!(firstRun && key2 === "userID" && typeof current[key2] === "string" && /^[0-9a-f]{64}$/i.test(current[key2])) && !isClaudeBootstrapAddition(key2, current[key2]))
|
|
117384
117566
|
return false;
|
|
117385
117567
|
delete current[key2];
|
|
117386
117568
|
}
|
|
@@ -117562,6 +117744,7 @@ var MCP_SERVER_NAME = "skills", MCP_COMMAND_NAME = "skills-mcp";
|
|
|
117562
117744
|
var init_runtime_mcp = __esm(() => {
|
|
117563
117745
|
init_source();
|
|
117564
117746
|
init_installer();
|
|
117747
|
+
init_agent_integration();
|
|
117565
117748
|
init_credential_profile_command();
|
|
117566
117749
|
init_mcp_registration_environment();
|
|
117567
117750
|
});
|
|
@@ -120456,30 +120639,30 @@ var exports_recurring = {};
|
|
|
120456
120639
|
__export(exports_recurring, {
|
|
120457
120640
|
registerRecurringCommands: () => registerRecurringCommands
|
|
120458
120641
|
});
|
|
120459
|
-
import { constants as
|
|
120642
|
+
import { constants as constants29, closeSync as closeSync30, fstatSync as fstatSync30, lstatSync as lstatSync43, openSync as openSync30, readSync as readSync22 } from "fs";
|
|
120460
120643
|
import { createInterface as createInterface2 } from "readline";
|
|
120461
120644
|
function readRequest(path) {
|
|
120462
|
-
const fd =
|
|
120645
|
+
const fd = openSync30(path, constants29.O_RDONLY | constants29.O_NOFOLLOW | constants29.O_NONBLOCK);
|
|
120463
120646
|
try {
|
|
120464
|
-
const before2 =
|
|
120647
|
+
const before2 = fstatSync30(fd);
|
|
120465
120648
|
if (!before2.isFile() || before2.size > 1048576 || before2.size < 1)
|
|
120466
120649
|
throw new RecurringInputError;
|
|
120467
120650
|
const bytes = Buffer.alloc(before2.size + 1);
|
|
120468
120651
|
let length = 0;
|
|
120469
120652
|
while (length < bytes.length) {
|
|
120470
|
-
const n2 =
|
|
120653
|
+
const n2 = readSync22(fd, bytes, length, bytes.length - length, length);
|
|
120471
120654
|
if (!n2)
|
|
120472
120655
|
break;
|
|
120473
120656
|
length += n2;
|
|
120474
120657
|
}
|
|
120475
|
-
const after2 =
|
|
120658
|
+
const after2 = fstatSync30(fd), current = lstatSync43(path);
|
|
120476
120659
|
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
120660
|
throw new RecurringInputError;
|
|
120478
120661
|
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
|
|
120479
120662
|
} catch {
|
|
120480
120663
|
throw new RecurringInputError;
|
|
120481
120664
|
} finally {
|
|
120482
|
-
|
|
120665
|
+
closeSync30(fd);
|
|
120483
120666
|
}
|
|
120484
120667
|
}
|
|
120485
120668
|
async function acceptAtTerminal(draft) {
|
|
@@ -123119,7 +123302,7 @@ var init_claude_installer_binding = __esm(() => {
|
|
|
123119
123302
|
});
|
|
123120
123303
|
|
|
123121
123304
|
// src/cli/commands/claude-installer-capture.ts
|
|
123122
|
-
import { closeSync as
|
|
123305
|
+
import { closeSync as closeSync31, constants as constants30, fstatSync as fstatSync31, lstatSync as lstatSync48, openSync as openSync31, readSync as readSync23 } from "fs";
|
|
123123
123306
|
import { isAbsolute as isAbsolute46, resolve as resolve44 } from "path";
|
|
123124
123307
|
function need11(condition, code2) {
|
|
123125
123308
|
if (!condition)
|
|
@@ -123141,19 +123324,19 @@ function readRequest2(path) {
|
|
|
123141
123324
|
const before2 = lstatSync48(path, { throwIfNoEntry: false });
|
|
123142
123325
|
if (!before2?.isFile() || before2.isSymbolicLink() || before2.size > MAX_REQUEST_BYTES)
|
|
123143
123326
|
throw new CaptureRefusal("INVALID_REQUEST_FILE: --request must name a regular non-symlink JSON file no larger than 64 KiB");
|
|
123144
|
-
const fd =
|
|
123327
|
+
const fd = openSync31(path, constants30.O_RDONLY | (constants30.O_NOFOLLOW ?? 0) | constants30.O_NONBLOCK);
|
|
123145
123328
|
try {
|
|
123146
|
-
const opened =
|
|
123329
|
+
const opened = fstatSync31(fd);
|
|
123147
123330
|
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
123331
|
const bytes = Buffer.alloc(MAX_REQUEST_BYTES + 1);
|
|
123149
123332
|
let length = 0;
|
|
123150
123333
|
while (length < bytes.length) {
|
|
123151
|
-
const count =
|
|
123334
|
+
const count = readSync23(fd, bytes, length, bytes.length - length, null);
|
|
123152
123335
|
if (!count)
|
|
123153
123336
|
break;
|
|
123154
123337
|
length += count;
|
|
123155
123338
|
}
|
|
123156
|
-
const after2 =
|
|
123339
|
+
const after2 = fstatSync31(fd), current = lstatSync48(path);
|
|
123157
123340
|
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
123341
|
try {
|
|
123159
123342
|
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
|
|
@@ -123161,7 +123344,7 @@ function readRequest2(path) {
|
|
|
123161
123344
|
throw new CaptureRefusal("INVALID_REQUEST_JSON: --request must contain one valid UTF-8 JSON object");
|
|
123162
123345
|
}
|
|
123163
123346
|
} finally {
|
|
123164
|
-
|
|
123347
|
+
closeSync31(fd);
|
|
123165
123348
|
}
|
|
123166
123349
|
}
|
|
123167
123350
|
function paths(value) {
|
|
@@ -123305,7 +123488,7 @@ var exports_agent_integration = {};
|
|
|
123305
123488
|
__export(exports_agent_integration, {
|
|
123306
123489
|
registerAgentIntegration: () => registerAgentIntegration
|
|
123307
123490
|
});
|
|
123308
|
-
import { existsSync as existsSync36, lstatSync as lstatSync49, readFileSync as readFileSync50, readSync as
|
|
123491
|
+
import { existsSync as existsSync36, lstatSync as lstatSync49, readFileSync as readFileSync50, readSync as readSync24, writeFileSync as writeFileSync27 } from "fs";
|
|
123309
123492
|
import { createHash as createHash48 } from "crypto";
|
|
123310
123493
|
import { homedir as homedir14 } from "os";
|
|
123311
123494
|
import { basename as basename25, isAbsolute as isAbsolute47, resolve as resolve45 } from "path";
|
|
@@ -123420,7 +123603,7 @@ function registerAgentIntegration(parent) {
|
|
|
123420
123603
|
const bytes = Buffer.alloc(1024 * 1024 + 1);
|
|
123421
123604
|
let length = 0;
|
|
123422
123605
|
while (length < bytes.length) {
|
|
123423
|
-
const count =
|
|
123606
|
+
const count = readSync24(0, bytes, length, bytes.length - length, null);
|
|
123424
123607
|
if (!count)
|
|
123425
123608
|
break;
|
|
123426
123609
|
length += count;
|
|
@@ -123976,17 +124159,17 @@ var exports_profiles = {};
|
|
|
123976
124159
|
__export(exports_profiles, {
|
|
123977
124160
|
registerProfiles: () => registerProfiles
|
|
123978
124161
|
});
|
|
123979
|
-
import { closeSync as
|
|
124162
|
+
import { closeSync as closeSync32, constants as constants31, fstatSync as fstatSync32, openSync as openSync32, readSync as readSync25, writeFileSync as writeFileSync28 } from "fs";
|
|
123980
124163
|
function readProfileInput(path) {
|
|
123981
|
-
const fd =
|
|
124164
|
+
const fd = openSync32(path, constants31.O_RDONLY | constants31.O_NONBLOCK);
|
|
123982
124165
|
try {
|
|
123983
|
-
const stat3 =
|
|
124166
|
+
const stat3 = fstatSync32(fd);
|
|
123984
124167
|
if (!stat3.isFile() || stat3.size > MAX_PROFILE_DOCUMENT_BYTES)
|
|
123985
124168
|
throw new Error("Profile input exceeds the size limit or is not a regular file");
|
|
123986
124169
|
const bytes = Buffer.alloc(MAX_PROFILE_DOCUMENT_BYTES + 1);
|
|
123987
124170
|
let size2 = 0;
|
|
123988
124171
|
while (size2 < bytes.length) {
|
|
123989
|
-
const read3 =
|
|
124172
|
+
const read3 = readSync25(fd, bytes, size2, bytes.length - size2, null);
|
|
123990
124173
|
if (!read3)
|
|
123991
124174
|
break;
|
|
123992
124175
|
size2 += read3;
|
|
@@ -123995,7 +124178,7 @@ function readProfileInput(path) {
|
|
|
123995
124178
|
throw new Error("Profile input exceeds the size limit");
|
|
123996
124179
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
|
|
123997
124180
|
} finally {
|
|
123998
|
-
|
|
124181
|
+
closeSync32(fd);
|
|
123999
124182
|
}
|
|
124000
124183
|
}
|
|
124001
124184
|
function registerProfiles(parent) {
|
|
@@ -124409,23 +124592,23 @@ __export(exports_grants, {
|
|
|
124409
124592
|
registerGrants: () => registerGrants
|
|
124410
124593
|
});
|
|
124411
124594
|
import {
|
|
124412
|
-
constants as
|
|
124413
|
-
closeSync as
|
|
124414
|
-
fstatSync as
|
|
124415
|
-
openSync as
|
|
124416
|
-
readSync as
|
|
124595
|
+
constants as constants32,
|
|
124596
|
+
closeSync as closeSync33,
|
|
124597
|
+
fstatSync as fstatSync33,
|
|
124598
|
+
openSync as openSync33,
|
|
124599
|
+
readSync as readSync26,
|
|
124417
124600
|
writeFileSync as writeFileSync29
|
|
124418
124601
|
} from "fs";
|
|
124419
124602
|
function readInput(path) {
|
|
124420
|
-
const fd =
|
|
124603
|
+
const fd = openSync33(path, constants32.O_RDONLY | constants32.O_NONBLOCK);
|
|
124421
124604
|
try {
|
|
124422
|
-
const stat3 =
|
|
124605
|
+
const stat3 = fstatSync33(fd);
|
|
124423
124606
|
if (!stat3.isFile() || stat3.size > MAX_EXECUTION_GRANT_BYTES)
|
|
124424
124607
|
throw new Error("Grant input must be a regular file within the policy size limit.");
|
|
124425
124608
|
const bytes = Buffer.alloc(MAX_EXECUTION_GRANT_BYTES + 1);
|
|
124426
124609
|
let size2 = 0;
|
|
124427
124610
|
while (size2 < bytes.length) {
|
|
124428
|
-
const count =
|
|
124611
|
+
const count = readSync26(fd, bytes, size2, bytes.length - size2, null);
|
|
124429
124612
|
if (!count)
|
|
124430
124613
|
break;
|
|
124431
124614
|
size2 += count;
|
|
@@ -124438,7 +124621,7 @@ function readInput(path) {
|
|
|
124438
124621
|
throw new Error("Grant input must be a JSON document containing a grants array.");
|
|
124439
124622
|
}
|
|
124440
124623
|
} finally {
|
|
124441
|
-
|
|
124624
|
+
closeSync33(fd);
|
|
124442
124625
|
}
|
|
124443
124626
|
}
|
|
124444
124627
|
function registerGrants(parent) {
|
|
@@ -125221,17 +125404,17 @@ var exports_metadata = {};
|
|
|
125221
125404
|
__export(exports_metadata, {
|
|
125222
125405
|
registerMetadata: () => registerMetadata
|
|
125223
125406
|
});
|
|
125224
|
-
import { closeSync as
|
|
125407
|
+
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
125408
|
function readPlan(path) {
|
|
125226
|
-
const fd =
|
|
125409
|
+
const fd = openSync34(path, constants33.O_RDONLY | constants33.O_NONBLOCK | constants33.O_NOFOLLOW);
|
|
125227
125410
|
try {
|
|
125228
|
-
const stat3 =
|
|
125411
|
+
const stat3 = fstatSync34(fd);
|
|
125229
125412
|
if (!stat3.isFile() || stat3.size > 8 * 1024 * 1024)
|
|
125230
125413
|
throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
|
|
125231
125414
|
const bytes = Buffer.alloc(stat3.size + 1);
|
|
125232
125415
|
let size2 = 0;
|
|
125233
125416
|
while (size2 < bytes.length) {
|
|
125234
|
-
const count =
|
|
125417
|
+
const count = readSync27(fd, bytes, size2, bytes.length - size2, null);
|
|
125235
125418
|
if (!count)
|
|
125236
125419
|
break;
|
|
125237
125420
|
size2 += count;
|
|
@@ -125240,7 +125423,7 @@ function readPlan(path) {
|
|
|
125240
125423
|
throw new SkillMetadataUpdateError("INVALID_METADATA_PLAN");
|
|
125241
125424
|
return metadataPlan(JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2))));
|
|
125242
125425
|
} finally {
|
|
125243
|
-
|
|
125426
|
+
closeSync34(fd);
|
|
125244
125427
|
}
|
|
125245
125428
|
}
|
|
125246
125429
|
function failure(error61) {
|
|
@@ -125606,7 +125789,7 @@ var init_registry_sync = __esm(() => {
|
|
|
125606
125789
|
});
|
|
125607
125790
|
|
|
125608
125791
|
// src/lib/review-export.ts
|
|
125609
|
-
import { constants as
|
|
125792
|
+
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
125793
|
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
125794
|
function exactVersion(spec) {
|
|
125612
125795
|
const at2 = spec.indexOf("@");
|
|
@@ -125670,16 +125853,16 @@ async function exportSkillVersionForReview(spec, output2, client2) {
|
|
|
125670
125853
|
if (bytes.byteLength !== metadata2.bundleByteSize || sha256Hex(bytes) !== metadata2.bundleSha256.toLowerCase()) {
|
|
125671
125854
|
throw new Error("Published bundle bytes do not match the exact version metadata.");
|
|
125672
125855
|
}
|
|
125673
|
-
const fd =
|
|
125856
|
+
const fd = openSync35(target, constants34.O_WRONLY | constants34.O_CREAT | constants34.O_EXCL | constants34.O_NOFOLLOW, 384);
|
|
125674
125857
|
try {
|
|
125675
125858
|
writeFileSync34(fd, bytes);
|
|
125676
125859
|
fsyncSync10(fd);
|
|
125677
|
-
if (
|
|
125860
|
+
if (fstatSync35(fd).size !== bytes.byteLength)
|
|
125678
125861
|
throw new Error("Incomplete review output write.");
|
|
125679
125862
|
} catch (error61) {
|
|
125680
125863
|
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
125864
|
} finally {
|
|
125682
|
-
|
|
125865
|
+
closeSync35(fd);
|
|
125683
125866
|
}
|
|
125684
125867
|
return { slug: slug2, version: version2, bundleSha256: metadata2.bundleSha256.toLowerCase(), bundleByteSize: bytes.byteLength, output: target };
|
|
125685
125868
|
}
|
|
@@ -126217,7 +126400,7 @@ function verifySessionOptions(options) {
|
|
|
126217
126400
|
if (options.userId === undefined !== (options.membershipId === undefined) || options.userId !== undefined && (!publicationUuid(options.userId) || !publicationUuid(options.membershipId)))
|
|
126218
126401
|
throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide both observed --user-id and --membership-id UUIDs.");
|
|
126219
126402
|
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
|
|
126403
|
+
throw new PrivatePublicationError("PUBLICATION_CODE_REQUIRED", "Use --code-stdin with a fresh code for noninteractive private-skill commands.");
|
|
126221
126404
|
}
|
|
126222
126405
|
function verifyOptions(options, action) {
|
|
126223
126406
|
verifySessionOptions(options);
|
|
@@ -126273,6 +126456,45 @@ function registerPrivatePublications(parent) {
|
|
|
126273
126456
|
process.exitCode = 1;
|
|
126274
126457
|
}
|
|
126275
126458
|
});
|
|
126459
|
+
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) => {
|
|
126460
|
+
try {
|
|
126461
|
+
if (!publicationUuid(skillId) || !/^[1-9]\d?$/.test(options.limit) || Number(options.limit) > 50 || options.cursor !== undefined && !publicationUuid(options.cursor))
|
|
126462
|
+
throw new PrivatePublicationError("INVALID_PRIVATE_HISTORY_INPUT", "Provide a private skill UUID, --limit from 1 to 50, and an optional UUID --cursor.");
|
|
126463
|
+
verifySessionOptions(options);
|
|
126464
|
+
const context2 = options.userId ? { userId: options.userId, membershipId: options.membershipId } : undefined;
|
|
126465
|
+
const pending = preparePrivateSkillHistorySession(context2);
|
|
126466
|
+
let code2;
|
|
126467
|
+
if (options.codeStdin)
|
|
126468
|
+
code2 = await readCode();
|
|
126469
|
+
else {
|
|
126470
|
+
await new RemoteSkillsAuthClient(pending.origin).requestCode(options.email);
|
|
126471
|
+
code2 = await promptCode();
|
|
126472
|
+
}
|
|
126473
|
+
if (code2 === null)
|
|
126474
|
+
return;
|
|
126475
|
+
const client2 = await pending.verify(options.email, code2);
|
|
126476
|
+
const history = await client2.listVersions(skillId, { limit: Number(options.limit), cursor: options.cursor });
|
|
126477
|
+
if (options.json)
|
|
126478
|
+
console.log(JSON.stringify(history));
|
|
126479
|
+
else {
|
|
126480
|
+
console.log(`Private versions of ${history.slug} (${history.skillId})`);
|
|
126481
|
+
console.log(`Current version: ${history.currentVersion ?? "Not published yet"}`);
|
|
126482
|
+
if (!history.versions.length)
|
|
126483
|
+
console.log("No versions on this page.");
|
|
126484
|
+
for (const version2 of history.versions)
|
|
126485
|
+
console.log(` ${version2.version}${version2.id === history.currentVersionId ? " (current)" : ""} published: ${version2.releasedAt ?? "Not released"} created: ${version2.createdAt}`);
|
|
126486
|
+
if (history.nextCursor)
|
|
126487
|
+
console.log(`More versions: repeat this command with --cursor ${history.nextCursor} and fresh verification.`);
|
|
126488
|
+
}
|
|
126489
|
+
} catch (error61) {
|
|
126490
|
+
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 };
|
|
126491
|
+
if (options.json)
|
|
126492
|
+
console.log(JSON.stringify(result2));
|
|
126493
|
+
else
|
|
126494
|
+
console.error(result2.error);
|
|
126495
|
+
process.exitCode = 1;
|
|
126496
|
+
}
|
|
126497
|
+
});
|
|
126276
126498
|
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
126499
|
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
126500
|
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");
|