@hasna/skills 0.8.10 → 0.8.11
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 +52 -1
- package/bin/index.js +1304 -574
- package/bin/mcp.js +329 -82
- package/bin/migrate.js +6 -5
- package/bin/server.js +12312 -73626
- package/bin/worker.js +7635 -60520
- package/dist/index.d.ts +4 -1
- package/dist/index.js +817 -261
- package/dist/lib/agent-discovery.d.ts +1 -1
- package/dist/lib/claude-marketplace-registry.d.ts +17 -0
- package/dist/lib/fleet-credentials.d.ts +18 -0
- package/dist/lib/hook-diagnostics.d.ts +7 -0
- package/dist/lib/recurring-recovery.d.ts +2 -2
- package/dist/lib/recurring-surface.d.ts +1 -1
- package/dist/lib/remote-client.d.ts +10 -3
- package/dist/lib/remote-credit-checkout.d.ts +22 -0
- package/dist/lib/remote-customer-operations.d.ts +2 -3
- package/dist/lib/selection-cache.d.ts +32 -0
- package/dist/lib/selection-resolver.d.ts +3 -1
- package/dist/lib/session-reconciliation.d.ts +100 -0
- package/dist/sdk/index.d.ts +3 -1
- package/dist/sdk/index.js +13212 -73972
- package/docs/plugin-admission.md +23 -0
- package/package.json +6 -5
package/bin/index.js
CHANGED
|
@@ -36868,7 +36868,7 @@ var package_default;
|
|
|
36868
36868
|
var init_package = __esm(() => {
|
|
36869
36869
|
package_default = {
|
|
36870
36870
|
name: "@hasna/skills",
|
|
36871
|
-
version: "0.8.
|
|
36871
|
+
version: "0.8.11",
|
|
36872
36872
|
description: "Skills library for AI coding agents",
|
|
36873
36873
|
type: "module",
|
|
36874
36874
|
bin: {
|
|
@@ -36930,10 +36930,11 @@ var init_package = __esm(() => {
|
|
|
36930
36930
|
typecheck: "tsc --noEmit",
|
|
36931
36931
|
"verify:release": "bun run scripts/release-guard.ts",
|
|
36932
36932
|
"verify:consumer-types": "bun run scripts/consumer-types.ts",
|
|
36933
|
-
|
|
36934
|
-
prepack: "bun run build && bun run verify:release && bun run verify:consumer-types",
|
|
36933
|
+
prepack: "bun run verify:generated && bun run verify:release && bun run verify:consumer-types",
|
|
36935
36934
|
prepublishOnly: "bun run verify:producer && bun run typecheck && bun run test",
|
|
36936
|
-
"verify:producer": "bun run scripts/release-dependencies.ts"
|
|
36935
|
+
"verify:producer": "bun run scripts/release-dependencies.ts",
|
|
36936
|
+
"verify:generated": "HASNA_SKILLS_RELEASE_ARTIFACT_TEST=1 bun test src/lib/release-artifacts.test.ts",
|
|
36937
|
+
"verify:consumer-credentials": "bun run scripts/consumer-credentials.ts"
|
|
36937
36938
|
},
|
|
36938
36939
|
keywords: [
|
|
36939
36940
|
"skills",
|
|
@@ -36955,7 +36956,6 @@ var init_package = __esm(() => {
|
|
|
36955
36956
|
license: "Apache-2.0",
|
|
36956
36957
|
devDependencies: {
|
|
36957
36958
|
"@hasna/contracts": "1.1.0",
|
|
36958
|
-
"@hasna/secrets": "0.4.2",
|
|
36959
36959
|
"@types/bun": "1.3.14",
|
|
36960
36960
|
"@types/node": "25.2.3",
|
|
36961
36961
|
"@types/react": "^18.2.0",
|
|
@@ -36968,6 +36968,7 @@ var init_package = __esm(() => {
|
|
|
36968
36968
|
"@aws-sdk/client-ecs": "^3.1079.0",
|
|
36969
36969
|
"@aws-sdk/client-s3": "^3.1079.0",
|
|
36970
36970
|
"@hasna/events": "0.1.18",
|
|
36971
|
+
"@hasna/secrets": "0.4.2",
|
|
36971
36972
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
36972
36973
|
chalk: "^5.3.0",
|
|
36973
36974
|
commander: "^12.1.0",
|
|
@@ -42784,14 +42785,15 @@ function profileSelectionSnapshot(selections) {
|
|
|
42784
42785
|
var MAX_PROFILE_SELECTIONS = 4096, MAX_PROFILE_DOCUMENT_BYTES, MAX_SKILL_SESSION_ID_CHARS = 256, PROFILE_SESSION_ENVELOPE_BYTES, MAX_RESOLVED_PROFILE_BYTES, LEGACY_PROFILE_SELECTIONS = 256, LEGACY_PROFILE_DOCUMENT_BYTES = 1e6;
|
|
42785
42786
|
var init_profile_limits = __esm(() => {
|
|
42786
42787
|
MAX_PROFILE_DOCUMENT_BYTES = 8 * 1024 * 1024;
|
|
42787
|
-
PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS *
|
|
42788
|
+
PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS * 12 + 512;
|
|
42788
42789
|
MAX_RESOLVED_PROFILE_BYTES = MAX_PROFILE_DOCUMENT_BYTES - PROFILE_SESSION_ENVELOPE_BYTES;
|
|
42789
42790
|
});
|
|
42790
42791
|
|
|
42791
42792
|
// src/lib/selection-cache.ts
|
|
42792
42793
|
import { createHash as createHash3, randomUUID as randomUUID3 } from "crypto";
|
|
42793
|
-
import { closeSync, constants as constants2, fstatSync, lstatSync as lstatSync3, mkdirSync as mkdirSync4, openSync, readSync, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
|
|
42794
|
+
import { closeSync, constants as constants2, fstatSync, fsyncSync, lstatSync as lstatSync3, mkdirSync as mkdirSync4, openSync, readSync, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
|
|
42794
42795
|
import { dirname as dirname4, join as join14, parse, resolve as resolve4 } from "path";
|
|
42796
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
|
|
42795
42797
|
function selectionCacheRoot(options = {}) {
|
|
42796
42798
|
return resolve4(options.cacheDir ?? join14(getDataDirReadOnly(), "selection-cache"));
|
|
42797
42799
|
}
|
|
@@ -42895,12 +42897,21 @@ function writeSelectionJson(path, value) {
|
|
|
42895
42897
|
throw new SkillSelectionError("RECEIPT_TOO_LARGE", "The Skills selection receipt exceeds its size limit.");
|
|
42896
42898
|
atomicWrite(path, bytes, 384);
|
|
42897
42899
|
}
|
|
42898
|
-
function atomicWrite(path, bytes, mode) {
|
|
42900
|
+
function atomicWrite(path, bytes, mode, durable = false) {
|
|
42899
42901
|
assertRegularPath(path, true);
|
|
42900
42902
|
const temporary = join14(dirname4(path), `.selection-${randomUUID3()}.tmp`);
|
|
42901
42903
|
try {
|
|
42902
|
-
|
|
42904
|
+
const fd = openSync(temporary, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, mode);
|
|
42905
|
+
try {
|
|
42906
|
+
writeFileSync4(fd, bytes);
|
|
42907
|
+
if (durable)
|
|
42908
|
+
fsyncSync(fd);
|
|
42909
|
+
} finally {
|
|
42910
|
+
closeSync(fd);
|
|
42911
|
+
}
|
|
42903
42912
|
renameSync2(temporary, path);
|
|
42913
|
+
if (durable)
|
|
42914
|
+
syncDirectory(dirname4(path));
|
|
42904
42915
|
} finally {
|
|
42905
42916
|
try {
|
|
42906
42917
|
unlinkSync(temporary);
|
|
@@ -43019,16 +43030,190 @@ function sessionReceiptPath(sessionId, options = {}) {
|
|
|
43019
43030
|
throw new SkillSelectionError("INVALID_SESSION", `A Skills session id must contain 1\u2013${MAX_SKILL_SESSION_ID_CHARS} characters.`);
|
|
43020
43031
|
return join14(selectionCacheRoot(options), "sessions", `${hash(sessionId)}.json`);
|
|
43021
43032
|
}
|
|
43022
|
-
function
|
|
43023
|
-
|
|
43024
|
-
|
|
43025
|
-
|
|
43026
|
-
|
|
43027
|
-
|
|
43028
|
-
|
|
43033
|
+
function skillSessionGeneration(receipt) {
|
|
43034
|
+
return receipt.generation ?? 0;
|
|
43035
|
+
}
|
|
43036
|
+
function validateSkillSessionBinding(binding) {
|
|
43037
|
+
if (!binding || typeof binding.sessionId !== "string" || !binding.sessionId.trim() || binding.sessionId.length > MAX_SKILL_SESSION_ID_CHARS || !Number.isSafeInteger(binding.generation) || binding.generation < 0 || !/^[a-f0-9]{64}$/.test(binding.receiptSha256)) {
|
|
43038
|
+
throw new SkillSelectionError("INVALID_RECEIPT", "The Skills session receipt contains an invalid parent snapshot binding.");
|
|
43039
|
+
}
|
|
43040
|
+
}
|
|
43041
|
+
function validateSkillSessionReceipt(receipt, sessionId) {
|
|
43042
|
+
validateSelectionReceipt(receipt);
|
|
43043
|
+
const keys2 = new Set(receipt.profile.selections.map(selectionKey));
|
|
43044
|
+
if (receipt.sessionId !== sessionId || !Array.isArray(receipt.loaded) || receipt.loaded.length > keys2.size || new Set(receipt.loaded).size !== receipt.loaded.length || !receipt.loaded.every((key) => keys2.has(key)) || receipt.generation !== undefined && (!Number.isSafeInteger(receipt.generation) || receipt.generation < 1)) {
|
|
43045
|
+
throw new SkillSelectionError("INVALID_RECEIPT", "The Skills session receipt is invalid.");
|
|
43046
|
+
}
|
|
43047
|
+
if (receipt.parent) {
|
|
43048
|
+
validateSkillSessionBinding(receipt.parent);
|
|
43049
|
+
if (receipt.parent.sessionId === sessionId)
|
|
43050
|
+
throw new SkillSelectionError("INVALID_RECEIPT", "A Skills child session cannot name itself as its parent.");
|
|
43051
|
+
}
|
|
43052
|
+
}
|
|
43053
|
+
function readSkillSessionSnapshotIfExists(sessionId, options = {}) {
|
|
43054
|
+
const path = sessionReceiptPath(sessionId, options), bytes = readRegularFile(path, MAX_PROFILE_DOCUMENT_BYTES);
|
|
43055
|
+
if (!bytes)
|
|
43056
|
+
return null;
|
|
43057
|
+
let receipt;
|
|
43058
|
+
try {
|
|
43059
|
+
receipt = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
43060
|
+
} catch {
|
|
43061
|
+
throw new SkillSelectionError("INVALID_RECEIPT", "The Skills session receipt is unreadable.");
|
|
43062
|
+
}
|
|
43063
|
+
validateSkillSessionReceipt(receipt, sessionId);
|
|
43064
|
+
const sha256 = sha256Hex(bytes);
|
|
43065
|
+
return { path, bytes, receipt, sha256, sessionId, generation: skillSessionGeneration(receipt), receiptSha256: sha256 };
|
|
43066
|
+
}
|
|
43067
|
+
function readSkillSessionSnapshot(sessionId, options = {}) {
|
|
43068
|
+
const snapshot = readSkillSessionSnapshotIfExists(sessionId, options);
|
|
43069
|
+
if (!snapshot)
|
|
43070
|
+
throw new SkillSelectionError("SESSION_NOT_FOUND", "The requested Skills session receipt does not exist.");
|
|
43071
|
+
return snapshot;
|
|
43072
|
+
}
|
|
43073
|
+
function skillSessionSnapshotBinding(snapshot) {
|
|
43074
|
+
return { sessionId: snapshot.sessionId, generation: snapshot.generation, receiptSha256: snapshot.receiptSha256 };
|
|
43075
|
+
}
|
|
43076
|
+
function withSessionWriteLocks(sessionIds, options, action) {
|
|
43077
|
+
const operationId = randomUUID3();
|
|
43078
|
+
const locks = [...new Set(sessionIds)].map((sessionId) => ({ sessionId, path: `${sessionReceiptPath(sessionId, options)}.write-lock` })).sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
|
|
43079
|
+
const owned = [];
|
|
43080
|
+
const assertOwned = () => {
|
|
43081
|
+
for (const lock of owned) {
|
|
43082
|
+
const current = lstatSync3(lock.path, { throwIfNoEntry: false });
|
|
43083
|
+
if (!current?.isFile() || current.dev !== lock.dev || current.ino !== lock.ino) {
|
|
43084
|
+
throw new SkillSelectionError("SESSION_WRITE_LOCK_CHANGED", "A session write lock changed during the operation; no replacement is permitted.");
|
|
43085
|
+
}
|
|
43086
|
+
}
|
|
43087
|
+
};
|
|
43088
|
+
try {
|
|
43089
|
+
for (const lock of locks) {
|
|
43090
|
+
assertRegularPath(lock.path, true);
|
|
43091
|
+
let fd;
|
|
43092
|
+
try {
|
|
43093
|
+
fd = openSync(lock.path, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, 384);
|
|
43094
|
+
} catch (error) {
|
|
43095
|
+
if (error.code === "EEXIST")
|
|
43096
|
+
throw new SkillSelectionError("SESSION_WRITE_LOCKED", "Another Skills process owns a required session write lock; retry after it completes. A surviving lock requires explicit recovery review.");
|
|
43097
|
+
throw error;
|
|
43098
|
+
}
|
|
43099
|
+
const stat = fstatSync(fd);
|
|
43100
|
+
owned.push({ path: lock.path, fd, dev: stat.dev, ino: stat.ino });
|
|
43101
|
+
writeFileSync4(fd, `${JSON.stringify({ schemaVersion: 1, operationId, sessionId: lock.sessionId, pid: process.pid })}
|
|
43102
|
+
`);
|
|
43103
|
+
}
|
|
43104
|
+
return action(assertOwned);
|
|
43105
|
+
} finally {
|
|
43106
|
+
for (const lock of owned.reverse()) {
|
|
43107
|
+
closeSync(lock.fd);
|
|
43108
|
+
const current = lstatSync3(lock.path, { throwIfNoEntry: false });
|
|
43109
|
+
if (current?.isFile() && current.dev === lock.dev && current.ino === lock.ino)
|
|
43110
|
+
unlinkSync(lock.path);
|
|
43029
43111
|
}
|
|
43030
43112
|
}
|
|
43031
|
-
|
|
43113
|
+
}
|
|
43114
|
+
function withSessionWriteLock(sessionId, options, action) {
|
|
43115
|
+
return withSessionWriteLocks([sessionId], options, action);
|
|
43116
|
+
}
|
|
43117
|
+
function sameSnapshot(actual, expected) {
|
|
43118
|
+
return actual === null ? expected === null : expected !== null && actual.sessionId === expected.sessionId && actual.generation === expected.generation && actual.receiptSha256 === expected.receiptSha256;
|
|
43119
|
+
}
|
|
43120
|
+
function nextSkillSessionGeneration(generation) {
|
|
43121
|
+
if (!Number.isSafeInteger(generation) || generation < 0 || generation >= Number.MAX_SAFE_INTEGER) {
|
|
43122
|
+
throw new SkillSelectionError("SESSION_GENERATION_EXHAUSTED", "The Skills session generation cannot advance safely; preserve the receipt and review recovery before continuing.");
|
|
43123
|
+
}
|
|
43124
|
+
return generation + 1;
|
|
43125
|
+
}
|
|
43126
|
+
function parentChanged() {
|
|
43127
|
+
throw new SkillSelectionError("SESSION_PARENT_CHANGED", "The parent Skills session changed while the child was resolving; resolve the child again from the current parent pin.");
|
|
43128
|
+
}
|
|
43129
|
+
function writeSkillSession(receipt, expected, options = {}) {
|
|
43130
|
+
validateSkillSessionReceipt(receipt, receipt.sessionId);
|
|
43131
|
+
if (expected.parent)
|
|
43132
|
+
validateSkillSessionBinding(expected.parent);
|
|
43133
|
+
if (expected.parent?.sessionId === receipt.sessionId)
|
|
43134
|
+
throw new SkillSelectionError("INVALID_RECEIPT", "A Skills child session cannot name itself as its parent.");
|
|
43135
|
+
const lockIds = expected.parent ? [receipt.sessionId, expected.parent.sessionId] : [receipt.sessionId];
|
|
43136
|
+
withSessionWriteLocks(lockIds, options, (assertOwned) => {
|
|
43137
|
+
const current = readSkillSessionSnapshotIfExists(receipt.sessionId, options);
|
|
43138
|
+
if (!sameSnapshot(current, expected.current) || current && !isDeepStrictEqual2(current.receipt.profile, receipt.profile)) {
|
|
43139
|
+
throw new SkillSelectionError("SESSION_RECEIPT_CHANGED", "The Skills session receipt changed while context was loading; resolve context again without replacing the current pin.");
|
|
43140
|
+
}
|
|
43141
|
+
let parent = null;
|
|
43142
|
+
if (expected.parent) {
|
|
43143
|
+
parent = readSkillSessionSnapshotIfExists(expected.parent.sessionId, options);
|
|
43144
|
+
if (!sameSnapshot(parent, expected.parent) || !parent || !isDeepStrictEqual2(parent.receipt.profile, receipt.profile))
|
|
43145
|
+
parentChanged();
|
|
43146
|
+
}
|
|
43147
|
+
const generation = nextSkillSessionGeneration(current?.generation ?? 0);
|
|
43148
|
+
const next = current ? { ...current.receipt, generation, loaded: [...new Set([...current.receipt.loaded, ...receipt.loaded])] } : { ...receipt, generation, ...expected.parent ? { parent: expected.parent } : {} };
|
|
43149
|
+
assertOwned();
|
|
43150
|
+
if (expected.parent) {
|
|
43151
|
+
parent = readSkillSessionSnapshotIfExists(expected.parent.sessionId, options);
|
|
43152
|
+
if (!sameSnapshot(parent, expected.parent))
|
|
43153
|
+
parentChanged();
|
|
43154
|
+
}
|
|
43155
|
+
writeSelectionJson(sessionReceiptPath(receipt.sessionId, options), next);
|
|
43156
|
+
});
|
|
43157
|
+
}
|
|
43158
|
+
function syncDirectory(path) {
|
|
43159
|
+
assertRegularPath(path);
|
|
43160
|
+
const fd = openSync(path, constants2.O_RDONLY | constants2.O_DIRECTORY | constants2.O_NOFOLLOW);
|
|
43161
|
+
try {
|
|
43162
|
+
fsyncSync(fd);
|
|
43163
|
+
} finally {
|
|
43164
|
+
closeSync(fd);
|
|
43165
|
+
}
|
|
43166
|
+
}
|
|
43167
|
+
function archiveBytes(path, bytes) {
|
|
43168
|
+
assertRegularPath(path, true);
|
|
43169
|
+
const fd = openSync(path, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, 384);
|
|
43170
|
+
try {
|
|
43171
|
+
writeFileSync4(fd, bytes);
|
|
43172
|
+
fsyncSync(fd);
|
|
43173
|
+
} finally {
|
|
43174
|
+
closeSync(fd);
|
|
43175
|
+
}
|
|
43176
|
+
}
|
|
43177
|
+
function replaceSkillSession(expected, replacement, plan, options = {}, beforeCommit = () => {}) {
|
|
43178
|
+
validateSkillSessionReceipt(replacement, replacement.sessionId);
|
|
43179
|
+
const bytes = Buffer.from(`${JSON.stringify(replacement)}
|
|
43180
|
+
`);
|
|
43181
|
+
if (bytes.length > MAX_PROFILE_DOCUMENT_BYTES)
|
|
43182
|
+
throw new SkillSelectionError("RECEIPT_TOO_LARGE", "The Skills selection receipt exceeds its size limit.");
|
|
43183
|
+
return withSessionWriteLock(replacement.sessionId, options, (assertOwned) => {
|
|
43184
|
+
const before2 = readSkillSessionSnapshot(replacement.sessionId, options);
|
|
43185
|
+
if (!sameSnapshot(before2, expected))
|
|
43186
|
+
throw new SkillSelectionError("SESSION_RECEIPT_CHANGED", "The Skills session receipt generation or bytes changed after review; inspect it and prepare a new plan.");
|
|
43187
|
+
if (replacement.generation !== nextSkillSessionGeneration(before2.generation))
|
|
43188
|
+
throw new SkillSelectionError("SESSION_GENERATION_CHANGED", "The replacement Skills session must advance exactly one generation.");
|
|
43189
|
+
if (before2.receipt.profile.authority !== replacement.profile.authority || before2.receipt.profile.workspaceId !== replacement.profile.workspaceId) {
|
|
43190
|
+
throw new SkillSelectionError("PROFILE_IDENTITY_MISMATCH", "A session reconciliation cannot change its Skills authority or workspace.");
|
|
43191
|
+
}
|
|
43192
|
+
const directory = join14(selectionCacheRoot(options), "session-reconciliations", randomUUID3());
|
|
43193
|
+
const archivePath = join14(directory, "original.json"), replacementPath = join14(directory, "replacement.json"), receiptPath = join14(directory, "receipt.json");
|
|
43194
|
+
const afterSha256 = sha256Hex(bytes);
|
|
43195
|
+
archiveBytes(archivePath, before2.bytes);
|
|
43196
|
+
archiveBytes(replacementPath, bytes);
|
|
43197
|
+
const receipt = { schemaVersion: 1, status: "prepared", sessionId: replacement.sessionId, beforeGeneration: before2.generation, afterGeneration: replacement.generation, beforeSha256: before2.sha256, afterSha256, archivePath, replacementPath, plan };
|
|
43198
|
+
archiveBytes(receiptPath, Buffer.from(`${JSON.stringify(receipt)}
|
|
43199
|
+
`));
|
|
43200
|
+
syncDirectory(directory);
|
|
43201
|
+
syncDirectory(dirname4(directory));
|
|
43202
|
+
syncDirectory(selectionCacheRoot(options));
|
|
43203
|
+
if (sha256Hex(readRegularFile(archivePath, MAX_PROFILE_DOCUMENT_BYTES)) !== before2.sha256 || !sameSnapshot(readSkillSessionSnapshot(replacement.sessionId, options), expected)) {
|
|
43204
|
+
throw new SkillSelectionError("SESSION_RECEIPT_CHANGED", "The session or its preservation archive changed before replacement; retained evidence must be reviewed.");
|
|
43205
|
+
}
|
|
43206
|
+
beforeCommit();
|
|
43207
|
+
assertOwned();
|
|
43208
|
+
try {
|
|
43209
|
+
atomicWrite(before2.path, bytes, 384, true);
|
|
43210
|
+
atomicWrite(receiptPath, Buffer.from(`${JSON.stringify({ ...receipt, status: "applied" })}
|
|
43211
|
+
`), 384, true);
|
|
43212
|
+
} catch {
|
|
43213
|
+
throw new SkillSelectionError("SESSION_RECONCILIATION_INCOMPLETE", `Inspect sessions show and the preserved operation receipt at ${receiptPath} before any retry; replacement may already have committed.`);
|
|
43214
|
+
}
|
|
43215
|
+
return { archivePath, receiptPath, beforeSha256: before2.sha256, afterSha256 };
|
|
43216
|
+
});
|
|
43032
43217
|
}
|
|
43033
43218
|
var SkillSelectionError, MAX_CACHED_PROFILE_AGE_MS, SELECTION_LOCK_FILE = "selection.lock.json";
|
|
43034
43219
|
var init_selection_cache = __esm(() => {
|
|
@@ -43048,6 +43233,7 @@ var init_selection_cache = __esm(() => {
|
|
|
43048
43233
|
});
|
|
43049
43234
|
|
|
43050
43235
|
// src/lib/agent-policy-limits.ts
|
|
43236
|
+
import { basename as basename3, isAbsolute as isAbsolute3, resolve as resolve5 } from "path";
|
|
43051
43237
|
function object(value) {
|
|
43052
43238
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
43053
43239
|
}
|
|
@@ -43112,7 +43298,9 @@ function assertAgentPolicyCollections(policy) {
|
|
|
43112
43298
|
text(source.path);
|
|
43113
43299
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
43114
43300
|
if (source.hashMode !== undefined)
|
|
43115
|
-
requireBound(["bytes", "path-bytes", "claude-plugin-registry"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
43301
|
+
requireBound(["bytes", "path-bytes", "claude-plugin-registry", "claude-marketplace-registry"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode === "bytes" || source.sha256 !== null));
|
|
43302
|
+
if (source.hashMode === "claude-marketplace-registry")
|
|
43303
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute3(source.path) && resolve5(source.path) === source.path && basename3(source.path) === "known_marketplaces.json");
|
|
43116
43304
|
if (source.hashMode === "claude-plugin-registry") {
|
|
43117
43305
|
requireBound(agent === "claude");
|
|
43118
43306
|
const managed = array(source.managedPlugins, 64);
|
|
@@ -50265,7 +50453,7 @@ var init_dist = __esm(() => {
|
|
|
50265
50453
|
});
|
|
50266
50454
|
|
|
50267
50455
|
// src/lib/agent-hermes.ts
|
|
50268
|
-
import { dirname as dirname5, isAbsolute as
|
|
50456
|
+
import { dirname as dirname5, isAbsolute as isAbsolute4, join as join17, resolve as resolve6 } from "path";
|
|
50269
50457
|
import { lstatSync as lstatSync6, readFileSync as readFileSync10, opendirSync } from "fs";
|
|
50270
50458
|
function object2(value) {
|
|
50271
50459
|
return Boolean(value && typeof value === "object" && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null));
|
|
@@ -50301,7 +50489,7 @@ function quoted(value) {
|
|
|
50301
50489
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
50302
50490
|
}
|
|
50303
50491
|
function hermesHookDefinitions(supervisor) {
|
|
50304
|
-
if (!
|
|
50492
|
+
if (!isAbsolute4(supervisor.runtime) || !isAbsolute4(supervisor.path))
|
|
50305
50493
|
throw new Error("Expected absolute Hermes supervisor paths");
|
|
50306
50494
|
const entry = (event) => ({ command: `${quoted(supervisor.runtime)} ${quoted(supervisor.path)} --event ${event}`, timeout: 15, ...event === "pre_tool_call" ? { fail_closed: true } : {} });
|
|
50307
50495
|
return { pre_llm_call: entry("pre_llm_call"), pre_tool_call: entry("pre_tool_call") };
|
|
@@ -50337,7 +50525,7 @@ function assertHermesEnvironment(home) {
|
|
|
50337
50525
|
throw new Error(`NATIVE_SKILL_DRIFT: Hermes ${variable} requires a dedicated discovery adapter; unset it before using this adapter`);
|
|
50338
50526
|
}
|
|
50339
50527
|
const selected = process.env.HERMES_HOME?.trim();
|
|
50340
|
-
if (selected && (!
|
|
50528
|
+
if (selected && (!isAbsolute4(selected) || resolve6(selected) !== join17(resolve6(home), ".hermes")))
|
|
50341
50529
|
throw new Error("NATIVE_SKILL_DRIFT: custom Hermes homes/profiles require their own reviewed bridge");
|
|
50342
50530
|
if (process.env.HERMES_ENABLE_PROJECT_PLUGINS?.trim() && !["0", "false", "no", "off"].includes(process.env.HERMES_ENABLE_PROJECT_PLUGINS.trim().toLowerCase()))
|
|
50343
50531
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes project plugins require a dedicated discovery review");
|
|
@@ -50360,7 +50548,7 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
|
|
|
50360
50548
|
assertHermesEnvironment(home);
|
|
50361
50549
|
if (read(join17(home, ".hermes", HERMES_OPT_OUT)) === null)
|
|
50362
50550
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes bundled skill reseeding is not disabled; run skills hook install");
|
|
50363
|
-
if (!supervisor || !
|
|
50551
|
+
if (!supervisor || !isAbsolute4(supervisor.path) || supervisor.runtime !== process.execPath || read(supervisor.path) !== renderHermesSupervisor(command, profile))
|
|
50364
50552
|
throw new Error("NATIVE_SKILL_DRIFT: Hermes owned supervisor changed; run skills hook install");
|
|
50365
50553
|
const raw = read(join17(home, ".hermes/shell-hooks-allowlist.json"));
|
|
50366
50554
|
let trust;
|
|
@@ -50386,7 +50574,7 @@ function assertHermesProtection(home, config, command, profile, supervisor) {
|
|
|
50386
50574
|
}
|
|
50387
50575
|
function assertNoHermesLegacyShadow(root) {
|
|
50388
50576
|
let entries = 0;
|
|
50389
|
-
for (let cursor =
|
|
50577
|
+
for (let cursor = resolve6(root);; cursor = dirname5(cursor)) {
|
|
50390
50578
|
if (lstatSync6(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
50391
50579
|
throw new Error("NATIVE_SKILL_DRIFT: symlink Hermes legacy discovery root");
|
|
50392
50580
|
if (dirname5(cursor) === cursor)
|
|
@@ -50490,13 +50678,13 @@ var init_agent_hermes = __esm(() => {
|
|
|
50490
50678
|
// src/lib/agent-discovery-directories.ts
|
|
50491
50679
|
import { createHash as createHash5 } from "crypto";
|
|
50492
50680
|
import { lstatSync as lstatSync7, opendirSync as opendirSync2 } from "fs";
|
|
50493
|
-
import { dirname as dirname6, isAbsolute as
|
|
50681
|
+
import { dirname as dirname6, isAbsolute as isAbsolute5, join as join18, resolve as resolve7 } from "path";
|
|
50494
50682
|
function need(value, message) {
|
|
50495
50683
|
if (!value)
|
|
50496
50684
|
throw new Error(message);
|
|
50497
50685
|
}
|
|
50498
50686
|
function safe(path) {
|
|
50499
|
-
need(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters &&
|
|
50687
|
+
need(typeof path === "string" && path.length <= AGENT_POLICY_LIMITS.pathCharacters && isAbsolute5(path) && resolve7(path) === path && !path.includes("\x00"), "Expected a canonical absolute discovery directory path");
|
|
50500
50688
|
for (let cursor = path;; cursor = dirname6(cursor)) {
|
|
50501
50689
|
need(!lstatSync7(cursor, { throwIfNoEntry: false })?.isSymbolicLink(), "Refusing symlink native discovery directory");
|
|
50502
50690
|
if (dirname6(cursor) === cursor)
|
|
@@ -50564,12 +50752,12 @@ var init_agent_discovery_directories = __esm(() => {
|
|
|
50564
50752
|
// src/lib/agent-discovery-bytes.ts
|
|
50565
50753
|
import { createHash as createHash6 } from "crypto";
|
|
50566
50754
|
import { closeSync as closeSync3, constants as constants4, fstatSync as fstatSync3, lstatSync as lstatSync8, openSync as openSync3, readSync as readSync3 } from "fs";
|
|
50567
|
-
import { dirname as dirname7, isAbsolute as
|
|
50755
|
+
import { dirname as dirname7, isAbsolute as isAbsolute6, resolve as resolve8 } from "path";
|
|
50568
50756
|
function discoveryByteBudget() {
|
|
50569
50757
|
return { remaining: AGENT_POLICY_LIMITS.discoveryRawTotalBytes };
|
|
50570
50758
|
}
|
|
50571
50759
|
function safe2(path) {
|
|
50572
|
-
if (typeof path !== "string" || !
|
|
50760
|
+
if (typeof path !== "string" || !isAbsolute6(path) || path !== resolve8(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00"))
|
|
50573
50761
|
throw new Error("Expected a canonical absolute raw discovery path");
|
|
50574
50762
|
for (let cursor = path;; cursor = dirname7(cursor)) {
|
|
50575
50763
|
if (lstatSync8(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
@@ -50635,7 +50823,7 @@ var init_agent_discovery_bytes = __esm(() => {
|
|
|
50635
50823
|
// src/lib/agent-discovery-path-bytes.ts
|
|
50636
50824
|
import { createHash as createHash7 } from "crypto";
|
|
50637
50825
|
import { lstatSync as lstatSync9, readlinkSync } from "fs";
|
|
50638
|
-
import { dirname as dirname8, isAbsolute as
|
|
50826
|
+
import { dirname as dirname8, isAbsolute as isAbsolute7, join as join19, parse as parse2, resolve as resolve9, sep as sep3 } from "path";
|
|
50639
50827
|
function identity3(stat, mutable = false) {
|
|
50640
50828
|
return {
|
|
50641
50829
|
dev: String(stat.dev),
|
|
@@ -50647,7 +50835,7 @@ function identity3(stat, mutable = false) {
|
|
|
50647
50835
|
};
|
|
50648
50836
|
}
|
|
50649
50837
|
function canonical(path) {
|
|
50650
|
-
if (typeof path !== "string" || !
|
|
50838
|
+
if (typeof path !== "string" || !isAbsolute7(path) || path !== resolve9(path) || path.length > AGENT_POLICY_LIMITS.pathCharacters || path.includes("\x00") || Buffer.from(path).toString("utf8") !== path)
|
|
50651
50839
|
throw new Error("Expected a canonical absolute discovery path");
|
|
50652
50840
|
}
|
|
50653
50841
|
function trace(path) {
|
|
@@ -50696,11 +50884,11 @@ function trace(path) {
|
|
|
50696
50884
|
if (!target || target.includes("\x00") || Buffer.byteLength(target) > AGENT_POLICY_LIMITS.pathCharacters || !after2.isSymbolicLink() || JSON.stringify(identity3(stat, true)) !== JSON.stringify(identity3(after2, true)))
|
|
50697
50885
|
throw new Error("Discovery link changed during read");
|
|
50698
50886
|
record2(candidate, { type: "link", target, ...identity3(stat, true) });
|
|
50699
|
-
if (
|
|
50887
|
+
if (isAbsolute7(target)) {
|
|
50700
50888
|
cursor = parse2(target).root;
|
|
50701
50889
|
root();
|
|
50702
50890
|
}
|
|
50703
|
-
const remainder =
|
|
50891
|
+
const remainder = isAbsolute7(target) ? target.slice(parse2(target).root.length) : target;
|
|
50704
50892
|
pending = [...remainder.split(sep3), ...pending];
|
|
50705
50893
|
if (pending.length + steps > AGENT_POLICY_LIMITS.discoveryPathSteps)
|
|
50706
50894
|
throw new Error("Discovery path step limit exceeded");
|
|
@@ -50756,12 +50944,12 @@ import { spawnSync } from "child_process";
|
|
|
50756
50944
|
import { closeSync as closeSync22, fstatSync as fstatSync22, openSync as openSync22, readFileSync as readFileSync22 } from "fs";
|
|
50757
50945
|
import { O_NOFOLLOW as O_NOFOLLOW2, O_NONBLOCK as O_NONBLOCK2, O_RDONLY as O_RDONLY2 } from "constants";
|
|
50758
50946
|
import { hostname as osHostname } from "os";
|
|
50759
|
-
import { isAbsolute as
|
|
50947
|
+
import { isAbsolute as isAbsolute8, join as join22 } from "path";
|
|
50760
50948
|
import { createRequire } from "module";
|
|
50761
50949
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
50762
50950
|
import { closeSync as closeSync4, fstatSync as fstatSync4, lstatSync as lstatSync10, openSync as openSync4, readFileSync as readFileSync11, realpathSync as realpathSync3, statSync as statSync7 } from "fs";
|
|
50763
50951
|
import { O_NOFOLLOW, O_NONBLOCK, O_RDONLY } from "constants";
|
|
50764
|
-
import { basename as
|
|
50952
|
+
import { basename as basename4, dirname as dirname9, join as join20, relative as relative4, sep as sep4 } from "path";
|
|
50765
50953
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
50766
50954
|
function envToken(name) {
|
|
50767
50955
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -50866,7 +51054,7 @@ function entryPoint(directory) {
|
|
|
50866
51054
|
function resolveInstalledSecrets(parentUrl) {
|
|
50867
51055
|
let directory = dirname9(fileURLToPath(parentUrl));
|
|
50868
51056
|
for (;; ) {
|
|
50869
|
-
if (
|
|
51057
|
+
if (basename4(directory) !== "node_modules") {
|
|
50870
51058
|
const candidate = join20(directory, "node_modules", PACKAGE);
|
|
50871
51059
|
let absent = false;
|
|
50872
51060
|
try {
|
|
@@ -50891,7 +51079,7 @@ function homeDir(env3) {
|
|
|
50891
51079
|
}
|
|
50892
51080
|
function absoluteOverride(env3, key) {
|
|
50893
51081
|
const value = env3[key]?.trim();
|
|
50894
|
-
return value &&
|
|
51082
|
+
return value && isAbsolute8(value) ? value : null;
|
|
50895
51083
|
}
|
|
50896
51084
|
function hasnaHomeDir(env3) {
|
|
50897
51085
|
const override = absoluteOverride(env3, HASNA_HOME_ENV_KEY);
|
|
@@ -51709,6 +51897,7 @@ __export(exports_fleet_credentials, {
|
|
|
51709
51897
|
SKILLS_API_URL_ENV: () => SKILLS_API_URL_ENV,
|
|
51710
51898
|
SKILLS_API_KEY_ENV_KEYS: () => SKILLS_API_KEY_ENV_KEYS,
|
|
51711
51899
|
SKILLS_API_KEY_ENV: () => SKILLS_API_KEY_ENV,
|
|
51900
|
+
REDACTED_VAULT_REFERENCE: () => REDACTED_VAULT_REFERENCE,
|
|
51712
51901
|
MissingSkillsFleetError: () => MissingSkillsFleetError
|
|
51713
51902
|
});
|
|
51714
51903
|
function isCredentialResolutionError(error) {
|
|
@@ -51717,10 +51906,15 @@ function isCredentialResolutionError(error) {
|
|
|
51717
51906
|
function isSkillsFleetCredentialError(error) {
|
|
51718
51907
|
return error instanceof SkillsFleetCredentialError || typeof error === "object" && error !== null && error.name === "SkillsFleetCredentialError";
|
|
51719
51908
|
}
|
|
51720
|
-
function
|
|
51909
|
+
function redactVaultReference(message, vaultReference) {
|
|
51910
|
+
if (!vaultReference)
|
|
51911
|
+
return message;
|
|
51912
|
+
return message.split(vaultReference).join(REDACTED_VAULT_REFERENCE);
|
|
51913
|
+
}
|
|
51914
|
+
function asSkillsFleetCredentialError(error, vaultReference) {
|
|
51721
51915
|
if (!isCredentialResolutionError(error))
|
|
51722
51916
|
return null;
|
|
51723
|
-
return new SkillsFleetCredentialError(error.message, "MISSING_API_CREDENTIAL");
|
|
51917
|
+
return new SkillsFleetCredentialError(redactVaultReference(error.message, vaultReference), "MISSING_API_CREDENTIAL");
|
|
51724
51918
|
}
|
|
51725
51919
|
function normalizeSkillsApiOrigin(apiUrl) {
|
|
51726
51920
|
const url = new URL(apiUrl);
|
|
@@ -51907,7 +52101,7 @@ async function resolveSkillsConnection(env3 = process.env, options = {}) {
|
|
|
51907
52101
|
try {
|
|
51908
52102
|
completed = await completePointerCredential(SKILLS_APP, pointer, env3);
|
|
51909
52103
|
} catch (error) {
|
|
51910
|
-
const translated = asSkillsFleetCredentialError(error);
|
|
52104
|
+
const translated = asSkillsFleetCredentialError(error, pointer.pointerVaultKey);
|
|
51911
52105
|
if (translated)
|
|
51912
52106
|
throw translated;
|
|
51913
52107
|
throw error;
|
|
@@ -51963,7 +52157,7 @@ function requireSkillsFleet(action = "This command", env3 = process.env, options
|
|
|
51963
52157
|
return fleet;
|
|
51964
52158
|
throw new MissingSkillsFleetError(action);
|
|
51965
52159
|
}
|
|
51966
|
-
var SKILLS_APP = "skills", ENV_KEYS, SKILLS_API_URL_ENV_KEYS, SKILLS_API_KEY_ENV_KEYS, SKILLS_API_URL_ENV, SKILLS_API_KEY_ENV, SkillsFleetCredentialError, localNoticePrinted = false, MissingSkillsFleetError;
|
|
52160
|
+
var SKILLS_APP = "skills", ENV_KEYS, SKILLS_API_URL_ENV_KEYS, SKILLS_API_KEY_ENV_KEYS, SKILLS_API_URL_ENV, SKILLS_API_KEY_ENV, SkillsFleetCredentialError, REDACTED_VAULT_REFERENCE = "[redacted vault reference]", localNoticePrinted = false, MissingSkillsFleetError;
|
|
51967
52161
|
var init_fleet_credentials = __esm(() => {
|
|
51968
52162
|
init_transport();
|
|
51969
52163
|
init_instance_credentials();
|
|
@@ -52909,11 +53103,18 @@ async function syncSelectionProfile(profileId, options = {}) {
|
|
|
52909
53103
|
return { profile, receipt, changed, downloaded, stationReported };
|
|
52910
53104
|
}
|
|
52911
53105
|
async function resolveSelectionContext(profileId, options = {}) {
|
|
52912
|
-
const
|
|
52913
|
-
const
|
|
53106
|
+
const sessionState = options.sessionId ? readSkillSessionSnapshotIfExists(options.sessionId, options) : null;
|
|
53107
|
+
const session = sessionState?.receipt ?? null;
|
|
53108
|
+
const parentState = !session && options.parentSessionId ? readSkillSessionSnapshotIfExists(options.parentSessionId, options) : null;
|
|
53109
|
+
if (!session && options.parentSessionId && !parentState) {
|
|
53110
|
+
throw new SkillSelectionError("SESSION_PARENT_NOT_FOUND", "A child Skills session requires an existing parent receipt so its inherited pin can be bound exactly.");
|
|
53111
|
+
}
|
|
53112
|
+
const parentSession = parentState?.receipt ?? null;
|
|
53113
|
+
const sessionSnapshot = sessionState ? skillSessionSnapshotBinding(sessionState) : null;
|
|
53114
|
+
const parentSnapshot = parentState ? skillSessionSnapshotBinding(parentState) : undefined;
|
|
52914
53115
|
const project = options.projectDir ? readProjectSelection(options.projectDir) : null;
|
|
52915
53116
|
if (session && session.profile.profileId !== profileId || parentSession && parentSession.profile.profileId !== profileId || project && project.profile.profileId !== profileId) {
|
|
52916
|
-
throw new SkillSelectionError("PROFILE_LOCK_MISMATCH", "The session or project is pinned to a different Skills profile. Select
|
|
53117
|
+
throw new SkillSelectionError("PROFILE_LOCK_MISMATCH", "The session or project is pinned to a different Skills profile. Select the pinned profile, or review skills sessions reconcile for an intentional session change and explicit project sync for a project change.");
|
|
52917
53118
|
}
|
|
52918
53119
|
if (options.cached) {
|
|
52919
53120
|
const receipt2 = session ?? parentSession ?? project ?? readSelectionProfile(profileId, options);
|
|
@@ -52921,7 +53122,7 @@ async function resolveSelectionContext(profileId, options = {}) {
|
|
|
52921
53122
|
throw new SkillSelectionError("CACHED_PROFILE_MISSING", "No verified Skills profile is cached; authenticate and sync it first.");
|
|
52922
53123
|
assertFreshCachedProfile(receipt2, options);
|
|
52923
53124
|
assertBinding(receipt2.profile, options);
|
|
52924
|
-
return { receipt: receipt2, session, inheritedLoaded: parentSession?.loaded };
|
|
53125
|
+
return { receipt: receipt2, session, sessionSnapshot, parentSnapshot, inheritedLoaded: parentSession?.loaded };
|
|
52925
53126
|
}
|
|
52926
53127
|
const client = options.client ?? await createProfileClient();
|
|
52927
53128
|
const current = await client.resolveProfile(profileId);
|
|
@@ -52934,7 +53135,7 @@ async function resolveSelectionContext(profileId, options = {}) {
|
|
|
52934
53135
|
throw new SkillSelectionError("PROFILE_IDENTITY_MISMATCH", "The pinned selection belongs to another Skills authority or workspace.");
|
|
52935
53136
|
}
|
|
52936
53137
|
const receipt = locked ?? { schemaVersion: 1, verifiedAt: new Date((options.now ?? Date.now)()).toISOString(), profile: current };
|
|
52937
|
-
return { receipt, session, client, inheritedLoaded: parentSession?.loaded };
|
|
53138
|
+
return { receipt, session, sessionSnapshot, parentSnapshot, client, inheritedLoaded: parentSession?.loaded };
|
|
52938
53139
|
}
|
|
52939
53140
|
function assertBinding(profile, options) {
|
|
52940
53141
|
if (options.authority !== undefined && profile.authority !== options.authority || options.workspaceId !== undefined && profile.workspaceId !== options.workspaceId) {
|
|
@@ -52973,7 +53174,7 @@ async function loadSelectedSkill(spec, profileId, options = {}) {
|
|
|
52973
53174
|
sessionId: options.sessionId,
|
|
52974
53175
|
loaded: [...new Set([...context.session?.loaded ?? [], selectionKey(selection)])]
|
|
52975
53176
|
};
|
|
52976
|
-
|
|
53177
|
+
writeSkillSession(session, { current: context.sessionSnapshot, parent: context.parentSnapshot }, options);
|
|
52977
53178
|
}
|
|
52978
53179
|
return { content, selection, receipt };
|
|
52979
53180
|
}
|
|
@@ -53214,8 +53415,8 @@ var init_plugin_projection = __esm(() => {
|
|
|
53214
53415
|
|
|
53215
53416
|
// src/lib/plugin-projection-store.ts
|
|
53216
53417
|
import { createHash as createHash10, randomUUID as randomUUID5 } from "crypto";
|
|
53217
|
-
import { constants as constants7, closeSync as closeSync7, fchmodSync, fstatSync as fstatSync7, fsyncSync, linkSync, lstatSync as lstatSync13, mkdirSync as mkdirSync6, openSync as openSync7, opendirSync as opendirSync3, readSync as readSync5, renameSync as renameSync3, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
|
|
53218
|
-
import { dirname as dirname10, isAbsolute as
|
|
53418
|
+
import { constants as constants7, closeSync as closeSync7, fchmodSync, fstatSync as fstatSync7, fsyncSync as fsyncSync2, linkSync, lstatSync as lstatSync13, mkdirSync as mkdirSync6, openSync as openSync7, opendirSync as opendirSync3, readSync as readSync5, renameSync as renameSync3, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
|
|
53419
|
+
import { dirname as dirname10, isAbsolute as isAbsolute9, join as join25, parse as parse4, resolve as resolve10 } from "path";
|
|
53219
53420
|
function stat(path) {
|
|
53220
53421
|
try {
|
|
53221
53422
|
return lstatSync13(path, { bigint: true });
|
|
@@ -53226,7 +53427,7 @@ function stat(path) {
|
|
|
53226
53427
|
}
|
|
53227
53428
|
}
|
|
53228
53429
|
function canonical2(path) {
|
|
53229
|
-
pluginNeed(typeof path === "string" && path.length <= 8192 &&
|
|
53430
|
+
pluginNeed(typeof path === "string" && path.length <= 8192 && isAbsolute9(path) && resolve10(path) === path && !/[\x00-\x1f\x7f]/.test(path), "Plugin storage paths must be canonical absolute paths");
|
|
53230
53431
|
}
|
|
53231
53432
|
function owner(stats, system = false) {
|
|
53232
53433
|
const current = uid();
|
|
@@ -53435,7 +53636,7 @@ function writeExclusive(path, bytes, mode) {
|
|
|
53435
53636
|
pluginNeed(count > 0, "Plugin file write did not progress");
|
|
53436
53637
|
offset += count;
|
|
53437
53638
|
}
|
|
53438
|
-
|
|
53639
|
+
fsyncSync2(fd);
|
|
53439
53640
|
} catch (error) {
|
|
53440
53641
|
if (created) {
|
|
53441
53642
|
same3(created, stat(path), true);
|
|
@@ -53608,7 +53809,7 @@ var init_selected_manifest = __esm(() => {
|
|
|
53608
53809
|
|
|
53609
53810
|
// src/lib/plugin-admission.ts
|
|
53610
53811
|
import { homedir as homedir3 } from "os";
|
|
53611
|
-
import { isAbsolute as
|
|
53812
|
+
import { isAbsolute as isAbsolute10, join as join26, resolve as resolve11 } from "path";
|
|
53612
53813
|
function pluginAdmissionRoot() {
|
|
53613
53814
|
return join26(homedir3(), ".hasna", "skills", "plugin-admission");
|
|
53614
53815
|
}
|
|
@@ -53621,7 +53822,7 @@ function validatePluginTarget(value) {
|
|
|
53621
53822
|
for (const registration of value.registrations) {
|
|
53622
53823
|
pluginKeys(registration, ["scope", "projectPath"]);
|
|
53623
53824
|
pluginNeed(registration.scope === "user" || registration.scope === "project", "Unsupported plugin registration scope");
|
|
53624
|
-
pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" &&
|
|
53825
|
+
pluginNeed(registration.scope === "user" ? registration.projectPath === null : typeof registration.projectPath === "string" && isAbsolute10(registration.projectPath) && resolve11(registration.projectPath) === registration.projectPath, "Plugin scope requires its exact project path");
|
|
53625
53826
|
const key = JSON.stringify([registration.scope, registration.projectPath]);
|
|
53626
53827
|
pluginNeed(!scopes.has(key), "Duplicate plugin registration scope");
|
|
53627
53828
|
scopes.add(key);
|
|
@@ -53629,7 +53830,7 @@ function validatePluginTarget(value) {
|
|
|
53629
53830
|
for (const key of ["native", "resolver"]) {
|
|
53630
53831
|
pluginKeys(value[key], key === "native" ? ["version", "executable", "digest"] : ["executable", "digest"]);
|
|
53631
53832
|
pluginText(value[key].executable);
|
|
53632
|
-
pluginNeed(
|
|
53833
|
+
pluginNeed(isAbsolute10(value[key].executable) && resolve11(value[key].executable) === value[key].executable, "Plugin executable must have a canonical absolute path");
|
|
53633
53834
|
pluginDigest(value[key].digest);
|
|
53634
53835
|
}
|
|
53635
53836
|
pluginNeed(["2.1.274", "2.1.276"].includes(value.native.version), "Plugin admission requires a certified Claude command-source runtime (2.1.274 or 2.1.276)");
|
|
@@ -53779,7 +53980,7 @@ function pluginResolverCommand(binding) {
|
|
|
53779
53980
|
}
|
|
53780
53981
|
function root(options) {
|
|
53781
53982
|
const path = options.storeRoot ?? pluginAdmissionRoot();
|
|
53782
|
-
pluginNeed(
|
|
53983
|
+
pluginNeed(isAbsolute10(path) && resolve11(path) === path, "Invalid plugin admission store root");
|
|
53783
53984
|
return path;
|
|
53784
53985
|
}
|
|
53785
53986
|
function pluginBindingPath(storeRoot, id) {
|
|
@@ -53987,7 +54188,7 @@ var init_plugin_admission = __esm(() => {
|
|
|
53987
54188
|
|
|
53988
54189
|
// src/lib/plugin-discovery.ts
|
|
53989
54190
|
import { closeSync as closeSync8, constants as constants8, fstatSync as fstatSync8, lstatSync as lstatSync14, openSync as openSync8, opendirSync as opendirSync4, readSync as readSync6 } from "fs";
|
|
53990
|
-
import { basename as
|
|
54191
|
+
import { basename as basename5, dirname as dirname11, isAbsolute as isAbsolute11, join as join27, resolve as resolve12 } from "path";
|
|
53991
54192
|
function validateManagedPluginWitnesses(value) {
|
|
53992
54193
|
pluginNeed(Array.isArray(value) && value.length > 0 && value.length <= PLUGIN_PROJECTION_LIMITS.registrations, "Invalid managed plugin witness collection");
|
|
53993
54194
|
const seen = new Set;
|
|
@@ -53996,12 +54197,12 @@ function validateManagedPluginWitnesses(value) {
|
|
|
53996
54197
|
pluginNeed(typeof item.bindingId === "string" && /^[a-f0-9]{64}$/.test(item.bindingId) && !seen.has(item.bindingId), "Invalid or duplicate managed plugin witness");
|
|
53997
54198
|
seen.add(item.bindingId);
|
|
53998
54199
|
pluginText(item.storeRoot);
|
|
53999
|
-
pluginNeed(
|
|
54200
|
+
pluginNeed(isAbsolute11(item.storeRoot) && resolve12(item.storeRoot) === item.storeRoot, "Invalid plugin receipt store path");
|
|
54000
54201
|
}
|
|
54001
54202
|
}
|
|
54002
54203
|
function safe3(path) {
|
|
54003
54204
|
pluginText(path);
|
|
54004
|
-
pluginNeed(
|
|
54205
|
+
pluginNeed(isAbsolute11(path) && resolve12(path) === path, "Invalid plugin registry path");
|
|
54005
54206
|
for (let at2 = path;; at2 = dirname11(at2)) {
|
|
54006
54207
|
pluginNeed(!lstatSync14(at2, { throwIfNoEntry: false })?.isSymbolicLink(), "Plugin registry path traverses a symlink");
|
|
54007
54208
|
if (at2 === dirname11(at2))
|
|
@@ -54070,7 +54271,7 @@ function hashManagedPluginRegistry(path, managed) {
|
|
|
54070
54271
|
pluginNeed(/^(?:[A-Za-z0-9][A-Za-z0-9._+-]*-)?[a-f0-9]{12}$/.test(row.version) && row.installPath === join27(cacheRoot, row.version), "Managed plugin cache path or version is outside its registration");
|
|
54071
54272
|
const approval = (producer) => {
|
|
54072
54273
|
pluginText(producer);
|
|
54073
|
-
const digest = `sha256:${
|
|
54274
|
+
const digest = `sha256:${basename5(producer)}`;
|
|
54074
54275
|
const receipt2 = readPluginAdmissionReceipt(witness.storeRoot, witness.bindingId, digest);
|
|
54075
54276
|
pluginNeed(receipt2.materializedPath === producer, "Managed producer path is not an approved immutable projection");
|
|
54076
54277
|
if (!verified.has(producer)) {
|
|
@@ -54133,10 +54334,181 @@ var init_plugin_discovery = __esm(() => {
|
|
|
54133
54334
|
init_plugin_projection_store();
|
|
54134
54335
|
});
|
|
54135
54336
|
|
|
54136
|
-
// src/lib/
|
|
54337
|
+
// src/lib/claude-marketplace-registry.ts
|
|
54137
54338
|
import { createHash as createHash11 } from "crypto";
|
|
54138
|
-
import {
|
|
54139
|
-
import {
|
|
54339
|
+
import { closeSync as closeSync9, constants as constants9, fstatSync as fstatSync9, lstatSync as lstatSync15, openSync as openSync9, readSync as readSync7 } from "fs";
|
|
54340
|
+
import { basename as basename6, dirname as dirname12, isAbsolute as isAbsolute12, resolve as resolve13 } from "path";
|
|
54341
|
+
function need2(value, reason) {
|
|
54342
|
+
if (!value)
|
|
54343
|
+
throw new Error(`Claude marketplace registry ${reason}`);
|
|
54344
|
+
}
|
|
54345
|
+
function absolutePath(value) {
|
|
54346
|
+
need2(typeof value === "string" && value.length > 0 && value.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.pathCharacters && !/[\x00-\x1f\x7f]/.test(value) && isAbsolute12(value) && resolve13(value) === value, "requires a normalized absolute path");
|
|
54347
|
+
}
|
|
54348
|
+
function parents(path) {
|
|
54349
|
+
const result2 = [];
|
|
54350
|
+
for (let at2 = dirname12(path);; at2 = dirname12(at2)) {
|
|
54351
|
+
const stat2 = lstatSync15(at2, { bigint: true });
|
|
54352
|
+
need2(stat2.isDirectory() && !stat2.isSymbolicLink(), "path traverses a symlink or non-directory");
|
|
54353
|
+
result2.push([at2, stat2]);
|
|
54354
|
+
if (at2 === dirname12(at2))
|
|
54355
|
+
return result2;
|
|
54356
|
+
}
|
|
54357
|
+
}
|
|
54358
|
+
function readRegistry2(path, budget) {
|
|
54359
|
+
absolutePath(path);
|
|
54360
|
+
need2(basename6(path) === "known_marketplaces.json", "requires known_marketplaces.json");
|
|
54361
|
+
need2(Number.isSafeInteger(budget.remaining) && budget.remaining >= 0, "has an invalid byte budget");
|
|
54362
|
+
const ancestors2 = parents(path), initial2 = lstatSync15(path, { bigint: true });
|
|
54363
|
+
need2(initial2.isFile() && !initial2.isSymbolicLink() && initial2.size <= BigInt(CLAUDE_MARKETPLACE_REGISTRY_LIMITS.bytes), "is not a bounded regular file");
|
|
54364
|
+
need2(initial2.size <= BigInt(budget.remaining), "exceeds its aggregate byte limit");
|
|
54365
|
+
const fd = openSync9(path, constants9.O_RDONLY | constants9.O_NOFOLLOW | constants9.O_NONBLOCK);
|
|
54366
|
+
try {
|
|
54367
|
+
const opened = fstatSync9(fd, { bigint: true });
|
|
54368
|
+
need2(opened.isFile() && sameFile(initial2, opened), "changed during open");
|
|
54369
|
+
const bytes = Buffer.alloc(Number(opened.size) + 1);
|
|
54370
|
+
let length = 0;
|
|
54371
|
+
while (length < bytes.length) {
|
|
54372
|
+
const count = readSync7(fd, bytes, length, bytes.length - length, null);
|
|
54373
|
+
if (!count)
|
|
54374
|
+
break;
|
|
54375
|
+
length += count;
|
|
54376
|
+
}
|
|
54377
|
+
const after2 = fstatSync9(fd, { bigint: true }), current = lstatSync15(path, { bigint: true });
|
|
54378
|
+
need2(current.isFile() && sameFile(opened, after2) && sameFile(after2, current) && BigInt(length) === opened.size, "changed during read");
|
|
54379
|
+
for (const [ancestor, before2] of ancestors2) {
|
|
54380
|
+
const now3 = lstatSync15(ancestor, { bigint: true });
|
|
54381
|
+
need2(now3.isDirectory() && before2.dev === now3.dev && before2.ino === now3.ino && before2.mode === now3.mode, "parent changed during read");
|
|
54382
|
+
}
|
|
54383
|
+
budget.remaining -= length;
|
|
54384
|
+
try {
|
|
54385
|
+
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes.subarray(0, length));
|
|
54386
|
+
} catch {
|
|
54387
|
+
throw new Error("Claude marketplace registry is not strict UTF-8");
|
|
54388
|
+
}
|
|
54389
|
+
} finally {
|
|
54390
|
+
closeSync9(fd);
|
|
54391
|
+
}
|
|
54392
|
+
}
|
|
54393
|
+
function parse5(text2) {
|
|
54394
|
+
let at2 = 0, nodes = 0;
|
|
54395
|
+
const numberPattern = /-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/y;
|
|
54396
|
+
const space = () => {
|
|
54397
|
+
while (at2 < text2.length && /[\x20\t\r\n]/.test(text2[at2]))
|
|
54398
|
+
at2++;
|
|
54399
|
+
};
|
|
54400
|
+
function string() {
|
|
54401
|
+
need2(text2[at2] === '"', "contains invalid JSON");
|
|
54402
|
+
const start = at2++;
|
|
54403
|
+
while (at2 < text2.length) {
|
|
54404
|
+
const character = text2[at2++];
|
|
54405
|
+
if (character === '"') {
|
|
54406
|
+
let value2;
|
|
54407
|
+
try {
|
|
54408
|
+
value2 = JSON.parse(text2.slice(start, at2));
|
|
54409
|
+
} catch {
|
|
54410
|
+
throw new Error("Claude marketplace registry contains invalid JSON string");
|
|
54411
|
+
}
|
|
54412
|
+
need2(value2.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.stringCharacters, "exceeds its string limit");
|
|
54413
|
+
return value2;
|
|
54414
|
+
}
|
|
54415
|
+
if (character === "\\")
|
|
54416
|
+
at2++;
|
|
54417
|
+
}
|
|
54418
|
+
throw new Error("Claude marketplace registry contains an unterminated JSON string");
|
|
54419
|
+
}
|
|
54420
|
+
function value(depth) {
|
|
54421
|
+
need2(depth <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.depth && ++nodes <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.nodes, "exceeds its nesting or node limit");
|
|
54422
|
+
space();
|
|
54423
|
+
const character = text2[at2];
|
|
54424
|
+
if (character === '"')
|
|
54425
|
+
return { kind: "string", value: string() };
|
|
54426
|
+
if (character === "{" || character === "[") {
|
|
54427
|
+
at2++;
|
|
54428
|
+
space();
|
|
54429
|
+
const object4 = character === "{", end = object4 ? "}" : "]", entries = [], items = [], keys2 = new Set;
|
|
54430
|
+
if (text2[at2] !== end)
|
|
54431
|
+
while (true) {
|
|
54432
|
+
if (object4) {
|
|
54433
|
+
space();
|
|
54434
|
+
const key = string();
|
|
54435
|
+
need2(!keys2.has(key), "contains a duplicate JSON key");
|
|
54436
|
+
keys2.add(key);
|
|
54437
|
+
space();
|
|
54438
|
+
need2(text2[at2++] === ":", "contains invalid JSON");
|
|
54439
|
+
entries.push([key, value(depth + 1)]);
|
|
54440
|
+
} else
|
|
54441
|
+
items.push(value(depth + 1));
|
|
54442
|
+
space();
|
|
54443
|
+
if (text2[at2] === end)
|
|
54444
|
+
break;
|
|
54445
|
+
need2(text2[at2++] === ",", "contains invalid JSON");
|
|
54446
|
+
}
|
|
54447
|
+
at2++;
|
|
54448
|
+
return object4 ? { kind: "object", entries } : { kind: "array", items };
|
|
54449
|
+
}
|
|
54450
|
+
for (const literal of ["true", "false", "null"])
|
|
54451
|
+
if (text2.startsWith(literal, at2)) {
|
|
54452
|
+
at2 += literal.length;
|
|
54453
|
+
return { kind: "literal", value: literal };
|
|
54454
|
+
}
|
|
54455
|
+
numberPattern.lastIndex = at2;
|
|
54456
|
+
const number = numberPattern.exec(text2);
|
|
54457
|
+
need2(number, "contains invalid JSON");
|
|
54458
|
+
at2 += number[0].length;
|
|
54459
|
+
return { kind: "number", value: number[0] };
|
|
54460
|
+
}
|
|
54461
|
+
const root2 = value(0);
|
|
54462
|
+
space();
|
|
54463
|
+
need2(at2 === text2.length && root2.kind === "object", "requires a JSON object without trailing content");
|
|
54464
|
+
need2(root2.entries.length <= CLAUDE_MARKETPLACE_REGISTRY_LIMITS.rows, "exceeds its marketplace row limit");
|
|
54465
|
+
return root2;
|
|
54466
|
+
}
|
|
54467
|
+
function exactKeys(value, keys2) {
|
|
54468
|
+
return value?.kind === "object" && value.entries.length === keys2.length && value.entries.every(([key]) => keys2.includes(key));
|
|
54469
|
+
}
|
|
54470
|
+
function textField(value) {
|
|
54471
|
+
need2(value?.kind === "string" && value.value.length > 0 && !/[\x00-\x1f\x7f]/.test(value.value), "contains an invalid recognized field");
|
|
54472
|
+
return value.value;
|
|
54473
|
+
}
|
|
54474
|
+
function normalizeRow(row) {
|
|
54475
|
+
if (!exactKeys(row, ["source", "installLocation", "lastUpdated"]))
|
|
54476
|
+
return;
|
|
54477
|
+
const source = field(row, "source");
|
|
54478
|
+
if (source?.kind !== "object")
|
|
54479
|
+
return;
|
|
54480
|
+
const type = field(source, "source");
|
|
54481
|
+
if (type?.kind !== "string" || !["github", "directory"].includes(type.value))
|
|
54482
|
+
return;
|
|
54483
|
+
const location = type.value === "github" ? "repo" : "path";
|
|
54484
|
+
if (!exactKeys(source, ["source", location]))
|
|
54485
|
+
return;
|
|
54486
|
+
const sourceLocation = textField(field(source, location));
|
|
54487
|
+
if (type.value === "directory")
|
|
54488
|
+
absolutePath(sourceLocation);
|
|
54489
|
+
absolutePath(textField(field(row, "installLocation")));
|
|
54490
|
+
const updated = textField(field(row, "lastUpdated"));
|
|
54491
|
+
need2(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/.test(updated), "contains an invalid recognized update timestamp");
|
|
54492
|
+
const millis = Date.parse(updated);
|
|
54493
|
+
need2(Number.isFinite(millis) && new Date(millis).toISOString() === updated, "contains an invalid recognized update timestamp");
|
|
54494
|
+
row.entries = row.entries.map(([key, value]) => [key, key === "lastUpdated" ? { kind: "validated-update-time" } : value]);
|
|
54495
|
+
}
|
|
54496
|
+
function captureClaudeMarketplaceRegistry(path, budget = { remaining: 256 * 1024 * 1024 }) {
|
|
54497
|
+
const value = parse5(readRegistry2(path, budget));
|
|
54498
|
+
for (const [, row] of value.entries)
|
|
54499
|
+
normalizeRow(row);
|
|
54500
|
+
const sha2562 = createHash11("sha256").update("hasna.skills.claude-marketplace-registry.v1\x00").update(JSON.stringify(value)).digest("hex");
|
|
54501
|
+
return { path, hashMode: "claude-marketplace-registry", sha256: sha2562 };
|
|
54502
|
+
}
|
|
54503
|
+
var CLAUDE_MARKETPLACE_REGISTRY_LIMITS, sameFile = (a, b) => a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid && a.gid === b.gid && a.nlink === b.nlink && a.size === b.size && a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs, field = (object4, key) => object4.entries.find(([name]) => name === key)?.[1];
|
|
54504
|
+
var init_claude_marketplace_registry = __esm(() => {
|
|
54505
|
+
CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
54506
|
+
});
|
|
54507
|
+
|
|
54508
|
+
// src/lib/agent-discovery.ts
|
|
54509
|
+
import { createHash as createHash12 } from "crypto";
|
|
54510
|
+
import { lstatSync as lstatSync16, readFileSync as readFileSync14, readdirSync as readdirSync9, realpathSync as realpathSync4 } from "fs";
|
|
54511
|
+
import { dirname as dirname13, isAbsolute as isAbsolute13, join as join28, resolve as resolve14, sep as sep5 } from "path";
|
|
54140
54512
|
function parseConfig(text2, path, toml = false) {
|
|
54141
54513
|
try {
|
|
54142
54514
|
const value = toml ? Bun.TOML.parse(text2) : JSON.parse(text2);
|
|
@@ -54148,12 +54520,12 @@ function parseConfig(text2, path, toml = false) {
|
|
|
54148
54520
|
}
|
|
54149
54521
|
}
|
|
54150
54522
|
function safe4(path) {
|
|
54151
|
-
if (!
|
|
54523
|
+
if (!isAbsolute13(path) || path.includes("\x00"))
|
|
54152
54524
|
throw new Error("Expected an absolute native discovery path");
|
|
54153
|
-
for (let cursor = path;; cursor =
|
|
54154
|
-
if (
|
|
54525
|
+
for (let cursor = path;; cursor = dirname13(cursor)) {
|
|
54526
|
+
if (lstatSync16(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
54155
54527
|
throw new Error(`Refusing symlink native discovery input: ${cursor}`);
|
|
54156
|
-
if (
|
|
54528
|
+
if (dirname13(cursor) === cursor)
|
|
54157
54529
|
break;
|
|
54158
54530
|
}
|
|
54159
54531
|
}
|
|
@@ -54161,7 +54533,7 @@ function read2(path, changes) {
|
|
|
54161
54533
|
safe4(path);
|
|
54162
54534
|
if (changes?.has(path))
|
|
54163
54535
|
return changes.get(path);
|
|
54164
|
-
const stat2 =
|
|
54536
|
+
const stat2 = lstatSync16(path, { throwIfNoEntry: false });
|
|
54165
54537
|
if (!stat2)
|
|
54166
54538
|
return null;
|
|
54167
54539
|
if (!stat2.isFile() || stat2.size > 16 * 1024 * 1024)
|
|
@@ -54169,6 +54541,14 @@ function read2(path, changes) {
|
|
|
54169
54541
|
return readFileSync14(path, "utf8");
|
|
54170
54542
|
}
|
|
54171
54543
|
function projected(source, changes, budget = discoveryByteBudget()) {
|
|
54544
|
+
if (source.hashMode === "claude-marketplace-registry") {
|
|
54545
|
+
if (source.format !== undefined || source.fields !== undefined || source.managedPlugins !== undefined || typeof source.sha256 !== "string" || !/^[a-f0-9]{64}$/.test(source.sha256) || changes?.has(source.path))
|
|
54546
|
+
throw new Error("Claude marketplace witnesses require an exact reviewed registry without synthetic changes");
|
|
54547
|
+
const sha2562 = captureClaudeMarketplaceRegistry(source.path, budget).sha256;
|
|
54548
|
+
if (sha2562 !== source.sha256)
|
|
54549
|
+
throw new Error(`Native discovery input changed; run skills hook install with a fresh discovery review: ${source.path}`);
|
|
54550
|
+
return sha2562;
|
|
54551
|
+
}
|
|
54172
54552
|
if (source.hashMode === "claude-plugin-registry") {
|
|
54173
54553
|
if (source.format !== undefined || source.fields !== undefined || !source.managedPlugins || changes?.has(source.path))
|
|
54174
54554
|
throw new Error("Managed plugin registry witnesses require verified native registrations");
|
|
@@ -54193,7 +54573,7 @@ function projected(source, changes, budget = discoveryByteBudget()) {
|
|
|
54193
54573
|
const object4 = source.format === "yaml" ? parseHermesConfig(text2) : parseConfig(text2, source.path, source.format === "toml");
|
|
54194
54574
|
if (!object4 || typeof object4 !== "object" || Array.isArray(object4))
|
|
54195
54575
|
throw new Error("Expected native discovery configuration object");
|
|
54196
|
-
return digest(JSON.stringify(Object.fromEntries((source.fields ?? []).map((
|
|
54576
|
+
return digest(JSON.stringify(Object.fromEntries((source.fields ?? []).map((field2) => [field2, object4[field2] ?? null]))));
|
|
54197
54577
|
}
|
|
54198
54578
|
function verifyAgentDiscovery(binding) {
|
|
54199
54579
|
if (!binding || !Array.isArray(binding.sources) || !Array.isArray(binding.roots) || binding.sources.length > AGENT_POLICY_LIMITS.discoverySources || binding.roots.length > AGENT_POLICY_LIMITS.discoveryRoots)
|
|
@@ -54204,9 +54584,10 @@ function verifyAgentDiscovery(binding) {
|
|
|
54204
54584
|
verifyDiscoveryDirectories(binding.directories);
|
|
54205
54585
|
const budget = discoveryByteBudget();
|
|
54206
54586
|
for (const source of binding.sources) {
|
|
54587
|
+
assertMarketplaceBinding(binding, source);
|
|
54207
54588
|
if (source.hashMode === "claude-plugin-registry" && binding.agent !== "claude")
|
|
54208
54589
|
throw new Error("Managed Claude registry witnesses cannot apply to another agent");
|
|
54209
|
-
if (source.format !== undefined && (!["json", "toml", "yaml"].includes(source.format) || !Array.isArray(source.fields) || !source.fields.length || source.fields.length > 64 || source.fields.some((
|
|
54590
|
+
if (source.format !== undefined && (!["json", "toml", "yaml"].includes(source.format) || !Array.isArray(source.fields) || !source.fields.length || source.fields.length > 64 || source.fields.some((field2) => typeof field2 !== "string" || !field2)))
|
|
54210
54591
|
throw new Error("Invalid native discovery projection");
|
|
54211
54592
|
if (source.sha256 !== null && !/^[a-f0-9]{64}$/.test(source.sha256))
|
|
54212
54593
|
throw new Error("Invalid native discovery digest");
|
|
@@ -54216,13 +54597,20 @@ function verifyAgentDiscovery(binding) {
|
|
|
54216
54597
|
for (const root2 of binding.roots)
|
|
54217
54598
|
safe4(root2);
|
|
54218
54599
|
}
|
|
54600
|
+
function assertMarketplaceBinding(binding, source) {
|
|
54601
|
+
if (source.hashMode === "claude-marketplace-registry" && (binding.agent !== "claude" || binding.method !== "reviewed"))
|
|
54602
|
+
throw new Error("Claude marketplace witnesses require explicit reviewed Claude discovery");
|
|
54603
|
+
}
|
|
54219
54604
|
function rebindAgentDiscovery(binding, changes) {
|
|
54220
54605
|
const budget = discoveryByteBudget();
|
|
54221
|
-
return { ...binding, sources: binding.sources.map((source) =>
|
|
54606
|
+
return { ...binding, sources: binding.sources.map((source) => {
|
|
54607
|
+
assertMarketplaceBinding(binding, source);
|
|
54608
|
+
return { ...source, sha256: projected(source, changes, budget) };
|
|
54609
|
+
}) };
|
|
54222
54610
|
}
|
|
54223
|
-
function assertProjectDiscovery(agent, directories, home, canonical3 =
|
|
54611
|
+
function assertProjectDiscovery(agent, directories, home, canonical3 = resolve14, reviewed) {
|
|
54224
54612
|
for (const directory of directories) {
|
|
54225
|
-
const isHome =
|
|
54613
|
+
const isHome = resolve14(directory) === resolve14(home);
|
|
54226
54614
|
if (agent === "hermes") {
|
|
54227
54615
|
assertHermesEnvironment(home);
|
|
54228
54616
|
continue;
|
|
@@ -54253,13 +54641,13 @@ function assertProjectDiscovery(agent, directories, home, canonical3 = resolve12
|
|
|
54253
54641
|
if (agent === "claude") {
|
|
54254
54642
|
const commands = canonical3(join28(directory, ".claude/commands"));
|
|
54255
54643
|
safe4(commands);
|
|
54256
|
-
if (
|
|
54644
|
+
if (lstatSync16(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
|
|
54257
54645
|
throw new Error("NATIVE_SKILL_DRIFT: legacy project command discovery requires a dedicated format adapter");
|
|
54258
54646
|
}
|
|
54259
54647
|
}
|
|
54260
54648
|
}
|
|
54261
54649
|
function resolveAgentDiscovery(options) {
|
|
54262
|
-
const canonical3 = options.canonical ??
|
|
54650
|
+
const canonical3 = options.canonical ?? resolve14, home = resolve14(options.home), agent = options.agent;
|
|
54263
54651
|
const sources = [], roots = new Set, builtinNames = [];
|
|
54264
54652
|
const witness = (path, format, fields) => {
|
|
54265
54653
|
const source = { path: canonical3(path), sha256: null, ...format ? { format, fields } : {} };
|
|
@@ -54290,7 +54678,7 @@ function resolveAgentDiscovery(options) {
|
|
|
54290
54678
|
continue;
|
|
54291
54679
|
if (normalized.startsWith("~") && normalized !== "~" && !normalized.startsWith("~/"))
|
|
54292
54680
|
unresolved("user-specific tilde expansion requires a separate discovery adapter");
|
|
54293
|
-
const path = normalized === "~" ? home : normalized.startsWith("~/") ? join28(home, normalized.slice(2)) :
|
|
54681
|
+
const path = normalized === "~" ? home : normalized.startsWith("~/") ? join28(home, normalized.slice(2)) : resolve14(home, ".hermes", normalized);
|
|
54294
54682
|
safe4(path);
|
|
54295
54683
|
roots.add(path);
|
|
54296
54684
|
}
|
|
@@ -54299,21 +54687,21 @@ function resolveAgentDiscovery(options) {
|
|
|
54299
54687
|
const executable = Bun.which("gemini");
|
|
54300
54688
|
if (executable) {
|
|
54301
54689
|
let packageRoot;
|
|
54302
|
-
for (let directory =
|
|
54690
|
+
for (let directory = dirname13(realpathSync4(executable)), depth = 0;depth < 8; directory = dirname13(directory), depth++) {
|
|
54303
54691
|
const path = join28(directory, "package.json"), raw = read2(path);
|
|
54304
54692
|
if (raw !== null && parseConfig(raw, path).name === "@google/gemini-cli") {
|
|
54305
54693
|
packageRoot = directory;
|
|
54306
54694
|
witness(path);
|
|
54307
54695
|
break;
|
|
54308
54696
|
}
|
|
54309
|
-
if (
|
|
54697
|
+
if (dirname13(directory) === directory)
|
|
54310
54698
|
break;
|
|
54311
54699
|
}
|
|
54312
54700
|
if (!packageRoot)
|
|
54313
54701
|
unresolved("installed Gemini package layout is not recognized");
|
|
54314
54702
|
const builtinRoot = join28(packageRoot, "bundle/builtin");
|
|
54315
54703
|
safe4(builtinRoot);
|
|
54316
|
-
if (!
|
|
54704
|
+
if (!lstatSync16(builtinRoot, { throwIfNoEntry: false })?.isDirectory())
|
|
54317
54705
|
unresolved("installed Gemini builtin root is missing");
|
|
54318
54706
|
for (const name of readdirSync9(builtinRoot).sort()) {
|
|
54319
54707
|
const text2 = witness(join28(builtinRoot, name, "SKILL.md"));
|
|
@@ -54351,7 +54739,7 @@ function resolveAgentDiscovery(options) {
|
|
|
54351
54739
|
unresolved("plugin hooks require a separate no-skill-injection review");
|
|
54352
54740
|
const commands = join28(root2, "commands");
|
|
54353
54741
|
safe4(commands);
|
|
54354
|
-
if (agent === "claude" && (manifest.commands !== undefined ||
|
|
54742
|
+
if (agent === "claude" && (manifest.commands !== undefined || lstatSync16(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length))
|
|
54355
54743
|
unresolved("legacy command discovery requires retirement or a dedicated format adapter");
|
|
54356
54744
|
const rootSkill = witness(join28(root2, "SKILL.md"));
|
|
54357
54745
|
if (rootSkill !== null)
|
|
@@ -54362,10 +54750,10 @@ function resolveAgentDiscovery(options) {
|
|
|
54362
54750
|
if (agent === "claude")
|
|
54363
54751
|
roots.add(join28(root2, "skills"));
|
|
54364
54752
|
for (const value of declared) {
|
|
54365
|
-
const path =
|
|
54753
|
+
const path = resolve14(root2, value);
|
|
54366
54754
|
if (path !== root2 && !path.startsWith(root2 + sep5))
|
|
54367
54755
|
unresolved("plugin skill path escapes its root");
|
|
54368
|
-
roots.add(path.endsWith(`${sep5}SKILL.md`) ?
|
|
54756
|
+
roots.add(path.endsWith(`${sep5}SKILL.md`) ? dirname13(path) : path);
|
|
54369
54757
|
}
|
|
54370
54758
|
}
|
|
54371
54759
|
if (agent === "claude") {
|
|
@@ -54373,7 +54761,7 @@ function resolveAgentDiscovery(options) {
|
|
|
54373
54761
|
const installed = registrations === null ? {} : parseConfig(registrations, join28(home, ".claude/plugins/installed_plugins.json")).plugins;
|
|
54374
54762
|
const commands = canonical3(join28(home, ".claude/commands"));
|
|
54375
54763
|
safe4(commands);
|
|
54376
|
-
if (
|
|
54764
|
+
if (lstatSync16(commands, { throwIfNoEntry: false })?.isDirectory() && readdirSync9(commands).length)
|
|
54377
54765
|
unresolved("legacy home command discovery requires a dedicated format adapter");
|
|
54378
54766
|
for (const [id, enabled] of Object.entries(config.enabledPlugins ?? {})) {
|
|
54379
54767
|
if (enabled === false)
|
|
@@ -54393,7 +54781,7 @@ function resolveAgentDiscovery(options) {
|
|
|
54393
54781
|
unresolved("unsupported plugin enablement");
|
|
54394
54782
|
const split2 = id.lastIndexOf("@"), name = id.slice(0, split2), marketplace = id.slice(split2 + 1);
|
|
54395
54783
|
const market = config.marketplaces?.[marketplace] ?? (marketplace === "personal" ? { source_type: "local", source: home } : undefined);
|
|
54396
|
-
if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !
|
|
54784
|
+
if (split2 < 1 || market?.source_type !== "local" || typeof market.source !== "string" || !isAbsolute13(market.source))
|
|
54397
54785
|
unresolved("enabled plugin marketplace is not an explicit local source");
|
|
54398
54786
|
const catalogText = witness(join28(market.source, ".agents/plugins/marketplace.json"));
|
|
54399
54787
|
if (catalogText === null)
|
|
@@ -54401,7 +54789,7 @@ function resolveAgentDiscovery(options) {
|
|
|
54401
54789
|
const catalog = parseConfig(catalogText, join28(market.source, ".agents/plugins/marketplace.json")), matches2 = Array.isArray(catalog.plugins) ? catalog.plugins.filter((item) => item.name === name) : [];
|
|
54402
54790
|
if (matches2.length !== 1 || matches2[0]?.source?.source !== "local" || typeof matches2[0]?.source?.path !== "string")
|
|
54403
54791
|
unresolved("plugin catalog source is missing or ambiguous");
|
|
54404
|
-
plugin(
|
|
54792
|
+
plugin(resolve14(market.source, matches2[0].source.path));
|
|
54405
54793
|
}
|
|
54406
54794
|
} else if (agent === "opencode") {
|
|
54407
54795
|
if (witness(join28(home, ".config/opencode/opencode.jsonc")) !== null || witness(join28(home, ".config/opencode/config.json")) !== null)
|
|
@@ -54409,18 +54797,18 @@ function resolveAgentDiscovery(options) {
|
|
|
54409
54797
|
if ((config.plugin?.length ?? 0) > 0 || config.skills?.urls?.length)
|
|
54410
54798
|
unresolved("external plugin or remote skill source");
|
|
54411
54799
|
for (const path of config.skills?.paths ?? []) {
|
|
54412
|
-
if (typeof path !== "string" || !
|
|
54800
|
+
if (typeof path !== "string" || !isAbsolute13(path))
|
|
54413
54801
|
unresolved("relative or malformed added skill root");
|
|
54414
54802
|
roots.add(path);
|
|
54415
54803
|
}
|
|
54416
54804
|
const localPlugins = join28(home, ".config/opencode/plugins");
|
|
54417
54805
|
safe4(localPlugins);
|
|
54418
|
-
if (
|
|
54806
|
+
if (lstatSync16(localPlugins, { throwIfNoEntry: false }) && readdirSync9(localPlugins).some((name) => name !== "skills-cli.js"))
|
|
54419
54807
|
unresolved("additional local plugin hooks require review");
|
|
54420
54808
|
} else if (agent === "hermes") {
|
|
54421
54809
|
for (const directory of [join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")]) {
|
|
54422
54810
|
safe4(directory);
|
|
54423
|
-
if (
|
|
54811
|
+
if (lstatSync16(directory, { throwIfNoEntry: false }))
|
|
54424
54812
|
unresolved("installed runtime/plugin discovery requires reviewed source bindings");
|
|
54425
54813
|
}
|
|
54426
54814
|
if (Bun.which("hermes") || Object.keys(config.plugins ?? {}).length)
|
|
@@ -54430,11 +54818,11 @@ function resolveAgentDiscovery(options) {
|
|
|
54430
54818
|
unresolved("custom extension or skill paths");
|
|
54431
54819
|
const directory = join28(home, ".gemini/extensions");
|
|
54432
54820
|
safe4(directory);
|
|
54433
|
-
if (
|
|
54821
|
+
if (lstatSync16(directory, { throwIfNoEntry: false }))
|
|
54434
54822
|
for (const name of readdirSync9(directory)) {
|
|
54435
54823
|
const root2 = join28(directory, name);
|
|
54436
54824
|
safe4(root2);
|
|
54437
|
-
if (!
|
|
54825
|
+
if (!lstatSync16(root2)?.isDirectory())
|
|
54438
54826
|
continue;
|
|
54439
54827
|
const raw = witness(join28(root2, "gemini-extension.json"));
|
|
54440
54828
|
if (raw === null)
|
|
@@ -54447,7 +54835,7 @@ function resolveAgentDiscovery(options) {
|
|
|
54447
54835
|
}
|
|
54448
54836
|
return { agent, roots: [...roots].sort(), sources, method: "automatic", ...agent === "gemini" ? { builtinNames } : {}, ...agent === "hermes" ? { directories: captureDiscoveryDirectories([join28(home, ".hermes/plugins"), join28(home, ".hermes/hermes-agent")].map((path) => canonical3(path))) } : {} };
|
|
54449
54837
|
}
|
|
54450
|
-
var digest = (text2) =>
|
|
54838
|
+
var digest = (text2) => createHash12("sha256").update(text2).digest("hex");
|
|
54451
54839
|
var init_agent_discovery = __esm(() => {
|
|
54452
54840
|
init_agent_policy_limits();
|
|
54453
54841
|
init_agent_hermes();
|
|
@@ -54456,6 +54844,7 @@ var init_agent_discovery = __esm(() => {
|
|
|
54456
54844
|
init_agent_discovery_path_bytes();
|
|
54457
54845
|
init_plugin_discovery();
|
|
54458
54846
|
init_plugin_admission();
|
|
54847
|
+
init_claude_marketplace_registry();
|
|
54459
54848
|
init_agent_discovery_directories();
|
|
54460
54849
|
});
|
|
54461
54850
|
|
|
@@ -54540,7 +54929,7 @@ var init_agent_adapters = __esm(() => {
|
|
|
54540
54929
|
});
|
|
54541
54930
|
|
|
54542
54931
|
// src/lib/agent-codex.ts
|
|
54543
|
-
import { isDeepStrictEqual as
|
|
54932
|
+
import { isDeepStrictEqual as isDeepStrictEqual3 } from "util";
|
|
54544
54933
|
function assertCodexPathConfigEditable(text2) {
|
|
54545
54934
|
const before2 = Bun.TOML.parse(text2);
|
|
54546
54935
|
if (before2.skills?.config === undefined)
|
|
@@ -54549,7 +54938,7 @@ function assertCodexPathConfigEditable(text2) {
|
|
|
54549
54938
|
delete expected.skills.config;
|
|
54550
54939
|
try {
|
|
54551
54940
|
const withoutSections = Bun.TOML.parse(text2.replace(CODEX_SKILL_CONFIG_SECTIONS, ""));
|
|
54552
|
-
if (
|
|
54941
|
+
if (isDeepStrictEqual3(withoutSections, expected))
|
|
54553
54942
|
return;
|
|
54554
54943
|
} catch {}
|
|
54555
54944
|
throw new Error("Codex skill path controls require ordinary [[skills.config]] TOML tables; preserve and convert inline or dotted config arrays before running skills hook install");
|
|
@@ -54587,7 +54976,7 @@ function disableCodexBundledSkills(text2) {
|
|
|
54587
54976
|
const candidates = new Set;
|
|
54588
54977
|
const consider = (candidate2) => {
|
|
54589
54978
|
try {
|
|
54590
|
-
if (
|
|
54979
|
+
if (isDeepStrictEqual3(Bun.TOML.parse(candidate2), expected))
|
|
54591
54980
|
candidates.add(candidate2);
|
|
54592
54981
|
} catch {}
|
|
54593
54982
|
};
|
|
@@ -54617,16 +55006,16 @@ var init_agent_codex = __esm(() => {
|
|
|
54617
55006
|
});
|
|
54618
55007
|
|
|
54619
55008
|
// src/lib/agent-integration.ts
|
|
54620
|
-
import { createHash as
|
|
54621
|
-
import { existsSync as existsSync15, lstatSync as
|
|
54622
|
-
import { dirname as
|
|
55009
|
+
import { createHash as createHash13, randomUUID as randomUUID6 } from "crypto";
|
|
55010
|
+
import { existsSync as existsSync15, lstatSync as lstatSync17, statSync as statSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync15, readdirSync as readdirSync10, opendirSync as opendirSync5, readlinkSync as readlinkSync2, realpathSync as realpathSync5, renameSync as renameSync4, rmdirSync as rmdirSync3, writeFileSync as writeFileSync5, unlinkSync as unlinkSync4, chmodSync, openSync as openSync10, closeSync as closeSync10, fsyncSync as fsyncSync3, fstatSync as fstatSync10, readSync as readSync8, constants as constants10, linkSync as linkSync2 } from "fs";
|
|
55011
|
+
import { dirname as dirname14, join as join29, resolve as resolve15, relative as relative5, isAbsolute as isAbsolute14, sep as sep6 } from "path";
|
|
54623
55012
|
import { homedir as homedir4 } from "os";
|
|
54624
55013
|
function assertSafePath(path) {
|
|
54625
|
-
let cursor =
|
|
55014
|
+
let cursor = resolve15(path);
|
|
54626
55015
|
while (true) {
|
|
54627
|
-
if (
|
|
55016
|
+
if (lstatSync17(cursor, { throwIfNoEntry: false })?.isSymbolicLink())
|
|
54628
55017
|
throw new Error(`Refusing symlink path: ${cursor}`);
|
|
54629
|
-
const parent =
|
|
55018
|
+
const parent = dirname14(cursor);
|
|
54630
55019
|
if (parent === cursor)
|
|
54631
55020
|
return;
|
|
54632
55021
|
cursor = parent;
|
|
@@ -54635,16 +55024,16 @@ function assertSafePath(path) {
|
|
|
54635
55024
|
function readRootAlias(home, agent) {
|
|
54636
55025
|
assertSafePath(home);
|
|
54637
55026
|
const realHome = realpathSync5(home), alias = join29(realHome, `.${agent}`);
|
|
54638
|
-
const stat2 =
|
|
55027
|
+
const stat2 = lstatSync17(alias, { throwIfNoEntry: false, bigint: true });
|
|
54639
55028
|
if (!stat2?.isSymbolicLink())
|
|
54640
55029
|
throw new Error(`Agent root alias changed after planning: ${alias}`);
|
|
54641
|
-
const link2 = readlinkSync2(alias), targetPath =
|
|
55030
|
+
const link2 = readlinkSync2(alias), targetPath = resolve15(dirname14(alias), link2);
|
|
54642
55031
|
assertSafePath(targetPath);
|
|
54643
|
-
const targetStat =
|
|
55032
|
+
const targetStat = lstatSync17(targetPath, { throwIfNoEntry: false });
|
|
54644
55033
|
if (!targetStat?.isDirectory())
|
|
54645
55034
|
throw new Error(`Agent root alias must target an existing directory: ${alias}`);
|
|
54646
55035
|
const target = realpathSync5(targetPath), inside = relative5(realHome, target);
|
|
54647
|
-
if (!inside || inside === ".." || inside.startsWith(`..${sep6}`) ||
|
|
55036
|
+
if (!inside || inside === ".." || inside.startsWith(`..${sep6}`) || isAbsolute14(inside))
|
|
54648
55037
|
throw new Error(`Agent root alias target must be inside the real home: ${alias}`);
|
|
54649
55038
|
return { agent, home: realHome, alias, target, link: link2, aliasIdentity: `${stat2.dev}:${stat2.ino}:${stat2.ctimeNs}`, targetIdentity: `${targetStat.dev}:${targetStat.ino}` };
|
|
54650
55039
|
}
|
|
@@ -54653,14 +55042,14 @@ function rootAliases(home, allowed = false) {
|
|
|
54653
55042
|
return [];
|
|
54654
55043
|
const result2 = [];
|
|
54655
55044
|
for (const agent of ["claude", "codex"])
|
|
54656
|
-
if (
|
|
55045
|
+
if (lstatSync17(join29(home, `.${agent}`), { throwIfNoEntry: false })?.isSymbolicLink())
|
|
54657
55046
|
result2.push(readRootAlias(home, agent));
|
|
54658
55047
|
if (result2.some((item, index) => result2.slice(index + 1).some((other) => item.target === other.target || item.target.startsWith(other.target + sep6) || other.target.startsWith(item.target + sep6))))
|
|
54659
55048
|
throw new Error("Agent root alias targets must not overlap");
|
|
54660
55049
|
return result2;
|
|
54661
55050
|
}
|
|
54662
55051
|
function canonicalAgentPath(path, aliases) {
|
|
54663
|
-
const absolute =
|
|
55052
|
+
const absolute = resolve15(path), binding = aliases.find((item) => absolute === item.alias || absolute.startsWith(item.alias + sep6));
|
|
54664
55053
|
return binding ? join29(binding.target, relative5(binding.alias, absolute)) : absolute;
|
|
54665
55054
|
}
|
|
54666
55055
|
function recheckRootAliases(aliases) {
|
|
@@ -54674,35 +55063,35 @@ function recheckRootAliases(aliases) {
|
|
|
54674
55063
|
}
|
|
54675
55064
|
function readNativeBytes(path, maximum = 64 * 1024 * 1024) {
|
|
54676
55065
|
assertSafePath(path);
|
|
54677
|
-
const before2 =
|
|
55066
|
+
const before2 = lstatSync17(path);
|
|
54678
55067
|
if (!before2.isFile() || before2.size > maximum)
|
|
54679
55068
|
throw new Error("Unsupported or oversized native skill file");
|
|
54680
|
-
const descriptor =
|
|
55069
|
+
const descriptor = openSync10(path, constants10.O_RDONLY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
|
|
54681
55070
|
try {
|
|
54682
|
-
const opened =
|
|
55071
|
+
const opened = fstatSync10(descriptor);
|
|
54683
55072
|
if (!opened.isFile() || opened.dev !== before2.dev || opened.ino !== before2.ino || opened.size !== before2.size)
|
|
54684
55073
|
throw new Error("Native skill file changed while reading");
|
|
54685
55074
|
const bytes = Buffer.allocUnsafe(before2.size + 1);
|
|
54686
55075
|
let length = 0;
|
|
54687
55076
|
while (length < bytes.length) {
|
|
54688
|
-
const count =
|
|
55077
|
+
const count = readSync8(descriptor, bytes, length, bytes.length - length, null);
|
|
54689
55078
|
if (!count)
|
|
54690
55079
|
break;
|
|
54691
55080
|
length += count;
|
|
54692
55081
|
}
|
|
54693
|
-
const after2 =
|
|
55082
|
+
const after2 = fstatSync10(descriptor);
|
|
54694
55083
|
if (length !== before2.size || after2.size !== before2.size || after2.mtimeMs !== opened.mtimeMs || after2.ctimeMs !== opened.ctimeMs)
|
|
54695
55084
|
throw new Error("Native skill file changed while reading");
|
|
54696
55085
|
return bytes.subarray(0, length);
|
|
54697
55086
|
} finally {
|
|
54698
|
-
|
|
55087
|
+
closeSync10(descriptor);
|
|
54699
55088
|
}
|
|
54700
55089
|
}
|
|
54701
55090
|
function treeHash(root2) {
|
|
54702
|
-
const hash2 =
|
|
55091
|
+
const hash2 = createHash13("sha256");
|
|
54703
55092
|
let bytes = 0, files = 0;
|
|
54704
55093
|
function visit2(path) {
|
|
54705
|
-
const stat2 =
|
|
55094
|
+
const stat2 = lstatSync17(path);
|
|
54706
55095
|
if (stat2.isSymbolicLink())
|
|
54707
55096
|
throw new Error(`Refusing symlink in skill: ${path}`);
|
|
54708
55097
|
const rel = relative5(root2, path);
|
|
@@ -54728,11 +55117,11 @@ function treeHash(root2) {
|
|
|
54728
55117
|
function projectAncestorDirectories(projects) {
|
|
54729
55118
|
const directories = new Set;
|
|
54730
55119
|
for (const project of projects) {
|
|
54731
|
-
for (let path =
|
|
55120
|
+
for (let path = resolve15(project), depth = 0;; depth++) {
|
|
54732
55121
|
if (depth >= 100)
|
|
54733
55122
|
throw new Error("NATIVE_SKILL_DRIFT: project ancestor discovery limit exceeded");
|
|
54734
55123
|
directories.add(path);
|
|
54735
|
-
const parent =
|
|
55124
|
+
const parent = dirname14(path);
|
|
54736
55125
|
if (parent === path)
|
|
54737
55126
|
break;
|
|
54738
55127
|
path = parent;
|
|
@@ -54759,10 +55148,10 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
|
|
|
54759
55148
|
throw new Error("Native skill discovery metadata limit exceeded");
|
|
54760
55149
|
}
|
|
54761
55150
|
function emptySiblingCacheAlias(path, parent) {
|
|
54762
|
-
const link2 = readlinkSync2(path), target =
|
|
54763
|
-
if (
|
|
55151
|
+
const link2 = readlinkSync2(path), target = resolve15(parent, link2);
|
|
55152
|
+
if (dirname14(target) !== parent || (isAbsolute14(link2) ? link2 !== target : dirname14(link2) !== "."))
|
|
54764
55153
|
return false;
|
|
54765
|
-
if (!
|
|
55154
|
+
if (!lstatSync17(target, { throwIfNoEntry: false })?.isDirectory())
|
|
54766
55155
|
return false;
|
|
54767
55156
|
const scan = cacheScans.get(target);
|
|
54768
55157
|
return Boolean(scan?.complete && !scan.hasSkills && scan.entries <= maxAliasProofEntries);
|
|
@@ -54774,7 +55163,7 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
|
|
|
54774
55163
|
assertSafePath(path);
|
|
54775
55164
|
if (!existsSync15(path))
|
|
54776
55165
|
return scan;
|
|
54777
|
-
const stat2 =
|
|
55166
|
+
const stat2 = lstatSync17(path);
|
|
54778
55167
|
if (stat2.isFile())
|
|
54779
55168
|
return scan;
|
|
54780
55169
|
if (!stat2.isDirectory())
|
|
@@ -54793,7 +55182,7 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
|
|
|
54793
55182
|
}
|
|
54794
55183
|
const bridge = !vendor && isOwnedCliBridge(path, bridgePaths);
|
|
54795
55184
|
const rootAlias = aliases.find((item) => path === item.target || path.startsWith(item.target + sep6));
|
|
54796
|
-
entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join29(home, ".codex", "skills", ".system"), aliases) + sep6) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome:
|
|
55185
|
+
entries.push({ agent, path, hash: treeHash(path), managed, vendor, ...agent === "codex" && path.startsWith(canonicalAgentPath(join29(home, ".codex", "skills", ".system"), aliases) + sep6) ? { system: true } : {}, ...bridge ? { bridge: true, bridgeHome: resolve15(home) } : {}, ...rootAlias ? { rootAlias } : {} });
|
|
54797
55186
|
return scan;
|
|
54798
55187
|
}
|
|
54799
55188
|
if (depth > (vendor ? 32 : 3))
|
|
@@ -54820,7 +55209,7 @@ function inventoryNativeSkills(home = homedir4(), options = {}) {
|
|
|
54820
55209
|
if (isVendor && !options.includeVendor)
|
|
54821
55210
|
continue;
|
|
54822
55211
|
const child = join29(path, name);
|
|
54823
|
-
if (isVendor &&
|
|
55212
|
+
if (isVendor && lstatSync17(child, { throwIfNoEntry: false })?.isSymbolicLink()) {
|
|
54824
55213
|
const target = statSync8(child, { throwIfNoEntry: false });
|
|
54825
55214
|
if (target?.isFile() || pluginCache && target?.isDirectory() && emptySiblingCacheAlias(child, path)) {
|
|
54826
55215
|
scan.entries++;
|
|
@@ -54942,7 +55331,7 @@ function configureHooks(config, agent, command, profileId, nativeReady) {
|
|
|
54942
55331
|
function disableCodexSkills(text2, skills, aliases, bridgePath) {
|
|
54943
55332
|
const bundled = disableCodexBundledSkills(text2);
|
|
54944
55333
|
let result2 = bundled;
|
|
54945
|
-
const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [
|
|
55334
|
+
const bridgeSelector = (entry) => typeof entry.name === "string" && entry.name.trim() === CLI_BRIDGE_NAME || typeof entry.path === "string" && [resolve15(bridgePath), resolve15(join29(bridgePath, "SKILL.md"))].includes(canonicalAgentPath(entry.path, aliases));
|
|
54946
55335
|
const previousConfig = Bun.TOML.parse(bundled).skills?.config;
|
|
54947
55336
|
if (previousConfig !== undefined && (!Array.isArray(previousConfig) || previousConfig.some((entry) => !entry || typeof entry !== "object" || entry.path !== undefined && entry.name !== undefined)))
|
|
54948
55337
|
throw new Error("Codex skill controls require one path or name selector per [[skills.config]] entry; review ambiguous entries before running skills hook install");
|
|
@@ -54954,7 +55343,7 @@ function disableCodexSkills(text2, skills, aliases, bridgePath) {
|
|
|
54954
55343
|
result2 = result2.replace(CODEX_SKILL_CONFIG_SECTIONS, (section) => {
|
|
54955
55344
|
const parsed = Bun.TOML.parse(section);
|
|
54956
55345
|
const declared = parsed.skills?.config?.[0];
|
|
54957
|
-
if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [
|
|
55346
|
+
if (!declared || !(skill.enabled && bridgeSelector(declared)) && !(typeof declared.path === "string" && [resolve15(path), resolve15(skill.path)].includes(canonicalAgentPath(declared.path, aliases))))
|
|
54958
55347
|
return section;
|
|
54959
55348
|
found = true;
|
|
54960
55349
|
return /^\s*enabled\s*=/m.test(section) ? section.replace(/^\s*enabled\s*=.*$/m, `enabled = ${skill.enabled}`) : `${section.trimEnd()}
|
|
@@ -54984,9 +55373,9 @@ function planAgentIntegration(options) {
|
|
|
54984
55373
|
throw new Error("Invalid existing Skills bridge policy");
|
|
54985
55374
|
if (policy.bridge?.agents !== undefined && (!Array.isArray(policy.bridge.agents) || policy.bridge.agents.some((agent) => !INTEGRATION_AGENTS.includes(agent))))
|
|
54986
55375
|
throw new Error("Invalid existing bridge agent inventory");
|
|
54987
|
-
for (const
|
|
54988
|
-
if (policy.bridge?.[
|
|
54989
|
-
throw new Error(`Invalid existing bridge ${
|
|
55376
|
+
for (const field2 of ["commands", "profiles"])
|
|
55377
|
+
if (policy.bridge?.[field2] !== undefined && (!policy.bridge[field2] || typeof policy.bridge[field2] !== "object" || Array.isArray(policy.bridge[field2]) || Object.entries(policy.bridge[field2]).some(([key, value]) => !INTEGRATION_AGENTS.includes(key) || typeof value !== "string" || !value || value.includes("\x00"))))
|
|
55378
|
+
throw new Error(`Invalid existing bridge ${field2} binding`);
|
|
54990
55379
|
const priorAgents = policy.bridge?.agents ?? [];
|
|
54991
55380
|
const profileId = options.profileId ?? policy.profileId ?? "default";
|
|
54992
55381
|
const validateProfile = (value) => {
|
|
@@ -55072,7 +55461,7 @@ function planAgentIntegration(options) {
|
|
|
55072
55461
|
version: CLI_BRIDGE_VERSION,
|
|
55073
55462
|
digest: CLI_BRIDGE_DIGEST,
|
|
55074
55463
|
agents: [...new Set([...priorAgents, ...options.agents])].sort(),
|
|
55075
|
-
home:
|
|
55464
|
+
home: resolve15(home),
|
|
55076
55465
|
includeVendor: true,
|
|
55077
55466
|
...options.agents.includes("hermes") ? { supervisors: { ...policy.bridge?.supervisors, hermes: { path: join29(dataDir3, "agent-hooks", "hermes.js"), runtime: process.execPath, sha256: sha(renderHermesSupervisor(bindings.get("hermes").command, bindings.get("hermes").profileId)) } } } : {},
|
|
55078
55467
|
commands: { ...policy.bridge?.commands, ...Object.fromEntries([...bindings].map(([agent, binding]) => [agent, binding.command])) },
|
|
@@ -55089,7 +55478,7 @@ function planAgentIntegration(options) {
|
|
|
55089
55478
|
}
|
|
55090
55479
|
function atomicWrite2(path, content) {
|
|
55091
55480
|
assertSafePath(path);
|
|
55092
|
-
mkdirSync7(
|
|
55481
|
+
mkdirSync7(dirname14(path), { recursive: true, mode: 448 });
|
|
55093
55482
|
const temporary = `${path}.skills-${randomUUID6()}`;
|
|
55094
55483
|
try {
|
|
55095
55484
|
writeFileSync5(temporary, content, { mode: 384, flag: "wx" });
|
|
@@ -55102,10 +55491,10 @@ function atomicWrite2(path, content) {
|
|
|
55102
55491
|
function applyAgentIntegration(plan) {
|
|
55103
55492
|
const policyPath = join29(plan.dataDir, "agent-policy.json");
|
|
55104
55493
|
assertSafePath(policyPath);
|
|
55105
|
-
const currentText = (path) =>
|
|
55494
|
+
const currentText = (path) => resolve15(path) === resolve15(policyPath) ? readManagedSkillPolicySnapshot(plan.dataDir)?.text ?? null : readOptional(path);
|
|
55106
55495
|
readManagedSkillPolicySnapshot(plan.dataDir);
|
|
55107
55496
|
for (const change of plan.changes)
|
|
55108
|
-
if (
|
|
55497
|
+
if (resolve15(change.path) === resolve15(policyPath))
|
|
55109
55498
|
parseManagedSkillPolicy(change.after);
|
|
55110
55499
|
const aliases = plan.rootAliases ?? [];
|
|
55111
55500
|
recheckRootAliases(aliases);
|
|
@@ -55135,7 +55524,7 @@ function applyAgentIntegration(plan) {
|
|
|
55135
55524
|
recheckRootAliases(aliases);
|
|
55136
55525
|
if (currentText(change.path) !== change.before)
|
|
55137
55526
|
throw new Error(`Configuration changed after planning: ${change.path}`);
|
|
55138
|
-
for (let directory =
|
|
55527
|
+
for (let directory = dirname14(change.path);!existsSync15(directory); directory = dirname14(directory))
|
|
55139
55528
|
createdDirectories.add(directory);
|
|
55140
55529
|
const after2 = change.after;
|
|
55141
55530
|
atomicWrite2(change.path, after2);
|
|
@@ -55175,11 +55564,11 @@ function applyAgentIntegration(plan) {
|
|
|
55175
55564
|
}
|
|
55176
55565
|
function syncArchiveDirectory(path) {
|
|
55177
55566
|
assertSafePath(path);
|
|
55178
|
-
const descriptor =
|
|
55567
|
+
const descriptor = openSync10(path, constants10.O_RDONLY | constants10.O_DIRECTORY | constants10.O_NOFOLLOW | constants10.O_NONBLOCK);
|
|
55179
55568
|
try {
|
|
55180
|
-
|
|
55569
|
+
fsyncSync3(descriptor);
|
|
55181
55570
|
} finally {
|
|
55182
|
-
|
|
55571
|
+
closeSync10(descriptor);
|
|
55183
55572
|
}
|
|
55184
55573
|
}
|
|
55185
55574
|
function writeArchiveJournal(path, value) {
|
|
@@ -55187,18 +55576,18 @@ function writeArchiveJournal(path, value) {
|
|
|
55187
55576
|
const temporary = `${path}.skills-${randomUUID6()}`;
|
|
55188
55577
|
let descriptor;
|
|
55189
55578
|
try {
|
|
55190
|
-
descriptor =
|
|
55579
|
+
descriptor = openSync10(temporary, constants10.O_WRONLY | constants10.O_CREAT | constants10.O_EXCL | constants10.O_NOFOLLOW, 384);
|
|
55191
55580
|
writeFileSync5(descriptor, `${JSON.stringify(value)}
|
|
55192
55581
|
`);
|
|
55193
|
-
|
|
55194
|
-
|
|
55582
|
+
fsyncSync3(descriptor);
|
|
55583
|
+
closeSync10(descriptor);
|
|
55195
55584
|
descriptor = undefined;
|
|
55196
55585
|
renameSync4(temporary, path);
|
|
55197
|
-
syncArchiveDirectory(
|
|
55586
|
+
syncArchiveDirectory(dirname14(path));
|
|
55198
55587
|
} finally {
|
|
55199
55588
|
if (descriptor !== undefined)
|
|
55200
|
-
|
|
55201
|
-
if (
|
|
55589
|
+
closeSync10(descriptor);
|
|
55590
|
+
if (lstatSync17(temporary, { throwIfNoEntry: false }))
|
|
55202
55591
|
unlinkSync4(temporary);
|
|
55203
55592
|
}
|
|
55204
55593
|
}
|
|
@@ -55231,7 +55620,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55231
55620
|
const moved = [];
|
|
55232
55621
|
const verifyArchive = (entry) => {
|
|
55233
55622
|
assertSafePath(entry.archive);
|
|
55234
|
-
const stat2 =
|
|
55623
|
+
const stat2 = lstatSync17(entry.archive);
|
|
55235
55624
|
if (entry.discoveryOnly ? !stat2.isFile() : !stat2.isDirectory())
|
|
55236
55625
|
throw new Error("Archive type changed");
|
|
55237
55626
|
if ((entry.discoveryOnly ? sha(readNativeBytes(entry.archive)) : treeHash(entry.archive)) !== entry.hash)
|
|
@@ -55239,14 +55628,14 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55239
55628
|
};
|
|
55240
55629
|
assertSafePath(archiveRoot);
|
|
55241
55630
|
const created = [];
|
|
55242
|
-
for (let path = archiveRoot;!existsSync15(path); path =
|
|
55631
|
+
for (let path = archiveRoot;!existsSync15(path); path = dirname14(path))
|
|
55243
55632
|
created.push(path);
|
|
55244
55633
|
mkdirSync7(archiveRoot, { recursive: true, mode: 448 });
|
|
55245
55634
|
try {
|
|
55246
55635
|
for (const directory of created)
|
|
55247
55636
|
syncArchiveDirectory(directory);
|
|
55248
55637
|
if (created.length)
|
|
55249
|
-
syncArchiveDirectory(
|
|
55638
|
+
syncArchiveDirectory(dirname14(created.at(-1)));
|
|
55250
55639
|
writeArchiveJournal(receiptPath, journal);
|
|
55251
55640
|
for (const [index, entry] of selected.entries()) {
|
|
55252
55641
|
recheckRootAliases(aliases);
|
|
@@ -55258,7 +55647,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55258
55647
|
writeArchiveJournal(receiptPath, journal);
|
|
55259
55648
|
renameSync4(move.source, move.archive);
|
|
55260
55649
|
moved.push(move);
|
|
55261
|
-
syncArchiveDirectory(
|
|
55650
|
+
syncArchiveDirectory(dirname14(move.source));
|
|
55262
55651
|
syncArchiveDirectory(archiveRoot);
|
|
55263
55652
|
verifyArchive(move);
|
|
55264
55653
|
move.status = "archived";
|
|
@@ -55279,7 +55668,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55279
55668
|
recheckRootAliases(aliases);
|
|
55280
55669
|
assertSafePath(entry.source);
|
|
55281
55670
|
assertSafePath(entry.archive);
|
|
55282
|
-
if (
|
|
55671
|
+
if (lstatSync17(entry.source, { throwIfNoEntry: false })) {
|
|
55283
55672
|
entry.status = "recovery-required";
|
|
55284
55673
|
entry.conflict = "source-occupied";
|
|
55285
55674
|
continue;
|
|
@@ -55293,10 +55682,10 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55293
55682
|
}
|
|
55294
55683
|
if (entry.discoveryOnly) {
|
|
55295
55684
|
linkSync2(entry.archive, entry.source);
|
|
55296
|
-
syncArchiveDirectory(
|
|
55685
|
+
syncArchiveDirectory(dirname14(entry.source));
|
|
55297
55686
|
unlinkSync4(entry.archive);
|
|
55298
55687
|
} else {
|
|
55299
|
-
if (
|
|
55688
|
+
if (lstatSync17(entry.source, { throwIfNoEntry: false })) {
|
|
55300
55689
|
entry.status = "recovery-required";
|
|
55301
55690
|
entry.conflict = "source-occupied";
|
|
55302
55691
|
continue;
|
|
@@ -55304,7 +55693,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55304
55693
|
renameSync4(entry.archive, entry.source);
|
|
55305
55694
|
}
|
|
55306
55695
|
entry.status = "restored";
|
|
55307
|
-
syncArchiveDirectory(
|
|
55696
|
+
syncArchiveDirectory(dirname14(entry.source));
|
|
55308
55697
|
syncArchiveDirectory(archiveRoot);
|
|
55309
55698
|
} catch {
|
|
55310
55699
|
entry.status = "recovery-required";
|
|
@@ -55324,7 +55713,7 @@ function archiveNativeSkills(inventory, options) {
|
|
|
55324
55713
|
return { entries: entries.map(({ status, conflict, ...entry }) => entry), receiptPath, ...aliases.length ? { rootAliases: aliases } : {} };
|
|
55325
55714
|
}
|
|
55326
55715
|
function assertManagedAgentBridge(agent, options = {}) {
|
|
55327
|
-
const home =
|
|
55716
|
+
const home = resolve15(options.home ?? homedir4()), dataDir3 = options.dataDir ?? getDataDirReadOnly();
|
|
55328
55717
|
assertSafePath(join29(dataDir3, "agent-policy.json"));
|
|
55329
55718
|
const snapshot = readManagedSkillPolicySnapshot(dataDir3);
|
|
55330
55719
|
if (!snapshot)
|
|
@@ -55447,7 +55836,7 @@ function assertNativeExportAllowed(dataDir3 = getDataDirReadOnly()) {
|
|
|
55447
55836
|
if (requiresCliSkillLoading(dataDir3))
|
|
55448
55837
|
throw new Error("NATIVE_SKILL_EXPORT_DISABLED: this station loads skills through the Skills CLI; use skills sync --selection-profile <id>");
|
|
55449
55838
|
}
|
|
55450
|
-
var sha = (data) =>
|
|
55839
|
+
var sha = (data) => createHash13("sha256").update(data).digest("hex"), HOOK_EVENTS, ROOTS, SKILLS_LOADING_POLICY = "Skills loading policy: discover skills with `skills list` or `skills search`, and read selected instructions with `skills load <slug>`. Use `skills sync` to refresh the shared profile. The only native skill is the owned skills-cli bridge. Create and edit payload skills in the Skills authoring workspace; do not copy payload instructions into native discovery folders. Context loading does not authorize execution; use `skills run` only when the task calls for running a skill.";
|
|
55451
55840
|
var init_agent_integration = __esm(() => {
|
|
55452
55841
|
init_config();
|
|
55453
55842
|
init_managed_policy();
|
|
@@ -55615,7 +56004,7 @@ var init_home_migration = __esm(() => {
|
|
|
55615
56004
|
import {
|
|
55616
56005
|
cpSync as cpSync2,
|
|
55617
56006
|
existsSync as existsSync17,
|
|
55618
|
-
lstatSync as
|
|
56007
|
+
lstatSync as lstatSync18,
|
|
55619
56008
|
mkdirSync as mkdirSync9,
|
|
55620
56009
|
mkdtempSync as mkdtempSync2,
|
|
55621
56010
|
readFileSync as readFileSync16,
|
|
@@ -55626,14 +56015,14 @@ import {
|
|
|
55626
56015
|
writeFileSync as writeFileSync7
|
|
55627
56016
|
} from "fs";
|
|
55628
56017
|
import { homedir as homedir5 } from "os";
|
|
55629
|
-
import { basename as
|
|
56018
|
+
import { basename as basename7, dirname as dirname15, join as join31 } from "path";
|
|
55630
56019
|
function isSkillsOwnershipMarker(marker) {
|
|
55631
56020
|
return typeof marker === "object" && marker !== null && Object.hasOwn(marker, "managedBy") && marker.managedBy === SYNC_MARKER_MANAGED_BY;
|
|
55632
56021
|
}
|
|
55633
56022
|
function hasSkillsOwnershipMarker(dir) {
|
|
55634
56023
|
const path = join31(dir, SYNC_MARKER_FILE);
|
|
55635
56024
|
try {
|
|
55636
|
-
if (!
|
|
56025
|
+
if (!lstatSync18(path).isFile())
|
|
55637
56026
|
return false;
|
|
55638
56027
|
const marker = JSON.parse(readFileSync16(path, "utf8"));
|
|
55639
56028
|
return isSkillsOwnershipMarker(marker);
|
|
@@ -55858,9 +56247,9 @@ function writeManagedSkillDir(dir, skillMd, options) {
|
|
|
55858
56247
|
const action = dirExists ? "update" : "create";
|
|
55859
56248
|
if (options.dryRun)
|
|
55860
56249
|
return { action, path: skillMdPath };
|
|
55861
|
-
const parentDir =
|
|
56250
|
+
const parentDir = dirname15(dir);
|
|
55862
56251
|
mkdirSync9(parentDir, { recursive: true });
|
|
55863
|
-
const transactionDir = mkdtempSync2(join31(parentDir, `.hasna-skills-write-${
|
|
56252
|
+
const transactionDir = mkdtempSync2(join31(parentDir, `.hasna-skills-write-${basename7(dir)}-`));
|
|
55864
56253
|
const candidateDir = join31(transactionDir, "candidate");
|
|
55865
56254
|
const backupDir = join31(transactionDir, "backup");
|
|
55866
56255
|
const candidateSkillMdPath = join31(candidateDir, "SKILL.md");
|
|
@@ -57710,7 +58099,7 @@ var _parse = (_Err) => {
|
|
|
57710
58099
|
return result2.value;
|
|
57711
58100
|
};
|
|
57712
58101
|
return fn;
|
|
57713
|
-
},
|
|
58102
|
+
}, parse6, _parseAsync = (_Err) => {
|
|
57714
58103
|
const fn = async (schema, value, _ctx, params) => {
|
|
57715
58104
|
const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
|
|
57716
58105
|
let result2 = schema._zod.run({ value, issues: [] }, ctx);
|
|
@@ -57755,16 +58144,16 @@ var _parse = (_Err) => {
|
|
|
57755
58144
|
result2 = await result2;
|
|
57756
58145
|
return result2.issues.length === 0;
|
|
57757
58146
|
}, _encode = (_Err) => {
|
|
57758
|
-
const
|
|
58147
|
+
const parse7 = _parse(_Err);
|
|
57759
58148
|
const fn = (schema, value, _ctx, _params) => {
|
|
57760
58149
|
const ctx = _ctx ? { ..._ctx, direction: "backward" } : { direction: "backward" };
|
|
57761
|
-
return
|
|
58150
|
+
return parse7(schema, value, ctx, finalizeParams(fn, _params));
|
|
57762
58151
|
};
|
|
57763
58152
|
return fn;
|
|
57764
58153
|
}, encode, _decode = (_Err) => {
|
|
57765
|
-
const
|
|
58154
|
+
const parse7 = _parse(_Err);
|
|
57766
58155
|
const fn = (schema, value, _ctx, _params) => {
|
|
57767
|
-
return
|
|
58156
|
+
return parse7(schema, value, _ctx, finalizeParams(fn, _params));
|
|
57768
58157
|
};
|
|
57769
58158
|
return fn;
|
|
57770
58159
|
}, decode, _encodeAsync = (_Err) => {
|
|
@@ -57795,7 +58184,7 @@ var init_parse = __esm(() => {
|
|
|
57795
58184
|
init_core();
|
|
57796
58185
|
init_errors();
|
|
57797
58186
|
init_util();
|
|
57798
|
-
|
|
58187
|
+
parse6 = /* @__PURE__ */ _parse($ZodRealError);
|
|
57799
58188
|
parseAsync = /* @__PURE__ */ _parseAsync($ZodRealError);
|
|
57800
58189
|
safeParse = /* @__PURE__ */ _safeParse($ZodRealError);
|
|
57801
58190
|
safeParseAsync = /* @__PURE__ */ _safeParseAsync($ZodRealError);
|
|
@@ -59758,14 +60147,14 @@ var init_schemas = __esm(() => {
|
|
|
59758
60147
|
const shape = zod.def.shape;
|
|
59759
60148
|
const propValues = {};
|
|
59760
60149
|
for (const key in shape) {
|
|
59761
|
-
const
|
|
59762
|
-
if (
|
|
60150
|
+
const field2 = shape[key]._zod;
|
|
60151
|
+
if (field2.values) {
|
|
59763
60152
|
if (!Object.prototype.hasOwnProperty.call(propValues, key)) {
|
|
59764
60153
|
assignProp(propValues, key, new Set);
|
|
59765
60154
|
}
|
|
59766
|
-
for (const v of
|
|
60155
|
+
for (const v of field2.values)
|
|
59767
60156
|
propValues[key].add(v);
|
|
59768
|
-
if (
|
|
60157
|
+
if (field2.optin !== undefined)
|
|
59769
60158
|
propValues[key].add(undefined);
|
|
59770
60159
|
}
|
|
59771
60160
|
}
|
|
@@ -60720,10 +61109,10 @@ var init_schemas = __esm(() => {
|
|
|
60720
61109
|
throw new Error("implement() must be called with a function");
|
|
60721
61110
|
}
|
|
60722
61111
|
return Object.defineProperty(function(...args) {
|
|
60723
|
-
const parsedArgs = inst._def.input ?
|
|
61112
|
+
const parsedArgs = inst._def.input ? parse6(inst._def.input, args) : args;
|
|
60724
61113
|
const result2 = Reflect.apply(func, this, parsedArgs);
|
|
60725
61114
|
if (inst._def.output) {
|
|
60726
|
-
return
|
|
61115
|
+
return parse6(inst._def.output, result2);
|
|
60727
61116
|
}
|
|
60728
61117
|
return result2;
|
|
60729
61118
|
}, "_zod", { value: inst._zod, enumerable: false });
|
|
@@ -72040,11 +72429,11 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
72040
72429
|
}
|
|
72041
72430
|
const allKeys = new Set(Object.keys(shape));
|
|
72042
72431
|
const requiredKeys = new Set([...allKeys].filter((key) => {
|
|
72043
|
-
const
|
|
72432
|
+
const field2 = def.shape[key];
|
|
72044
72433
|
if (ctx.io === "input") {
|
|
72045
|
-
return inputOptin(
|
|
72434
|
+
return inputOptin(field2) === undefined;
|
|
72046
72435
|
} else {
|
|
72047
|
-
return
|
|
72436
|
+
return field2._zod.optout === undefined;
|
|
72048
72437
|
}
|
|
72049
72438
|
}));
|
|
72050
72439
|
if (requiredKeys.size > 0) {
|
|
@@ -72424,7 +72813,7 @@ __export(exports_core2, {
|
|
|
72424
72813
|
prettifyError: () => prettifyError,
|
|
72425
72814
|
parseURLObject: () => parseURLObject,
|
|
72426
72815
|
parseAsync: () => parseAsync,
|
|
72427
|
-
parse: () =>
|
|
72816
|
+
parse: () => parse6,
|
|
72428
72817
|
meta: () => meta,
|
|
72429
72818
|
mergeValues: () => mergeValues,
|
|
72430
72819
|
memoizer: () => memoizer,
|
|
@@ -72814,12 +73203,12 @@ var init_errors2 = __esm(() => {
|
|
|
72814
73203
|
});
|
|
72815
73204
|
|
|
72816
73205
|
// node_modules/zod/v4/classic/parse.js
|
|
72817
|
-
var
|
|
73206
|
+
var parse8, parseAsync2, safeParse2, safeParseAsync2, encode2, decode2, encodeAsync2, decodeAsync2, safeEncode2, safeDecode2, safeEncodeAsync2, safeDecodeAsync2;
|
|
72818
73207
|
var init_parse2 = __esm(() => {
|
|
72819
73208
|
init_core2();
|
|
72820
73209
|
init_errors2();
|
|
72821
73210
|
init_core2();
|
|
72822
|
-
|
|
73211
|
+
parse8 = /* @__PURE__ */ _parse(ZodRealError);
|
|
72823
73212
|
parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
72824
73213
|
safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
72825
73214
|
safeParseAsync2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
@@ -73620,7 +74009,7 @@ var init_schemas2 = __esm(() => {
|
|
|
73620
74009
|
exports_util.own(this, "~standard", value);
|
|
73621
74010
|
},
|
|
73622
74011
|
parse: function _parse2(data, params) {
|
|
73623
|
-
return
|
|
74012
|
+
return parse8(this, data, params, { callee: _parse2 });
|
|
73624
74013
|
},
|
|
73625
74014
|
parseAsync: async function _parseAsync2(data, params) {
|
|
73626
74015
|
return await parseAsync2(this, data, params, { callee: _parseAsync2 });
|
|
@@ -75313,7 +75702,7 @@ __export(exports_external, {
|
|
|
75313
75702
|
pipe: () => pipe,
|
|
75314
75703
|
partialRecord: () => partialRecord,
|
|
75315
75704
|
parseAsync: () => parseAsync2,
|
|
75316
|
-
parse: () =>
|
|
75705
|
+
parse: () => parse8,
|
|
75317
75706
|
overwrite: () => _overwrite,
|
|
75318
75707
|
output: () => output,
|
|
75319
75708
|
optional: () => optional,
|
|
@@ -75794,7 +76183,7 @@ var init_v4 = __esm(() => {
|
|
|
75794
76183
|
});
|
|
75795
76184
|
|
|
75796
76185
|
// src/lib/canonical-json.ts
|
|
75797
|
-
import { createHash as
|
|
76186
|
+
import { createHash as createHash14 } from "crypto";
|
|
75798
76187
|
function canonicalJson2(value, maximumBytes = 2 * 1024 * 1024) {
|
|
75799
76188
|
return canonicalJsonAtDepth(value, maximumBytes, 64);
|
|
75800
76189
|
}
|
|
@@ -75838,7 +76227,7 @@ function canonicalJsonAtDepth(value, maximumBytes, maximumDepth) {
|
|
|
75838
76227
|
return visit3(value, 0);
|
|
75839
76228
|
}
|
|
75840
76229
|
function canonicalJsonSha256(value, maximumBytes) {
|
|
75841
|
-
return
|
|
76230
|
+
return createHash14("sha256").update(canonicalJson2(value, maximumBytes)).digest("hex");
|
|
75842
76231
|
}
|
|
75843
76232
|
var init_canonical_json = () => {};
|
|
75844
76233
|
|
|
@@ -76592,13 +76981,13 @@ var init_remote_workspace_leave = __esm(() => {
|
|
|
76592
76981
|
|
|
76593
76982
|
// src/lib/auth-store.ts
|
|
76594
76983
|
import { chmodSync as chmodSync2, existsSync as existsSync20, mkdirSync as mkdirSync11, readFileSync as readFileSync19, renameSync as renameSync7, statSync as statSync11, unlinkSync as unlinkSync5, writeFileSync as writeFileSync9 } from "fs";
|
|
76595
|
-
import { basename as
|
|
76984
|
+
import { basename as basename8, dirname as dirname16, join as join34 } from "path";
|
|
76596
76985
|
function getAuthFilePath(env3 = process.env) {
|
|
76597
76986
|
return skillsCredentialFilePath(env3);
|
|
76598
76987
|
}
|
|
76599
76988
|
function getIdentityFilePath(env3 = process.env) {
|
|
76600
76989
|
const file2 = skillsCredentialFilePath(env3);
|
|
76601
|
-
return join34(
|
|
76990
|
+
return join34(dirname16(file2), basename8(file2).replace(/^credentials/, "identity") + ".json");
|
|
76602
76991
|
}
|
|
76603
76992
|
function getAuthIdentity(env3 = process.env) {
|
|
76604
76993
|
return readIdentity(env3);
|
|
@@ -76614,10 +77003,10 @@ function readIdentity(env3 = process.env) {
|
|
|
76614
77003
|
if (selected && normalizeSkillsApiOrigin(bound) !== selected)
|
|
76615
77004
|
return {};
|
|
76616
77005
|
const identity4 = {};
|
|
76617
|
-
for (const
|
|
76618
|
-
const value = record6[
|
|
77006
|
+
for (const field2 of ["email", "orgId", "orgSlug", "userId"]) {
|
|
77007
|
+
const value = record6[field2];
|
|
76619
77008
|
if (typeof value === "string" && value.length > 0)
|
|
76620
|
-
identity4[
|
|
77009
|
+
identity4[field2] = value;
|
|
76621
77010
|
}
|
|
76622
77011
|
return identity4;
|
|
76623
77012
|
} catch {
|
|
@@ -76632,7 +77021,7 @@ function getAuthConfig(env3 = process.env, options = {}) {
|
|
|
76632
77021
|
}
|
|
76633
77022
|
function writeCredentialValues(values2, env3 = process.env) {
|
|
76634
77023
|
const file2 = skillsCredentialFilePath(env3);
|
|
76635
|
-
mkdirSync11(
|
|
77024
|
+
mkdirSync11(dirname16(file2), { recursive: true, mode: 448 });
|
|
76636
77025
|
const lines = [];
|
|
76637
77026
|
const written = new Set;
|
|
76638
77027
|
if (existsSync20(file2)) {
|
|
@@ -76700,10 +77089,10 @@ function saveAuthConfig(config2, env3 = process.env, authenticatedOrigin) {
|
|
|
76700
77089
|
const apiUrl = authenticatedOrigin ? normalizeSkillsApiOrigin(authenticatedOrigin) : resolveSkillsApiOrigin(env3)?.origin ?? defaultFleetGatewayBaseUrl("skills");
|
|
76701
77090
|
const file2 = writeCredentialValues({ SKILLS_API_KEY: null, SKILLS_API_URL: null, [SKILLS_API_KEY_REF]: null, [SKILLS_API_KEY_ENV]: apiKey, [SKILLS_BOUND_API_URL]: apiUrl, [SKILLS_API_URL_ENV]: apiUrl }, env3);
|
|
76702
77091
|
const identity4 = {};
|
|
76703
|
-
for (const
|
|
76704
|
-
const value = config2[
|
|
77092
|
+
for (const field2 of ["email", "orgId", "orgSlug", "userId"]) {
|
|
77093
|
+
const value = config2[field2];
|
|
76705
77094
|
if (typeof value === "string" && value.length > 0)
|
|
76706
|
-
identity4[
|
|
77095
|
+
identity4[field2] = value;
|
|
76707
77096
|
}
|
|
76708
77097
|
const identityFile = getIdentityFilePath(env3);
|
|
76709
77098
|
if (Object.keys(identity4).length > 0) {
|
|
@@ -76896,15 +77285,44 @@ var init_remote_account = __esm(() => {
|
|
|
76896
77285
|
};
|
|
76897
77286
|
});
|
|
76898
77287
|
|
|
77288
|
+
// src/lib/remote-credit-checkout.ts
|
|
77289
|
+
function creditCheckoutRequestKey(value) {
|
|
77290
|
+
if (value === undefined)
|
|
77291
|
+
return crypto.randomUUID();
|
|
77292
|
+
if (typeof value !== "string" || !creditCheckoutKeyPattern.test(value))
|
|
77293
|
+
throw new Error("Checkout idempotency key must be 8-255 URL-safe characters");
|
|
77294
|
+
return value;
|
|
77295
|
+
}
|
|
77296
|
+
function creditCheckoutFailure(value, status, key) {
|
|
77297
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
77298
|
+
return { code: "CREDIT_CHECKOUT_UNCONFIRMED" };
|
|
77299
|
+
const row = value;
|
|
77300
|
+
if (row.requestIdempotencyKey !== undefined && row.requestIdempotencyKey !== key)
|
|
77301
|
+
return { code: "CREDIT_CHECKOUT_UNCONFIRMED" };
|
|
77302
|
+
const code = status === 409 && row.error === "credit checkout in_progress" ? "CREDIT_CHECKOUT_IN_PROGRESS" : status === 409 && row.error === "credit checkout expired" && row.requestIdempotencyKey === key ? "CREDIT_CHECKOUT_EXPIRED" : status === 409 && row.error === "credit checkout fulfilled" && row.requestIdempotencyKey === key ? "CREDIT_CHECKOUT_FULFILLED" : "CREDIT_CHECKOUT_UNCONFIRMED";
|
|
77303
|
+
const delay2 = row.retryAfterSeconds;
|
|
77304
|
+
return { code, ...code === "CREDIT_CHECKOUT_IN_PROGRESS" || status === 503 && row.error === "credit checkout creation unresolved" ? typeof delay2 === "number" && Number.isSafeInteger(delay2) && delay2 > 0 && delay2 <= 3600 ? { retryAfterSeconds: delay2 } : {} : {} };
|
|
77305
|
+
}
|
|
77306
|
+
var creditCheckoutKeyPattern, creditCheckoutMessages;
|
|
77307
|
+
var init_remote_credit_checkout = __esm(() => {
|
|
77308
|
+
creditCheckoutKeyPattern = /^[A-Za-z0-9._:-]{8,255}$/;
|
|
77309
|
+
creditCheckoutMessages = {
|
|
77310
|
+
CREDIT_CHECKOUT_UNCONFIRMED: "Checkout creation could not be confirmed. Keep the request idempotency key, inspect billing, and use the same key for an explicit retry on the same server, account and pack. No automatic retry was made.",
|
|
77311
|
+
CREDIT_CHECKOUT_IN_PROGRESS: "This checkout is still being created. Wait before explicitly retrying the same server, account and pack with the same request idempotency key. No automatic retry was made.",
|
|
77312
|
+
CREDIT_CHECKOUT_EXPIRED: "This checkout has expired. Inspect billing before deliberately starting a new purchase with a new request idempotency key. Do not retry this checkout automatically.",
|
|
77313
|
+
CREDIT_CHECKOUT_FULFILLED: "This checkout is already fulfilled. Inspect the account balance; do not create another checkout to recover this purchase."
|
|
77314
|
+
};
|
|
77315
|
+
});
|
|
77316
|
+
|
|
76899
77317
|
// src/lib/remote-profile.ts
|
|
76900
|
-
function customerNamePatch(input2,
|
|
76901
|
-
if (!isRecord4(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2,
|
|
77318
|
+
function customerNamePatch(input2, field2) {
|
|
77319
|
+
if (!isRecord4(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field2))
|
|
76902
77320
|
throw new Error("Provide only the requested name field.");
|
|
76903
|
-
const value = input2[
|
|
77321
|
+
const value = input2[field2];
|
|
76904
77322
|
if (typeof value !== "string" || /[\p{Cc}\p{Cs}\u2028\u2029]/u.test(value) || !value.trim() || [...value.trim()].length > 100) {
|
|
76905
77323
|
throw new Error("Use a name of 1\u2013100 characters without control characters or newlines.");
|
|
76906
77324
|
}
|
|
76907
|
-
return { [
|
|
77325
|
+
return { [field2]: value.trim() };
|
|
76908
77326
|
}
|
|
76909
77327
|
function isRecord4(value) {
|
|
76910
77328
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -76941,10 +77359,10 @@ async function readQuoteUnavailableCode(response) {
|
|
|
76941
77359
|
let timer;
|
|
76942
77360
|
let deadlineExceeded = false;
|
|
76943
77361
|
const expired = Symbol("quote body deadline");
|
|
76944
|
-
const deadline = new Promise((
|
|
77362
|
+
const deadline = new Promise((resolve16) => {
|
|
76945
77363
|
timer = setTimeout(() => {
|
|
76946
77364
|
deadlineExceeded = true;
|
|
76947
|
-
|
|
77365
|
+
resolve16(expired);
|
|
76948
77366
|
reader.cancel().catch(() => {});
|
|
76949
77367
|
}, 1500);
|
|
76950
77368
|
});
|
|
@@ -77059,6 +77477,7 @@ __export(exports_remote_client, {
|
|
|
77059
77477
|
RemoteRouteUnsupportedError: () => RemoteRouteUnsupportedError,
|
|
77060
77478
|
RemoteRequestError: () => RemoteRequestError,
|
|
77061
77479
|
RemoteQuoteUnavailableError: () => RemoteQuoteUnavailableError,
|
|
77480
|
+
RemoteCreditCheckoutError: () => RemoteCreditCheckoutError,
|
|
77062
77481
|
RemoteCapabilityUnavailableError: () => RemoteCapabilityUnavailableError
|
|
77063
77482
|
});
|
|
77064
77483
|
|
|
@@ -77509,14 +77928,43 @@ class RemoteSkillsClient {
|
|
|
77509
77928
|
async listCreditPacks() {
|
|
77510
77929
|
return parseRemoteCreditPacks(await (await this.requestNewRoute("/api/v1/billing/credits")).json());
|
|
77511
77930
|
}
|
|
77512
|
-
async createCreditCheckout(packId) {
|
|
77931
|
+
async createCreditCheckout(packId, options = {}) {
|
|
77932
|
+
const requestIdempotencyKey = creditCheckoutRequestKey(options.idempotencyKey);
|
|
77513
77933
|
const packs = await this.listCreditPacks();
|
|
77514
77934
|
if (!packs.some((pack) => pack.id === packId))
|
|
77515
77935
|
throw new Error("Choose a credit pack returned by skills credits packs");
|
|
77516
|
-
|
|
77517
|
-
|
|
77518
|
-
|
|
77519
|
-
|
|
77936
|
+
let response;
|
|
77937
|
+
try {
|
|
77938
|
+
response = await this.request("/api/v1/billing/credits", {
|
|
77939
|
+
method: "POST",
|
|
77940
|
+
body: JSON.stringify({ packId, idempotencyKey: requestIdempotencyKey })
|
|
77941
|
+
});
|
|
77942
|
+
} catch {
|
|
77943
|
+
throw new RemoteCreditCheckoutError("CREDIT_CHECKOUT_UNCONFIRMED", 0, requestIdempotencyKey);
|
|
77944
|
+
}
|
|
77945
|
+
if (response.status === 404 || response.status === 405) {
|
|
77946
|
+
response.body?.cancel().catch(() => {});
|
|
77947
|
+
throw new RemoteRouteUnsupportedError("/api/v1/billing/credits", response.status, this.apiUrl);
|
|
77948
|
+
}
|
|
77949
|
+
let value;
|
|
77950
|
+
try {
|
|
77951
|
+
value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 4096)));
|
|
77952
|
+
} catch {
|
|
77953
|
+
throw new RemoteCreditCheckoutError("CREDIT_CHECKOUT_UNCONFIRMED", response.status, requestIdempotencyKey);
|
|
77954
|
+
}
|
|
77955
|
+
if (!response.ok) {
|
|
77956
|
+
const failure = creditCheckoutFailure(value, response.status, requestIdempotencyKey);
|
|
77957
|
+
throw new RemoteCreditCheckoutError(failure.code, response.status, requestIdempotencyKey, failure.retryAfterSeconds);
|
|
77958
|
+
}
|
|
77959
|
+
try {
|
|
77960
|
+
const checkout = parseRemoteCheckout(value);
|
|
77961
|
+
const echo = value.requestIdempotencyKey;
|
|
77962
|
+
if (echo !== undefined && echo !== requestIdempotencyKey)
|
|
77963
|
+
throw new Error("checkout request key changed");
|
|
77964
|
+
return { ...checkout, requestIdempotencyKey };
|
|
77965
|
+
} catch {
|
|
77966
|
+
throw new RemoteCreditCheckoutError("CREDIT_CHECKOUT_UNCONFIRMED", response.status, requestIdempotencyKey);
|
|
77967
|
+
}
|
|
77520
77968
|
}
|
|
77521
77969
|
async getUsage() {
|
|
77522
77970
|
return this.arrayResponse("/api/v1/billing/usage");
|
|
@@ -77749,13 +78197,13 @@ class RemoteSkillsClient {
|
|
|
77749
78197
|
return normalizeUpdatedSincePage(await response.json());
|
|
77750
78198
|
}
|
|
77751
78199
|
}
|
|
77752
|
-
function requireOptionalString(record7,
|
|
77753
|
-
if (record7[
|
|
78200
|
+
function requireOptionalString(record7, field2) {
|
|
78201
|
+
if (record7[field2] === undefined)
|
|
77754
78202
|
return;
|
|
77755
|
-
if (typeof record7[
|
|
77756
|
-
throw new Error(`Remote payload did not match the expected contract (${
|
|
78203
|
+
if (typeof record7[field2] !== "string") {
|
|
78204
|
+
throw new Error(`Remote payload did not match the expected contract (${field2} must be a string when present)`);
|
|
77757
78205
|
}
|
|
77758
|
-
return record7[
|
|
78206
|
+
return record7[field2];
|
|
77759
78207
|
}
|
|
77760
78208
|
function isVersionRecord(value) {
|
|
77761
78209
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -77886,7 +78334,7 @@ async function createRemoteSkillsClient(env3 = process.env) {
|
|
|
77886
78334
|
function createRemoteSkillsClientReadOnly(env3 = process.env) {
|
|
77887
78335
|
return createRemoteSkillsClient(env3);
|
|
77888
78336
|
}
|
|
77889
|
-
var RemoteRouteUnsupportedError, RemoteRequestError, RemoteQuoteUnavailableError, RemoteWorkspaceMemberError, RemoteWorkspaceSelectionError, RemoteCapabilityUnavailableError, INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
|
|
78337
|
+
var RemoteRouteUnsupportedError, RemoteRequestError, RemoteCreditCheckoutError, RemoteQuoteUnavailableError, RemoteWorkspaceMemberError, RemoteWorkspaceSelectionError, RemoteCapabilityUnavailableError, INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
|
|
77890
78338
|
var init_remote_client = __esm(() => {
|
|
77891
78339
|
init_remote_recurring();
|
|
77892
78340
|
init_remote_invitations();
|
|
@@ -77898,6 +78346,7 @@ var init_remote_client = __esm(() => {
|
|
|
77898
78346
|
init_fleet_credentials();
|
|
77899
78347
|
init_remote_account();
|
|
77900
78348
|
init_remote_files();
|
|
78349
|
+
init_remote_credit_checkout();
|
|
77901
78350
|
init_remote_quote_errors();
|
|
77902
78351
|
init_remote_permissions();
|
|
77903
78352
|
RemoteRouteUnsupportedError = class RemoteRouteUnsupportedError extends Error {
|
|
@@ -77922,6 +78371,19 @@ var init_remote_client = __esm(() => {
|
|
|
77922
78371
|
this.name = "RemoteRequestError";
|
|
77923
78372
|
}
|
|
77924
78373
|
};
|
|
78374
|
+
RemoteCreditCheckoutError = class RemoteCreditCheckoutError extends RemoteRequestError {
|
|
78375
|
+
code;
|
|
78376
|
+
requestIdempotencyKey;
|
|
78377
|
+
retryAfterSeconds;
|
|
78378
|
+
constructor(code, status, requestIdempotencyKey, retryAfterSeconds) {
|
|
78379
|
+
super("/api/v1/billing/credits", status);
|
|
78380
|
+
this.code = code;
|
|
78381
|
+
this.requestIdempotencyKey = requestIdempotencyKey;
|
|
78382
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
78383
|
+
this.name = "RemoteCreditCheckoutError";
|
|
78384
|
+
this.message = creditCheckoutMessages[code];
|
|
78385
|
+
}
|
|
78386
|
+
};
|
|
77925
78387
|
RemoteQuoteUnavailableError = class RemoteQuoteUnavailableError extends RemoteRequestError {
|
|
77926
78388
|
code;
|
|
77927
78389
|
constructor(path, code) {
|
|
@@ -77962,7 +78424,7 @@ var init_remote_client = __esm(() => {
|
|
|
77962
78424
|
});
|
|
77963
78425
|
|
|
77964
78426
|
// src/lib/revision.ts
|
|
77965
|
-
import { createHash as
|
|
78427
|
+
import { createHash as createHash15 } from "crypto";
|
|
77966
78428
|
function revisionIdOf(content) {
|
|
77967
78429
|
const canonical3 = JSON.stringify({
|
|
77968
78430
|
slug: content.slug,
|
|
@@ -77977,7 +78439,7 @@ function revisionIdOf(content) {
|
|
|
77977
78439
|
bundleSha256: content.bundleSha256 ?? null,
|
|
77978
78440
|
bundleByteSize: content.bundleByteSize ?? null
|
|
77979
78441
|
});
|
|
77980
|
-
return
|
|
78442
|
+
return createHash15("sha256").update(canonical3).digest("hex");
|
|
77981
78443
|
}
|
|
77982
78444
|
var REVISION_ID_PATTERN;
|
|
77983
78445
|
var init_revision = __esm(() => {
|
|
@@ -78007,7 +78469,7 @@ var init_skill_bundles = __esm(() => {
|
|
|
78007
78469
|
|
|
78008
78470
|
// src/lib/pull.ts
|
|
78009
78471
|
import { existsSync as existsSync21, mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, readFileSync as readFileSync20, renameSync as renameSync8, rmSync as rmSync6, writeFileSync as writeFileSync10 } from "fs";
|
|
78010
|
-
import { dirname as
|
|
78472
|
+
import { dirname as dirname17, join as join35 } from "path";
|
|
78011
78473
|
async function pullSkills(options = {}) {
|
|
78012
78474
|
const client2 = options.client !== undefined ? options.client : await createRemoteSkillsClient();
|
|
78013
78475
|
if (!client2) {
|
|
@@ -78311,7 +78773,7 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
|
|
|
78311
78773
|
try {
|
|
78312
78774
|
for (const entry of entries) {
|
|
78313
78775
|
const destination = join35(staging, entry.path);
|
|
78314
|
-
mkdirSync12(
|
|
78776
|
+
mkdirSync12(dirname17(destination), { recursive: true });
|
|
78315
78777
|
writeFileSync10(destination, entry.bytes, { mode: entry.mode });
|
|
78316
78778
|
}
|
|
78317
78779
|
writePullMarker(staging, {
|
|
@@ -78426,8 +78888,8 @@ var init_pull = __esm(() => {
|
|
|
78426
78888
|
});
|
|
78427
78889
|
|
|
78428
78890
|
// src/lib/skill-context.ts
|
|
78429
|
-
import { createHash as
|
|
78430
|
-
import { resolve as
|
|
78891
|
+
import { createHash as createHash16 } from "crypto";
|
|
78892
|
+
import { resolve as resolve16 } from "path";
|
|
78431
78893
|
function words2(value) {
|
|
78432
78894
|
return new Set(value.toLowerCase().match(/[a-z0-9]+/g) ?? []);
|
|
78433
78895
|
}
|
|
@@ -78462,7 +78924,7 @@ async function buildSkillContext(input2, options = {}) {
|
|
|
78462
78924
|
const promptWords = words2(prompt);
|
|
78463
78925
|
const promptNames = new Set(prompt.toLowerCase().match(/[a-z0-9]+(?:-[a-z0-9]+)*/g) ?? []);
|
|
78464
78926
|
const loaded = new Set(resolved.session?.loaded ?? []);
|
|
78465
|
-
const paths = [...input2.paths ?? [], ...input2.cwd ? [input2.cwd,
|
|
78927
|
+
const paths = [...input2.paths ?? [], ...input2.cwd ? [input2.cwd, resolve16(input2.cwd)] : []];
|
|
78466
78928
|
const candidates = profile.selections.map((selection) => {
|
|
78467
78929
|
const key = selectionKey(selection);
|
|
78468
78930
|
if (input2.restore && loaded.has(key))
|
|
@@ -78515,7 +78977,7 @@ ${content}`;
|
|
|
78515
78977
|
`);
|
|
78516
78978
|
const receipt = {
|
|
78517
78979
|
schemaVersion: 1,
|
|
78518
|
-
id:
|
|
78980
|
+
id: createHash16("sha256").update(JSON.stringify({ profile: profile.profileRevision, sessionId, selections, omitted })).digest("hex"),
|
|
78519
78981
|
profileId: profile.profileId,
|
|
78520
78982
|
profileRevision: profile.profileRevision,
|
|
78521
78983
|
authority: profile.authority,
|
|
@@ -78527,7 +78989,7 @@ ${content}`;
|
|
|
78527
78989
|
selections
|
|
78528
78990
|
};
|
|
78529
78991
|
if (sessionId)
|
|
78530
|
-
|
|
78992
|
+
writeSkillSession({ ...resolved.receipt, sessionId, loaded: [...loaded] }, { current: resolved.sessionSnapshot, parent: resolved.parentSnapshot }, options);
|
|
78531
78993
|
return { context, selections, omitted, receipt };
|
|
78532
78994
|
}
|
|
78533
78995
|
var init_skill_context = __esm(() => {
|
|
@@ -78536,6 +78998,107 @@ var init_skill_context = __esm(() => {
|
|
|
78536
78998
|
init_selected_document();
|
|
78537
78999
|
});
|
|
78538
79000
|
|
|
79001
|
+
// src/lib/session-reconciliation.ts
|
|
79002
|
+
import { createHash as createHash17 } from "crypto";
|
|
79003
|
+
function exactTimestamp(value) {
|
|
79004
|
+
const parsed = value === undefined ? Number.NaN : Date.parse(value);
|
|
79005
|
+
if (!Number.isFinite(parsed) || new Date(parsed).toISOString() !== value) {
|
|
79006
|
+
throw new SkillSelectionError("SESSION_PLAN_WINDOW_INVALID", "The reviewed plan must include its exact canonical issuedAt and expiresAt timestamps.");
|
|
79007
|
+
}
|
|
79008
|
+
return parsed;
|
|
79009
|
+
}
|
|
79010
|
+
function assertPlanWindow(issuedAt, expiresAt, now3) {
|
|
79011
|
+
const issued = exactTimestamp(issuedAt), expires = exactTimestamp(expiresAt);
|
|
79012
|
+
if (expires - issued !== SESSION_RECONCILIATION_PLAN_TTL_MS) {
|
|
79013
|
+
throw new SkillSelectionError("SESSION_PLAN_WINDOW_INVALID", "A session reconciliation approval is valid for exactly five minutes and cannot be extended by the caller.");
|
|
79014
|
+
}
|
|
79015
|
+
if (now3 < issued || now3 >= expires) {
|
|
79016
|
+
throw new SkillSelectionError("SESSION_PLAN_EXPIRED", "The reviewed session reconciliation plan is not currently valid; inspect the receipt and prepare a new plan.");
|
|
79017
|
+
}
|
|
79018
|
+
}
|
|
79019
|
+
function inspectSkillSession(sessionId, options = {}) {
|
|
79020
|
+
const snapshot = readSkillSessionSnapshot(sessionId, options), { receipt } = snapshot;
|
|
79021
|
+
return {
|
|
79022
|
+
sessionId,
|
|
79023
|
+
path: snapshot.path,
|
|
79024
|
+
receiptSha256: snapshot.sha256,
|
|
79025
|
+
generation: snapshot.generation,
|
|
79026
|
+
verifiedAt: receipt.verifiedAt,
|
|
79027
|
+
authority: receipt.profile.authority,
|
|
79028
|
+
workspaceId: receipt.profile.workspaceId,
|
|
79029
|
+
profileId: receipt.profile.profileId,
|
|
79030
|
+
profileRevision: receipt.profile.profileRevision,
|
|
79031
|
+
selectionCount: receipt.profile.selections.length,
|
|
79032
|
+
loadedCount: receipt.loaded.length
|
|
79033
|
+
};
|
|
79034
|
+
}
|
|
79035
|
+
async function reconcileSkillSession(input2, options = {}) {
|
|
79036
|
+
if (![input2.fromProfile, input2.fromRevision, input2.selectionProfile, input2.profileRevision].every((value) => typeof value === "string" && value.trim()) || !/^[a-f0-9]{64}$/.test(input2.receiptSha256)) {
|
|
79037
|
+
throw new SkillSelectionError("INVALID_SESSION_RECONCILIATION", "Name the exact old receipt SHA256, old profile/revision and intended target profile/revision.");
|
|
79038
|
+
}
|
|
79039
|
+
if (input2.apply && (!input2.planDigest || !input2.planIssuedAt || !input2.planExpiresAt)) {
|
|
79040
|
+
throw new SkillSelectionError("SESSION_PLAN_REQUIRED", "Review the session reconciliation plan and provide its exact digest, issuedAt and expiresAt before applying it.");
|
|
79041
|
+
}
|
|
79042
|
+
if (!input2.apply && (input2.planDigest !== undefined || input2.planIssuedAt !== undefined || input2.planExpiresAt !== undefined)) {
|
|
79043
|
+
throw new SkillSelectionError("SESSION_PLAN_WINDOW_INVALID", "Plan timestamps are minted by the planner and may only be replayed with --apply.");
|
|
79044
|
+
}
|
|
79045
|
+
const now3 = (options.now ?? Date.now)();
|
|
79046
|
+
const issuedAt = input2.apply ? input2.planIssuedAt : new Date(now3).toISOString();
|
|
79047
|
+
const expiresAt = input2.apply ? input2.planExpiresAt : new Date(now3 + SESSION_RECONCILIATION_PLAN_TTL_MS).toISOString();
|
|
79048
|
+
if (input2.apply)
|
|
79049
|
+
assertPlanWindow(issuedAt, expiresAt, now3);
|
|
79050
|
+
const snapshot = readSkillSessionSnapshot(input2.sessionId, options), old = snapshot.receipt;
|
|
79051
|
+
if (snapshot.sha256 !== input2.receiptSha256 || old.profile.profileId !== input2.fromProfile || old.profile.profileRevision !== input2.fromRevision) {
|
|
79052
|
+
throw new SkillSelectionError("SESSION_RECEIPT_CHANGED", "The current session receipt does not match the reviewed old bytes, profile and revision.");
|
|
79053
|
+
}
|
|
79054
|
+
const client2 = options.client ?? await createProfileClient();
|
|
79055
|
+
const target = structuredClone(await client2.resolveProfile(input2.selectionProfile));
|
|
79056
|
+
validateResolvedProfile(target, client2.authority);
|
|
79057
|
+
if (target.profileId !== input2.selectionProfile || target.profileRevision !== input2.profileRevision) {
|
|
79058
|
+
throw new SkillSelectionError("SESSION_TARGET_CHANGED", "The API selection profile does not match the intended target revision; review the current selection before proceeding.");
|
|
79059
|
+
}
|
|
79060
|
+
if (old.profile.authority !== target.authority || old.profile.workspaceId !== target.workspaceId) {
|
|
79061
|
+
throw new SkillSelectionError("PROFILE_IDENTITY_MISMATCH", "A session reconciliation cannot change its Skills authority or workspace.");
|
|
79062
|
+
}
|
|
79063
|
+
const targetKeys = new Set(target.selections.map(selectionKey));
|
|
79064
|
+
const loaded = old.loaded.filter((key) => targetKeys.has(key));
|
|
79065
|
+
const replacementGeneration = nextSkillSessionGeneration(snapshot.generation);
|
|
79066
|
+
const plan = {
|
|
79067
|
+
schemaVersion: 1,
|
|
79068
|
+
issuedAt,
|
|
79069
|
+
expiresAt,
|
|
79070
|
+
sessionId: input2.sessionId,
|
|
79071
|
+
sessionPath: snapshot.path,
|
|
79072
|
+
before: { receiptSha256: snapshot.sha256, generation: snapshot.generation, profileId: old.profile.profileId, profileRevision: old.profile.profileRevision, selectionCount: old.profile.selections.length },
|
|
79073
|
+
target: { authority: target.authority, workspaceId: target.workspaceId, profileId: target.profileId, profileRevision: target.profileRevision, profileSha256: digest3(target), selectionCount: target.selections.length },
|
|
79074
|
+
replacementGeneration,
|
|
79075
|
+
retainedLoadedCount: loaded.length,
|
|
79076
|
+
retiredLoadedCount: old.loaded.length - loaded.length,
|
|
79077
|
+
scope: "Only this receipt; existing child sessions, project locks, shared profiles, hooks and running processes are unchanged."
|
|
79078
|
+
};
|
|
79079
|
+
const planDigest = digest3(plan);
|
|
79080
|
+
if (input2.planDigest !== undefined && input2.planDigest !== planDigest)
|
|
79081
|
+
throw new SkillSelectionError("SESSION_PLAN_CHANGED", "The session reconciliation plan differs from the reviewed plan.");
|
|
79082
|
+
if (!input2.apply)
|
|
79083
|
+
return { applied: false, plan, planDigest, archivePath: undefined, receiptPath: undefined, beforeSha256: snapshot.sha256, afterSha256: undefined };
|
|
79084
|
+
assertPlanWindow(issuedAt, expiresAt, (options.now ?? Date.now)());
|
|
79085
|
+
const replacement = {
|
|
79086
|
+
...old,
|
|
79087
|
+
generation: replacementGeneration,
|
|
79088
|
+
verifiedAt: new Date((options.now ?? Date.now)()).toISOString(),
|
|
79089
|
+
profile: target,
|
|
79090
|
+
loaded
|
|
79091
|
+
};
|
|
79092
|
+
const result2 = replaceSkillSession(skillSessionSnapshotBinding(snapshot), replacement, { ...plan, planDigest }, options, () => assertPlanWindow(issuedAt, expiresAt, (options.now ?? Date.now)()));
|
|
79093
|
+
return { applied: true, plan, planDigest, ...result2 };
|
|
79094
|
+
}
|
|
79095
|
+
var SESSION_RECONCILIATION_PLAN_TTL_MS, digest3 = (value) => createHash17("sha256").update(JSON.stringify(value)).digest("hex");
|
|
79096
|
+
var init_session_reconciliation = __esm(() => {
|
|
79097
|
+
init_profile_client();
|
|
79098
|
+
init_selection_cache();
|
|
79099
|
+
SESSION_RECONCILIATION_PLAN_TTL_MS = 5 * 60 * 1000;
|
|
79100
|
+
});
|
|
79101
|
+
|
|
78539
79102
|
// src/cli/commands/context.ts
|
|
78540
79103
|
var exports_context = {};
|
|
78541
79104
|
__export(exports_context, {
|
|
@@ -78545,7 +79108,7 @@ __export(exports_context, {
|
|
|
78545
79108
|
parseSkillContextInput: () => parseSkillContextInput,
|
|
78546
79109
|
contextResolverOptions: () => contextResolverOptions
|
|
78547
79110
|
});
|
|
78548
|
-
import { readSync as
|
|
79111
|
+
import { readSync as readSync9 } from "fs";
|
|
78549
79112
|
function selectedProfileId(explicit) {
|
|
78550
79113
|
return explicit ?? process.env.HASNA_SKILLS_SELECTION_PROFILE ?? readManagedSkillPolicy()?.profileId ?? "default";
|
|
78551
79114
|
}
|
|
@@ -78559,6 +79122,25 @@ function contextResolverOptions(options) {
|
|
|
78559
79122
|
return { cached: true, authority };
|
|
78560
79123
|
}
|
|
78561
79124
|
function registerContextCommands(parent) {
|
|
79125
|
+
const sessions = parent.command("sessions").description("Inspect exact session pins and explicitly reconcile one reviewed receipt");
|
|
79126
|
+
sessions.command("show <id>").option("--json", "Return metadata as JSON", false).description("Inspect one session receipt without displaying payloads or changing its pin").action(async (id, options) => {
|
|
79127
|
+
try {
|
|
79128
|
+
const result2 = inspectSkillSession(id);
|
|
79129
|
+
await writeCliOutput(options.json ? JSON.stringify(result2) : `${JSON.stringify(id)}: ${result2.profileId} at ${result2.profileRevision}
|
|
79130
|
+
Receipt SHA256: ${result2.receiptSha256}`);
|
|
79131
|
+
} catch (error61) {
|
|
79132
|
+
reportContextError(error61, options.json);
|
|
79133
|
+
}
|
|
79134
|
+
});
|
|
79135
|
+
sessions.command("reconcile <id>").requiredOption("--from-profile <id>", "Expected current session profile").requiredOption("--from-revision <revision>", "Expected current session profile revision").requiredOption("--receipt-sha256 <sha256>", "Expected exact current receipt bytes").requiredOption("--selection-profile <id>", "Intended target selection profile").requiredOption("--profile-revision <revision>", "Expected current API target revision").option("--apply", "Archive the old receipt and atomically apply the reviewed plan", false).option("--plan-digest <sha256>", "Exact reviewed plan digest; required with --apply").option("--plan-issued-at <timestamp>", "Exact reviewed plan issuedAt; required with --apply").option("--plan-expires-at <timestamp>", "Exact reviewed plan expiresAt; required with --apply").option("--json", "Return the plan or application receipt as JSON", false).description("Plan an intentional migration of one session pin; ordinary hooks never migrate pins").action(async (id, options) => {
|
|
79136
|
+
try {
|
|
79137
|
+
const result2 = await reconcileSkillSession({ ...options, sessionId: id });
|
|
79138
|
+
await writeCliOutput(options.json ? JSON.stringify(result2) : result2.applied ? `Reconciled ${JSON.stringify(id)} to ${result2.plan.target.profileId} at ${result2.plan.target.profileRevision}.
|
|
79139
|
+
Preserved original receipt: ${result2.archivePath}` : `Planned one session reconciliation. Review --json output, then use --apply --plan-digest ${result2.planDigest} --plan-issued-at ${result2.plan.issuedAt} --plan-expires-at ${result2.plan.expiresAt}.`);
|
|
79140
|
+
} catch (error61) {
|
|
79141
|
+
reportContextError(error61, options.json);
|
|
79142
|
+
}
|
|
79143
|
+
});
|
|
78562
79144
|
parent.command("load <skill>").description("Load an exact API-selected skill and return its version/digest receipt").option("--selection-profile <id>", "Selection profile (separate from the credential --profile)").option("--cached", "Use only an explicitly selected verified cache, at most 24 hours old", false).option("--session <id>", "Pin this load to a session").option("--file <path>", "Read an exact bundle file (default: SKILL.md, README.md, then CLAUDE.md)").option("--json", "Return content and provenance as JSON", false).action(async (skill, options) => {
|
|
78563
79145
|
try {
|
|
78564
79146
|
const result2 = await loadSelectedSkill(skill, selectedProfileId(options.selectionProfile), {
|
|
@@ -78604,7 +79186,7 @@ async function readContextStdin() {
|
|
|
78604
79186
|
let size2 = 0;
|
|
78605
79187
|
while (true) {
|
|
78606
79188
|
const chunk2 = Buffer.allocUnsafe(8192);
|
|
78607
|
-
const count =
|
|
79189
|
+
const count = readSync9(0, chunk2, 0, chunk2.length, null);
|
|
78608
79190
|
if (count === 0)
|
|
78609
79191
|
break;
|
|
78610
79192
|
size2 += count;
|
|
@@ -78662,6 +79244,7 @@ var init_context = __esm(() => {
|
|
|
78662
79244
|
init_selection_resolver();
|
|
78663
79245
|
init_selection_cache();
|
|
78664
79246
|
init_managed_policy();
|
|
79247
|
+
init_session_reconciliation();
|
|
78665
79248
|
});
|
|
78666
79249
|
|
|
78667
79250
|
// src/cli/commands/profile-sync.ts
|
|
@@ -79080,12 +79663,12 @@ function handleBrowseError(error61) {
|
|
|
79080
79663
|
async function writeJson(value, space) {
|
|
79081
79664
|
const text3 = `${JSON.stringify(value, null, space)}
|
|
79082
79665
|
`;
|
|
79083
|
-
await new Promise((
|
|
79666
|
+
await new Promise((resolve17, reject2) => {
|
|
79084
79667
|
process.stdout.write(text3, (error61) => {
|
|
79085
79668
|
if (error61)
|
|
79086
79669
|
reject2(error61);
|
|
79087
79670
|
else
|
|
79088
|
-
|
|
79671
|
+
resolve17();
|
|
79089
79672
|
});
|
|
79090
79673
|
});
|
|
79091
79674
|
}
|
|
@@ -80429,7 +81012,7 @@ var init_init = __esm(() => {
|
|
|
80429
81012
|
});
|
|
80430
81013
|
|
|
80431
81014
|
// src/lib/home-adoption.ts
|
|
80432
|
-
import { constants as
|
|
81015
|
+
import { constants as constants11, closeSync as closeSync11, fstatSync as fstatSync11, lstatSync as lstatSync19, openSync as openSync11, readSync as readSync10, existsSync as existsSync24, mkdirSync as mkdirSync13, readdirSync as readdirSync13, readFileSync as readFileSync25, rmSync as rmSync7, statSync as statSync12, writeFileSync as writeFileSync12 } from "fs";
|
|
80433
81016
|
import { homedir as homedir7 } from "os";
|
|
80434
81017
|
import { join as join38 } from "path";
|
|
80435
81018
|
function indexCanonicalCorpus(corpusRoot) {
|
|
@@ -80584,25 +81167,25 @@ function adoptUnmarkedHomes(options = {}) {
|
|
|
80584
81167
|
function pruneOwnership(dir) {
|
|
80585
81168
|
let descriptor;
|
|
80586
81169
|
try {
|
|
80587
|
-
const directory =
|
|
81170
|
+
const directory = lstatSync19(dir);
|
|
80588
81171
|
if (!directory.isDirectory())
|
|
80589
81172
|
return;
|
|
80590
|
-
const markerPath = join38(dir, SYNC_MARKER_FILE), markerPathBefore =
|
|
81173
|
+
const markerPath = join38(dir, SYNC_MARKER_FILE), markerPathBefore = lstatSync19(markerPath);
|
|
80591
81174
|
if (!markerPathBefore.isFile())
|
|
80592
81175
|
return;
|
|
80593
|
-
descriptor =
|
|
80594
|
-
const before2 =
|
|
81176
|
+
descriptor = openSync11(markerPath, constants11.O_RDONLY | constants11.O_NOFOLLOW | constants11.O_NONBLOCK);
|
|
81177
|
+
const before2 = fstatSync11(descriptor);
|
|
80595
81178
|
if (!before2.isFile() || before2.dev !== markerPathBefore.dev || before2.ino !== markerPathBefore.ino || before2.size !== markerPathBefore.size || before2.mtimeMs !== markerPathBefore.mtimeMs || before2.ctimeMs !== markerPathBefore.ctimeMs || before2.size < 1 || before2.size > 65536)
|
|
80596
81179
|
return;
|
|
80597
81180
|
const bytes = Buffer.alloc(before2.size + 1);
|
|
80598
81181
|
let length = 0;
|
|
80599
81182
|
while (length < bytes.length) {
|
|
80600
|
-
const count =
|
|
81183
|
+
const count = readSync10(descriptor, bytes, length, bytes.length - length, length);
|
|
80601
81184
|
if (!count)
|
|
80602
81185
|
break;
|
|
80603
81186
|
length += count;
|
|
80604
81187
|
}
|
|
80605
|
-
const after2 =
|
|
81188
|
+
const after2 = fstatSync11(descriptor), current = lstatSync19(dir), markerPathAfter = lstatSync19(markerPath);
|
|
80606
81189
|
if (!markerPathAfter.isFile() || markerPathAfter.dev !== before2.dev || markerPathAfter.ino !== before2.ino || markerPathAfter.size !== before2.size || markerPathAfter.mtimeMs !== before2.mtimeMs || markerPathAfter.ctimeMs !== before2.ctimeMs || length !== before2.size || after2.size !== before2.size || after2.mtimeMs !== before2.mtimeMs || after2.ctimeMs !== before2.ctimeMs || !current.isDirectory() || current.dev !== directory.dev || current.ino !== directory.ino)
|
|
80607
81190
|
return;
|
|
80608
81191
|
const text3 = bytes.subarray(0, length).toString("utf8"), marker = JSON.parse(text3);
|
|
@@ -80613,7 +81196,7 @@ function pruneOwnership(dir) {
|
|
|
80613
81196
|
return;
|
|
80614
81197
|
} finally {
|
|
80615
81198
|
if (descriptor !== undefined)
|
|
80616
|
-
|
|
81199
|
+
closeSync11(descriptor);
|
|
80617
81200
|
}
|
|
80618
81201
|
}
|
|
80619
81202
|
function pruneStrayHomes(options = {}) {
|
|
@@ -80798,7 +81381,7 @@ var init_home_census = __esm(() => {
|
|
|
80798
81381
|
});
|
|
80799
81382
|
|
|
80800
81383
|
// src/cli/env-assignment.ts
|
|
80801
|
-
import { closeSync as
|
|
81384
|
+
import { closeSync as closeSync12, constants as constants12, fstatSync as fstatSync12, ftruncateSync as ftruncateSync2, lstatSync as lstatSync20, openSync as openSync12, readFileSync as readFileSync27, writeSync as writeSync3 } from "fs";
|
|
80802
81385
|
function serializeValue(value) {
|
|
80803
81386
|
if (controls.test(value))
|
|
80804
81387
|
throw new EnvAssignmentError("Environment values cannot contain control characters or newlines.");
|
|
@@ -80877,7 +81460,7 @@ function setEnvAssignment(path, assignment) {
|
|
|
80877
81460
|
try {
|
|
80878
81461
|
const previous = (() => {
|
|
80879
81462
|
try {
|
|
80880
|
-
return
|
|
81463
|
+
return lstatSync20(path);
|
|
80881
81464
|
} catch (error61) {
|
|
80882
81465
|
if (error61.code === "ENOENT")
|
|
80883
81466
|
return;
|
|
@@ -80886,8 +81469,8 @@ function setEnvAssignment(path, assignment) {
|
|
|
80886
81469
|
})();
|
|
80887
81470
|
if (previous && !previous.isFile())
|
|
80888
81471
|
throw new EnvAssignmentError("The project .env must be a regular file, not a symlink or special file.");
|
|
80889
|
-
descriptor =
|
|
80890
|
-
const opened =
|
|
81472
|
+
descriptor = openSync12(path, previous ? constants12.O_RDWR | constants12.O_NOFOLLOW | constants12.O_NONBLOCK : constants12.O_WRONLY | constants12.O_CREAT | constants12.O_EXCL | constants12.O_NOFOLLOW, 384);
|
|
81473
|
+
const opened = fstatSync12(descriptor);
|
|
80891
81474
|
if (!opened.isFile() || previous && (opened.ino !== previous.ino || opened.dev !== previous.dev)) {
|
|
80892
81475
|
throw new EnvAssignmentError("The project .env changed while opening it; retry with a regular file.");
|
|
80893
81476
|
}
|
|
@@ -80914,7 +81497,7 @@ function setEnvAssignment(path, assignment) {
|
|
|
80914
81497
|
throw new EnvAssignmentError("Cannot safely read or write the project .env file.");
|
|
80915
81498
|
} finally {
|
|
80916
81499
|
if (descriptor !== undefined)
|
|
80917
|
-
|
|
81500
|
+
closeSync12(descriptor);
|
|
80918
81501
|
}
|
|
80919
81502
|
}
|
|
80920
81503
|
var INVALID_LAYOUT = "Cannot safely update .env with multiline or unsupported assignments. Use single-line KEY=VALUE entries or edit the file manually.", controls, EnvAssignmentError;
|
|
@@ -81397,12 +81980,12 @@ function parseExecution(value) {
|
|
|
81397
81980
|
].includes(v.status) || typeof v.skill !== "string" || typeof v.version !== "string" || !Array.isArray(v.artifacts))
|
|
81398
81981
|
throw Error("Unsupported cloud execution response");
|
|
81399
81982
|
runId(v.id);
|
|
81400
|
-
for (const
|
|
81983
|
+
for (const field2 of [
|
|
81401
81984
|
"bundleDigest",
|
|
81402
81985
|
"inputDigest",
|
|
81403
81986
|
"runtimeImageDigest"
|
|
81404
81987
|
])
|
|
81405
|
-
if (typeof v[
|
|
81988
|
+
if (typeof v[field2] !== "string" || !/^(sha256:)?[a-f0-9]{64}$/.test(v[field2]))
|
|
81406
81989
|
throw Error("Invalid cloud execution integrity receipt");
|
|
81407
81990
|
return v;
|
|
81408
81991
|
}
|
|
@@ -81423,11 +82006,11 @@ var init_cloud_executions = __esm(() => {
|
|
|
81423
82006
|
// node_modules/@hasna/secrets/dist/sdk.js
|
|
81424
82007
|
import { isIP as isIP3 } from "net";
|
|
81425
82008
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
81426
|
-
import { closeSync as
|
|
82009
|
+
import { closeSync as closeSync13, fstatSync as fstatSync13, openSync as openSync13, readFileSync as readFileSync29 } from "fs";
|
|
81427
82010
|
import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
|
|
81428
82011
|
import { createRequire as createRequire2 } from "module";
|
|
81429
82012
|
import { hostname as osHostname2 } from "os";
|
|
81430
|
-
import { isAbsolute as
|
|
82013
|
+
import { isAbsolute as isAbsolute15, join as join41 } from "path";
|
|
81431
82014
|
import { createRequire as createRequire22 } from "module";
|
|
81432
82015
|
function envToken2(name) {
|
|
81433
82016
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -81451,7 +82034,7 @@ function homeDir2(env3) {
|
|
|
81451
82034
|
}
|
|
81452
82035
|
function absoluteOverride2(env3, key) {
|
|
81453
82036
|
const value = env3[key]?.trim();
|
|
81454
|
-
return value &&
|
|
82037
|
+
return value && isAbsolute15(value) ? value : null;
|
|
81455
82038
|
}
|
|
81456
82039
|
function hasnaHomeDir2(env3) {
|
|
81457
82040
|
const override = absoluteOverride2(env3, HASNA_HOME_ENV_KEY2);
|
|
@@ -81528,7 +82111,7 @@ function readAppConfigFile2(path) {
|
|
|
81528
82111
|
};
|
|
81529
82112
|
let fd = -1;
|
|
81530
82113
|
try {
|
|
81531
|
-
fd =
|
|
82114
|
+
fd = openSync13(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
|
|
81532
82115
|
} catch (error61) {
|
|
81533
82116
|
const code = error61.code;
|
|
81534
82117
|
if (code === "ENOENT" || code === "ENOTDIR")
|
|
@@ -81538,7 +82121,7 @@ function readAppConfigFile2(path) {
|
|
|
81538
82121
|
unsafe(`the path could not be opened (${code ?? "unknown error"})`);
|
|
81539
82122
|
}
|
|
81540
82123
|
try {
|
|
81541
|
-
const before2 =
|
|
82124
|
+
const before2 = fstatSync13(fd);
|
|
81542
82125
|
if (!before2.isFile())
|
|
81543
82126
|
unsafe("the path is not a regular file");
|
|
81544
82127
|
if (!configFileModeAllowed2(before2.mode)) {
|
|
@@ -81550,14 +82133,14 @@ function readAppConfigFile2(path) {
|
|
|
81550
82133
|
if (before2.size > MAX_CREDENTIAL_FILE_BYTES2)
|
|
81551
82134
|
unsafe("the file exceeds the size limit");
|
|
81552
82135
|
const bytes = readFileSync29(fd);
|
|
81553
|
-
const after2 =
|
|
82136
|
+
const after2 = fstatSync13(fd);
|
|
81554
82137
|
if (!configFileReadsCoherent2(before2, after2)) {
|
|
81555
82138
|
unsafe("the file changed while being read");
|
|
81556
82139
|
}
|
|
81557
82140
|
return parseEnvFile2(bytes.toString("utf8"));
|
|
81558
82141
|
} finally {
|
|
81559
82142
|
if (fd !== -1)
|
|
81560
|
-
|
|
82143
|
+
closeSync13(fd);
|
|
81561
82144
|
}
|
|
81562
82145
|
}
|
|
81563
82146
|
function readCredentialFile2(path, apiKeyKeys) {
|
|
@@ -82588,7 +83171,7 @@ function createSecretsClientFromEnv(env3 = process.env, overrides = {}) {
|
|
|
82588
83171
|
});
|
|
82589
83172
|
return new SecretsClient({ ...clientOverrides, baseUrl, apiKey });
|
|
82590
83173
|
}
|
|
82591
|
-
var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE", CredentialResolutionError2, CredentialFileUnsafeError2, HASNA_HOME_ENV_KEY2 = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY2 = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY2 = "HASNA_STATION", HASNA_HOME_DIR2 = ".hasna", CONFIG_SUBDIR2 = "config", CREDENTIALS_FILE2 = "credentials", KEYCHAIN_SECURITY_BIN2 = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX2 = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS2 = 44, KEYCHAIN_SPAWN_TIMEOUT_MS2 = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG2, SAFE_PROFILE2, ILLEGAL_IN_HEADER_VALUE2, VAULT_POINTER_SHAPE2, CREDENTIAL_SHAPED_KEY2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", AMBIENT_ENVIRONMENT2, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN2 = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN2, DNS_LABEL_PATTERN2, ClientTransportConfigurationError2, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, defaultSleep = (ms) => new Promise((
|
|
83174
|
+
var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), CREDENTIAL_PROFILE_ENV_KEY2 = "HASNA_PROFILE", CredentialResolutionError2, CredentialFileUnsafeError2, HASNA_HOME_ENV_KEY2 = "HASNA_HOME", HASNA_CONFIG_HOME_ENV_KEY2 = "HASNA_CONFIG_HOME", KEYCHAIN_STATION_ENV_KEY2 = "HASNA_STATION", HASNA_HOME_DIR2 = ".hasna", CONFIG_SUBDIR2 = "config", CREDENTIALS_FILE2 = "credentials", KEYCHAIN_SECURITY_BIN2 = "/usr/bin/security", KEYCHAIN_SERVICE_PREFIX2 = "hasna.credentials", KEYCHAIN_ITEM_NOT_FOUND_STATUS2 = 44, KEYCHAIN_SPAWN_TIMEOUT_MS2 = 1e4, MAX_CREDENTIAL_FILE_BYTES2, SAFE_APP_SLUG2, SAFE_PROFILE2, ILLEGAL_IN_HEADER_VALUE2, VAULT_POINTER_SHAPE2, CREDENTIAL_SHAPED_KEY2, INSPECT_CUSTOM2, CREDENTIAL_SEAL2, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", AMBIENT_ENVIRONMENT2, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk2, DEFAULT_FLEET_GATEWAY_ORIGIN2 = "https://api.hasna.com", DEFAULT_AUTHORITY_SOURCE = "default", ASCII_CONTROL_PATTERN2, DNS_LABEL_PATTERN2, ClientTransportConfigurationError2, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS2, AUTHORITY_OVERRIDE_HEADERS2, defaultSleep = (ms) => new Promise((resolve17) => setTimeout(resolve17, ms)), init_transport2, MAX_CREDENTIAL_FILE_BYTES22, INSPECT_CUSTOM22, CREDENTIAL_SEAL22, AMBIENT_ENVIRONMENT22, SECRETS_PACKAGE_SPECIFIER2, requireSecretsSdk22, IDEMPOTENT_METHODS22, AUTHORITY_OVERRIDE_HEADERS22, init_storage, PATHS_RESOLVER_APP_SLUG_RE3, SQLITE_SIDECAR_FILES, LEGACY_SERVICE_FILES, init_data_dir, SecretsTestIsolationError, TEST_ENTRYPOINT_RE, init_test_isolation, init_client, ApiError;
|
|
82592
83175
|
var init_sdk = __esm(() => {
|
|
82593
83176
|
init_transport2 = __esm2(() => {
|
|
82594
83177
|
CredentialResolutionError2 = class CredentialResolutionError3 extends Error {
|
|
@@ -82723,7 +83306,7 @@ var init_sdk = __esm(() => {
|
|
|
82723
83306
|
});
|
|
82724
83307
|
|
|
82725
83308
|
// src/lib/execution-secrets.ts
|
|
82726
|
-
import { constants as
|
|
83309
|
+
import { constants as constants13, closeSync as closeSync14, fstatSync as fstatSync14, openSync as openSync14, readSync as readSync11, realpathSync as realpathSync6 } from "fs";
|
|
82727
83310
|
import { hostname as stationHostname } from "os";
|
|
82728
83311
|
function selectedSecretBindingsTemplate(scope, names, createClient2 = createSecretsClientFromEnv) {
|
|
82729
83312
|
let secretsAuthority;
|
|
@@ -82747,7 +83330,7 @@ function refuse(code, message) {
|
|
|
82747
83330
|
function record7(value) {
|
|
82748
83331
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
82749
83332
|
}
|
|
82750
|
-
function
|
|
83333
|
+
function exactKeys2(value, keys2) {
|
|
82751
83334
|
return Object.keys(value).length === keys2.length && keys2.every((key) => Object.hasOwn(value, key));
|
|
82752
83335
|
}
|
|
82753
83336
|
function identifier2(value) {
|
|
@@ -82767,13 +83350,13 @@ function declaredSecretNames(value) {
|
|
|
82767
83350
|
function readSelectedSecretBindings(path) {
|
|
82768
83351
|
let fd;
|
|
82769
83352
|
try {
|
|
82770
|
-
fd =
|
|
82771
|
-
const stat2 =
|
|
83353
|
+
fd = openSync14(path, constants13.O_RDONLY | constants13.O_NOFOLLOW | constants13.O_NONBLOCK);
|
|
83354
|
+
const stat2 = fstatSync14(fd);
|
|
82772
83355
|
if (!stat2.isFile() || stat2.size > 65536)
|
|
82773
83356
|
throw new Error;
|
|
82774
83357
|
const bytes = Buffer.alloc(65537);
|
|
82775
83358
|
let size2 = 0, count;
|
|
82776
|
-
while ((count =
|
|
83359
|
+
while ((count = readSync11(fd, bytes, size2, bytes.length - size2, null)) > 0) {
|
|
82777
83360
|
size2 += count;
|
|
82778
83361
|
if (size2 > 65536)
|
|
82779
83362
|
throw new Error;
|
|
@@ -82783,11 +83366,11 @@ function readSelectedSecretBindings(path) {
|
|
|
82783
83366
|
return refuse("INVALID_SECRET_BINDINGS", "Secret bindings must be a regular JSON file of at most 64 KiB, containing reference names only.");
|
|
82784
83367
|
} finally {
|
|
82785
83368
|
if (fd !== undefined)
|
|
82786
|
-
|
|
83369
|
+
closeSync14(fd);
|
|
82787
83370
|
}
|
|
82788
83371
|
}
|
|
82789
83372
|
function validateSelectedSecretBindings(value, scope, names) {
|
|
82790
|
-
if (!record7(value) || !
|
|
83373
|
+
if (!record7(value) || !exactKeys2(value, ["schema", "selection", "consumer", "secretsAuthority", "bindings"]) || value.schema !== "hasna.skills-secret-bindings.v1" || !record7(value.selection) || !exactKeys2(value.selection, ["authority", "workspaceId", "profileId", "profileRevision", "slug", "version", "bundleDigest"]) || !record7(value.consumer) || !exactKeys2(value.consumer, ["stationId", "workspaceDirectory"]) || !record7(value.bindings)) {
|
|
82791
83374
|
return refuse("INVALID_SECRET_BINDINGS", "Secret bindings do not match the hasna.skills-secret-bindings.v1 contract.");
|
|
82792
83375
|
}
|
|
82793
83376
|
for (const [key, expected] of Object.entries({ authority: scope.selection.authority, workspaceId: scope.selection.workspaceId, profileId: scope.profileId, profileRevision: scope.selection.profileRevision, slug: scope.selection.slug, version: scope.selection.version, bundleDigest: scope.selection.bundleDigest })) {
|
|
@@ -82812,7 +83395,7 @@ function validateSelectedSecretBindings(value, scope, names) {
|
|
|
82812
83395
|
} catch {
|
|
82813
83396
|
return refuse("INVALID_SECRET_BINDINGS", "Secret bindings require a canonical HTTPS Secrets /v1 authority (loopback HTTP is allowed).");
|
|
82814
83397
|
}
|
|
82815
|
-
if (!
|
|
83398
|
+
if (!exactKeys2(value.bindings, names) || Object.values(value.bindings).some((key) => !identifier2(key) || !/^[A-Za-z0-9][A-Za-z0-9._/-]*$/.test(key) || key.split("/").some((part) => !part || part === "." || part === ".."))) {
|
|
82816
83399
|
return refuse("INVALID_SECRET_BINDINGS", "Bind every declared environment name exactly once to a vault key; undeclared bindings and values are refused.");
|
|
82817
83400
|
}
|
|
82818
83401
|
return structuredClone(value);
|
|
@@ -82990,7 +83573,7 @@ var init_execution_grants = __esm(() => {
|
|
|
82990
83573
|
});
|
|
82991
83574
|
|
|
82992
83575
|
// src/lib/execution-grant-client.ts
|
|
82993
|
-
import { isDeepStrictEqual as
|
|
83576
|
+
import { isDeepStrictEqual as isDeepStrictEqual4 } from "util";
|
|
82994
83577
|
function id(value) {
|
|
82995
83578
|
if (!grantIdentifier(value))
|
|
82996
83579
|
throw new Error("Invalid execution grant profile or revision identifier.");
|
|
@@ -83042,7 +83625,7 @@ async function saveExecutionGrantPolicy(profileId, grants, revision) {
|
|
|
83042
83625
|
headers: revision === undefined ? { "If-None-Match": "*" } : { "If-Match": `"${revision}"` },
|
|
83043
83626
|
body: JSON.stringify({ grants: snapshot })
|
|
83044
83627
|
}));
|
|
83045
|
-
if (policy.profileId !== profileId || policy.previousRevision !== (revision ?? null) || !
|
|
83628
|
+
if (policy.profileId !== profileId || policy.previousRevision !== (revision ?? null) || !isDeepStrictEqual4(policy.grants, snapshot)) {
|
|
83046
83629
|
throw new Error("The API did not preserve the reviewed execution grant policy; read it before retrying.");
|
|
83047
83630
|
}
|
|
83048
83631
|
return policy;
|
|
@@ -83053,7 +83636,7 @@ async function resolveExecutionGrant(input2) {
|
|
|
83053
83636
|
if (!grantRecord(value) || Object.keys(value).length !== 3 || !grantIdentifier(value.policyRevision) || !grantIdentifier(value.grantId) || !grantRecord(value.bindings)) {
|
|
83054
83637
|
throw new SkillSelectionError("INVALID_EXECUTION_GRANT", "The Skills API returned an invalid execution grant.");
|
|
83055
83638
|
}
|
|
83056
|
-
if (!
|
|
83639
|
+
if (!isDeepStrictEqual4(value.bindings.selection, snapshot.selection) || !isDeepStrictEqual4(value.bindings.consumer, snapshot.consumer)) {
|
|
83057
83640
|
throw new SkillSelectionError("EXECUTION_GRANT_SCOPE_MISMATCH", "The Skills API returned a grant for a different selection or consumer.");
|
|
83058
83641
|
}
|
|
83059
83642
|
return value;
|
|
@@ -83072,10 +83655,10 @@ __export(exports_selected_run, {
|
|
|
83072
83655
|
prepareSelectedSecretBindings: () => prepareSelectedSecretBindings,
|
|
83073
83656
|
executeSelectedLocal: () => executeSelectedLocal
|
|
83074
83657
|
});
|
|
83075
|
-
import { createHash as
|
|
83658
|
+
import { createHash as createHash18 } from "crypto";
|
|
83076
83659
|
import { spawn as spawn2 } from "child_process";
|
|
83077
83660
|
import { mkdirSync as mkdirSync14, mkdtempSync as mkdtempSync4, writeFileSync as writeFileSync13, realpathSync as realpathSync7 } from "fs";
|
|
83078
|
-
import { dirname as
|
|
83661
|
+
import { dirname as dirname18, join as join42, resolve as resolve17 } from "path";
|
|
83079
83662
|
import { tmpdir, hostname as stationHostname2 } from "os";
|
|
83080
83663
|
async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
83081
83664
|
const context = await resolveSelectionContext(profileId, options);
|
|
@@ -83164,11 +83747,11 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
83164
83747
|
throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
|
|
83165
83748
|
});
|
|
83166
83749
|
const destination = join42(runDirectory, entry.path);
|
|
83167
|
-
mkdirSync14(
|
|
83750
|
+
mkdirSync14(dirname18(destination), { recursive: true, mode: 448 });
|
|
83168
83751
|
writeFileSync13(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
|
|
83169
83752
|
}
|
|
83170
83753
|
env3.SKILLS_INPUT_JSON = input2;
|
|
83171
|
-
env3.SKILLS_WORKSPACE_DIR =
|
|
83754
|
+
env3.SKILLS_WORKSPACE_DIR = resolve17(options.cwd ?? process.cwd());
|
|
83172
83755
|
env3.SKILLS_RUN_DIR = runDirectory;
|
|
83173
83756
|
if (runtime.version) {
|
|
83174
83757
|
const version2 = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env3, "", Math.min(timeoutMs, 5000));
|
|
@@ -83198,7 +83781,7 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
83198
83781
|
selection: selection2,
|
|
83199
83782
|
target: "local",
|
|
83200
83783
|
runtime: runtimeName,
|
|
83201
|
-
inputDigest: `sha256:${
|
|
83784
|
+
inputDigest: `sha256:${createHash18("sha256").update(input2).digest("hex")}`,
|
|
83202
83785
|
runDirectory,
|
|
83203
83786
|
...executionGrant ? { executionGrant } : {},
|
|
83204
83787
|
...bindings ? { secretBinding: { schema: bindings.schema, selection: bindings.selection, consumer: bindings.consumer, secretsAuthority: bindings.secretsAuthority, bindings: bindings.bindings } } : {},
|
|
@@ -87415,7 +87998,7 @@ var init_runs = __esm(() => {
|
|
|
87415
87998
|
});
|
|
87416
87999
|
|
|
87417
88000
|
// src/lib/run-state.ts
|
|
87418
|
-
import { createHash as
|
|
88001
|
+
import { createHash as createHash19, randomBytes } from "crypto";
|
|
87419
88002
|
import { existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync30, readdirSync as readdirSync16, statSync as statSync15, writeFileSync as writeFileSync14 } from "fs";
|
|
87420
88003
|
import { extname, join as join43, relative as relative6 } from "path";
|
|
87421
88004
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
@@ -87552,7 +88135,7 @@ function collectRunArtifacts(context) {
|
|
|
87552
88135
|
artifacts.push({
|
|
87553
88136
|
path: toProjectRelative(context.targetDir, path),
|
|
87554
88137
|
mime: mimeForPath(path),
|
|
87555
|
-
sha256:
|
|
88138
|
+
sha256: createHash19("sha256").update(bytes).digest("hex"),
|
|
87556
88139
|
sizeBytes: stat2.size
|
|
87557
88140
|
});
|
|
87558
88141
|
}
|
|
@@ -88555,12 +89138,12 @@ class StdioServerTransport {
|
|
|
88555
89138
|
this.onclose?.();
|
|
88556
89139
|
}
|
|
88557
89140
|
send(message) {
|
|
88558
|
-
return new Promise((
|
|
89141
|
+
return new Promise((resolve18) => {
|
|
88559
89142
|
const json2 = serializeMessage(message);
|
|
88560
89143
|
if (this._stdout.write(json2)) {
|
|
88561
|
-
|
|
89144
|
+
resolve18();
|
|
88562
89145
|
} else {
|
|
88563
|
-
this._stdout.once("drain",
|
|
89146
|
+
this._stdout.once("drain", resolve18);
|
|
88564
89147
|
}
|
|
88565
89148
|
});
|
|
88566
89149
|
}
|
|
@@ -88602,7 +89185,7 @@ var init_schemas3 = __esm(() => {
|
|
|
88602
89185
|
own(this, "with", value);
|
|
88603
89186
|
},
|
|
88604
89187
|
parse(data, params) {
|
|
88605
|
-
return
|
|
89188
|
+
return parse6(this, data, params, { callee: this.parse });
|
|
88606
89189
|
},
|
|
88607
89190
|
parseAsync(data, params) {
|
|
88608
89191
|
return parseAsync(this, data, params, { callee: this.parseAsync });
|
|
@@ -90746,7 +91329,7 @@ class Protocol {
|
|
|
90746
91329
|
return;
|
|
90747
91330
|
}
|
|
90748
91331
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
|
|
90749
|
-
await new Promise((
|
|
91332
|
+
await new Promise((resolve18) => setTimeout(resolve18, pollInterval));
|
|
90750
91333
|
options?.signal?.throwIfAborted();
|
|
90751
91334
|
}
|
|
90752
91335
|
} catch (error61) {
|
|
@@ -90758,7 +91341,7 @@ class Protocol {
|
|
|
90758
91341
|
}
|
|
90759
91342
|
request(request2, resultSchema, options) {
|
|
90760
91343
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
90761
|
-
return new Promise((
|
|
91344
|
+
return new Promise((resolve18, reject2) => {
|
|
90762
91345
|
const earlyReject = (error61) => {
|
|
90763
91346
|
reject2(error61);
|
|
90764
91347
|
};
|
|
@@ -90836,7 +91419,7 @@ class Protocol {
|
|
|
90836
91419
|
if (!parseResult.success) {
|
|
90837
91420
|
reject2(parseResult.error);
|
|
90838
91421
|
} else {
|
|
90839
|
-
|
|
91422
|
+
resolve18(parseResult.data);
|
|
90840
91423
|
}
|
|
90841
91424
|
} catch (error61) {
|
|
90842
91425
|
reject2(error61);
|
|
@@ -91027,12 +91610,12 @@ class Protocol {
|
|
|
91027
91610
|
interval = task.pollInterval;
|
|
91028
91611
|
}
|
|
91029
91612
|
} catch {}
|
|
91030
|
-
return new Promise((
|
|
91613
|
+
return new Promise((resolve18, reject2) => {
|
|
91031
91614
|
if (signal.aborted) {
|
|
91032
91615
|
reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
91033
91616
|
return;
|
|
91034
91617
|
}
|
|
91035
|
-
const timeoutId = setTimeout(
|
|
91618
|
+
const timeoutId = setTimeout(resolve18, interval);
|
|
91036
91619
|
signal.addEventListener("abort", () => {
|
|
91037
91620
|
clearTimeout(timeoutId);
|
|
91038
91621
|
reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -91509,11 +92092,11 @@ var require_codegen = __commonJS((exports) => {
|
|
|
91509
92092
|
const rhs = this.rhs === undefined ? "" : ` = ${this.rhs}`;
|
|
91510
92093
|
return `${varKind} ${this.name}${rhs};` + _n;
|
|
91511
92094
|
}
|
|
91512
|
-
optimizeNames(names,
|
|
92095
|
+
optimizeNames(names, constants14) {
|
|
91513
92096
|
if (!names[this.name.str])
|
|
91514
92097
|
return;
|
|
91515
92098
|
if (this.rhs)
|
|
91516
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
92099
|
+
this.rhs = optimizeExpr(this.rhs, names, constants14);
|
|
91517
92100
|
return this;
|
|
91518
92101
|
}
|
|
91519
92102
|
get names() {
|
|
@@ -91531,10 +92114,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
91531
92114
|
render({ _n }) {
|
|
91532
92115
|
return `${this.lhs} = ${this.rhs};` + _n;
|
|
91533
92116
|
}
|
|
91534
|
-
optimizeNames(names,
|
|
92117
|
+
optimizeNames(names, constants14) {
|
|
91535
92118
|
if (this.lhs instanceof code_1.Name && !names[this.lhs.str] && !this.sideEffects)
|
|
91536
92119
|
return;
|
|
91537
|
-
this.rhs = optimizeExpr(this.rhs, names,
|
|
92120
|
+
this.rhs = optimizeExpr(this.rhs, names, constants14);
|
|
91538
92121
|
return this;
|
|
91539
92122
|
}
|
|
91540
92123
|
get names() {
|
|
@@ -91600,8 +92183,8 @@ var require_codegen = __commonJS((exports) => {
|
|
|
91600
92183
|
optimizeNodes() {
|
|
91601
92184
|
return `${this.code}` ? this : undefined;
|
|
91602
92185
|
}
|
|
91603
|
-
optimizeNames(names,
|
|
91604
|
-
this.code = optimizeExpr(this.code, names,
|
|
92186
|
+
optimizeNames(names, constants14) {
|
|
92187
|
+
this.code = optimizeExpr(this.code, names, constants14);
|
|
91605
92188
|
return this;
|
|
91606
92189
|
}
|
|
91607
92190
|
get names() {
|
|
@@ -91631,12 +92214,12 @@ var require_codegen = __commonJS((exports) => {
|
|
|
91631
92214
|
}
|
|
91632
92215
|
return nodes.length > 0 ? this : undefined;
|
|
91633
92216
|
}
|
|
91634
|
-
optimizeNames(names,
|
|
92217
|
+
optimizeNames(names, constants14) {
|
|
91635
92218
|
const { nodes } = this;
|
|
91636
92219
|
let i = nodes.length;
|
|
91637
92220
|
while (i--) {
|
|
91638
92221
|
const n2 = nodes[i];
|
|
91639
|
-
if (n2.optimizeNames(names,
|
|
92222
|
+
if (n2.optimizeNames(names, constants14))
|
|
91640
92223
|
continue;
|
|
91641
92224
|
subtractNames(names, n2.names);
|
|
91642
92225
|
nodes.splice(i, 1);
|
|
@@ -91693,12 +92276,12 @@ var require_codegen = __commonJS((exports) => {
|
|
|
91693
92276
|
return;
|
|
91694
92277
|
return this;
|
|
91695
92278
|
}
|
|
91696
|
-
optimizeNames(names,
|
|
92279
|
+
optimizeNames(names, constants14) {
|
|
91697
92280
|
var _a3;
|
|
91698
|
-
this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names,
|
|
91699
|
-
if (!(super.optimizeNames(names,
|
|
92281
|
+
this.else = (_a3 = this.else) === null || _a3 === undefined ? undefined : _a3.optimizeNames(names, constants14);
|
|
92282
|
+
if (!(super.optimizeNames(names, constants14) || this.else))
|
|
91700
92283
|
return;
|
|
91701
|
-
this.condition = optimizeExpr(this.condition, names,
|
|
92284
|
+
this.condition = optimizeExpr(this.condition, names, constants14);
|
|
91702
92285
|
return this;
|
|
91703
92286
|
}
|
|
91704
92287
|
get names() {
|
|
@@ -91723,10 +92306,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
91723
92306
|
render(opts) {
|
|
91724
92307
|
return `for(${this.iteration})` + super.render(opts);
|
|
91725
92308
|
}
|
|
91726
|
-
optimizeNames(names,
|
|
91727
|
-
if (!super.optimizeNames(names,
|
|
92309
|
+
optimizeNames(names, constants14) {
|
|
92310
|
+
if (!super.optimizeNames(names, constants14))
|
|
91728
92311
|
return;
|
|
91729
|
-
this.iteration = optimizeExpr(this.iteration, names,
|
|
92312
|
+
this.iteration = optimizeExpr(this.iteration, names, constants14);
|
|
91730
92313
|
return this;
|
|
91731
92314
|
}
|
|
91732
92315
|
get names() {
|
|
@@ -91764,10 +92347,10 @@ var require_codegen = __commonJS((exports) => {
|
|
|
91764
92347
|
render(opts) {
|
|
91765
92348
|
return `for(${this.varKind} ${this.name} ${this.loop} ${this.iterable})` + super.render(opts);
|
|
91766
92349
|
}
|
|
91767
|
-
optimizeNames(names,
|
|
91768
|
-
if (!super.optimizeNames(names,
|
|
92350
|
+
optimizeNames(names, constants14) {
|
|
92351
|
+
if (!super.optimizeNames(names, constants14))
|
|
91769
92352
|
return;
|
|
91770
|
-
this.iterable = optimizeExpr(this.iterable, names,
|
|
92353
|
+
this.iterable = optimizeExpr(this.iterable, names, constants14);
|
|
91771
92354
|
return this;
|
|
91772
92355
|
}
|
|
91773
92356
|
get names() {
|
|
@@ -91812,11 +92395,11 @@ var require_codegen = __commonJS((exports) => {
|
|
|
91812
92395
|
(_b = this.finally) === null || _b === undefined || _b.optimizeNodes();
|
|
91813
92396
|
return this;
|
|
91814
92397
|
}
|
|
91815
|
-
optimizeNames(names,
|
|
92398
|
+
optimizeNames(names, constants14) {
|
|
91816
92399
|
var _a3, _b;
|
|
91817
|
-
super.optimizeNames(names,
|
|
91818
|
-
(_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names,
|
|
91819
|
-
(_b = this.finally) === null || _b === undefined || _b.optimizeNames(names,
|
|
92400
|
+
super.optimizeNames(names, constants14);
|
|
92401
|
+
(_a3 = this.catch) === null || _a3 === undefined || _a3.optimizeNames(names, constants14);
|
|
92402
|
+
(_b = this.finally) === null || _b === undefined || _b.optimizeNames(names, constants14);
|
|
91820
92403
|
return this;
|
|
91821
92404
|
}
|
|
91822
92405
|
get names() {
|
|
@@ -92090,7 +92673,7 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92090
92673
|
function addExprNames(names, from) {
|
|
92091
92674
|
return from instanceof code_1._CodeOrName ? addNames(names, from.names) : names;
|
|
92092
92675
|
}
|
|
92093
|
-
function optimizeExpr(expr, names,
|
|
92676
|
+
function optimizeExpr(expr, names, constants14) {
|
|
92094
92677
|
if (expr instanceof code_1.Name)
|
|
92095
92678
|
return replaceName(expr);
|
|
92096
92679
|
if (!canOptimize(expr))
|
|
@@ -92105,14 +92688,14 @@ var require_codegen = __commonJS((exports) => {
|
|
|
92105
92688
|
return items;
|
|
92106
92689
|
}, []));
|
|
92107
92690
|
function replaceName(n2) {
|
|
92108
|
-
const c =
|
|
92691
|
+
const c = constants14[n2.str];
|
|
92109
92692
|
if (c === undefined || names[n2.str] !== 1)
|
|
92110
92693
|
return n2;
|
|
92111
92694
|
delete names[n2.str];
|
|
92112
92695
|
return c;
|
|
92113
92696
|
}
|
|
92114
92697
|
function canOptimize(e2) {
|
|
92115
|
-
return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 &&
|
|
92698
|
+
return e2 instanceof code_1._Code && e2._items.some((c) => c instanceof code_1.Name && names[c.str] === 1 && constants14[c.str] !== undefined);
|
|
92116
92699
|
}
|
|
92117
92700
|
}
|
|
92118
92701
|
function subtractNames(names, from) {
|
|
@@ -94017,7 +94600,7 @@ var require_compile = __commonJS((exports) => {
|
|
|
94017
94600
|
const schOrFunc = root2.refs[ref];
|
|
94018
94601
|
if (schOrFunc)
|
|
94019
94602
|
return schOrFunc;
|
|
94020
|
-
let _sch =
|
|
94603
|
+
let _sch = resolve18.call(this, root2, ref);
|
|
94021
94604
|
if (_sch === undefined) {
|
|
94022
94605
|
const schema = (_a3 = root2.localRefs) === null || _a3 === undefined ? undefined : _a3[ref];
|
|
94023
94606
|
const { schemaId } = this.opts;
|
|
@@ -94044,7 +94627,7 @@ var require_compile = __commonJS((exports) => {
|
|
|
94044
94627
|
function sameSchemaEnv(s1, s2) {
|
|
94045
94628
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
94046
94629
|
}
|
|
94047
|
-
function
|
|
94630
|
+
function resolve18(root2, ref) {
|
|
94048
94631
|
let sch;
|
|
94049
94632
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
94050
94633
|
ref = sch;
|
|
@@ -94842,11 +95425,11 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
94842
95425
|
if (typeof uri === "string") {
|
|
94843
95426
|
uri = normalizeString(uri, options);
|
|
94844
95427
|
} else if (typeof uri === "object") {
|
|
94845
|
-
uri =
|
|
95428
|
+
uri = parse11(serialize(uri, options), options);
|
|
94846
95429
|
}
|
|
94847
95430
|
return uri;
|
|
94848
95431
|
}
|
|
94849
|
-
function
|
|
95432
|
+
function resolve18(baseURI, relativeURI, options) {
|
|
94850
95433
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
94851
95434
|
const {
|
|
94852
95435
|
parsed: baseParsed,
|
|
@@ -94882,8 +95465,8 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
94882
95465
|
function resolveComponent(base2, relative7, options, skipNormalization) {
|
|
94883
95466
|
const target = {};
|
|
94884
95467
|
if (!skipNormalization) {
|
|
94885
|
-
base2 =
|
|
94886
|
-
relative7 =
|
|
95468
|
+
base2 = parse11(serialize(base2, options), options);
|
|
95469
|
+
relative7 = parse11(serialize(relative7, options), options);
|
|
94887
95470
|
}
|
|
94888
95471
|
options = options || {};
|
|
94889
95472
|
if (!options.tolerant && relative7.scheme) {
|
|
@@ -95183,7 +95766,7 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
95183
95766
|
}
|
|
95184
95767
|
return { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme };
|
|
95185
95768
|
}
|
|
95186
|
-
function
|
|
95769
|
+
function parse11(uri, opts) {
|
|
95187
95770
|
return parseWithStatus(uri, opts).parsed;
|
|
95188
95771
|
}
|
|
95189
95772
|
function normalizeString(uri, opts) {
|
|
@@ -95216,11 +95799,11 @@ var require_fast_uri = __commonJS((exports, module) => {
|
|
|
95216
95799
|
var fastUri = {
|
|
95217
95800
|
SCHEMES,
|
|
95218
95801
|
normalize: normalize3,
|
|
95219
|
-
resolve:
|
|
95802
|
+
resolve: resolve18,
|
|
95220
95803
|
resolveComponent,
|
|
95221
95804
|
equal,
|
|
95222
95805
|
serialize,
|
|
95223
|
-
parse:
|
|
95806
|
+
parse: parse11
|
|
95224
95807
|
};
|
|
95225
95808
|
module.exports = fastUri;
|
|
95226
95809
|
module.exports.default = fastUri;
|
|
@@ -99002,7 +99585,7 @@ class McpServer {
|
|
|
99002
99585
|
let task = createTaskResult.task;
|
|
99003
99586
|
const pollInterval = task.pollInterval ?? 5000;
|
|
99004
99587
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
99005
|
-
await new Promise((
|
|
99588
|
+
await new Promise((resolve18) => setTimeout(resolve18, pollInterval));
|
|
99006
99589
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
99007
99590
|
if (!updatedTask) {
|
|
99008
99591
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -99045,11 +99628,11 @@ class McpServer {
|
|
|
99045
99628
|
return EMPTY_COMPLETION_RESULT;
|
|
99046
99629
|
}
|
|
99047
99630
|
const promptShape = getObjectShape(prompt.argsSchema);
|
|
99048
|
-
const
|
|
99049
|
-
if (!isCompletable(
|
|
99631
|
+
const field2 = promptShape?.[request2.params.argument.name];
|
|
99632
|
+
if (!isCompletable(field2)) {
|
|
99050
99633
|
return EMPTY_COMPLETION_RESULT;
|
|
99051
99634
|
}
|
|
99052
|
-
const completer = getCompleter(
|
|
99635
|
+
const completer = getCompleter(field2);
|
|
99053
99636
|
if (!completer) {
|
|
99054
99637
|
return EMPTY_COMPLETION_RESULT;
|
|
99055
99638
|
}
|
|
@@ -99321,8 +99904,8 @@ class McpServer {
|
|
|
99321
99904
|
};
|
|
99322
99905
|
this._registeredPrompts[name] = registeredPrompt;
|
|
99323
99906
|
if (argsSchema) {
|
|
99324
|
-
const hasCompletable = Object.values(argsSchema).some((
|
|
99325
|
-
const inner =
|
|
99907
|
+
const hasCompletable = Object.values(argsSchema).some((field2) => {
|
|
99908
|
+
const inner = field2 instanceof ZodOptional ? field2._def?.innerType : field2;
|
|
99326
99909
|
return isCompletable(inner);
|
|
99327
99910
|
});
|
|
99328
99911
|
if (hasCompletable) {
|
|
@@ -99514,9 +100097,9 @@ function promptArgumentsFromSchema(schema) {
|
|
|
99514
100097
|
const shape = getObjectShape(schema);
|
|
99515
100098
|
if (!shape)
|
|
99516
100099
|
return [];
|
|
99517
|
-
return Object.entries(shape).map(([name,
|
|
99518
|
-
const description = getSchemaDescription(
|
|
99519
|
-
const isOptional = isSchemaOptional(
|
|
100100
|
+
return Object.entries(shape).map(([name, field2]) => {
|
|
100101
|
+
const description = getSchemaDescription(field2);
|
|
100102
|
+
const isOptional = isSchemaOptional(field2);
|
|
99520
100103
|
return {
|
|
99521
100104
|
name,
|
|
99522
100105
|
description,
|
|
@@ -99575,7 +100158,7 @@ var init_remote_customer_operations = __esm(() => {
|
|
|
99575
100158
|
{ name: "list_remote_skills", title: "List Remote Skills", parameter: null, mutates: false, invoke: (client2) => client2.listSkills() },
|
|
99576
100159
|
{ name: "get_billing_status", title: "Get Billing Status", parameter: null, mutates: false, invoke: (client2) => client2.getBillingStatus() },
|
|
99577
100160
|
{ name: "list_credit_packs", title: "List Credit Packs", parameter: null, mutates: false, invoke: (client2) => client2.listCreditPacks() },
|
|
99578
|
-
{ name: "create_credit_checkout", title: "Create Credit Checkout", parameter: "pack_id", mutates: true, invoke: (client2, value) => client2.createCreditCheckout(value) },
|
|
100161
|
+
{ name: "create_credit_checkout", title: "Create Credit Checkout", parameter: "pack_id", mutates: true, invoke: (client2, value, options) => client2.createCreditCheckout(value, options) },
|
|
99579
100162
|
{ name: "get_billing_usage", title: "Get Billing Usage", parameter: null, mutates: false, invoke: (client2) => client2.getUsage() },
|
|
99580
100163
|
{ name: "list_invoices", title: "List Invoices", parameter: null, mutates: false, invoke: (client2) => client2.listInvoices() },
|
|
99581
100164
|
{ name: "create_billing_checkout", title: "Create Billing Checkout", parameter: null, mutates: true, invoke: (client2) => client2.createBillingCheckout() },
|
|
@@ -99689,7 +100272,7 @@ var init_remote_invitation_recovery = __esm(() => {
|
|
|
99689
100272
|
});
|
|
99690
100273
|
|
|
99691
100274
|
// src/lib/remote-private-publications.ts
|
|
99692
|
-
import { createHash as
|
|
100275
|
+
import { createHash as createHash20 } from "crypto";
|
|
99693
100276
|
function checkedPublicationDeclaration(value) {
|
|
99694
100277
|
if (!exact(value, ["idempotencyKey", "version", "expectedCurrentVersionId", "manifestText", "archiveSha256", "archiveByteSize"]) || !publicationUuid(value.idempotencyKey) || !(value.expectedCurrentVersionId === null || publicationUuid(value.expectedCurrentVersionId)) || typeof value.version !== "string" || !value.version || value.version.length > 128 || /[\p{Cc}\p{Cs}]/u.test(value.version) || typeof value.manifestText !== "string" || Buffer.byteLength(value.manifestText) > 16384 || !hash3(value.archiveSha256) || !Number.isSafeInteger(value.archiveByteSize) || Number(value.archiveByteSize) < 1 || Number(value.archiveByteSize) > PRIVATE_PUBLICATION_MAX_BYTES)
|
|
99695
100278
|
return bad();
|
|
@@ -99934,12 +100517,12 @@ class RemotePrivatePublicationsClient {
|
|
|
99934
100517
|
previous = view;
|
|
99935
100518
|
if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
|
|
99936
100519
|
return view;
|
|
99937
|
-
await new Promise((
|
|
100520
|
+
await new Promise((resolve18) => {
|
|
99938
100521
|
const timer = setTimeout(done, Math.min(1000, until - Date.now()));
|
|
99939
100522
|
function done() {
|
|
99940
100523
|
clearTimeout(timer);
|
|
99941
100524
|
options.signal?.removeEventListener("abort", done);
|
|
99942
|
-
|
|
100525
|
+
resolve18();
|
|
99943
100526
|
}
|
|
99944
100527
|
options.signal?.addEventListener("abort", done, { once: true });
|
|
99945
100528
|
});
|
|
@@ -99950,7 +100533,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
|
|
|
99950
100533
|
throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
|
|
99951
100534
|
}, invalid5 = () => {
|
|
99952
100535
|
throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
|
|
99953
|
-
}, 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), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record10(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date6 = (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) =>
|
|
100536
|
+
}, 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), hash3 = (v) => typeof v === "string" && /^[a-f0-9]{64}$/.test(v), record10 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys3) => record10(v) && Object.keys(v).sort().join(",") === keys3.sort().join(","), date6 = (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) => createHash20("sha256").update(bytes).digest("hex");
|
|
99954
100537
|
var init_remote_private_publications = __esm(() => {
|
|
99955
100538
|
init_fleet_credentials();
|
|
99956
100539
|
init_remote_workspace_selection();
|
|
@@ -100227,11 +100810,11 @@ var init_remote_auth = __esm(() => {
|
|
|
100227
100810
|
});
|
|
100228
100811
|
|
|
100229
100812
|
// src/lib/workspace-profile.ts
|
|
100230
|
-
import { constants as
|
|
100231
|
-
import { dirname as
|
|
100813
|
+
import { constants as constants14, closeSync as closeSync15, fstatSync as fstatSync15, lstatSync as lstatSync21, mkdirSync as mkdirSync16, mkdtempSync as mkdtempSync5, openSync as openSync15, readFileSync as readFileSync31, renameSync as renameSync9, rmSync as rmSync8, writeFileSync as writeFileSync15 } from "fs";
|
|
100814
|
+
import { dirname as dirname19, join as join44 } from "path";
|
|
100232
100815
|
function stat2(path) {
|
|
100233
100816
|
try {
|
|
100234
|
-
return
|
|
100817
|
+
return lstatSync21(path);
|
|
100235
100818
|
} catch (error61) {
|
|
100236
100819
|
if (error61.code === "ENOENT")
|
|
100237
100820
|
return null;
|
|
@@ -100241,14 +100824,14 @@ function stat2(path) {
|
|
|
100241
100824
|
function safeText(file2) {
|
|
100242
100825
|
if (stat2(file2) === null)
|
|
100243
100826
|
return null;
|
|
100244
|
-
const fd =
|
|
100827
|
+
const fd = openSync15(file2, constants14.O_RDONLY | constants14.O_NOFOLLOW | constants14.O_NONBLOCK);
|
|
100245
100828
|
try {
|
|
100246
|
-
const s =
|
|
100829
|
+
const s = fstatSync15(fd);
|
|
100247
100830
|
if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
|
|
100248
100831
|
return fail2("The selected profile must use bounded owner-only regular files.");
|
|
100249
100832
|
return readFileSync31(fd, "utf8");
|
|
100250
100833
|
} finally {
|
|
100251
|
-
|
|
100834
|
+
closeSync15(fd);
|
|
100252
100835
|
}
|
|
100253
100836
|
}
|
|
100254
100837
|
function checkIdentityMetadata(file2, identity4) {
|
|
@@ -100313,18 +100896,18 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
|
|
|
100313
100896
|
`);
|
|
100314
100897
|
if (Buffer.byteLength(credentialBody("x".repeat(8192)), "utf8") > 65536)
|
|
100315
100898
|
return fail2("The selected profile has insufficient space for a bounded credential. Reduce its unrelated configuration before signing in.");
|
|
100316
|
-
const
|
|
100317
|
-
for (let path =
|
|
100899
|
+
const parents2 = [];
|
|
100900
|
+
for (let path = dirname19(file2);; path = dirname19(path)) {
|
|
100318
100901
|
const before2 = stat2(path);
|
|
100319
100902
|
if (before2 && (!before2.isDirectory() || before2.isSymbolicLink()))
|
|
100320
100903
|
return fail2("The profile directory must not be a symbolic link.");
|
|
100321
|
-
|
|
100322
|
-
if (path ===
|
|
100904
|
+
parents2.push([path, before2]);
|
|
100905
|
+
if (path === dirname19(path))
|
|
100323
100906
|
break;
|
|
100324
100907
|
}
|
|
100325
100908
|
const unchanged2 = () => {
|
|
100326
100909
|
unchangedFiles();
|
|
100327
|
-
for (const [path, before2] of
|
|
100910
|
+
for (const [path, before2] of parents2) {
|
|
100328
100911
|
const now3 = stat2(path);
|
|
100329
100912
|
if (!before2 ? now3 !== null : !now3 || !now3.isDirectory() || before2.dev !== now3.dev || before2.ino !== now3.ino)
|
|
100330
100913
|
changed();
|
|
@@ -100378,14 +100961,14 @@ async function prepareWorkspaceEnrollment(membershipId, source = process.env) {
|
|
|
100378
100961
|
return fail2("The new profile exceeds the credential reader size limit.");
|
|
100379
100962
|
const identity4 = JSON.stringify({ email: verified.user.email, userId: verified.user.id, orgId: verified.organization.id, orgSlug: verified.organization.slug, apiUrl: origin }, null, 2) + `
|
|
100380
100963
|
`;
|
|
100381
|
-
mkdirSync16(
|
|
100382
|
-
const temp = mkdtempSync5(join44(
|
|
100964
|
+
mkdirSync16(dirname19(file2), { recursive: true, mode: 448 });
|
|
100965
|
+
const temp = mkdtempSync5(join44(dirname19(file2), ".workspace-login-"));
|
|
100383
100966
|
let identityInstalled = false;
|
|
100384
100967
|
try {
|
|
100385
100968
|
writeFileSync15(join44(temp, "credentials"), body, { mode: 384, flag: "wx" });
|
|
100386
100969
|
writeFileSync15(join44(temp, "identity"), identity4, { mode: 384, flag: "wx" });
|
|
100387
100970
|
unchangedFiles();
|
|
100388
|
-
for (const [path, before2] of
|
|
100971
|
+
for (const [path, before2] of parents2) {
|
|
100389
100972
|
const now3 = stat2(path);
|
|
100390
100973
|
if (!now3 || !now3.isDirectory() || now3.isSymbolicLink() || before2 && (before2.dev !== now3.dev || before2.ino !== now3.ino))
|
|
100391
100974
|
changed();
|
|
@@ -100595,8 +101178,8 @@ var init_recurring_customer = __esm(() => {
|
|
|
100595
101178
|
});
|
|
100596
101179
|
|
|
100597
101180
|
// src/lib/recurring-recovery.ts
|
|
100598
|
-
import { constants as
|
|
100599
|
-
import { dirname as
|
|
101181
|
+
import { constants as constants15, closeSync as closeSync16, fsyncSync as fsyncSync4, fstatSync as fstatSync16, lstatSync as lstatSync22, mkdirSync as mkdirSync17, openSync as openSync16, readSync as readSync12, realpathSync as realpathSync8, renameSync as renameSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync16 } from "fs";
|
|
101182
|
+
import { dirname as dirname20, isAbsolute as isAbsolute16, join as join45, resolve as resolve18 } from "path";
|
|
100600
101183
|
import { randomUUID as randomUUID7 } from "crypto";
|
|
100601
101184
|
|
|
100602
101185
|
class RecoveryOwner {
|
|
@@ -100604,14 +101187,14 @@ class RecoveryOwner {
|
|
|
100604
101187
|
parents = [];
|
|
100605
101188
|
constructor(directory) {
|
|
100606
101189
|
this.directory = directory;
|
|
100607
|
-
if (!
|
|
101190
|
+
if (!isAbsolute16(directory) || resolve18(directory) !== directory || realpathSync8(directory) !== directory)
|
|
100608
101191
|
invalid6();
|
|
100609
|
-
for (let path = directory;; path =
|
|
100610
|
-
const stat3 =
|
|
101192
|
+
for (let path = directory;; path = dirname20(path)) {
|
|
101193
|
+
const stat3 = lstatSync22(path);
|
|
100611
101194
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
100612
101195
|
invalid6();
|
|
100613
101196
|
this.parents.push({ path, dev: stat3.dev, ino: stat3.ino });
|
|
100614
|
-
if (path ===
|
|
101197
|
+
if (path === dirname20(path))
|
|
100615
101198
|
break;
|
|
100616
101199
|
}
|
|
100617
101200
|
this.assert();
|
|
@@ -100620,59 +101203,59 @@ class RecoveryOwner {
|
|
|
100620
101203
|
if (realpathSync8(this.directory) !== this.directory)
|
|
100621
101204
|
invalid6();
|
|
100622
101205
|
for (const prior of this.parents) {
|
|
100623
|
-
const now3 =
|
|
101206
|
+
const now3 = lstatSync22(prior.path);
|
|
100624
101207
|
if (!now3.isDirectory() || now3.isSymbolicLink() || now3.dev !== prior.dev || now3.ino !== prior.ino)
|
|
100625
101208
|
invalid6();
|
|
100626
101209
|
}
|
|
100627
|
-
const own2 =
|
|
101210
|
+
const own2 = lstatSync22(this.directory);
|
|
100628
101211
|
if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
100629
101212
|
invalid6();
|
|
100630
101213
|
}
|
|
100631
101214
|
read(name) {
|
|
100632
101215
|
this.assert();
|
|
100633
|
-
const fd =
|
|
101216
|
+
const fd = openSync16(join45(this.directory, name), constants15.O_RDONLY | constants15.O_NOFOLLOW | constants15.O_NONBLOCK);
|
|
100634
101217
|
try {
|
|
100635
|
-
const before2 =
|
|
101218
|
+
const before2 = fstatSync16(fd);
|
|
100636
101219
|
if (!before2.isFile() || before2.nlink !== 1 || (before2.mode & 4095) !== 384 || before2.size < 1 || before2.size > 8192 || process.getuid && before2.uid !== process.getuid())
|
|
100637
101220
|
invalid6();
|
|
100638
101221
|
const bytes = Buffer.alloc(before2.size + 1);
|
|
100639
101222
|
let size2 = 0;
|
|
100640
101223
|
while (size2 < bytes.length) {
|
|
100641
|
-
const n2 =
|
|
101224
|
+
const n2 = readSync12(fd, bytes, size2, bytes.length - size2, size2);
|
|
100642
101225
|
if (!n2)
|
|
100643
101226
|
break;
|
|
100644
101227
|
size2 += n2;
|
|
100645
101228
|
}
|
|
100646
|
-
const after2 =
|
|
101229
|
+
const after2 = fstatSync16(fd), path = lstatSync22(join45(this.directory, name));
|
|
100647
101230
|
if (size2 !== before2.size || after2.size !== before2.size || before2.mtimeMs !== after2.mtimeMs || before2.ctimeMs !== after2.ctimeMs || path.dev !== before2.dev || path.ino !== before2.ino || !path.isFile() || path.isSymbolicLink())
|
|
100648
101231
|
invalid6();
|
|
100649
101232
|
this.assert();
|
|
100650
101233
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
|
|
100651
101234
|
} finally {
|
|
100652
|
-
|
|
101235
|
+
closeSync16(fd);
|
|
100653
101236
|
}
|
|
100654
101237
|
}
|
|
100655
101238
|
write(name, value) {
|
|
100656
101239
|
this.assert();
|
|
100657
101240
|
const bytes = canonicalJson2(value, 8192) + `
|
|
100658
101241
|
`;
|
|
100659
|
-
const fd =
|
|
101242
|
+
const fd = openSync16(join45(this.directory, name), constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
|
|
100660
101243
|
try {
|
|
100661
101244
|
writeFileSync16(fd, bytes);
|
|
100662
|
-
|
|
101245
|
+
fsyncSync4(fd);
|
|
100663
101246
|
} finally {
|
|
100664
|
-
|
|
101247
|
+
closeSync16(fd);
|
|
100665
101248
|
}
|
|
100666
101249
|
this.assert();
|
|
100667
101250
|
this.sync();
|
|
100668
101251
|
}
|
|
100669
101252
|
sync() {
|
|
100670
101253
|
this.assert();
|
|
100671
|
-
const fd =
|
|
101254
|
+
const fd = openSync16(this.directory, constants15.O_RDONLY | constants15.O_NOFOLLOW);
|
|
100672
101255
|
try {
|
|
100673
|
-
|
|
101256
|
+
fsyncSync4(fd);
|
|
100674
101257
|
} finally {
|
|
100675
|
-
|
|
101258
|
+
closeSync16(fd);
|
|
100676
101259
|
}
|
|
100677
101260
|
}
|
|
100678
101261
|
saveState(state, expected) {
|
|
@@ -100690,20 +101273,20 @@ class RecoveryOwner {
|
|
|
100690
101273
|
this.assert();
|
|
100691
101274
|
let fd;
|
|
100692
101275
|
try {
|
|
100693
|
-
fd =
|
|
101276
|
+
fd = openSync16(join45(this.directory, "operation.lock"), constants15.O_WRONLY | constants15.O_CREAT | constants15.O_EXCL | constants15.O_NOFOLLOW, 384);
|
|
100694
101277
|
} catch {
|
|
100695
101278
|
throw new RecurringCustomerError("RECURRING_RECOVERY_BUSY", "Recovery is locked. Confirm the original process has stopped before explicitly reconciling the retained lock; no request was retried.");
|
|
100696
101279
|
}
|
|
100697
|
-
const owner2 =
|
|
101280
|
+
const owner2 = fstatSync16(fd);
|
|
100698
101281
|
try {
|
|
100699
101282
|
writeFileSync16(fd, JSON.stringify({ pid: process.pid }));
|
|
100700
|
-
|
|
101283
|
+
fsyncSync4(fd);
|
|
100701
101284
|
this.sync();
|
|
100702
101285
|
return await action();
|
|
100703
101286
|
} finally {
|
|
100704
|
-
|
|
101287
|
+
closeSync16(fd);
|
|
100705
101288
|
this.assert();
|
|
100706
|
-
const now3 =
|
|
101289
|
+
const now3 = lstatSync22(join45(this.directory, "operation.lock"));
|
|
100707
101290
|
if (owner2.dev !== now3.dev || owner2.ino !== now3.ino || !now3.isFile() || now3.isSymbolicLink())
|
|
100708
101291
|
invalid6();
|
|
100709
101292
|
unlinkSync6(join45(this.directory, "operation.lock"));
|
|
@@ -100739,7 +101322,7 @@ function base2(customer, organizationId) {
|
|
|
100739
101322
|
};
|
|
100740
101323
|
}
|
|
100741
101324
|
function create3(directory, intent) {
|
|
100742
|
-
if (!
|
|
101325
|
+
if (!isAbsolute16(directory) || resolve18(directory) !== directory || realpathSync8(dirname20(directory)) !== dirname20(directory))
|
|
100743
101326
|
invalid6();
|
|
100744
101327
|
mkdirSync17(directory, { mode: 448 });
|
|
100745
101328
|
const owner2 = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
|
|
@@ -100902,7 +101485,7 @@ var init_recurring_recovery = __esm(() => {
|
|
|
100902
101485
|
});
|
|
100903
101486
|
|
|
100904
101487
|
// src/lib/recurring-surface.ts
|
|
100905
|
-
import { isAbsolute as
|
|
101488
|
+
import { isAbsolute as isAbsolute17 } from "path";
|
|
100906
101489
|
function recurringMcpSchema(action) {
|
|
100907
101490
|
return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
|
|
100908
101491
|
}
|
|
@@ -101007,7 +101590,7 @@ var init_recurring_surface = __esm(() => {
|
|
|
101007
101590
|
uuid13 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
|
|
101008
101591
|
context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
|
|
101009
101592
|
page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
|
|
101010
|
-
directory = exports_external.string().max(4096).refine(
|
|
101593
|
+
directory = exports_external.string().max(4096).refine(isAbsolute17, "Use an absolute recovery directory");
|
|
101011
101594
|
email4 = exports_external.string().trim().toLowerCase().email().max(254);
|
|
101012
101595
|
code = exports_external.string().regex(/^\d{6}$/);
|
|
101013
101596
|
recurringSurfaceSchemas = {
|
|
@@ -101976,11 +102559,11 @@ var init_mcp_contracts = __esm(() => {
|
|
|
101976
102559
|
name: operation.name,
|
|
101977
102560
|
title: operation.title,
|
|
101978
102561
|
description: `${operation.title} on the configured server; unavailable capabilities fail explicitly.`,
|
|
101979
|
-
params: operation.parameter ? [operation.parameter] : [],
|
|
102562
|
+
params: operation.parameter ? [operation.parameter, ...operation.name === "create_credit_checkout" ? ["idempotency_key?"] : []] : [],
|
|
101980
102563
|
category: "execution",
|
|
101981
102564
|
sideEffects: operation.mutates ? "local-process-or-remote-run" : "none",
|
|
101982
102565
|
stable: true,
|
|
101983
|
-
inputSchema: objectSchema(operation.parameter ? { [operation.parameter]: stringSchema("Server resource identifier.") } : {}, operation.parameter ? [operation.parameter] : []),
|
|
102566
|
+
inputSchema: objectSchema(operation.parameter ? { [operation.parameter]: stringSchema("Server resource identifier."), ...operation.name === "create_credit_checkout" ? { idempotency_key: { type: "string", pattern: "^[A-Za-z0-9._:-]{8,255}$", description: "Caller-owned key retained before submission; reuse only for explicit recovery of the same server/account/pack." } } : {} } : {}, operation.parameter ? [operation.parameter] : []),
|
|
101984
102567
|
outputSchema: { oneOf: [objectSchema({}, [], "Server response.", true), { type: "array", items: objectSchema({}, [], "Server record.", true) }] }
|
|
101985
102568
|
}));
|
|
101986
102569
|
remoteCustomerContracts.push({
|
|
@@ -102913,14 +103496,14 @@ var init_operation_tools = __esm(() => {
|
|
|
102913
103496
|
|
|
102914
103497
|
// src/lib/feedback.ts
|
|
102915
103498
|
import { appendFileSync as appendFileSync2, existsSync as existsSync29, mkdirSync as mkdirSync18 } from "fs";
|
|
102916
|
-
import { dirname as
|
|
103499
|
+
import { dirname as dirname21, join as join47 } from "path";
|
|
102917
103500
|
import { Database } from "bun:sqlite";
|
|
102918
103501
|
function getFeedbackDbPath() {
|
|
102919
103502
|
return join47(getDataDir(), "skills.db");
|
|
102920
103503
|
}
|
|
102921
103504
|
function getFeedbackDb() {
|
|
102922
103505
|
const dbPath = getFeedbackDbPath();
|
|
102923
|
-
const dir =
|
|
103506
|
+
const dir = dirname21(dbPath);
|
|
102924
103507
|
if (!existsSync29(dir))
|
|
102925
103508
|
mkdirSync18(dir, { recursive: true });
|
|
102926
103509
|
const db = new Database(dbPath);
|
|
@@ -102949,7 +103532,7 @@ function saveFeedback(input2) {
|
|
|
102949
103532
|
const category = input2.category ?? "general";
|
|
102950
103533
|
if (isApiMode()) {
|
|
102951
103534
|
const path = join47(getDataDir(), "feedback.jsonl");
|
|
102952
|
-
const dir =
|
|
103535
|
+
const dir = dirname21(path);
|
|
102953
103536
|
if (!existsSync29(dir))
|
|
102954
103537
|
mkdirSync18(dir, { recursive: true });
|
|
102955
103538
|
appendFileSync2(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
|
|
@@ -103427,7 +104010,7 @@ var init_schedule_tools = __esm(() => {
|
|
|
103427
104010
|
});
|
|
103428
104011
|
|
|
103429
104012
|
// src/lib/native-storage.ts
|
|
103430
|
-
import { createHash as
|
|
104013
|
+
import { createHash as createHash21, createHmac as createHmac3 } from "crypto";
|
|
103431
104014
|
import {
|
|
103432
104015
|
existsSync as existsSync31,
|
|
103433
104016
|
mkdirSync as mkdirSync20,
|
|
@@ -103436,7 +104019,7 @@ import {
|
|
|
103436
104019
|
statSync as statSync17,
|
|
103437
104020
|
writeFileSync as writeFileSync18
|
|
103438
104021
|
} from "fs";
|
|
103439
|
-
import { dirname as
|
|
104022
|
+
import { dirname as dirname22, join as join49, normalize as normalize3, relative as relative7, sep as sep7 } from "path";
|
|
103440
104023
|
function resolveSkillsNativeStorageConfig(env3 = process.env) {
|
|
103441
104024
|
assertNoRetiredModeEnvVars(env3, {
|
|
103442
104025
|
app: SKILLS_ENV_NAMESPACE,
|
|
@@ -103504,7 +104087,7 @@ function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
|
|
|
103504
104087
|
files.push({
|
|
103505
104088
|
path: relativePath,
|
|
103506
104089
|
sizeBytes: bytes.byteLength,
|
|
103507
|
-
sha256:
|
|
104090
|
+
sha256: createHash21("sha256").update(bytes).digest("hex"),
|
|
103508
104091
|
...options.includeFileContents ? { contentBase64: Buffer.from(bytes).toString("base64") } : {}
|
|
103509
104092
|
});
|
|
103510
104093
|
}
|
|
@@ -103796,20 +104379,20 @@ var init_private_publication_customer = __esm(() => {
|
|
|
103796
104379
|
});
|
|
103797
104380
|
|
|
103798
104381
|
// src/lib/private-publication-recovery.ts
|
|
103799
|
-
import { constants as
|
|
103800
|
-
import { dirname as
|
|
104382
|
+
import { constants as constants16, closeSync as closeSync17, fsyncSync as fsyncSync5, fstatSync as fstatSync17, lstatSync as lstatSync23, mkdirSync as mkdirSync21, openSync as openSync17, readSync as readSync13, realpathSync as realpathSync9, renameSync as renameSync11, unlinkSync as unlinkSync7, writeFileSync as writeFileSync19 } from "fs";
|
|
104383
|
+
import { dirname as dirname23, isAbsolute as isAbsolute18, join as join50, resolve as resolve19 } from "path";
|
|
103801
104384
|
import { randomUUID as randomUUID8 } from "crypto";
|
|
103802
104385
|
function safeDirectory(directory2) {
|
|
103803
|
-
if (!
|
|
104386
|
+
if (!isAbsolute18(directory2) || directory2 !== resolve19(directory2) || realpathSync9(directory2) !== directory2)
|
|
103804
104387
|
return fail3();
|
|
103805
|
-
for (let path = directory2;; path =
|
|
103806
|
-
const stat3 =
|
|
104388
|
+
for (let path = directory2;; path = dirname23(path)) {
|
|
104389
|
+
const stat3 = lstatSync23(path);
|
|
103807
104390
|
if (!stat3.isDirectory() || stat3.isSymbolicLink())
|
|
103808
104391
|
return fail3();
|
|
103809
|
-
if (path ===
|
|
104392
|
+
if (path === dirname23(path))
|
|
103810
104393
|
break;
|
|
103811
104394
|
}
|
|
103812
|
-
const own2 =
|
|
104395
|
+
const own2 = lstatSync23(directory2);
|
|
103813
104396
|
if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
103814
104397
|
return fail3();
|
|
103815
104398
|
return { dev: own2.dev, ino: own2.ino };
|
|
@@ -103821,35 +104404,35 @@ function unchangedDirectory(directory2, identity4) {
|
|
|
103821
104404
|
}
|
|
103822
104405
|
function readOwned(directory2, name, max2) {
|
|
103823
104406
|
const identity4 = safeDirectory(directory2), file2 = join50(directory2, name);
|
|
103824
|
-
const fd =
|
|
104407
|
+
const fd = openSync17(file2, constants16.O_RDONLY | constants16.O_NOFOLLOW);
|
|
103825
104408
|
try {
|
|
103826
|
-
const stat3 =
|
|
104409
|
+
const stat3 = fstatSync17(fd);
|
|
103827
104410
|
if (!stat3.isFile() || stat3.nlink !== 1 || stat3.size > max2 || stat3.size < 1 || (stat3.mode & 63) !== 0 || process.getuid && stat3.uid !== process.getuid())
|
|
103828
104411
|
return fail3();
|
|
103829
104412
|
const buffer = Buffer.alloc(Math.min(max2, stat3.size) + 1);
|
|
103830
104413
|
let length = 0;
|
|
103831
104414
|
while (length < buffer.length) {
|
|
103832
|
-
const count =
|
|
104415
|
+
const count = readSync13(fd, buffer, length, buffer.length - length, length);
|
|
103833
104416
|
if (count === 0)
|
|
103834
104417
|
break;
|
|
103835
104418
|
length += count;
|
|
103836
104419
|
}
|
|
103837
|
-
const bytes = buffer.subarray(0, length), after2 =
|
|
104420
|
+
const bytes = buffer.subarray(0, length), after2 = fstatSync17(fd);
|
|
103838
104421
|
unchangedDirectory(directory2, identity4);
|
|
103839
104422
|
if (bytes.length !== stat3.size || stat3.size !== after2.size || stat3.mtimeMs !== after2.mtimeMs || stat3.ctimeMs !== after2.ctimeMs)
|
|
103840
104423
|
return fail3();
|
|
103841
104424
|
return bytes;
|
|
103842
104425
|
} finally {
|
|
103843
|
-
|
|
104426
|
+
closeSync17(fd);
|
|
103844
104427
|
}
|
|
103845
104428
|
}
|
|
103846
104429
|
function writeOwned(directory2, name, bytes) {
|
|
103847
|
-
const fd =
|
|
104430
|
+
const fd = openSync17(join50(directory2, name), constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
|
|
103848
104431
|
try {
|
|
103849
104432
|
writeFileSync19(fd, bytes);
|
|
103850
|
-
|
|
104433
|
+
fsyncSync5(fd);
|
|
103851
104434
|
} finally {
|
|
103852
|
-
|
|
104435
|
+
closeSync17(fd);
|
|
103853
104436
|
}
|
|
103854
104437
|
}
|
|
103855
104438
|
function save(directory2, value) {
|
|
@@ -103858,11 +104441,11 @@ function save(directory2, value) {
|
|
|
103858
104441
|
`);
|
|
103859
104442
|
unchangedDirectory(directory2, identity4);
|
|
103860
104443
|
renameSync11(join50(directory2, temporary), join50(directory2, "receipt.json"));
|
|
103861
|
-
const fd =
|
|
104444
|
+
const fd = openSync17(directory2, constants16.O_RDONLY | constants16.O_NOFOLLOW);
|
|
103862
104445
|
try {
|
|
103863
|
-
|
|
104446
|
+
fsyncSync5(fd);
|
|
103864
104447
|
} finally {
|
|
103865
|
-
|
|
104448
|
+
closeSync17(fd);
|
|
103866
104449
|
}
|
|
103867
104450
|
}
|
|
103868
104451
|
function bind2(client2, receipt) {
|
|
@@ -103873,20 +104456,20 @@ async function locked(directory2, action) {
|
|
|
103873
104456
|
const identity4 = safeDirectory(directory2), file2 = join50(directory2, "operation.lock");
|
|
103874
104457
|
let fd;
|
|
103875
104458
|
try {
|
|
103876
|
-
fd =
|
|
104459
|
+
fd = openSync17(file2, constants16.O_WRONLY | constants16.O_CREAT | constants16.O_EXCL | constants16.O_NOFOLLOW, 384);
|
|
103877
104460
|
} catch {
|
|
103878
104461
|
throw new PrivatePublicationError("PUBLICATION_RECOVERY_BUSY", "Another operation holds this recovery directory. If it crashed, confirm that process has stopped before explicitly removing operation.lock and resuming.");
|
|
103879
104462
|
}
|
|
103880
|
-
const lock =
|
|
104463
|
+
const lock = fstatSync17(fd);
|
|
103881
104464
|
try {
|
|
103882
104465
|
writeFileSync19(fd, JSON.stringify({ pid: process.pid }) + `
|
|
103883
104466
|
`);
|
|
103884
|
-
|
|
104467
|
+
fsyncSync5(fd);
|
|
103885
104468
|
return await action();
|
|
103886
104469
|
} finally {
|
|
103887
|
-
|
|
104470
|
+
closeSync17(fd);
|
|
103888
104471
|
unchangedDirectory(directory2, identity4);
|
|
103889
|
-
const now3 =
|
|
104472
|
+
const now3 = lstatSync23(file2);
|
|
103890
104473
|
if (now3.dev !== lock.dev || now3.ino !== lock.ino || !now3.isFile() || now3.isSymbolicLink())
|
|
103891
104474
|
fail3();
|
|
103892
104475
|
unlinkSync7(file2);
|
|
@@ -103938,15 +104521,15 @@ async function preparePrivatePublication(client2, sourceDirectory, recoveryDirec
|
|
|
103938
104521
|
phase: "prepared",
|
|
103939
104522
|
intent: null
|
|
103940
104523
|
};
|
|
103941
|
-
if (!
|
|
104524
|
+
if (!isAbsolute18(recoveryDirectory) || resolve19(recoveryDirectory) !== recoveryDirectory || realpathSync9(dirname23(recoveryDirectory)) !== dirname23(recoveryDirectory))
|
|
103942
104525
|
return fail3();
|
|
103943
104526
|
mkdirSync21(recoveryDirectory, { mode: 448 });
|
|
103944
104527
|
safeDirectory(recoveryDirectory);
|
|
103945
|
-
const parent =
|
|
104528
|
+
const parent = openSync17(dirname23(recoveryDirectory), constants16.O_RDONLY | constants16.O_NOFOLLOW);
|
|
103946
104529
|
try {
|
|
103947
|
-
|
|
104530
|
+
fsyncSync5(parent);
|
|
103948
104531
|
} finally {
|
|
103949
|
-
|
|
104532
|
+
closeSync17(parent);
|
|
103950
104533
|
}
|
|
103951
104534
|
writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
|
|
103952
104535
|
save(recoveryDirectory, receipt);
|
|
@@ -104039,10 +104622,10 @@ var init_private_publication_recovery = __esm(() => {
|
|
|
104039
104622
|
});
|
|
104040
104623
|
|
|
104041
104624
|
// src/mcp/private-publication-tools.ts
|
|
104042
|
-
import { isAbsolute as
|
|
104625
|
+
import { isAbsolute as isAbsolute19 } from "path";
|
|
104043
104626
|
function registerPrivatePublicationTools(server) {
|
|
104044
104627
|
const uuid9 = exports_external.string().regex(/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/);
|
|
104045
|
-
const directory2 = exports_external.string().max(4096).refine(
|
|
104628
|
+
const directory2 = exports_external.string().max(4096).refine(isAbsolute19, "Use an absolute local directory");
|
|
104046
104629
|
const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
|
|
104047
104630
|
const description = "Manage a private source publication using fresh workspace-bound verification and a host-local recovery directory. Publishing requires explicit UUID current-version comparison and upload consent. Resume reuses immutable saved bytes and intent; an uncertain PUT is finalized for server verification, never uploaded twice. Sessions and signed URLs are not returned or persisted. Private execution is unavailable. Host request history may contain the supplied verification code.";
|
|
104048
104631
|
const handler = (action) => async (value) => {
|
|
@@ -104197,6 +104780,14 @@ function registerRemoteCustomerTools(server) {
|
|
|
104197
104780
|
});
|
|
104198
104781
|
}
|
|
104199
104782
|
for (const operation of REMOTE_CUSTOMER_OPERATIONS) {
|
|
104783
|
+
if (operation.name === "create_credit_checkout") {
|
|
104784
|
+
server.registerTool(operation.name, {
|
|
104785
|
+
title: operation.title,
|
|
104786
|
+
description: "Create one external checkout link on the selected Skills server. Retain an idempotency_key before calling and reuse it only for explicit recovery on the same server, account and pack. No automatic retries; payment requires customer confirmation.",
|
|
104787
|
+
inputSchema: { pack_id: exports_external.string().min(1), idempotency_key: exports_external.string().regex(/^[A-Za-z0-9._:-]{8,255}$/).optional() }
|
|
104788
|
+
}, ({ pack_id, idempotency_key }) => callRemote((client2) => operation.invoke(client2, pack_id, { idempotencyKey: idempotency_key })));
|
|
104789
|
+
continue;
|
|
104790
|
+
}
|
|
104200
104791
|
const inputSchema = {};
|
|
104201
104792
|
if (operation.parameter)
|
|
104202
104793
|
inputSchema[operation.parameter] = exports_external.string().min(1);
|
|
@@ -104273,6 +104864,15 @@ async function callRemote(action) {
|
|
|
104273
104864
|
return mcpError("AUTH_REQUIRED", "Configure a Skills API and sign in with skills auth login");
|
|
104274
104865
|
return mcpJson(await action(client2));
|
|
104275
104866
|
} catch (error61) {
|
|
104867
|
+
if (error61 instanceof RemoteCreditCheckoutError) {
|
|
104868
|
+
return { ...mcpJson({
|
|
104869
|
+
code: error61.code,
|
|
104870
|
+
message: error61.message,
|
|
104871
|
+
status: error61.status,
|
|
104872
|
+
requestIdempotencyKey: error61.requestIdempotencyKey,
|
|
104873
|
+
...error61.retryAfterSeconds === undefined ? {} : { retryAfterSeconds: error61.retryAfterSeconds }
|
|
104874
|
+
}), isError: true };
|
|
104875
|
+
}
|
|
104276
104876
|
if (error61 instanceof RemoteCapabilityUnavailableError) {
|
|
104277
104877
|
return { ...mcpJson({ code: error61.code, message: error61.message, status: error61.status }), isError: true };
|
|
104278
104878
|
}
|
|
@@ -104385,7 +104985,7 @@ var init_mcp2 = __esm(() => {
|
|
|
104385
104985
|
// src/cli/commands/runtime-mcp.ts
|
|
104386
104986
|
import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as readFileSync34, writeFileSync as writeFileSync20 } from "fs";
|
|
104387
104987
|
import { homedir as homedir9 } from "os";
|
|
104388
|
-
import { dirname as
|
|
104988
|
+
import { dirname as dirname24, join as join51 } from "path";
|
|
104389
104989
|
async function handleMcp(options) {
|
|
104390
104990
|
if (options.register) {
|
|
104391
104991
|
let agents;
|
|
@@ -104559,7 +105159,7 @@ function writeJsonObject(path, data) {
|
|
|
104559
105159
|
`);
|
|
104560
105160
|
}
|
|
104561
105161
|
function writeTextFile(path, content) {
|
|
104562
|
-
mkdirSync22(
|
|
105162
|
+
mkdirSync22(dirname24(path), { recursive: true });
|
|
104563
105163
|
writeFileSync20(path, content.endsWith(`
|
|
104564
105164
|
`) ? content : `${content}
|
|
104565
105165
|
`);
|
|
@@ -104622,7 +105222,7 @@ function registerRemoteAccount(parent) {
|
|
|
104622
105222
|
billing.command("portal").option("--json", "Output as JSON", false).description("Create an external customer billing portal link").action((options) => execute(options, (client2) => client2.createBillingPortal()));
|
|
104623
105223
|
const credits = parent.command("credits").description("Inspect and purchase credits from the configured server");
|
|
104624
105224
|
credits.command("packs").option("--json", "Output as JSON", false).action((options) => execute(options, (client2) => client2.listCreditPacks()));
|
|
104625
|
-
credits.command("buy").argument("<pack-id>", "An ID returned by credits packs").option("--json", "Output as JSON", false).description("Create an external checkout link; payment is confirmed in the browser").action((packId, options) => execute(options, (client2) => client2.createCreditCheckout(packId)));
|
|
105225
|
+
credits.command("buy").argument("<pack-id>", "An ID returned by credits packs").option("--json", "Output as JSON", false).option("--idempotency-key <key>", "Retain and reuse this request key for explicit checkout recovery").description("Create an external checkout link; payment is confirmed in the browser. No automatic retries.").action((packId, options) => execute(options, (client2) => client2.createCreditCheckout(packId, { idempotencyKey: options.idempotencyKey })));
|
|
104626
105226
|
}
|
|
104627
105227
|
async function execute(options, action) {
|
|
104628
105228
|
try {
|
|
@@ -104633,6 +105233,23 @@ async function execute(options, action) {
|
|
|
104633
105233
|
console.log(JSON.stringify(result2, null, 2));
|
|
104634
105234
|
} catch (error61) {
|
|
104635
105235
|
const message = error61 instanceof Error ? error61.message : "The Skills server request failed";
|
|
105236
|
+
if (error61 instanceof RemoteCreditCheckoutError) {
|
|
105237
|
+
const result2 = {
|
|
105238
|
+
error: error61.message,
|
|
105239
|
+
code: error61.code,
|
|
105240
|
+
status: error61.status,
|
|
105241
|
+
requestIdempotencyKey: error61.requestIdempotencyKey,
|
|
105242
|
+
...error61.retryAfterSeconds === undefined ? {} : { retryAfterSeconds: error61.retryAfterSeconds }
|
|
105243
|
+
};
|
|
105244
|
+
if (options.json)
|
|
105245
|
+
console.log(JSON.stringify(result2));
|
|
105246
|
+
else
|
|
105247
|
+
console.error(`${error61.message}
|
|
105248
|
+
Request key: ${error61.requestIdempotencyKey}` + (error61.code === "CREDIT_CHECKOUT_UNCONFIRMED" || error61.code === "CREDIT_CHECKOUT_IN_PROGRESS" ? `
|
|
105249
|
+
For explicit recovery, pass this key with --idempotency-key. Keep the same server, account and pack.` : ""));
|
|
105250
|
+
process.exitCode = 1;
|
|
105251
|
+
return;
|
|
105252
|
+
}
|
|
104636
105253
|
if (options.json)
|
|
104637
105254
|
console.log(JSON.stringify({
|
|
104638
105255
|
error: message,
|
|
@@ -104652,9 +105269,9 @@ var exports_runtime = {};
|
|
|
104652
105269
|
__export(exports_runtime, {
|
|
104653
105270
|
registerRuntime: () => registerRuntime
|
|
104654
105271
|
});
|
|
104655
|
-
import { createHash as
|
|
104656
|
-
import { lstatSync as
|
|
104657
|
-
import { basename as
|
|
105272
|
+
import { createHash as createHash22, randomUUID as randomUUID9 } from "crypto";
|
|
105273
|
+
import { lstatSync as lstatSync24, mkdirSync as mkdirSync23, readFileSync as readFileSync35, realpathSync as realpathSync10, writeFileSync as writeFileSync21 } from "fs";
|
|
105274
|
+
import { basename as basename9, isAbsolute as isAbsolute20, join as join52 } from "path";
|
|
104658
105275
|
import { createInterface } from "readline";
|
|
104659
105276
|
function registerRuntime(parent) {
|
|
104660
105277
|
parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill; use -- to end Skills options").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("--remote", "Run on the configured server, using its catalog and quote", false).option("--target <target>", "Execution target: local or cloud").option("--secret-bindings <path>", "Reviewed, exact-selection local execution vault bindings (JSON file)").option("--secret-bindings-template", "Print a scoped bindings template without resolving secrets or running the skill", false).option("--input <json>", "Structured cloud execution input").option("--skill-version <version>", "Exact selected skill version").option("--selection-profile <id>", "Selected Skills profile").option("--session <id>", "Pinned Skills session").option("--cached", "Use the explicit verified selected cache", false).option("--yes", "Approve the server's quoted credit cost for this run", false).option("--idempotency-key <key>", "Reuse this key when retrying the same remote submission").option("--file <path>", "Attach a local input file to a remote run (repeatable)", (value, prior) => [...prior, value], []).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options, command) => {
|
|
@@ -104684,7 +105301,7 @@ function registerRuntime(parent) {
|
|
|
104684
105301
|
if (!expected)
|
|
104685
105302
|
throw new Error("Cloud artifact not found");
|
|
104686
105303
|
const bytes = await client2.download(id2, name);
|
|
104687
|
-
if (bytes.length !== expected.byteSize ||
|
|
105304
|
+
if (bytes.length !== expected.byteSize || createHash22("sha256").update(bytes).digest("hex") !== expected.sha256)
|
|
104688
105305
|
throw new Error("Cloud artifact integrity verification failed");
|
|
104689
105306
|
writeFileSync21(options.output, bytes, { flag: "wx", mode: 384 });
|
|
104690
105307
|
console.log(JSON.stringify({ path: options.output, sha256: expected.sha256, byteSize: bytes.length }));
|
|
@@ -104772,7 +105389,7 @@ Updating ${name}...
|
|
|
104772
105389
|
async function readUpdatedVersion(bunExecutable) {
|
|
104773
105390
|
const output2 = await readUpdateCommand([bunExecutable, "pm", "bin", "-g"]);
|
|
104774
105391
|
const globalBin = output2.replace(/\r?\n$/, "");
|
|
104775
|
-
if (!globalBin || !
|
|
105392
|
+
if (!globalBin || !isAbsolute20(globalBin) || /[\r\n\0]/.test(globalBin))
|
|
104776
105393
|
throw new Error("Update bin discovery failed");
|
|
104777
105394
|
const installed = Bun.which("skills", { PATH: globalBin, cwd: globalBin });
|
|
104778
105395
|
const selected = Bun.which("skills");
|
|
@@ -104908,14 +105525,14 @@ function requireHttpUrl(value) {
|
|
|
104908
105525
|
}
|
|
104909
105526
|
function promptLine(question) {
|
|
104910
105527
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
104911
|
-
return new Promise((
|
|
105528
|
+
return new Promise((resolve20) => {
|
|
104912
105529
|
let settled = false;
|
|
104913
105530
|
const finish = (answer) => {
|
|
104914
105531
|
if (settled)
|
|
104915
105532
|
return;
|
|
104916
105533
|
settled = true;
|
|
104917
105534
|
rl.close();
|
|
104918
|
-
|
|
105535
|
+
resolve20(answer);
|
|
104919
105536
|
};
|
|
104920
105537
|
rl.once("SIGINT", () => finish(null));
|
|
104921
105538
|
rl.once("close", () => finish(null));
|
|
@@ -105092,10 +105709,10 @@ async function handleRun(name, args2, options, separatorBeforeSkill) {
|
|
|
105092
105709
|
try {
|
|
105093
105710
|
parsePollingOptions(options);
|
|
105094
105711
|
inputFiles = (options.file ?? []).map((path) => {
|
|
105095
|
-
const info =
|
|
105712
|
+
const info = lstatSync24(path);
|
|
105096
105713
|
if (!info.isFile() || info.size > 20 * 1024 * 1024)
|
|
105097
105714
|
throw new Error("Input must be a regular file no larger than 20 MiB");
|
|
105098
|
-
return { name:
|
|
105715
|
+
return { name: basename9(path), bytes: new Uint8Array(readFileSync35(path)) };
|
|
105099
105716
|
});
|
|
105100
105717
|
describeRemoteFiles(inputFiles);
|
|
105101
105718
|
client2 = new RemoteSkillsClient(routing.apiKey, routing.apiOrigin);
|
|
@@ -105522,7 +106139,7 @@ function ensureSafeExportParent(root2, relativePath) {
|
|
|
105522
106139
|
if (part)
|
|
105523
106140
|
parent = join52(parent, part);
|
|
105524
106141
|
try {
|
|
105525
|
-
if (!
|
|
106142
|
+
if (!lstatSync24(parent).isDirectory() || lstatSync24(parent).isSymbolicLink())
|
|
105526
106143
|
throw new Error("Unsafe artifact directory");
|
|
105527
106144
|
} catch (error61) {
|
|
105528
106145
|
if (error61.code !== "ENOENT")
|
|
@@ -105560,7 +106177,7 @@ async function pollRemoteRun(client2, runId2, options) {
|
|
|
105560
106177
|
const remaining = deadline - Date.now();
|
|
105561
106178
|
if (remaining <= 0)
|
|
105562
106179
|
break;
|
|
105563
|
-
await new Promise((
|
|
106180
|
+
await new Promise((resolve20) => setTimeout(resolve20, Math.min(options.intervalMs, remaining)));
|
|
105564
106181
|
}
|
|
105565
106182
|
return {
|
|
105566
106183
|
run: current ?? { id: runId2, status: "queued" },
|
|
@@ -105752,7 +106369,7 @@ async function readCode() {
|
|
|
105752
106369
|
function promptCode() {
|
|
105753
106370
|
const { stdin, stderr: output2 } = process;
|
|
105754
106371
|
const { isRaw: wasRaw, readableFlowing: wasFlowing } = stdin;
|
|
105755
|
-
return new Promise((
|
|
106372
|
+
return new Promise((resolve20) => {
|
|
105756
106373
|
let value = "", settled = false;
|
|
105757
106374
|
const finish = (answer) => {
|
|
105758
106375
|
if (settled)
|
|
@@ -105769,7 +106386,7 @@ function promptCode() {
|
|
|
105769
106386
|
`);
|
|
105770
106387
|
if (answer === null)
|
|
105771
106388
|
process.exitCode = 130;
|
|
105772
|
-
|
|
106389
|
+
resolve20(answer);
|
|
105773
106390
|
};
|
|
105774
106391
|
const cancel = () => finish(null);
|
|
105775
106392
|
const keypress = (text3, key) => {
|
|
@@ -105814,37 +106431,37 @@ var exports_recurring = {};
|
|
|
105814
106431
|
__export(exports_recurring, {
|
|
105815
106432
|
registerRecurringCommands: () => registerRecurringCommands
|
|
105816
106433
|
});
|
|
105817
|
-
import { constants as
|
|
106434
|
+
import { constants as constants17, closeSync as closeSync18, fstatSync as fstatSync18, lstatSync as lstatSync25, openSync as openSync18, readSync as readSync14 } from "fs";
|
|
105818
106435
|
import { createInterface as createInterface2 } from "readline";
|
|
105819
106436
|
function readRequest(path) {
|
|
105820
|
-
const fd =
|
|
106437
|
+
const fd = openSync18(path, constants17.O_RDONLY | constants17.O_NOFOLLOW | constants17.O_NONBLOCK);
|
|
105821
106438
|
try {
|
|
105822
|
-
const before2 =
|
|
106439
|
+
const before2 = fstatSync18(fd);
|
|
105823
106440
|
if (!before2.isFile() || before2.size > 1048576 || before2.size < 1)
|
|
105824
106441
|
throw new RecurringInputError;
|
|
105825
106442
|
const bytes = Buffer.alloc(before2.size + 1);
|
|
105826
106443
|
let length = 0;
|
|
105827
106444
|
while (length < bytes.length) {
|
|
105828
|
-
const n2 =
|
|
106445
|
+
const n2 = readSync14(fd, bytes, length, bytes.length - length, length);
|
|
105829
106446
|
if (!n2)
|
|
105830
106447
|
break;
|
|
105831
106448
|
length += n2;
|
|
105832
106449
|
}
|
|
105833
|
-
const after2 =
|
|
106450
|
+
const after2 = fstatSync18(fd), current = lstatSync25(path);
|
|
105834
106451
|
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())
|
|
105835
106452
|
throw new RecurringInputError;
|
|
105836
106453
|
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, length)));
|
|
105837
106454
|
} catch {
|
|
105838
106455
|
throw new RecurringInputError;
|
|
105839
106456
|
} finally {
|
|
105840
|
-
|
|
106457
|
+
closeSync18(fd);
|
|
105841
106458
|
}
|
|
105842
106459
|
}
|
|
105843
106460
|
async function acceptAtTerminal(draft) {
|
|
105844
|
-
await new Promise((
|
|
106461
|
+
await new Promise((resolve20, reject2) => process.stderr.write(`${jsonText(draft)}
|
|
105845
106462
|
This grants an additional recurring budget. Each occurrence reprices within the approved ceilings. Revocation prevents new authority; an already-authorized attempt may finish, and cancellation is separate.
|
|
105846
|
-
`, (error61) => error61 ? reject2(error61) :
|
|
105847
|
-
return new Promise((
|
|
106463
|
+
`, (error61) => error61 ? reject2(error61) : resolve20()));
|
|
106464
|
+
return new Promise((resolve20) => {
|
|
105848
106465
|
const rl = createInterface2({ input: process.stdin, output: process.stderr });
|
|
105849
106466
|
let settled = false;
|
|
105850
106467
|
const finish = (accepted) => {
|
|
@@ -105855,7 +106472,7 @@ This grants an additional recurring budget. Each occurrence reprices within the
|
|
|
105855
106472
|
rl.close();
|
|
105856
106473
|
if (!accepted)
|
|
105857
106474
|
process.exitCode = 130;
|
|
105858
|
-
|
|
106475
|
+
resolve20(accepted);
|
|
105859
106476
|
};
|
|
105860
106477
|
const timer = setTimeout(() => finish(false), 5 * 60 * 1000);
|
|
105861
106478
|
rl.once("SIGINT", () => finish(false));
|
|
@@ -106263,7 +106880,7 @@ var init_portable_snapshot_filter = __esm(() => {
|
|
|
106263
106880
|
});
|
|
106264
106881
|
|
|
106265
106882
|
// src/lib/station-snapshot.ts
|
|
106266
|
-
import { createHash as
|
|
106883
|
+
import { createHash as createHash23 } from "crypto";
|
|
106267
106884
|
import {
|
|
106268
106885
|
copyFileSync,
|
|
106269
106886
|
mkdirSync as mkdirSync24,
|
|
@@ -106271,14 +106888,14 @@ import {
|
|
|
106271
106888
|
statSync as statSync19,
|
|
106272
106889
|
writeFileSync as writeFileSync22
|
|
106273
106890
|
} from "fs";
|
|
106274
|
-
import { dirname as
|
|
106891
|
+
import { dirname as dirname26, isAbsolute as isAbsolute21, relative as relative8, resolve as resolve20, sep as sep9 } from "path";
|
|
106275
106892
|
function validateStationId(stationId) {
|
|
106276
106893
|
if (!/^[a-z0-9-]+$/.test(stationId)) {
|
|
106277
106894
|
throw new StationSnapshotError("INVALID_STATION", `station id must be a slug, got: ${stationId}`);
|
|
106278
106895
|
}
|
|
106279
106896
|
}
|
|
106280
106897
|
function sha256File(filePath) {
|
|
106281
|
-
return
|
|
106898
|
+
return createHash23("sha256").update(readFileSync36(filePath)).digest("hex");
|
|
106282
106899
|
}
|
|
106283
106900
|
function scanHome(definition, homesRoot) {
|
|
106284
106901
|
const homePath = homePathFor(definition, homesRoot);
|
|
@@ -106349,7 +106966,7 @@ function humanHomes(scanned) {
|
|
|
106349
106966
|
}));
|
|
106350
106967
|
}
|
|
106351
106968
|
function writeStationSnapshot(options) {
|
|
106352
|
-
const repoRoot =
|
|
106969
|
+
const repoRoot = resolve20(options.repoRoot ?? process.cwd());
|
|
106353
106970
|
const { scanned, plans, totalBytes } = planStationSnapshot(options);
|
|
106354
106971
|
const manifestFiles = plans.map((plan) => ({
|
|
106355
106972
|
relativePath: plan.source.relativePath,
|
|
@@ -106375,9 +106992,9 @@ function writeStationSnapshot(options) {
|
|
|
106375
106992
|
const conflicts = [];
|
|
106376
106993
|
const untouched = [];
|
|
106377
106994
|
for (const plan of plans) {
|
|
106378
|
-
const destination =
|
|
106995
|
+
const destination = resolve20(repoRoot, plan.destination);
|
|
106379
106996
|
const destinationRelative = relative8(repoRoot, destination);
|
|
106380
|
-
if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep9) ||
|
|
106997
|
+
if (destinationRelative.startsWith("..") || destinationRelative.startsWith(sep9) || isAbsolute21(destinationRelative)) {
|
|
106381
106998
|
throw new StationSnapshotError("DESTINATION_ESCAPE", `destination escapes repo root: ${plan.destination}`);
|
|
106382
106999
|
}
|
|
106383
107000
|
let existingDigest = null;
|
|
@@ -106398,8 +107015,8 @@ function writeStationSnapshot(options) {
|
|
|
106398
107015
|
}
|
|
106399
107016
|
let written = 0;
|
|
106400
107017
|
for (const plan of untouched) {
|
|
106401
|
-
const destination =
|
|
106402
|
-
mkdirSync24(
|
|
107018
|
+
const destination = resolve20(repoRoot, plan.destination);
|
|
107019
|
+
mkdirSync24(dirname26(destination), { recursive: true });
|
|
106403
107020
|
copyFileSync(plan.source.fullPath, destination);
|
|
106404
107021
|
written += 1;
|
|
106405
107022
|
}
|
|
@@ -106417,8 +107034,8 @@ function writeStationSnapshot(options) {
|
|
|
106417
107034
|
},
|
|
106418
107035
|
files: manifestFiles
|
|
106419
107036
|
};
|
|
106420
|
-
const manifestPath =
|
|
106421
|
-
mkdirSync24(
|
|
107037
|
+
const manifestPath = resolve20(repoRoot, "resources", options.stationId, "skills", "sync-manifest.json");
|
|
107038
|
+
mkdirSync24(dirname26(manifestPath), { recursive: true });
|
|
106422
107039
|
writeFileSync22(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
106423
107040
|
`);
|
|
106424
107041
|
return {
|
|
@@ -106852,10 +107469,10 @@ var init_create_sync_config = __esm(() => {
|
|
|
106852
107469
|
// src/lib/codex-hook-rpc.ts
|
|
106853
107470
|
import { execFile, spawn as spawn3 } from "child_process";
|
|
106854
107471
|
import { realpathSync as realpathSync11, statSync as statSync20 } from "fs";
|
|
106855
|
-
import { isAbsolute as
|
|
107472
|
+
import { isAbsolute as isAbsolute22 } from "path";
|
|
106856
107473
|
import { promisify } from "util";
|
|
106857
107474
|
async function connectCodexHookRpc(options) {
|
|
106858
|
-
const found =
|
|
107475
|
+
const found = isAbsolute22(options.command) ? options.command : Bun.which(options.command, { PATH: process.env.PATH });
|
|
106859
107476
|
if (!found)
|
|
106860
107477
|
throw new Error("CODEX_HOOK_TRUST_NATIVE_UNAVAILABLE: install Codex or pass --codex-command");
|
|
106861
107478
|
const binary = realpathSync11(found), stat3 = statSync20(binary);
|
|
@@ -106941,13 +107558,13 @@ async function connectCodexHookRpc(options) {
|
|
|
106941
107558
|
request(method2, params) {
|
|
106942
107559
|
if (stopped)
|
|
106943
107560
|
return Promise.reject(new Error("CODEX_HOOK_TRUST_NATIVE_RPC_CLOSED"));
|
|
106944
|
-
return new Promise((
|
|
107561
|
+
return new Promise((resolve21, reject2) => {
|
|
106945
107562
|
const id2 = nextId++;
|
|
106946
107563
|
const timer = setTimeout(() => {
|
|
106947
107564
|
fail4();
|
|
106948
107565
|
child.kill();
|
|
106949
107566
|
}, 20000);
|
|
106950
|
-
pending.set(id2, { resolve:
|
|
107567
|
+
pending.set(id2, { resolve: resolve21, reject: reject2, timer });
|
|
106951
107568
|
child.stdin.write(JSON.stringify({ id: id2, method: method2, params }) + `
|
|
106952
107569
|
`);
|
|
106953
107570
|
});
|
|
@@ -106957,14 +107574,14 @@ async function connectCodexHookRpc(options) {
|
|
|
106957
107574
|
child.stdin.end();
|
|
106958
107575
|
if (child.exitCode !== null || child.signalCode !== null)
|
|
106959
107576
|
return;
|
|
106960
|
-
await new Promise((
|
|
107577
|
+
await new Promise((resolve21) => {
|
|
106961
107578
|
const timer = setTimeout(() => {
|
|
106962
107579
|
child.kill();
|
|
106963
|
-
|
|
107580
|
+
resolve21();
|
|
106964
107581
|
}, 1000);
|
|
106965
107582
|
child.once("exit", () => {
|
|
106966
107583
|
clearTimeout(timer);
|
|
106967
|
-
|
|
107584
|
+
resolve21();
|
|
106968
107585
|
});
|
|
106969
107586
|
});
|
|
106970
107587
|
}
|
|
@@ -106985,7 +107602,7 @@ var init_codex_hook_rpc = __esm(() => {
|
|
|
106985
107602
|
});
|
|
106986
107603
|
|
|
106987
107604
|
// src/lib/codex-hook-trust-layout.ts
|
|
106988
|
-
import { isDeepStrictEqual as
|
|
107605
|
+
import { isDeepStrictEqual as isDeepStrictEqual5 } from "util";
|
|
106989
107606
|
function codexTrustTextWitness(text3, keys3) {
|
|
106990
107607
|
const parsed = Bun.TOML.parse(text3), wanted = new Set(keys3);
|
|
106991
107608
|
const headers = [...text3.matchAll(/^[ \t]*(\[[^\r\n]+\])[ \t]*(#[^\r\n]*)?(?:\r?\n|$)/gm)];
|
|
@@ -107032,11 +107649,11 @@ function codexTrustTextWitness(text3, keys3) {
|
|
|
107032
107649
|
comments.push(line);
|
|
107033
107650
|
continue;
|
|
107034
107651
|
}
|
|
107035
|
-
const
|
|
107036
|
-
if (!
|
|
107652
|
+
const field2 = /^[ \t]*(?:enabled|trusted_hash)[ \t]*=[ \t]*(?:true|false|"(?:[^"\\]|\\.)*"|'[^']*')[ \t]*(#[^\r\n]*)?$/.exec(line);
|
|
107653
|
+
if (!field2)
|
|
107037
107654
|
throw fail4();
|
|
107038
|
-
if (
|
|
107039
|
-
comments.push(
|
|
107655
|
+
if (field2[1])
|
|
107656
|
+
comments.push(field2[1]);
|
|
107040
107657
|
}
|
|
107041
107658
|
replacements2.push({ start, end, comments: comments.join(`
|
|
107042
107659
|
`) + `
|
|
@@ -107050,7 +107667,7 @@ function codexTrustTextWitness(text3, keys3) {
|
|
|
107050
107667
|
if (expected.hooks)
|
|
107051
107668
|
delete expected.hooks.state;
|
|
107052
107669
|
try {
|
|
107053
|
-
if (!
|
|
107670
|
+
if (!isDeepStrictEqual5(prune(Bun.TOML.parse(noState)), prune(expected)))
|
|
107054
107671
|
throw fail4();
|
|
107055
107672
|
} catch {
|
|
107056
107673
|
throw fail4();
|
|
@@ -107071,59 +107688,59 @@ var fail4 = () => new Error('CODEX_HOOK_TRUST_UNSUPPORTED_LAYOUT: preserve and c
|
|
|
107071
107688
|
var init_codex_hook_trust_layout = () => {};
|
|
107072
107689
|
|
|
107073
107690
|
// src/lib/codex-hook-trust-files.ts
|
|
107074
|
-
import { closeSync as
|
|
107075
|
-
import { createHash as
|
|
107076
|
-
import { dirname as
|
|
107077
|
-
function
|
|
107691
|
+
import { closeSync as closeSync19, constants as constants18, fstatSync as fstatSync19, fsyncSync as fsyncSync6, lstatSync as lstatSync26, openSync as openSync19, readSync as readSync15, writeFileSync as writeFileSync23 } from "fs";
|
|
107692
|
+
import { createHash as createHash24 } from "crypto";
|
|
107693
|
+
import { dirname as dirname27 } from "path";
|
|
107694
|
+
function need3(value, code2) {
|
|
107078
107695
|
if (!value)
|
|
107079
107696
|
throw new Error(`CODEX_HOOK_TRUST_${code2}`);
|
|
107080
107697
|
}
|
|
107081
107698
|
function safeParents(file2) {
|
|
107082
|
-
for (let p =
|
|
107083
|
-
const s =
|
|
107084
|
-
|
|
107085
|
-
|
|
107086
|
-
if (
|
|
107699
|
+
for (let p = dirname27(file2);; p = dirname27(p)) {
|
|
107700
|
+
const s = lstatSync26(p);
|
|
107701
|
+
need3(s.isDirectory() && !s.isSymbolicLink(), "UNSAFE_PARENT");
|
|
107702
|
+
need3((s.mode & 18) === 0 || s.uid === 0 && (s.mode & 512) !== 0, "UNSAFE_PARENT");
|
|
107703
|
+
if (dirname27(p) === p)
|
|
107087
107704
|
break;
|
|
107088
107705
|
}
|
|
107089
107706
|
}
|
|
107090
107707
|
function snapshot(file2, privateFile = false, options = {}) {
|
|
107091
107708
|
const readOnlyPackage = options.readOnlyPackage === true && !privateFile;
|
|
107092
107709
|
safeParents(file2);
|
|
107093
|
-
const initial2 =
|
|
107094
|
-
|
|
107095
|
-
|
|
107096
|
-
const fd =
|
|
107710
|
+
const initial2 = lstatSync26(file2, { bigint: true });
|
|
107711
|
+
need3(initial2.isFile() && initial2.uid === BigInt(process.getuid()) && (initial2.nlink === 1n || readOnlyPackage && initial2.nlink > 1n) && (initial2.mode & 0o022n) === 0n && (!privateFile || (initial2.mode & 0o777n) === 0o600n), "UNSAFE_FILE");
|
|
107712
|
+
need3(initial2.size <= 8n * 1024n * 1024n, "FILE_BOUND");
|
|
107713
|
+
const fd = openSync19(file2, constants18.O_RDONLY | constants18.O_NOFOLLOW | constants18.O_NONBLOCK);
|
|
107097
107714
|
try {
|
|
107098
|
-
const before2 =
|
|
107099
|
-
|
|
107715
|
+
const before2 = fstatSync19(fd, { bigint: true });
|
|
107716
|
+
need3(sameStat(initial2, before2), "INPUT_CHANGED");
|
|
107100
107717
|
const bytes = Buffer.alloc(Number(before2.size) + 1);
|
|
107101
107718
|
let length = 0;
|
|
107102
107719
|
while (length < bytes.length) {
|
|
107103
|
-
const n2 =
|
|
107720
|
+
const n2 = readSync15(fd, bytes, length, bytes.length - length, null);
|
|
107104
107721
|
if (!n2)
|
|
107105
107722
|
break;
|
|
107106
107723
|
length += n2;
|
|
107107
107724
|
}
|
|
107108
|
-
|
|
107725
|
+
need3(length === Number(before2.size) && sameStat(before2, fstatSync19(fd, { bigint: true })) && sameStat(before2, lstatSync26(file2, { bigint: true })), "INPUT_CHANGED");
|
|
107109
107726
|
const content = bytes.subarray(0, length), text3 = new TextDecoder("utf-8", { fatal: true }).decode(content);
|
|
107110
|
-
return { file: file2, privateFile, readOnlyPackage, text: text3, bytes: content, stat: before2, sha256:
|
|
107727
|
+
return { file: file2, privateFile, readOnlyPackage, text: text3, bytes: content, stat: before2, sha256: createHash24("sha256").update(content).digest("hex") };
|
|
107111
107728
|
} finally {
|
|
107112
|
-
|
|
107729
|
+
closeSync19(fd);
|
|
107113
107730
|
}
|
|
107114
107731
|
}
|
|
107115
107732
|
function unchanged2(before2) {
|
|
107116
107733
|
const after2 = snapshot(before2.file, before2.privateFile, before2.readOnlyPackage ? { readOnlyPackage: true } : {});
|
|
107117
|
-
|
|
107734
|
+
need3(sameStat(before2.stat, after2.stat) && after2.sha256 === before2.sha256, "INPUT_CHANGED");
|
|
107118
107735
|
}
|
|
107119
107736
|
function save2(file2, content) {
|
|
107120
107737
|
safeParents(file2);
|
|
107121
|
-
const fd =
|
|
107738
|
+
const fd = openSync19(file2, constants18.O_WRONLY | constants18.O_CREAT | constants18.O_EXCL | constants18.O_NOFOLLOW, 384);
|
|
107122
107739
|
try {
|
|
107123
107740
|
writeFileSync23(fd, content);
|
|
107124
|
-
|
|
107741
|
+
fsyncSync6(fd);
|
|
107125
107742
|
} finally {
|
|
107126
|
-
|
|
107743
|
+
closeSync19(fd);
|
|
107127
107744
|
}
|
|
107128
107745
|
}
|
|
107129
107746
|
var sameStat = (a, b) => ["dev", "ino", "uid", "nlink", "mode", "size", "mtimeNs", "ctimeNs"].every((key) => a[key] === b[key]);
|
|
@@ -107131,26 +107748,26 @@ var init_codex_hook_trust_files = () => {};
|
|
|
107131
107748
|
|
|
107132
107749
|
// src/lib/codex-hook-trust-identity.ts
|
|
107133
107750
|
import { realpathSync as realpathSync12 } from "fs";
|
|
107134
|
-
import { dirname as
|
|
107751
|
+
import { dirname as dirname28, isAbsolute as isAbsolute23, join as join55 } from "path";
|
|
107135
107752
|
function bindSkillsCli(command, reviewed) {
|
|
107136
107753
|
const normal = Bun.which("skills", { PATH: process.env.PATH });
|
|
107137
|
-
|
|
107754
|
+
need3(normal, "SKILLS_COMMAND_UNAVAILABLE");
|
|
107138
107755
|
const resolved = realpathSync12(normal);
|
|
107139
|
-
const bound =
|
|
107140
|
-
|
|
107756
|
+
const bound = isAbsolute23(command) ? command : command === "skills" ? normal : undefined;
|
|
107757
|
+
need3(bound && realpathSync12(bound) === resolved, "SKILLS_COMMAND_MISMATCH");
|
|
107141
107758
|
const entrypoint = reviewed?.path ?? process.argv[1];
|
|
107142
|
-
|
|
107759
|
+
need3(entrypoint && realpathSync12(entrypoint) === resolved, "SKILLS_ENTRYPOINT_MISMATCH");
|
|
107143
107760
|
const cli = snapshot(resolved, false, { readOnlyPackage: true });
|
|
107144
|
-
const manifest = snapshot(join55(
|
|
107761
|
+
const manifest = snapshot(join55(dirname28(dirname28(resolved)), "package.json"), false, { readOnlyPackage: true });
|
|
107145
107762
|
const pkg = JSON.parse(manifest.text);
|
|
107146
|
-
|
|
107763
|
+
need3(pkg.name === "@hasna/skills" && /^\d+\.\d+\.\d+$/.test(pkg.version) && pkg.bin?.skills === "bin/index.js" && resolved === join55(dirname28(manifest.file), "bin/index.js"), "SKILLS_PACKAGE_MISMATCH");
|
|
107147
107764
|
if (reviewed)
|
|
107148
|
-
|
|
107149
|
-
|
|
107765
|
+
need3(/^[a-f0-9]{64}$/.test(reviewed.sha256) && reviewed.sha256 === cli.sha256 && reviewed.version === pkg.version, "SKILLS_RELEASE_MISMATCH");
|
|
107766
|
+
need3((cli.stat.mode & 0o100n) !== 0n, "SKILLS_COMMAND_NOT_EXECUTABLE");
|
|
107150
107767
|
return {
|
|
107151
107768
|
receipt: { path: resolved, version: pkg.version, sha256: cli.sha256, manifestSha256: manifest.sha256 },
|
|
107152
107769
|
recheck() {
|
|
107153
|
-
|
|
107770
|
+
need3(Bun.which("skills", { PATH: process.env.PATH }) === normal && realpathSync12(normal) === resolved && realpathSync12(bound) === resolved && realpathSync12(entrypoint) === resolved, "SKILLS_COMMAND_CHANGED");
|
|
107154
107771
|
unchanged2(cli);
|
|
107155
107772
|
unchanged2(manifest);
|
|
107156
107773
|
}
|
|
@@ -107161,15 +107778,15 @@ var init_codex_hook_trust_identity = __esm(() => {
|
|
|
107161
107778
|
});
|
|
107162
107779
|
|
|
107163
107780
|
// src/lib/agent-codex-trust.ts
|
|
107164
|
-
import { lstatSync as
|
|
107165
|
-
import { createHash as
|
|
107166
|
-
import { join as join56, resolve as
|
|
107781
|
+
import { lstatSync as lstatSync27, mkdirSync as mkdirSync25, readdirSync as readdirSync20 } from "fs";
|
|
107782
|
+
import { createHash as createHash25, randomUUID as randomUUID10 } from "crypto";
|
|
107783
|
+
import { join as join56, resolve as resolve21 } from "path";
|
|
107167
107784
|
import { homedir as homedir11 } from "os";
|
|
107168
|
-
import { isDeepStrictEqual as
|
|
107785
|
+
import { isDeepStrictEqual as isDeepStrictEqual6 } from "util";
|
|
107169
107786
|
async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRpc) {
|
|
107170
107787
|
let rpc, journal;
|
|
107171
107788
|
try {
|
|
107172
|
-
const home =
|
|
107789
|
+
const home = resolve21(options.home ?? homedir11()), dataDir3 = resolve21(options.dataDir ?? getDataDirReadOnly());
|
|
107173
107790
|
assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
|
|
107174
107791
|
const policyFile = snapshot(join56(dataDir3, "agent-policy.json"), true), policy = parseManagedSkillPolicy(policyFile.text);
|
|
107175
107792
|
const binding = policy.bridge, alias = binding.rootAliases?.find((item) => item.agent === "codex");
|
|
@@ -107180,35 +107797,35 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
107180
107797
|
for (const [event, [nativeEvent, label]] of Object.entries(eventNames)) {
|
|
107181
107798
|
const command = renderAgentHookCommand(binding.commands.codex, "codex", binding.profiles.codex, event);
|
|
107182
107799
|
const groups = declarations[event];
|
|
107183
|
-
|
|
107800
|
+
need3(Array.isArray(groups), "DECLARATION_CHANGED");
|
|
107184
107801
|
const matches2 = groups.flatMap((group, gi) => (group.hooks ?? []).flatMap((entry, hi) => entry.command === command ? [{ group, entry, gi, hi }] : []));
|
|
107185
|
-
|
|
107802
|
+
need3(matches2.length === 1 && isDeepStrictEqual6(matches2[0].group, { hooks: [{ type: "command", command, timeout: 15 }] }), "DECLARATION_CHANGED");
|
|
107186
107803
|
expected.push({ event: nativeEvent, key: `${join56(home, ".codex/hooks.json")}:${label}:${matches2[0].gi}:${matches2[0].hi}`, command });
|
|
107187
107804
|
}
|
|
107188
107805
|
codexTrustTextWitness(configFile.text, expected.map((h) => h.key));
|
|
107189
107806
|
rpc = await connect({ command: options.codexCommand ?? "codex", home, codexHome });
|
|
107190
|
-
|
|
107807
|
+
need3(SUPPORTED_CODEX_HOOK_VERSIONS.includes(rpc.version), "NATIVE_UNSUPPORTED_VERSION");
|
|
107191
107808
|
const list2 = async () => {
|
|
107192
107809
|
const response = await rpc.request("hooks/list", { cwds: [home] });
|
|
107193
|
-
|
|
107810
|
+
need3(Array.isArray(response?.data) && response.data.length === 1 && response.data[0].cwd === home && Array.isArray(response.data[0].hooks) && response.data[0].hooks.length <= 1e4 && !response.data[0].errors?.length && !response.data[0].warnings?.length, "NATIVE_DISCOVERY_REFUSED");
|
|
107194
107811
|
return response.data[0].hooks;
|
|
107195
107812
|
};
|
|
107196
107813
|
const admit = (hooks) => expected.map((wanted) => {
|
|
107197
107814
|
const canonicalKey = wanted.key.replace(join56(home, ".codex/hooks.json"), hooksPath);
|
|
107198
107815
|
const matches2 = hooks.filter((h2) => h2.key === wanted.key || h2.key === canonicalKey);
|
|
107199
|
-
|
|
107816
|
+
need3(matches2.length === 1, "AMBIGUOUS_IDENTITY");
|
|
107200
107817
|
const h = matches2[0];
|
|
107201
|
-
|
|
107202
|
-
|
|
107203
|
-
|
|
107818
|
+
need3(h.eventName === wanted.event && h.handlerType === "command" && h.command === wanted.command && h.matcher === null && h.timeoutSec === 15 && h.async === false && h.statusMessage === null && h.additionalContextLimit === null && [hooksPath, join56(home, ".codex/hooks.json")].includes(h.sourcePath) && h.source === "user" && h.pluginId === null && h.isManaged === false && /^sha256:[a-f0-9]{64}$/.test(h.currentHash) && typeof h.enabled === "boolean", "NATIVE_IDENTITY_CHANGED");
|
|
107819
|
+
need3(hooks.filter((other) => other.command === wanted.command).length === 1, "AMBIGUOUS_IDENTITY");
|
|
107820
|
+
need3(["trusted", "untrusted", "modified"].includes(h.trustStatus), "UNKNOWN_TRUST_STATUS");
|
|
107204
107821
|
return { key: h.key, event: wanted.event, command: wanted.command, handlerType: h.handlerType, timeoutSec: h.timeoutSec, sourcePath: h.sourcePath, currentHash: h.currentHash, enabled: h.enabled, trustStatus: h.trustStatus };
|
|
107205
107822
|
});
|
|
107206
107823
|
const discovered = await list2(), admitted = admit(discovered);
|
|
107207
107824
|
const config2 = await rpc.request("config/read", { includeLayers: true, cwd: home });
|
|
107208
107825
|
const layers = config2?.layers?.filter((layer) => layer.name?.type === "user" && layer.name.file === configPath && !layer.name.profile);
|
|
107209
|
-
|
|
107210
|
-
|
|
107211
|
-
|
|
107826
|
+
need3(layers?.length === 1 && /^sha256:[a-f0-9]{64}$/.test(layers[0].version) && !layers[0].disabledReason && isDeepStrictEqual6(layers[0].config, original), "NATIVE_CONFIG_MISMATCH");
|
|
107827
|
+
need3(config2.config && config2.config.features?.hooks !== false, "NATIVE_HOOKS_DISABLED");
|
|
107828
|
+
need3(config2.layers.slice(0, config2.layers.indexOf(layers[0])).every((layer) => layer.config?.hooks === undefined && layer.config?.features?.hooks === undefined), "NATIVE_CONFIG_OVERRIDDEN");
|
|
107212
107829
|
const keys3 = admitted.map((h) => h.key), planned = admitted.filter((h) => !h.enabled || h.trustStatus !== "trusted");
|
|
107213
107830
|
const preservationText = codexTrustTextWitness(configFile.text, keys3);
|
|
107214
107831
|
const checkInputs = () => {
|
|
@@ -107219,19 +107836,19 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
107219
107836
|
unchanged2(configFile);
|
|
107220
107837
|
};
|
|
107221
107838
|
checkInputs();
|
|
107222
|
-
const planDigest =
|
|
107839
|
+
const planDigest = createHash25("sha256").update(json2({ version: 1, home, configPath, configSha256: configFile.sha256, configVersion: layers[0].version, policySha256: policyFile.sha256, hooksSha256: hooksFile.sha256, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, declarations: expected, admitted })).digest("hex");
|
|
107223
107840
|
const baseReceipt = { planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, ownedNativeProcessId: rpc.processId, agent: "codex", applied: false, planned, nativeEligible: planned.length === 0, transport: "owned-stdio-process", existingSessionsReloaded: false, nativeExecutionVerified: false };
|
|
107224
107841
|
if (options.apply)
|
|
107225
|
-
|
|
107842
|
+
need3(options.reviewedPlanDigest === planDigest, "PLAN_CHANGED: run the dry-run again and pass its reviewed --plan-digest with --apply");
|
|
107226
107843
|
const parent = join56(dataDir3, "native-hook-trust");
|
|
107227
|
-
const st =
|
|
107844
|
+
const st = lstatSync27(parent, { throwIfNoEntry: false });
|
|
107228
107845
|
if (st) {
|
|
107229
|
-
|
|
107846
|
+
need3(st.isDirectory() && !st.isSymbolicLink() && st.uid === process.getuid() && (st.mode & 511) === 448, "UNSAFE_JOURNAL");
|
|
107230
107847
|
const priorJournals = readdirSync20(parent);
|
|
107231
|
-
|
|
107848
|
+
need3(priorJournals.length < 1000, "JOURNAL_BOUND");
|
|
107232
107849
|
for (const name of priorJournals) {
|
|
107233
|
-
|
|
107234
|
-
|
|
107850
|
+
need3(/^[a-f0-9-]{36}$/.test(name), "UNSAFE_JOURNAL");
|
|
107851
|
+
need3(lstatSync27(join56(parent, name, "receipt.json"), { throwIfNoEntry: false })?.isFile(), "RECONCILE_REQUIRED: inspect the incomplete private journal before applying again");
|
|
107235
107852
|
}
|
|
107236
107853
|
}
|
|
107237
107854
|
if (!options.apply || !planned.length)
|
|
@@ -107244,7 +107861,7 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
107244
107861
|
save2(join56(journal, "hooks.before.json"), hooksFile.bytes);
|
|
107245
107862
|
save2(join56(journal, "policy.before.json"), policyFile.bytes);
|
|
107246
107863
|
save2(join56(journal, "intent.json"), json2({ version: 1, planDigest, skillsCli: skillsCli.receipt, nativeVersion: rpc.version, configPath, beforeSha256: configFile.sha256, hooksSha256: hooksFile.sha256, policySha256: policyFile.sha256, expectedVersion: layers[0].version, hooks: planned }));
|
|
107247
|
-
|
|
107864
|
+
need3(isDeepStrictEqual6(admit(await list2()), admitted), "NATIVE_DISCOVERY_CHANGED");
|
|
107248
107865
|
checkInputs();
|
|
107249
107866
|
let result2;
|
|
107250
107867
|
try {
|
|
@@ -107252,19 +107869,19 @@ async function enrollCodexNativeHooks(options = {}, connect = connectCodexHookRp
|
|
|
107252
107869
|
} catch {
|
|
107253
107870
|
throw new Error("CODEX_HOOK_TRUST_NATIVE_WRITE_FAILED: reconcile the private journal before retrying");
|
|
107254
107871
|
}
|
|
107255
|
-
|
|
107872
|
+
need3(result2?.status === "ok" && result2.filePath === configPath && /^sha256:[a-f0-9]{64}$/.test(result2.version), "NATIVE_WRITE_OVERRIDDEN");
|
|
107256
107873
|
const after2 = snapshot(configPath, true), expectedConfig = structuredClone(original);
|
|
107257
107874
|
expectedConfig.hooks ??= {};
|
|
107258
107875
|
expectedConfig.hooks.state ??= {};
|
|
107259
107876
|
for (const h of planned)
|
|
107260
107877
|
expectedConfig.hooks.state[h.key] = { ...expectedConfig.hooks.state[h.key], enabled: true, trusted_hash: h.currentHash };
|
|
107261
|
-
|
|
107878
|
+
need3(isDeepStrictEqual6(structure(after2.text), expectedConfig) && codexTrustTextWitness(after2.text, keys3) === preservationText, "PRESERVATION_FAILED");
|
|
107262
107879
|
unchanged2(policyFile);
|
|
107263
107880
|
unchanged2(hooksFile);
|
|
107264
107881
|
assertManagedAgentBridge("codex", { home, dataDir: dataDir3, projectDir: home });
|
|
107265
107882
|
const current = await list2(), confirmed = admit(current);
|
|
107266
|
-
|
|
107267
|
-
|
|
107883
|
+
need3(confirmed.every((h) => h.enabled && h.trustStatus === "trusted") && isDeepStrictEqual6(confirmed.map((h) => [h.key, h.currentHash]), admitted.map((h) => [h.key, h.currentHash])), "NATIVE_NOT_ELIGIBLE");
|
|
107884
|
+
need3(isDeepStrictEqual6(current.filter((h) => !keys3.includes(h.key)), discovered.filter((h) => !keys3.includes(h.key))), "UNRELATED_HOOK_CHANGED");
|
|
107268
107885
|
unchanged2(after2);
|
|
107269
107886
|
unchanged2(hooksFile);
|
|
107270
107887
|
unchanged2(policyFile);
|
|
@@ -107298,39 +107915,142 @@ var init_agent_codex_trust = __esm(() => {
|
|
|
107298
107915
|
eventNames = { UserPromptSubmit: ["userPromptSubmit", "user_prompt_submit"], SessionStart: ["sessionStart", "session_start"], SubagentStart: ["subagentStart", "subagent_start"] };
|
|
107299
107916
|
});
|
|
107300
107917
|
|
|
107918
|
+
// src/lib/hook-diagnostics.ts
|
|
107919
|
+
function hookChildError(stdout, stage) {
|
|
107920
|
+
let code2;
|
|
107921
|
+
if (stdout.length <= 16 * 1024) {
|
|
107922
|
+
try {
|
|
107923
|
+
code2 = JSON.parse(stdout)?.error?.code;
|
|
107924
|
+
} catch {}
|
|
107925
|
+
}
|
|
107926
|
+
return new HookDiagnosticError(typeof code2 === "string" && CONTEXT_ERROR_CODES.has(code2) ? code2 : "SKILLS_CONTEXT_FAILED", stage);
|
|
107927
|
+
}
|
|
107928
|
+
function hookFailureReason(error61, profileId) {
|
|
107929
|
+
const owned = error61 instanceof HookDiagnosticError;
|
|
107930
|
+
const code2 = owned && (CONTEXT_ERROR_CODES.has(error61.code) || ["SKILLS_HOOK_TIMEOUT", "SKILLS_HOOK_INVALID_RESPONSE"].includes(error61.code)) ? error61.code : "SKILLS_HOOK_FAILED";
|
|
107931
|
+
const profile = typeof profileId === "string" && /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/.test(profileId) && !profileId.includes("..") ? profileId : undefined;
|
|
107932
|
+
const identity4 = [profile ? `profile=${profile}` : undefined, owned ? `stage=${error61.stage}` : undefined].filter(Boolean).join(", ");
|
|
107933
|
+
const prefix = `Skills context is unavailable [${code2}]${identity4 ? ` (${identity4})` : ""}.`;
|
|
107934
|
+
if (code2 === "PROFILE_LOCK_MISMATCH") {
|
|
107935
|
+
return `${prefix} This session or project is pinned to a different profile. Inspect the session with skills sessions show <session-id> --json; review skills sessions reconcile for an intentional session change, or explicit project sync for a project change. Sync alone does not change that pin.`;
|
|
107936
|
+
}
|
|
107937
|
+
if (code2.startsWith("SESSION_")) {
|
|
107938
|
+
return `${prefix} Inspect the session with skills sessions show <session-id> --json and review its parent or concurrent writer before retrying. Do not remove or rewrite its receipt to bypass this refusal.`;
|
|
107939
|
+
}
|
|
107940
|
+
if (["PROFILE_IDENTITY_MISMATCH", "BUNDLE_DIGEST_MISMATCH", "BUNDLE_IDENTITY_MISMATCH", "INVALID_RECEIPT", "INVALID_CACHE_FILE", "UNSAFE_CACHE_PATH"].includes(code2)) {
|
|
107941
|
+
return `${prefix} Verify the selected authority and receipt integrity before repairing the profile; do not bypass verification or substitute another cache.`;
|
|
107942
|
+
}
|
|
107943
|
+
const selected = profile ?? "<id>";
|
|
107944
|
+
return `${prefix} Run skills sync --selection-profile ${selected} --json, then diagnose with skills context --stdin --json --cached --selection-profile ${selected} using the same hook session and working-directory fields. Do not include credentials in diagnostic input.`;
|
|
107945
|
+
}
|
|
107946
|
+
var CONTEXT_ERROR_CODES, HookDiagnosticError;
|
|
107947
|
+
var init_hook_diagnostics = __esm(() => {
|
|
107948
|
+
CONTEXT_ERROR_CODES = new Set([
|
|
107949
|
+
"SKILLS_CONTEXT_FAILED",
|
|
107950
|
+
"PROFILE_LOCK_MISMATCH",
|
|
107951
|
+
"PROFILE_IDENTITY_MISMATCH",
|
|
107952
|
+
"PROFILE_APPLIED_REPORT_FAILED",
|
|
107953
|
+
"CACHED_AUTHORITY_REQUIRED",
|
|
107954
|
+
"CACHED_PROFILE_EXPIRED",
|
|
107955
|
+
"CACHED_PROFILE_MISSING",
|
|
107956
|
+
"CACHED_BUNDLE_MISSING",
|
|
107957
|
+
"INVALID_CONTEXT_INPUT",
|
|
107958
|
+
"CONTEXT_INPUT_TOO_LARGE",
|
|
107959
|
+
"INVALID_CONTEXT_BUDGET",
|
|
107960
|
+
"INVALID_SELECTION",
|
|
107961
|
+
"INVALID_SELECTION_ALIASES",
|
|
107962
|
+
"INVALID_RECEIPT",
|
|
107963
|
+
"INVALID_CACHE_FILE",
|
|
107964
|
+
"UNSAFE_CACHE_PATH",
|
|
107965
|
+
"RECEIPT_TOO_LARGE",
|
|
107966
|
+
"BUNDLE_DIGEST_MISMATCH",
|
|
107967
|
+
"BUNDLE_IDENTITY_MISMATCH",
|
|
107968
|
+
"BUNDLE_UNAVAILABLE",
|
|
107969
|
+
"BUNDLE_TOO_LARGE",
|
|
107970
|
+
"SKILL_NOT_SELECTED",
|
|
107971
|
+
"INVALID_SESSION",
|
|
107972
|
+
"SESSION_PARENT_NOT_FOUND",
|
|
107973
|
+
"SESSION_NOT_FOUND",
|
|
107974
|
+
"SESSION_GENERATION_CHANGED",
|
|
107975
|
+
"SESSION_GENERATION_EXHAUSTED",
|
|
107976
|
+
"SESSION_PARENT_CHANGED",
|
|
107977
|
+
"SESSION_RECEIPT_CHANGED",
|
|
107978
|
+
"SESSION_RECONCILIATION_INCOMPLETE",
|
|
107979
|
+
"SESSION_WRITE_LOCKED",
|
|
107980
|
+
"SESSION_WRITE_LOCK_CHANGED"
|
|
107981
|
+
]);
|
|
107982
|
+
HookDiagnosticError = class HookDiagnosticError extends Error {
|
|
107983
|
+
code;
|
|
107984
|
+
stage;
|
|
107985
|
+
constructor(code2, stage) {
|
|
107986
|
+
super("Skills hook operation failed");
|
|
107987
|
+
this.code = code2;
|
|
107988
|
+
this.stage = stage;
|
|
107989
|
+
}
|
|
107990
|
+
};
|
|
107991
|
+
});
|
|
107992
|
+
|
|
107301
107993
|
// src/cli/commands/agent-integration.ts
|
|
107302
107994
|
var exports_agent_integration = {};
|
|
107303
107995
|
__export(exports_agent_integration, {
|
|
107304
107996
|
registerAgentIntegration: () => registerAgentIntegration
|
|
107305
107997
|
});
|
|
107306
107998
|
import { readFileSync as readFileSync37 } from "fs";
|
|
107307
|
-
import { isAbsolute as
|
|
107999
|
+
import { isAbsolute as isAbsolute24 } from "path";
|
|
108000
|
+
function pinnedHookProfile(input3, configuredProfile) {
|
|
108001
|
+
try {
|
|
108002
|
+
const parsed = parseSkillContextInput(JSON.stringify(input3));
|
|
108003
|
+
if (!parsed.sessionId)
|
|
108004
|
+
return configuredProfile;
|
|
108005
|
+
const sessionId = parsed.agentId ? `${parsed.sessionId}:${parsed.agentId}` : parsed.sessionId;
|
|
108006
|
+
const session = readSkillSessionSnapshotIfExists(sessionId);
|
|
108007
|
+
const parent = !session && parsed.agentId ? readSkillSessionSnapshotIfExists(parsed.sessionId) : null;
|
|
108008
|
+
return session?.receipt.profile.profileId ?? parent?.receipt.profile.profileId ?? configuredProfile;
|
|
108009
|
+
} catch (error61) {
|
|
108010
|
+
if (error61 instanceof SkillSelectionError)
|
|
108011
|
+
throw new HookDiagnosticError(error61.code, "context");
|
|
108012
|
+
throw error61;
|
|
108013
|
+
}
|
|
108014
|
+
}
|
|
107308
108015
|
async function contextForHook(input3, profileId, cached2, deadline) {
|
|
107309
108016
|
const remaining = deadline - Date.now();
|
|
107310
108017
|
if (remaining <= 0)
|
|
107311
|
-
throw new
|
|
108018
|
+
throw new HookDiagnosticError("SKILLS_HOOK_TIMEOUT", "context");
|
|
107312
108019
|
const args2 = [process.execPath, process.argv[1], "context", "--stdin", "--json", "--selection-profile", profileId];
|
|
107313
108020
|
if (cached2)
|
|
107314
108021
|
args2.push("--cached");
|
|
107315
108022
|
const child = Bun.spawn(args2, { stdin: new Blob([JSON.stringify(input3)]), stdout: "pipe", stderr: "pipe", env: { ...process.env, NO_COLOR: "1" } });
|
|
107316
|
-
|
|
108023
|
+
let timedOut = false;
|
|
108024
|
+
const timer = setTimeout(() => {
|
|
108025
|
+
timedOut = true;
|
|
108026
|
+
child.kill("SIGKILL");
|
|
108027
|
+
}, Math.min(6500, remaining));
|
|
107317
108028
|
let result2;
|
|
107318
108029
|
let status;
|
|
108030
|
+
let output2;
|
|
107319
108031
|
try {
|
|
107320
108032
|
const [stdout, , exitCode] = await Promise.all([new Response(child.stdout).text(), new Response(child.stderr).text(), child.exited]);
|
|
108033
|
+
if (timedOut)
|
|
108034
|
+
throw new HookDiagnosticError("SKILLS_HOOK_TIMEOUT", "context");
|
|
107321
108035
|
status = exitCode;
|
|
107322
|
-
|
|
108036
|
+
output2 = stdout;
|
|
107323
108037
|
} finally {
|
|
107324
108038
|
clearTimeout(timer);
|
|
107325
108039
|
}
|
|
107326
108040
|
if (status !== 0) {
|
|
107327
|
-
|
|
108041
|
+
const failure = hookChildError(output2, "context");
|
|
108042
|
+
if (cached2 && RECOVERABLE_CONTEXT_CACHE_ERRORS.has(failure.code)) {
|
|
107328
108043
|
return contextForHook(input3, profileId, false, deadline);
|
|
107329
108044
|
}
|
|
107330
|
-
throw
|
|
108045
|
+
throw failure;
|
|
108046
|
+
}
|
|
108047
|
+
try {
|
|
108048
|
+
result2 = JSON.parse(output2);
|
|
108049
|
+
} catch {
|
|
108050
|
+
throw new HookDiagnosticError("SKILLS_HOOK_INVALID_RESPONSE", "context");
|
|
107331
108051
|
}
|
|
107332
108052
|
if (typeof result2?.context !== "string")
|
|
107333
|
-
throw new
|
|
108053
|
+
throw new HookDiagnosticError("SKILLS_HOOK_INVALID_RESPONSE", "context");
|
|
107334
108054
|
return result2;
|
|
107335
108055
|
}
|
|
107336
108056
|
function agents(value) {
|
|
@@ -107377,6 +108097,7 @@ function registerAgentIntegration(parent) {
|
|
|
107377
108097
|
hook.command("user-prompt").requiredOption("--agent <agent>", `Native payload/output adapter: ${INTEGRATION_AGENTS.join(", ")}`).option("--event <event>", "Native lifecycle event supplied by the installed adapter").option("--selection-profile <id>", "Selection profile to load").description("Read native lifecycle JSON on stdin and return selected context").action(async (options) => {
|
|
107378
108098
|
const deadline = Date.now() + 12000;
|
|
107379
108099
|
let event = options.agent === "hermes" && options.event === "pre_tool_call" ? "pre_tool_call" : "UserPromptSubmit";
|
|
108100
|
+
let selectionProfile;
|
|
107380
108101
|
try {
|
|
107381
108102
|
if (agents(options.agent).length !== 1)
|
|
107382
108103
|
throw new Error("A hook invocation requires one agent");
|
|
@@ -107393,18 +108114,18 @@ function registerAgentIntegration(parent) {
|
|
|
107393
108114
|
input3.hook_event_name = event;
|
|
107394
108115
|
const projects = [process.cwd()];
|
|
107395
108116
|
if (input3.cwd !== undefined) {
|
|
107396
|
-
if (typeof input3.cwd !== "string" || !
|
|
108117
|
+
if (typeof input3.cwd !== "string" || !isAbsolute24(input3.cwd) || input3.cwd.includes("\x00"))
|
|
107397
108118
|
throw new Error("Invalid native hook working directory");
|
|
107398
108119
|
projects.push(input3.cwd);
|
|
107399
108120
|
}
|
|
107400
108121
|
if (options.agent === "cursor") {
|
|
107401
|
-
if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !
|
|
108122
|
+
if (!Array.isArray(input3.workspace_roots) || input3.workspace_roots.length > 32 || input3.workspace_roots.some((path) => typeof path !== "string" || !isAbsolute24(path) || path.includes("\x00")))
|
|
107402
108123
|
throw new Error("Invalid Cursor workspace roots");
|
|
107403
108124
|
projects.push(...input3.workspace_roots);
|
|
107404
108125
|
input3.cwd ??= input3.workspace_roots[0] ?? process.cwd();
|
|
107405
108126
|
input3.session_id ??= input3.conversation_id;
|
|
107406
108127
|
}
|
|
107407
|
-
|
|
108128
|
+
selectionProfile = selectedProfileId(options.selectionProfile);
|
|
107408
108129
|
if (options.agent === "hermes" && event === "pre_tool_call") {
|
|
107409
108130
|
assertManagedAgentBridge("hermes", { projectDirs: projects, profileId: selectionProfile });
|
|
107410
108131
|
assertHermesTool(input3);
|
|
@@ -107426,17 +108147,24 @@ function registerAgentIntegration(parent) {
|
|
|
107426
108147
|
if (event === "SessionStart") {
|
|
107427
108148
|
const remaining = deadline - Date.now();
|
|
107428
108149
|
if (remaining <= 0)
|
|
107429
|
-
throw new
|
|
108150
|
+
throw new HookDiagnosticError("SKILLS_HOOK_TIMEOUT", "sync");
|
|
107430
108151
|
const refresh = Bun.spawn([process.execPath, process.argv[1], "sync", "--selection-profile", selectionProfile, "--json"], { stdin: "ignore", stdout: "pipe", stderr: "pipe", env: { ...process.env, NO_COLOR: "1" } });
|
|
107431
|
-
|
|
108152
|
+
let timedOut = false;
|
|
108153
|
+
const timer = setTimeout(() => {
|
|
108154
|
+
timedOut = true;
|
|
108155
|
+
refresh.kill("SIGKILL");
|
|
108156
|
+
}, Math.min(6500, remaining));
|
|
107432
108157
|
try {
|
|
107433
|
-
const [, , status] = await Promise.all([new Response(refresh.stdout).text(), new Response(refresh.stderr).text(), refresh.exited]);
|
|
108158
|
+
const [stdout, , status] = await Promise.all([new Response(refresh.stdout).text(), new Response(refresh.stderr).text(), refresh.exited]);
|
|
108159
|
+
if (timedOut)
|
|
108160
|
+
throw new HookDiagnosticError("SKILLS_HOOK_TIMEOUT", "sync");
|
|
107434
108161
|
if (status !== 0)
|
|
107435
|
-
throw
|
|
108162
|
+
throw hookChildError(stdout, "sync");
|
|
107436
108163
|
} finally {
|
|
107437
108164
|
clearTimeout(timer);
|
|
107438
108165
|
}
|
|
107439
108166
|
}
|
|
108167
|
+
selectionProfile = pinnedHookProfile(input3, selectionProfile);
|
|
107440
108168
|
const result2 = await contextForHook(input3, selectionProfile, true, deadline);
|
|
107441
108169
|
const output2 = hookContextOutput(event, result2);
|
|
107442
108170
|
if (options.agent === "hermes") {
|
|
@@ -107449,7 +108177,7 @@ function registerAgentIntegration(parent) {
|
|
|
107449
108177
|
await writeCliOutput(JSON.stringify(output2));
|
|
107450
108178
|
}
|
|
107451
108179
|
} catch (error61) {
|
|
107452
|
-
const reason = error61 instanceof Error && error61.message.startsWith("NATIVE_SKILL_DRIFT:") ? error61.message :
|
|
108180
|
+
const reason = error61 instanceof Error && error61.message.startsWith("NATIVE_SKILL_DRIFT:") ? error61.message : hookFailureReason(error61, selectionProfile);
|
|
107453
108181
|
if (options.agent === "hermes") {
|
|
107454
108182
|
await writeCliOutput(JSON.stringify(event === "pre_tool_call" ? { action: "block", message: reason } : { context: `Required Skills context is unavailable. ${reason} Do not substitute native skill payloads; stop and repair the bridge before task actions.` }));
|
|
107455
108183
|
} else if (options.agent === "claude" && event === "PreToolUse")
|
|
@@ -107489,6 +108217,8 @@ var init_agent_integration2 = __esm(() => {
|
|
|
107489
108217
|
init_agent_adapters();
|
|
107490
108218
|
init_agent_integration();
|
|
107491
108219
|
init_agent_codex_trust();
|
|
108220
|
+
init_hook_diagnostics();
|
|
108221
|
+
init_selection_cache();
|
|
107492
108222
|
RECOVERABLE_CONTEXT_CACHE_ERRORS = new Set(["CACHED_PROFILE_EXPIRED", "CACHED_PROFILE_MISSING", "CACHED_BUNDLE_MISSING"]);
|
|
107493
108223
|
});
|
|
107494
108224
|
|
|
@@ -107627,17 +108357,17 @@ var exports_profiles = {};
|
|
|
107627
108357
|
__export(exports_profiles, {
|
|
107628
108358
|
registerProfiles: () => registerProfiles
|
|
107629
108359
|
});
|
|
107630
|
-
import { closeSync as
|
|
108360
|
+
import { closeSync as closeSync20, constants as constants19, fstatSync as fstatSync20, openSync as openSync20, readSync as readSync16, writeFileSync as writeFileSync24 } from "fs";
|
|
107631
108361
|
function readProfileInput(path) {
|
|
107632
|
-
const fd =
|
|
108362
|
+
const fd = openSync20(path, constants19.O_RDONLY | constants19.O_NONBLOCK);
|
|
107633
108363
|
try {
|
|
107634
|
-
const stat3 =
|
|
108364
|
+
const stat3 = fstatSync20(fd);
|
|
107635
108365
|
if (!stat3.isFile() || stat3.size > MAX_PROFILE_DOCUMENT_BYTES)
|
|
107636
108366
|
throw new Error("Profile input exceeds the size limit or is not a regular file");
|
|
107637
108367
|
const bytes = Buffer.alloc(MAX_PROFILE_DOCUMENT_BYTES + 1);
|
|
107638
108368
|
let size2 = 0;
|
|
107639
108369
|
while (size2 < bytes.length) {
|
|
107640
|
-
const read3 =
|
|
108370
|
+
const read3 = readSync16(fd, bytes, size2, bytes.length - size2, null);
|
|
107641
108371
|
if (!read3)
|
|
107642
108372
|
break;
|
|
107643
108373
|
size2 += read3;
|
|
@@ -107646,7 +108376,7 @@ function readProfileInput(path) {
|
|
|
107646
108376
|
throw new Error("Profile input exceeds the size limit");
|
|
107647
108377
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size2));
|
|
107648
108378
|
} finally {
|
|
107649
|
-
|
|
108379
|
+
closeSync20(fd);
|
|
107650
108380
|
}
|
|
107651
108381
|
}
|
|
107652
108382
|
function registerProfiles(parent) {
|
|
@@ -107697,23 +108427,23 @@ __export(exports_grants, {
|
|
|
107697
108427
|
registerGrants: () => registerGrants
|
|
107698
108428
|
});
|
|
107699
108429
|
import {
|
|
107700
|
-
constants as
|
|
107701
|
-
closeSync as
|
|
107702
|
-
fstatSync as
|
|
107703
|
-
openSync as
|
|
107704
|
-
readSync as
|
|
108430
|
+
constants as constants20,
|
|
108431
|
+
closeSync as closeSync21,
|
|
108432
|
+
fstatSync as fstatSync21,
|
|
108433
|
+
openSync as openSync21,
|
|
108434
|
+
readSync as readSync17,
|
|
107705
108435
|
writeFileSync as writeFileSync25
|
|
107706
108436
|
} from "fs";
|
|
107707
108437
|
function readInput(path) {
|
|
107708
|
-
const fd =
|
|
108438
|
+
const fd = openSync21(path, constants20.O_RDONLY | constants20.O_NONBLOCK);
|
|
107709
108439
|
try {
|
|
107710
|
-
const stat3 =
|
|
108440
|
+
const stat3 = fstatSync21(fd);
|
|
107711
108441
|
if (!stat3.isFile() || stat3.size > MAX_EXECUTION_GRANT_BYTES)
|
|
107712
108442
|
throw new Error("Grant input must be a regular file within the policy size limit.");
|
|
107713
108443
|
const bytes = Buffer.alloc(MAX_EXECUTION_GRANT_BYTES + 1);
|
|
107714
108444
|
let size2 = 0;
|
|
107715
108445
|
while (size2 < bytes.length) {
|
|
107716
|
-
const count =
|
|
108446
|
+
const count = readSync17(fd, bytes, size2, bytes.length - size2, null);
|
|
107717
108447
|
if (!count)
|
|
107718
108448
|
break;
|
|
107719
108449
|
size2 += count;
|
|
@@ -107726,7 +108456,7 @@ function readInput(path) {
|
|
|
107726
108456
|
throw new Error("Grant input must be a JSON document containing a grants array.");
|
|
107727
108457
|
}
|
|
107728
108458
|
} finally {
|
|
107729
|
-
|
|
108459
|
+
closeSync21(fd);
|
|
107730
108460
|
}
|
|
107731
108461
|
}
|
|
107732
108462
|
function registerGrants(parent) {
|
|
@@ -107762,7 +108492,7 @@ var init_grants = __esm(() => {
|
|
|
107762
108492
|
});
|
|
107763
108493
|
|
|
107764
108494
|
// src/lib/station-hydrate.ts
|
|
107765
|
-
import { createHash as
|
|
108495
|
+
import { createHash as createHash26 } from "crypto";
|
|
107766
108496
|
import {
|
|
107767
108497
|
copyFileSync as copyFileSync2,
|
|
107768
108498
|
mkdirSync as mkdirSync26,
|
|
@@ -107771,7 +108501,7 @@ import {
|
|
|
107771
108501
|
statSync as statSync21,
|
|
107772
108502
|
writeFileSync as writeFileSync26
|
|
107773
108503
|
} from "fs";
|
|
107774
|
-
import { dirname as
|
|
108504
|
+
import { dirname as dirname29, join as join57, resolve as resolve22, sep as sep10 } from "path";
|
|
107775
108505
|
function fail5(code2, message, detail = []) {
|
|
107776
108506
|
throw new StationSnapshotError(code2, message, detail);
|
|
107777
108507
|
}
|
|
@@ -107965,12 +108695,12 @@ function skillSha256(skill) {
|
|
|
107965
108695
|
return sha256File(skill.files[0].winner.fullPath);
|
|
107966
108696
|
}
|
|
107967
108697
|
const joined = skill.files.map((file2) => sha256File(file2.winner.fullPath));
|
|
107968
|
-
return
|
|
108698
|
+
return createHash26("sha256").update(joined.sort().join(`
|
|
107969
108699
|
`)).digest("hex");
|
|
107970
108700
|
}
|
|
107971
108701
|
function writeStationHydration(options) {
|
|
107972
|
-
const repoRoot =
|
|
107973
|
-
const cacheRoot =
|
|
108702
|
+
const repoRoot = resolve22(options.repoRoot ?? process.cwd());
|
|
108703
|
+
const cacheRoot = resolve22(options.cacheRoot ?? resolveCorpusRoot());
|
|
107974
108704
|
const plan = planStationHydration(options.stationId, repoRoot);
|
|
107975
108705
|
const resultSkills = plan.winners.map((skill) => ({
|
|
107976
108706
|
ident: skill.ident,
|
|
@@ -108004,13 +108734,13 @@ function writeStationHydration(options) {
|
|
|
108004
108734
|
for (const skill of plan.winners) {
|
|
108005
108735
|
for (const file2 of skill.files) {
|
|
108006
108736
|
const destination = join57(cacheRoot, skill.ident, file2.withinIdent);
|
|
108007
|
-
const
|
|
108737
|
+
const digest4 = sha256File(file2.winner.fullPath);
|
|
108008
108738
|
let existingDigest = null;
|
|
108009
108739
|
try {
|
|
108010
108740
|
existingDigest = sha256File(destination);
|
|
108011
108741
|
} catch {}
|
|
108012
108742
|
if (existingDigest !== null) {
|
|
108013
|
-
if (existingDigest ===
|
|
108743
|
+
if (existingDigest === digest4) {
|
|
108014
108744
|
continue;
|
|
108015
108745
|
}
|
|
108016
108746
|
conflicts.push(`existing destination differs from snapshot winner: ${destination}`);
|
|
@@ -108024,7 +108754,7 @@ function writeStationHydration(options) {
|
|
|
108024
108754
|
}
|
|
108025
108755
|
let written = 0;
|
|
108026
108756
|
for (const entry of toWrite) {
|
|
108027
|
-
mkdirSync26(
|
|
108757
|
+
mkdirSync26(dirname29(entry.destination), { recursive: true });
|
|
108028
108758
|
copyFileSync2(entry.fullPath, entry.destination);
|
|
108029
108759
|
written += 1;
|
|
108030
108760
|
}
|
|
@@ -108045,8 +108775,8 @@ function writeStationHydration(options) {
|
|
|
108045
108775
|
},
|
|
108046
108776
|
skills: resultSkills
|
|
108047
108777
|
};
|
|
108048
|
-
const hydrationManifestPath = join57(
|
|
108049
|
-
mkdirSync26(
|
|
108778
|
+
const hydrationManifestPath = join57(dirname29(cacheRoot), `hydration-${options.stationId}.json`);
|
|
108779
|
+
mkdirSync26(dirname29(hydrationManifestPath), { recursive: true });
|
|
108050
108780
|
writeFileSync26(hydrationManifestPath, `${JSON.stringify(hydration, null, 2)}
|
|
108051
108781
|
`);
|
|
108052
108782
|
return {
|
|
@@ -108122,10 +108852,10 @@ var init_hydrate = __esm(() => {
|
|
|
108122
108852
|
});
|
|
108123
108853
|
|
|
108124
108854
|
// src/lib/prepare-skill.ts
|
|
108125
|
-
import { createHash as
|
|
108126
|
-
import { chmodSync as chmodSync3, existsSync as existsSync34, lstatSync as
|
|
108855
|
+
import { createHash as createHash27, randomUUID as randomUUID11 } from "crypto";
|
|
108856
|
+
import { chmodSync as chmodSync3, existsSync as existsSync34, lstatSync as lstatSync28, mkdirSync as mkdirSync27, mkdtempSync as mkdtempSync6, readFileSync as readFileSync39, readdirSync as readdirSync22, renameSync as renameSync12, rmSync as rmSync9, writeFileSync as writeFileSync27 } from "fs";
|
|
108127
108857
|
import { tmpdir as tmpdir2 } from "os";
|
|
108128
|
-
import { dirname as
|
|
108858
|
+
import { dirname as dirname30, isAbsolute as isAbsolute25, join as join58, relative as relative9, resolve as resolve23, sep as sep11 } from "path";
|
|
108129
108859
|
function prepareSkill(name, options) {
|
|
108130
108860
|
const normalized = normalizePortableSkillName(name);
|
|
108131
108861
|
if (!new RegExp(SEMVER_PATTERN).test(options.version))
|
|
@@ -108170,7 +108900,7 @@ function prepareSkill(name, options) {
|
|
|
108170
108900
|
mkdirSync27(join58(staging, directory2), { recursive: true });
|
|
108171
108901
|
for (const file2 of before2.files) {
|
|
108172
108902
|
const destination = join58(staging, file2.path);
|
|
108173
|
-
mkdirSync27(
|
|
108903
|
+
mkdirSync27(dirname30(destination), { recursive: true });
|
|
108174
108904
|
writeFileSync27(destination, file2.bytes, { mode: file2.mode });
|
|
108175
108905
|
}
|
|
108176
108906
|
const stagedManifest = join58(staging, "skill.json");
|
|
@@ -108230,8 +108960,8 @@ function validateRuntimeEntrypoint(candidate2, root2) {
|
|
|
108230
108960
|
const entry = candidate2.runtime.entrypoint;
|
|
108231
108961
|
if (typeof entry !== "string")
|
|
108232
108962
|
return;
|
|
108233
|
-
const target =
|
|
108234
|
-
if (
|
|
108963
|
+
const target = resolve23(root2, entry), rel = relative9(root2, target);
|
|
108964
|
+
if (isAbsolute25(entry) || /^[a-zA-Z]:/.test(entry) || entry.includes("\\") || !rel || rel === ".." || rel.startsWith(`..${sep11}`) || isAbsolute25(rel) || !existsSync34(target) || !lstatSync28(target).isFile()) {
|
|
108235
108965
|
throw new Error("Executable runtime.entrypoint must name an existing regular file inside the skill directory.");
|
|
108236
108966
|
}
|
|
108237
108967
|
}
|
|
@@ -108239,31 +108969,31 @@ function isRecord6(value) {
|
|
|
108239
108969
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
108240
108970
|
}
|
|
108241
108971
|
function validateRawCandidate(candidate2) {
|
|
108242
|
-
for (const
|
|
108243
|
-
if (typeof candidate2[
|
|
108244
|
-
throw new Error(`skill.json ${
|
|
108972
|
+
for (const field2 of ["standard", "name", "description", "version"]) {
|
|
108973
|
+
if (typeof candidate2[field2] !== "string" || !candidate2[field2].trim())
|
|
108974
|
+
throw new Error(`skill.json ${field2} is required.`);
|
|
108245
108975
|
}
|
|
108246
|
-
for (const
|
|
108247
|
-
if (candidate2[
|
|
108248
|
-
throw new Error(`Invalid skill.json ${
|
|
108976
|
+
for (const field2 of ["displayName", "category"]) {
|
|
108977
|
+
if (candidate2[field2] !== undefined && (typeof candidate2[field2] !== "string" || !candidate2[field2].trim()))
|
|
108978
|
+
throw new Error(`Invalid skill.json ${field2}.`);
|
|
108249
108979
|
}
|
|
108250
108980
|
if (candidate2.tags !== undefined && (!Array.isArray(candidate2.tags) || candidate2.tags.some((tag) => typeof tag !== "string" || !tag.trim())))
|
|
108251
108981
|
throw new Error("Invalid skill.json tags.");
|
|
108252
108982
|
const issues = validatePortableManifestContract(candidate2, { strict: true });
|
|
108253
108983
|
if (issues.length)
|
|
108254
108984
|
throw new Error(`Invalid skill.json: ${issues.map((issue2) => issue2.code).join(", ")}`);
|
|
108255
|
-
for (const
|
|
108256
|
-
const items = candidate2[
|
|
108985
|
+
for (const field2 of ["inputs", "commands"]) {
|
|
108986
|
+
const items = candidate2[field2];
|
|
108257
108987
|
if (items === undefined)
|
|
108258
108988
|
continue;
|
|
108259
108989
|
if (!Array.isArray(items))
|
|
108260
|
-
throw new Error(`skill.json ${
|
|
108990
|
+
throw new Error(`skill.json ${field2} must be an array.`);
|
|
108261
108991
|
for (const item of items) {
|
|
108262
108992
|
if (!isRecord6(item) || typeof item.name !== "string" || !item.name.trim())
|
|
108263
|
-
throw new Error(`Invalid skill.json ${
|
|
108264
|
-
if (
|
|
108993
|
+
throw new Error(`Invalid skill.json ${field2} name.`);
|
|
108994
|
+
if (field2 === "inputs" && (typeof item.type !== "string" || !item.type.trim() || item.required !== undefined && typeof item.required !== "boolean"))
|
|
108265
108995
|
throw new Error("Invalid skill.json input type or required flag.");
|
|
108266
|
-
if (
|
|
108996
|
+
if (field2 === "commands") {
|
|
108267
108997
|
if (!/^[a-z0-9][a-z0-9._-]*$/.test(item.name))
|
|
108268
108998
|
throw new Error("Invalid skill.json command name.");
|
|
108269
108999
|
for (const target of ["entry", "command"])
|
|
@@ -108303,11 +109033,11 @@ function compareVersions(left, right) {
|
|
|
108303
109033
|
return 0;
|
|
108304
109034
|
}
|
|
108305
109035
|
function snapshot2(root2) {
|
|
108306
|
-
const rootStat =
|
|
109036
|
+
const rootStat = lstatSync28(root2);
|
|
108307
109037
|
if (rootStat.isSymbolicLink() || !rootStat.isDirectory())
|
|
108308
109038
|
throw new Error("Skill root must be a real directory, not a symlink.");
|
|
108309
109039
|
const files = [], directories = [];
|
|
108310
|
-
const hash4 =
|
|
109040
|
+
const hash4 = createHash27("sha256").update(`${rootStat.dev}:${rootStat.ino}\x00`);
|
|
108311
109041
|
let count = 0, bytes = 0;
|
|
108312
109042
|
const walk2 = (relative10) => {
|
|
108313
109043
|
for (const name of readdirSync22(join58(root2, relative10)).sort()) {
|
|
@@ -108316,7 +109046,7 @@ function snapshot2(root2) {
|
|
|
108316
109046
|
const path = relative10 ? `${relative10}/${name}` : name;
|
|
108317
109047
|
if (++count > 20000)
|
|
108318
109048
|
throw new Error("Skill exceeds the preparation entry limit (20000).");
|
|
108319
|
-
const absolute = join58(root2, path), stat3 =
|
|
109049
|
+
const absolute = join58(root2, path), stat3 = lstatSync28(absolute);
|
|
108320
109050
|
if (stat3.isSymbolicLink())
|
|
108321
109051
|
throw new Error(`Skill contains a symlink: ${path}. No files were changed.`);
|
|
108322
109052
|
if (stat3.isDirectory() && name === "node_modules")
|
|
@@ -108731,7 +109461,7 @@ var init_schedule = __esm(() => {
|
|
|
108731
109461
|
|
|
108732
109462
|
// src/lib/registry-sync.ts
|
|
108733
109463
|
import { mkdirSync as mkdirSync28, writeFileSync as writeFileSync28 } from "fs";
|
|
108734
|
-
import { dirname as
|
|
109464
|
+
import { dirname as dirname31, relative as relative10 } from "path";
|
|
108735
109465
|
function createRegistrySyncArtifact(options = {}) {
|
|
108736
109466
|
const profile = options.profile ?? "all";
|
|
108737
109467
|
const includeDocs = options.includeDocs ?? true;
|
|
@@ -108788,7 +109518,7 @@ function createRegistrySyncArtifact(options = {}) {
|
|
|
108788
109518
|
};
|
|
108789
109519
|
}
|
|
108790
109520
|
function writeRegistrySyncArtifact(path, artifact) {
|
|
108791
|
-
mkdirSync28(
|
|
109521
|
+
mkdirSync28(dirname31(path), { recursive: true });
|
|
108792
109522
|
writeFileSync28(path, `${JSON.stringify(artifact, null, 2)}
|
|
108793
109523
|
`);
|
|
108794
109524
|
}
|
|
@@ -108821,12 +109551,12 @@ function registerRegistry(parent) {
|
|
|
108821
109551
|
async function writeJson2(value, space) {
|
|
108822
109552
|
const text3 = `${JSON.stringify(value, null, space)}
|
|
108823
109553
|
`;
|
|
108824
|
-
await new Promise((
|
|
109554
|
+
await new Promise((resolve24, reject2) => {
|
|
108825
109555
|
process.stdout.write(text3, (error61) => {
|
|
108826
109556
|
if (error61)
|
|
108827
109557
|
reject2(error61);
|
|
108828
109558
|
else
|
|
108829
|
-
|
|
109559
|
+
resolve24();
|
|
108830
109560
|
});
|
|
108831
109561
|
});
|
|
108832
109562
|
}
|
|
@@ -109283,7 +110013,7 @@ var exports_private_publications = {};
|
|
|
109283
110013
|
__export(exports_private_publications, {
|
|
109284
110014
|
registerPrivatePublications: () => registerPrivatePublications
|
|
109285
110015
|
});
|
|
109286
|
-
import { resolve as
|
|
110016
|
+
import { resolve as resolve24 } from "path";
|
|
109287
110017
|
function verifyOptions(options, action) {
|
|
109288
110018
|
if (options.userId === undefined !== (options.membershipId === undefined) || options.userId !== undefined && (!publicationUuid(options.userId) || !publicationUuid(options.membershipId)))
|
|
109289
110019
|
throw new PrivatePublicationError("PUBLICATION_CONTEXT_REQUIRED", "Provide both observed --user-id and --membership-id UUIDs.");
|
|
@@ -109328,9 +110058,9 @@ function registerPrivatePublications(parent) {
|
|
|
109328
110058
|
if (code2 === null)
|
|
109329
110059
|
return;
|
|
109330
110060
|
const context2 = options.userId ? { userId: options.userId, membershipId: options.membershipId } : undefined;
|
|
109331
|
-
const client2 = await privatePublicationSession(options.email, code2, context2), directory2 =
|
|
110061
|
+
const client2 = await privatePublicationSession(options.email, code2, context2), directory2 = resolve24(options.recoveryDir);
|
|
109332
110062
|
if (action === "publish")
|
|
109333
|
-
await preparePrivatePublication(client2,
|
|
110063
|
+
await preparePrivatePublication(client2, resolve24(args2[0]), directory2, { skillId: options.skillId, expectedCurrentVersionId: options.expectedCurrentVersion ?? null, idempotencyKey: options.idempotencyKey });
|
|
109334
110064
|
const result2 = action === "publish" || action === "resume" ? await continuePrivatePublication(client2, directory2, { confirm: true, waitMs: Number(options.waitSeconds) * 1000 }) : await inspectPrivatePublication(client2, directory2, action === "cancel");
|
|
109335
110065
|
print2(result2, options.json);
|
|
109336
110066
|
} catch (error61) {
|
|
@@ -109431,7 +110161,7 @@ __export(exports_auth, {
|
|
|
109431
110161
|
import { createInterface as createInterface3 } from "readline";
|
|
109432
110162
|
function prompt(question) {
|
|
109433
110163
|
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
109434
|
-
return new Promise((
|
|
110164
|
+
return new Promise((resolve25) => {
|
|
109435
110165
|
let settled = false;
|
|
109436
110166
|
const finish = (answer) => {
|
|
109437
110167
|
if (settled)
|
|
@@ -109440,7 +110170,7 @@ function prompt(question) {
|
|
|
109440
110170
|
rl.close();
|
|
109441
110171
|
if (answer === null)
|
|
109442
110172
|
process.exitCode = 130;
|
|
109443
|
-
|
|
110173
|
+
resolve25(answer);
|
|
109444
110174
|
};
|
|
109445
110175
|
rl.once("SIGINT", () => finish(null));
|
|
109446
110176
|
rl.once("close", () => finish(null));
|
|
@@ -109548,7 +110278,7 @@ function printWhoami(payload) {
|
|
|
109548
110278
|
console.log(source_default.dim("(offline \u2014 showing cached info)"));
|
|
109549
110279
|
}
|
|
109550
110280
|
function sleep(ms) {
|
|
109551
|
-
return new Promise((
|
|
110281
|
+
return new Promise((resolve25) => setTimeout(resolve25, ms));
|
|
109552
110282
|
}
|
|
109553
110283
|
function browserCommand(url2) {
|
|
109554
110284
|
if (process.platform === "darwin")
|
|
@@ -110050,7 +110780,7 @@ function promptInvitationProof(kind) {
|
|
|
110050
110780
|
const label = kind === "token" ? "invitation token" : "recovery code";
|
|
110051
110781
|
const character = kind === "token" ? /^[A-Za-z0-9_-]$/ : /^\d$/;
|
|
110052
110782
|
const { stdin, stderr: output2 } = process, wasRaw = stdin.isRaw, wasFlowing = stdin.readableFlowing;
|
|
110053
|
-
return new Promise((
|
|
110783
|
+
return new Promise((resolve25) => {
|
|
110054
110784
|
let value = "", settled = false, overflow = false;
|
|
110055
110785
|
const finish = (answer) => {
|
|
110056
110786
|
if (settled)
|
|
@@ -110067,7 +110797,7 @@ function promptInvitationProof(kind) {
|
|
|
110067
110797
|
`);
|
|
110068
110798
|
if (answer === null)
|
|
110069
110799
|
process.exitCode = 130;
|
|
110070
|
-
|
|
110800
|
+
resolve25(answer);
|
|
110071
110801
|
};
|
|
110072
110802
|
const cancel = () => finish(null);
|
|
110073
110803
|
const keypress = (text3, key) => {
|
|
@@ -110777,8 +111507,8 @@ async function currentRemoteDigest(client2, slug2) {
|
|
|
110777
111507
|
}
|
|
110778
111508
|
if (!body || typeof body !== "object")
|
|
110779
111509
|
return;
|
|
110780
|
-
const
|
|
110781
|
-
return typeof
|
|
111510
|
+
const digest4 = body.bundleSha256;
|
|
111511
|
+
return typeof digest4 === "string" && digest4 ? digest4 : undefined;
|
|
110782
111512
|
}
|
|
110783
111513
|
async function reconcileRegistry(options = {}) {
|
|
110784
111514
|
const conflict = options.conflict ?? "skip";
|