@hasna/skills 0.8.9 → 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 +103 -1
- package/bin/index.js +26509 -24016
- package/bin/mcp.js +596 -222
- package/bin/migrate.js +7 -5
- package/bin/server.js +12313 -73626
- package/bin/worker.js +7636 -60520
- package/dist/cli/commands/plugin-admission.d.ts +2 -0
- package/dist/index.d.ts +9 -2
- package/dist/index.js +23559 -21779
- package/dist/lib/agent-adapters.d.ts +1 -0
- package/dist/lib/agent-codex-trust.d.ts +42 -0
- package/dist/lib/agent-discovery.d.ts +4 -2
- package/dist/lib/claude-marketplace-registry.d.ts +17 -0
- package/dist/lib/codex-hook-rpc.d.ts +13 -0
- package/dist/lib/codex-hook-trust-files.d.ts +15 -0
- package/dist/lib/codex-hook-trust-identity.d.ts +16 -0
- package/dist/lib/codex-hook-trust-layout.d.ts +3 -0
- package/dist/lib/fleet-credentials.d.ts +18 -0
- package/dist/lib/hook-diagnostics.d.ts +7 -0
- package/dist/lib/plugin-admission.d.ts +101 -0
- package/dist/lib/plugin-discovery.d.ts +13 -0
- package/dist/lib/plugin-projection-store.d.ts +14 -0
- package/dist/lib/plugin-projection.d.ts +80 -0
- package/dist/lib/profile-client.d.ts +10 -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 +14 -4
- package/dist/lib/remote-credit-checkout.d.ts +22 -0
- package/dist/lib/remote-customer-operations.d.ts +3 -4
- package/dist/lib/remote-permissions.d.ts +24 -0
- 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 +5 -2
- package/dist/sdk/index.js +18528 -78089
- package/docs/plugin-admission.md +221 -0
- package/package.json +7 -5
package/bin/mcp.js
CHANGED
|
@@ -20019,7 +20019,7 @@ var package_default;
|
|
|
20019
20019
|
var init_package = __esm(() => {
|
|
20020
20020
|
package_default = {
|
|
20021
20021
|
name: "@hasna/skills",
|
|
20022
|
-
version: "0.8.
|
|
20022
|
+
version: "0.8.11",
|
|
20023
20023
|
description: "Skills library for AI coding agents",
|
|
20024
20024
|
type: "module",
|
|
20025
20025
|
bin: {
|
|
@@ -20057,6 +20057,7 @@ var init_package = __esm(() => {
|
|
|
20057
20057
|
"bin/",
|
|
20058
20058
|
"migrations/",
|
|
20059
20059
|
"docs/skill-standard.md",
|
|
20060
|
+
"docs/plugin-admission.md",
|
|
20060
20061
|
"schemas/",
|
|
20061
20062
|
"LICENSE",
|
|
20062
20063
|
"README.md",
|
|
@@ -20080,10 +20081,11 @@ var init_package = __esm(() => {
|
|
|
20080
20081
|
typecheck: "tsc --noEmit",
|
|
20081
20082
|
"verify:release": "bun run scripts/release-guard.ts",
|
|
20082
20083
|
"verify:consumer-types": "bun run scripts/consumer-types.ts",
|
|
20083
|
-
|
|
20084
|
-
prepack: "bun run build && bun run verify:release && bun run verify:consumer-types",
|
|
20084
|
+
prepack: "bun run verify:generated && bun run verify:release && bun run verify:consumer-types",
|
|
20085
20085
|
prepublishOnly: "bun run verify:producer && bun run typecheck && bun run test",
|
|
20086
|
-
"verify:producer": "bun run scripts/release-dependencies.ts"
|
|
20086
|
+
"verify:producer": "bun run scripts/release-dependencies.ts",
|
|
20087
|
+
"verify:generated": "HASNA_SKILLS_RELEASE_ARTIFACT_TEST=1 bun test src/lib/release-artifacts.test.ts",
|
|
20088
|
+
"verify:consumer-credentials": "bun run scripts/consumer-credentials.ts"
|
|
20087
20089
|
},
|
|
20088
20090
|
keywords: [
|
|
20089
20091
|
"skills",
|
|
@@ -20105,7 +20107,6 @@ var init_package = __esm(() => {
|
|
|
20105
20107
|
license: "Apache-2.0",
|
|
20106
20108
|
devDependencies: {
|
|
20107
20109
|
"@hasna/contracts": "1.1.0",
|
|
20108
|
-
"@hasna/secrets": "0.4.2",
|
|
20109
20110
|
"@types/bun": "1.3.14",
|
|
20110
20111
|
"@types/node": "25.2.3",
|
|
20111
20112
|
"@types/react": "^18.2.0",
|
|
@@ -20118,6 +20119,7 @@ var init_package = __esm(() => {
|
|
|
20118
20119
|
"@aws-sdk/client-ecs": "^3.1079.0",
|
|
20119
20120
|
"@aws-sdk/client-s3": "^3.1079.0",
|
|
20120
20121
|
"@hasna/events": "0.1.18",
|
|
20122
|
+
"@hasna/secrets": "0.4.2",
|
|
20121
20123
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
20122
20124
|
chalk: "^5.3.0",
|
|
20123
20125
|
commander: "^12.1.0",
|
|
@@ -21106,6 +21108,7 @@ __export(exports_fleet_credentials, {
|
|
|
21106
21108
|
SKILLS_API_URL_ENV: () => SKILLS_API_URL_ENV,
|
|
21107
21109
|
SKILLS_API_KEY_ENV_KEYS: () => SKILLS_API_KEY_ENV_KEYS,
|
|
21108
21110
|
SKILLS_API_KEY_ENV: () => SKILLS_API_KEY_ENV,
|
|
21111
|
+
REDACTED_VAULT_REFERENCE: () => REDACTED_VAULT_REFERENCE,
|
|
21109
21112
|
MissingSkillsFleetError: () => MissingSkillsFleetError
|
|
21110
21113
|
});
|
|
21111
21114
|
function isCredentialResolutionError(error61) {
|
|
@@ -21114,10 +21117,15 @@ function isCredentialResolutionError(error61) {
|
|
|
21114
21117
|
function isSkillsFleetCredentialError(error61) {
|
|
21115
21118
|
return error61 instanceof SkillsFleetCredentialError || typeof error61 === "object" && error61 !== null && error61.name === "SkillsFleetCredentialError";
|
|
21116
21119
|
}
|
|
21117
|
-
function
|
|
21120
|
+
function redactVaultReference(message, vaultReference) {
|
|
21121
|
+
if (!vaultReference)
|
|
21122
|
+
return message;
|
|
21123
|
+
return message.split(vaultReference).join(REDACTED_VAULT_REFERENCE);
|
|
21124
|
+
}
|
|
21125
|
+
function asSkillsFleetCredentialError(error61, vaultReference) {
|
|
21118
21126
|
if (!isCredentialResolutionError(error61))
|
|
21119
21127
|
return null;
|
|
21120
|
-
return new SkillsFleetCredentialError(error61.message, "MISSING_API_CREDENTIAL");
|
|
21128
|
+
return new SkillsFleetCredentialError(redactVaultReference(error61.message, vaultReference), "MISSING_API_CREDENTIAL");
|
|
21121
21129
|
}
|
|
21122
21130
|
function normalizeSkillsApiOrigin(apiUrl) {
|
|
21123
21131
|
const url2 = new URL(apiUrl);
|
|
@@ -21304,7 +21312,7 @@ async function resolveSkillsConnection(env = process.env, options = {}) {
|
|
|
21304
21312
|
try {
|
|
21305
21313
|
completed = await completePointerCredential(SKILLS_APP, pointer, env);
|
|
21306
21314
|
} catch (error61) {
|
|
21307
|
-
const translated = asSkillsFleetCredentialError(error61);
|
|
21315
|
+
const translated = asSkillsFleetCredentialError(error61, pointer.pointerVaultKey);
|
|
21308
21316
|
if (translated)
|
|
21309
21317
|
throw translated;
|
|
21310
21318
|
throw error61;
|
|
@@ -21360,7 +21368,7 @@ function requireSkillsFleet(action = "This command", env = process.env, options
|
|
|
21360
21368
|
return fleet;
|
|
21361
21369
|
throw new MissingSkillsFleetError(action);
|
|
21362
21370
|
}
|
|
21363
|
-
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;
|
|
21371
|
+
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;
|
|
21364
21372
|
var init_fleet_credentials = __esm(() => {
|
|
21365
21373
|
init_transport();
|
|
21366
21374
|
init_instance_credentials();
|
|
@@ -39489,14 +39497,15 @@ function profileSelectionSnapshot(selections) {
|
|
|
39489
39497
|
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;
|
|
39490
39498
|
var init_profile_limits = __esm(() => {
|
|
39491
39499
|
MAX_PROFILE_DOCUMENT_BYTES = 8 * 1024 * 1024;
|
|
39492
|
-
PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS *
|
|
39500
|
+
PROFILE_SESSION_ENVELOPE_BYTES = MAX_PROFILE_SELECTIONS * 67 + MAX_SKILL_SESSION_ID_CHARS * 12 + 512;
|
|
39493
39501
|
MAX_RESOLVED_PROFILE_BYTES = MAX_PROFILE_DOCUMENT_BYTES - PROFILE_SESSION_ENVELOPE_BYTES;
|
|
39494
39502
|
});
|
|
39495
39503
|
|
|
39496
39504
|
// src/lib/selection-cache.ts
|
|
39497
39505
|
import { createHash as createHash3, randomUUID } from "crypto";
|
|
39498
|
-
import { closeSync as closeSync5, constants as constants2, fstatSync as fstatSync5, lstatSync as lstatSync5, mkdirSync as mkdirSync4, openSync as openSync5, readSync as readSync2, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
|
|
39506
|
+
import { closeSync as closeSync5, constants as constants2, fstatSync as fstatSync5, fsyncSync, lstatSync as lstatSync5, mkdirSync as mkdirSync4, openSync as openSync5, readSync as readSync2, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
|
|
39499
39507
|
import { dirname as dirname5, join as join13, parse as parse6, resolve as resolve3 } from "path";
|
|
39508
|
+
import { isDeepStrictEqual } from "util";
|
|
39500
39509
|
function selectionCacheRoot(options = {}) {
|
|
39501
39510
|
return resolve3(options.cacheDir ?? join13(getDataDirReadOnly(), "selection-cache"));
|
|
39502
39511
|
}
|
|
@@ -39600,12 +39609,21 @@ function writeSelectionJson(path, value) {
|
|
|
39600
39609
|
throw new SkillSelectionError("RECEIPT_TOO_LARGE", "The Skills selection receipt exceeds its size limit.");
|
|
39601
39610
|
atomicWrite(path, bytes, 384);
|
|
39602
39611
|
}
|
|
39603
|
-
function atomicWrite(path, bytes, mode) {
|
|
39612
|
+
function atomicWrite(path, bytes, mode, durable = false) {
|
|
39604
39613
|
assertRegularPath(path, true);
|
|
39605
39614
|
const temporary = join13(dirname5(path), `.selection-${randomUUID()}.tmp`);
|
|
39606
39615
|
try {
|
|
39607
|
-
|
|
39616
|
+
const fd = openSync5(temporary, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, mode);
|
|
39617
|
+
try {
|
|
39618
|
+
writeFileSync4(fd, bytes);
|
|
39619
|
+
if (durable)
|
|
39620
|
+
fsyncSync(fd);
|
|
39621
|
+
} finally {
|
|
39622
|
+
closeSync5(fd);
|
|
39623
|
+
}
|
|
39608
39624
|
renameSync2(temporary, path);
|
|
39625
|
+
if (durable)
|
|
39626
|
+
syncDirectory(dirname5(path));
|
|
39609
39627
|
} finally {
|
|
39610
39628
|
try {
|
|
39611
39629
|
unlinkSync(temporary);
|
|
@@ -39718,16 +39736,130 @@ function sessionReceiptPath(sessionId, options = {}) {
|
|
|
39718
39736
|
throw new SkillSelectionError("INVALID_SESSION", `A Skills session id must contain 1\u2013${MAX_SKILL_SESSION_ID_CHARS} characters.`);
|
|
39719
39737
|
return join13(selectionCacheRoot(options), "sessions", `${hash2(sessionId)}.json`);
|
|
39720
39738
|
}
|
|
39721
|
-
function
|
|
39722
|
-
|
|
39723
|
-
|
|
39724
|
-
|
|
39725
|
-
|
|
39726
|
-
|
|
39727
|
-
|
|
39739
|
+
function skillSessionGeneration(receipt) {
|
|
39740
|
+
return receipt.generation ?? 0;
|
|
39741
|
+
}
|
|
39742
|
+
function validateSkillSessionBinding(binding) {
|
|
39743
|
+
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)) {
|
|
39744
|
+
throw new SkillSelectionError("INVALID_RECEIPT", "The Skills session receipt contains an invalid parent snapshot binding.");
|
|
39745
|
+
}
|
|
39746
|
+
}
|
|
39747
|
+
function validateSkillSessionReceipt(receipt, sessionId) {
|
|
39748
|
+
validateSelectionReceipt(receipt);
|
|
39749
|
+
const keys = new Set(receipt.profile.selections.map(selectionKey));
|
|
39750
|
+
if (receipt.sessionId !== sessionId || !Array.isArray(receipt.loaded) || receipt.loaded.length > keys.size || new Set(receipt.loaded).size !== receipt.loaded.length || !receipt.loaded.every((key) => keys.has(key)) || receipt.generation !== undefined && (!Number.isSafeInteger(receipt.generation) || receipt.generation < 1)) {
|
|
39751
|
+
throw new SkillSelectionError("INVALID_RECEIPT", "The Skills session receipt is invalid.");
|
|
39752
|
+
}
|
|
39753
|
+
if (receipt.parent) {
|
|
39754
|
+
validateSkillSessionBinding(receipt.parent);
|
|
39755
|
+
if (receipt.parent.sessionId === sessionId)
|
|
39756
|
+
throw new SkillSelectionError("INVALID_RECEIPT", "A Skills child session cannot name itself as its parent.");
|
|
39757
|
+
}
|
|
39758
|
+
}
|
|
39759
|
+
function readSkillSessionSnapshotIfExists(sessionId, options = {}) {
|
|
39760
|
+
const path = sessionReceiptPath(sessionId, options), bytes = readRegularFile(path, MAX_PROFILE_DOCUMENT_BYTES);
|
|
39761
|
+
if (!bytes)
|
|
39762
|
+
return null;
|
|
39763
|
+
let receipt;
|
|
39764
|
+
try {
|
|
39765
|
+
receipt = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
39766
|
+
} catch {
|
|
39767
|
+
throw new SkillSelectionError("INVALID_RECEIPT", "The Skills session receipt is unreadable.");
|
|
39768
|
+
}
|
|
39769
|
+
validateSkillSessionReceipt(receipt, sessionId);
|
|
39770
|
+
const sha256 = sha256Hex(bytes);
|
|
39771
|
+
return { path, bytes, receipt, sha256, sessionId, generation: skillSessionGeneration(receipt), receiptSha256: sha256 };
|
|
39772
|
+
}
|
|
39773
|
+
function skillSessionSnapshotBinding(snapshot) {
|
|
39774
|
+
return { sessionId: snapshot.sessionId, generation: snapshot.generation, receiptSha256: snapshot.receiptSha256 };
|
|
39775
|
+
}
|
|
39776
|
+
function withSessionWriteLocks(sessionIds, options, action) {
|
|
39777
|
+
const operationId = randomUUID();
|
|
39778
|
+
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);
|
|
39779
|
+
const owned = [];
|
|
39780
|
+
const assertOwned = () => {
|
|
39781
|
+
for (const lock of owned) {
|
|
39782
|
+
const current = lstatSync5(lock.path, { throwIfNoEntry: false });
|
|
39783
|
+
if (!current?.isFile() || current.dev !== lock.dev || current.ino !== lock.ino) {
|
|
39784
|
+
throw new SkillSelectionError("SESSION_WRITE_LOCK_CHANGED", "A session write lock changed during the operation; no replacement is permitted.");
|
|
39785
|
+
}
|
|
39786
|
+
}
|
|
39787
|
+
};
|
|
39788
|
+
try {
|
|
39789
|
+
for (const lock of locks) {
|
|
39790
|
+
assertRegularPath(lock.path, true);
|
|
39791
|
+
let fd;
|
|
39792
|
+
try {
|
|
39793
|
+
fd = openSync5(lock.path, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW, 384);
|
|
39794
|
+
} catch (error61) {
|
|
39795
|
+
if (error61.code === "EEXIST")
|
|
39796
|
+
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.");
|
|
39797
|
+
throw error61;
|
|
39798
|
+
}
|
|
39799
|
+
const stat = fstatSync5(fd);
|
|
39800
|
+
owned.push({ path: lock.path, fd, dev: stat.dev, ino: stat.ino });
|
|
39801
|
+
writeFileSync4(fd, `${JSON.stringify({ schemaVersion: 1, operationId, sessionId: lock.sessionId, pid: process.pid })}
|
|
39802
|
+
`);
|
|
39803
|
+
}
|
|
39804
|
+
return action(assertOwned);
|
|
39805
|
+
} finally {
|
|
39806
|
+
for (const lock of owned.reverse()) {
|
|
39807
|
+
closeSync5(lock.fd);
|
|
39808
|
+
const current = lstatSync5(lock.path, { throwIfNoEntry: false });
|
|
39809
|
+
if (current?.isFile() && current.dev === lock.dev && current.ino === lock.ino)
|
|
39810
|
+
unlinkSync(lock.path);
|
|
39728
39811
|
}
|
|
39729
39812
|
}
|
|
39730
|
-
|
|
39813
|
+
}
|
|
39814
|
+
function sameSnapshot(actual, expected) {
|
|
39815
|
+
return actual === null ? expected === null : expected !== null && actual.sessionId === expected.sessionId && actual.generation === expected.generation && actual.receiptSha256 === expected.receiptSha256;
|
|
39816
|
+
}
|
|
39817
|
+
function nextSkillSessionGeneration(generation) {
|
|
39818
|
+
if (!Number.isSafeInteger(generation) || generation < 0 || generation >= Number.MAX_SAFE_INTEGER) {
|
|
39819
|
+
throw new SkillSelectionError("SESSION_GENERATION_EXHAUSTED", "The Skills session generation cannot advance safely; preserve the receipt and review recovery before continuing.");
|
|
39820
|
+
}
|
|
39821
|
+
return generation + 1;
|
|
39822
|
+
}
|
|
39823
|
+
function parentChanged() {
|
|
39824
|
+
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.");
|
|
39825
|
+
}
|
|
39826
|
+
function writeSkillSession(receipt, expected, options = {}) {
|
|
39827
|
+
validateSkillSessionReceipt(receipt, receipt.sessionId);
|
|
39828
|
+
if (expected.parent)
|
|
39829
|
+
validateSkillSessionBinding(expected.parent);
|
|
39830
|
+
if (expected.parent?.sessionId === receipt.sessionId)
|
|
39831
|
+
throw new SkillSelectionError("INVALID_RECEIPT", "A Skills child session cannot name itself as its parent.");
|
|
39832
|
+
const lockIds = expected.parent ? [receipt.sessionId, expected.parent.sessionId] : [receipt.sessionId];
|
|
39833
|
+
withSessionWriteLocks(lockIds, options, (assertOwned) => {
|
|
39834
|
+
const current = readSkillSessionSnapshotIfExists(receipt.sessionId, options);
|
|
39835
|
+
if (!sameSnapshot(current, expected.current) || current && !isDeepStrictEqual(current.receipt.profile, receipt.profile)) {
|
|
39836
|
+
throw new SkillSelectionError("SESSION_RECEIPT_CHANGED", "The Skills session receipt changed while context was loading; resolve context again without replacing the current pin.");
|
|
39837
|
+
}
|
|
39838
|
+
let parent = null;
|
|
39839
|
+
if (expected.parent) {
|
|
39840
|
+
parent = readSkillSessionSnapshotIfExists(expected.parent.sessionId, options);
|
|
39841
|
+
if (!sameSnapshot(parent, expected.parent) || !parent || !isDeepStrictEqual(parent.receipt.profile, receipt.profile))
|
|
39842
|
+
parentChanged();
|
|
39843
|
+
}
|
|
39844
|
+
const generation = nextSkillSessionGeneration(current?.generation ?? 0);
|
|
39845
|
+
const next = current ? { ...current.receipt, generation, loaded: [...new Set([...current.receipt.loaded, ...receipt.loaded])] } : { ...receipt, generation, ...expected.parent ? { parent: expected.parent } : {} };
|
|
39846
|
+
assertOwned();
|
|
39847
|
+
if (expected.parent) {
|
|
39848
|
+
parent = readSkillSessionSnapshotIfExists(expected.parent.sessionId, options);
|
|
39849
|
+
if (!sameSnapshot(parent, expected.parent))
|
|
39850
|
+
parentChanged();
|
|
39851
|
+
}
|
|
39852
|
+
writeSelectionJson(sessionReceiptPath(receipt.sessionId, options), next);
|
|
39853
|
+
});
|
|
39854
|
+
}
|
|
39855
|
+
function syncDirectory(path) {
|
|
39856
|
+
assertRegularPath(path);
|
|
39857
|
+
const fd = openSync5(path, constants2.O_RDONLY | constants2.O_DIRECTORY | constants2.O_NOFOLLOW);
|
|
39858
|
+
try {
|
|
39859
|
+
fsyncSync(fd);
|
|
39860
|
+
} finally {
|
|
39861
|
+
closeSync5(fd);
|
|
39862
|
+
}
|
|
39731
39863
|
}
|
|
39732
39864
|
var SkillSelectionError, MAX_CACHED_PROFILE_AGE_MS, SELECTION_LOCK_FILE = "selection.lock.json";
|
|
39733
39865
|
var init_selection_cache = __esm(() => {
|
|
@@ -39747,6 +39879,7 @@ var init_selection_cache = __esm(() => {
|
|
|
39747
39879
|
});
|
|
39748
39880
|
|
|
39749
39881
|
// src/lib/agent-policy-limits.ts
|
|
39882
|
+
import { basename as basename4, isAbsolute as isAbsolute4, resolve as resolve4 } from "path";
|
|
39750
39883
|
function object4(value) {
|
|
39751
39884
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
39752
39885
|
}
|
|
@@ -39811,7 +39944,20 @@ function assertAgentPolicyCollections(policy) {
|
|
|
39811
39944
|
text(source.path);
|
|
39812
39945
|
requireBound(source.sha256 === null || typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256));
|
|
39813
39946
|
if (source.hashMode !== undefined)
|
|
39814
|
-
requireBound(["bytes", "path-bytes"].includes(source.hashMode) && source.format === undefined && source.fields === undefined && (source.hashMode
|
|
39947
|
+
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));
|
|
39948
|
+
if (source.hashMode === "claude-marketplace-registry")
|
|
39949
|
+
requireBound(agent === "claude" && value.agent === "claude" && value.method === "reviewed" && !/[\x00-\x1f\x7f]/.test(source.path) && isAbsolute4(source.path) && resolve4(source.path) === source.path && basename4(source.path) === "known_marketplaces.json");
|
|
39950
|
+
if (source.hashMode === "claude-plugin-registry") {
|
|
39951
|
+
requireBound(agent === "claude");
|
|
39952
|
+
const managed = array3(source.managedPlugins, 64);
|
|
39953
|
+
requireBound(managed.length > 0);
|
|
39954
|
+
for (const entry of managed) {
|
|
39955
|
+
requireBound(object4(entry) && Object.keys(entry).every((key) => ["bindingId", "storeRoot"].includes(key)));
|
|
39956
|
+
text(entry.storeRoot);
|
|
39957
|
+
requireBound(typeof entry.bindingId === "string" && /^[a-f0-9]{64}$/.test(entry.bindingId));
|
|
39958
|
+
}
|
|
39959
|
+
} else
|
|
39960
|
+
requireBound(source.managedPlugins === undefined);
|
|
39815
39961
|
if (source.format !== undefined)
|
|
39816
39962
|
requireBound(["json", "toml", "yaml"].includes(source.format));
|
|
39817
39963
|
if (source.fields !== undefined)
|
|
@@ -40036,10 +40182,10 @@ class HttpProfileClient {
|
|
|
40036
40182
|
this.origin = normalizeSkillsApiOrigin(origin);
|
|
40037
40183
|
this.authority = skillsApiRequestUrl(this.origin, "/api/v1/").replace(/\/+$/, "");
|
|
40038
40184
|
}
|
|
40039
|
-
async
|
|
40185
|
+
async requestRoute(route, init = {}) {
|
|
40040
40186
|
let response;
|
|
40041
40187
|
try {
|
|
40042
|
-
response = await fetch(skillsApiRequestUrl(this.origin,
|
|
40188
|
+
response = await fetch(skillsApiRequestUrl(this.origin, route), {
|
|
40043
40189
|
...init,
|
|
40044
40190
|
redirect: "error",
|
|
40045
40191
|
credentials: "omit",
|
|
@@ -40060,6 +40206,9 @@ class HttpProfileClient {
|
|
|
40060
40206
|
}
|
|
40061
40207
|
return response;
|
|
40062
40208
|
}
|
|
40209
|
+
request(path, init = {}) {
|
|
40210
|
+
return this.requestRoute(`/api/v1${path}`, init);
|
|
40211
|
+
}
|
|
40063
40212
|
async read(response, limit = MAX_PROFILE_DOCUMENT_BYTES) {
|
|
40064
40213
|
try {
|
|
40065
40214
|
return JSON.parse(new TextDecoder().decode(await readBoundedResponse(response, limit)));
|
|
@@ -40085,6 +40234,12 @@ class HttpProfileClient {
|
|
|
40085
40234
|
invalid();
|
|
40086
40235
|
return result;
|
|
40087
40236
|
}
|
|
40237
|
+
async resolvePrincipal() {
|
|
40238
|
+
const result = await this.read(await this.requestRoute("/api/auth/whoami"), 16 * 1024);
|
|
40239
|
+
if (!object5(result) || Object.keys(result).sort().join(",") !== "organization,user" || !object5(result.user) || Object.keys(result.user).sort().join(",") !== "email,id,role" || !object5(result.organization) || Object.keys(result.organization).sort().join(",") !== "id,name,slug" || !identifier(result.user.id) || typeof result.user.email !== "string" || !result.user.email.trim() || !["owner", "admin", "member", "viewer"].includes(String(result.user.role)) || !identifier(result.organization.id) || !identifier(result.organization.slug) || typeof result.organization.name !== "string" || !result.organization.name.trim())
|
|
40240
|
+
invalid();
|
|
40241
|
+
return { userId: result.user.id, accountId: result.organization.id, role: result.user.role };
|
|
40242
|
+
}
|
|
40088
40243
|
async recordStation(id, input2) {
|
|
40089
40244
|
if (!identifier(id) || !identifier(input2.profileId) || !identifier(input2.profileRevision) || !Array.isArray(input2.selections) || input2.selections.length > MAX_PROFILE_SELECTIONS)
|
|
40090
40245
|
throw new Error("Invalid station state");
|
|
@@ -47371,6 +47526,72 @@ var init_agent_discovery_path_bytes = __esm(() => {
|
|
|
47371
47526
|
init_agent_discovery_bytes();
|
|
47372
47527
|
});
|
|
47373
47528
|
|
|
47529
|
+
// src/lib/plugin-projection.ts
|
|
47530
|
+
var PLUGIN_PROJECTION_LIMITS;
|
|
47531
|
+
var init_plugin_projection = __esm(() => {
|
|
47532
|
+
init_selection_cache();
|
|
47533
|
+
PLUGIN_PROJECTION_LIMITS = Object.freeze({ files: 1024, bytes: 64 * 1024 * 1024, fileBytes: 16 * 1024 * 1024, metadataBytes: 512 * 1024, registrations: 64, history: 128 });
|
|
47534
|
+
});
|
|
47535
|
+
|
|
47536
|
+
// src/lib/plugin-projection-store.ts
|
|
47537
|
+
import { constants as constants5, closeSync as closeSync8, fchmodSync, fstatSync as fstatSync8, fsyncSync as fsyncSync2, linkSync, lstatSync as lstatSync8, mkdirSync as mkdirSync6, openSync as openSync8, opendirSync, readSync as readSync4, renameSync as renameSync3, rmdirSync as rmdirSync2, rmSync as rmSync2, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
|
|
47538
|
+
var READ_FLAGS, WRITE_FLAGS;
|
|
47539
|
+
var init_plugin_projection_store = __esm(() => {
|
|
47540
|
+
init_plugin_projection();
|
|
47541
|
+
READ_FLAGS = constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK;
|
|
47542
|
+
WRITE_FLAGS = constants5.O_WRONLY | constants5.O_CREAT | constants5.O_EXCL | constants5.O_NOFOLLOW | constants5.O_NONBLOCK;
|
|
47543
|
+
});
|
|
47544
|
+
|
|
47545
|
+
// src/lib/selected-manifest.ts
|
|
47546
|
+
function jsonEntry(entries, path) {
|
|
47547
|
+
const entry = entries.find((candidate) => candidate.path === path);
|
|
47548
|
+
if (!entry)
|
|
47549
|
+
return {};
|
|
47550
|
+
try {
|
|
47551
|
+
const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(entry.bytes));
|
|
47552
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
47553
|
+
throw new Error;
|
|
47554
|
+
return value;
|
|
47555
|
+
} catch {
|
|
47556
|
+
throw new SkillSelectionError("INVALID_SKILL_MANIFEST", "The selected skill has an invalid execution manifest.");
|
|
47557
|
+
}
|
|
47558
|
+
}
|
|
47559
|
+
function describeEntries(entries) {
|
|
47560
|
+
const manifest = jsonEntry(entries, "skill.json"), packageJson = jsonEntry(entries, "package.json");
|
|
47561
|
+
const docs = entries.find((entry) => entry.path === "SKILL.md");
|
|
47562
|
+
const frontmatter = docs ? parseSkillFrontmatter(new TextDecoder().decode(docs.bytes)) : null;
|
|
47563
|
+
const kind = frontmatter?.kind === "instruction" || manifest.kind === "instruction" || packageJson.skills?.kind === "instruction" ? "instruction" : "executable";
|
|
47564
|
+
return { kind, manifest, packageJson };
|
|
47565
|
+
}
|
|
47566
|
+
var init_selected_manifest = __esm(() => {
|
|
47567
|
+
init_skill_validation();
|
|
47568
|
+
init_selection_cache();
|
|
47569
|
+
});
|
|
47570
|
+
|
|
47571
|
+
// src/lib/plugin-admission.ts
|
|
47572
|
+
var init_plugin_admission = __esm(() => {
|
|
47573
|
+
init_profile_client();
|
|
47574
|
+
init_skill_bundle();
|
|
47575
|
+
init_selection_cache();
|
|
47576
|
+
init_selection_resolver();
|
|
47577
|
+
init_plugin_projection();
|
|
47578
|
+
init_plugin_projection_store();
|
|
47579
|
+
init_selected_manifest();
|
|
47580
|
+
});
|
|
47581
|
+
|
|
47582
|
+
// src/lib/plugin-discovery.ts
|
|
47583
|
+
var init_plugin_discovery = __esm(() => {
|
|
47584
|
+
init_plugin_admission();
|
|
47585
|
+
init_plugin_projection();
|
|
47586
|
+
init_plugin_projection_store();
|
|
47587
|
+
});
|
|
47588
|
+
|
|
47589
|
+
// src/lib/claude-marketplace-registry.ts
|
|
47590
|
+
var CLAUDE_MARKETPLACE_REGISTRY_LIMITS;
|
|
47591
|
+
var init_claude_marketplace_registry = __esm(() => {
|
|
47592
|
+
CLAUDE_MARKETPLACE_REGISTRY_LIMITS = Object.freeze({ bytes: 1024 * 1024, rows: 1024, depth: 32, nodes: 65536, stringCharacters: 16384, pathCharacters: 4096 });
|
|
47593
|
+
});
|
|
47594
|
+
|
|
47374
47595
|
// src/lib/agent-discovery.ts
|
|
47375
47596
|
var init_agent_discovery = __esm(() => {
|
|
47376
47597
|
init_agent_policy_limits();
|
|
@@ -47378,6 +47599,9 @@ var init_agent_discovery = __esm(() => {
|
|
|
47378
47599
|
init_agent_discovery_directories();
|
|
47379
47600
|
init_agent_discovery_bytes();
|
|
47380
47601
|
init_agent_discovery_path_bytes();
|
|
47602
|
+
init_plugin_discovery();
|
|
47603
|
+
init_plugin_admission();
|
|
47604
|
+
init_claude_marketplace_registry();
|
|
47381
47605
|
init_agent_discovery_directories();
|
|
47382
47606
|
});
|
|
47383
47607
|
|
|
@@ -47418,7 +47642,7 @@ function normalizeSkillName(name) {
|
|
|
47418
47642
|
}
|
|
47419
47643
|
|
|
47420
47644
|
// src/lib/project-state.ts
|
|
47421
|
-
import { existsSync as existsSync10, mkdirSync as
|
|
47645
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync12, writeFileSync as writeFileSync5 } from "fs";
|
|
47422
47646
|
import { join as join16 } from "path";
|
|
47423
47647
|
function getProjectStateDir(targetDir = process.cwd()) {
|
|
47424
47648
|
return join16(targetDir, SKILLS_PROJECT_DIR);
|
|
@@ -47452,7 +47676,7 @@ function ensureProjectConfig(targetDir = process.cwd()) {
|
|
|
47452
47676
|
}
|
|
47453
47677
|
function saveProjectConfig(config2, targetDir = process.cwd()) {
|
|
47454
47678
|
const dir = getProjectStateDir(targetDir);
|
|
47455
|
-
|
|
47679
|
+
mkdirSync7(dir, { recursive: true });
|
|
47456
47680
|
const normalized = normalizeProjectConfig({ ...config2, updatedAt: new Date().toISOString() });
|
|
47457
47681
|
writeFileSync5(getProjectConfigPath(targetDir), JSON.stringify(normalized, null, 2) + `
|
|
47458
47682
|
`);
|
|
@@ -47539,7 +47763,7 @@ var init_project_state = __esm(() => {
|
|
|
47539
47763
|
});
|
|
47540
47764
|
|
|
47541
47765
|
// src/lib/installer.ts
|
|
47542
|
-
import { existsSync as existsSync11, readFileSync as readFileSync13, rmSync as
|
|
47766
|
+
import { existsSync as existsSync11, readFileSync as readFileSync13, rmSync as rmSync3 } from "fs";
|
|
47543
47767
|
import { join as join17 } from "path";
|
|
47544
47768
|
import { homedir as homedir2 } from "os";
|
|
47545
47769
|
function getSkillPath(name) {
|
|
@@ -47941,11 +48165,18 @@ var init_selected_document = __esm(() => {
|
|
|
47941
48165
|
|
|
47942
48166
|
// src/lib/selection-resolver.ts
|
|
47943
48167
|
async function resolveSelectionContext(profileId, options = {}) {
|
|
47944
|
-
const
|
|
47945
|
-
const
|
|
48168
|
+
const sessionState = options.sessionId ? readSkillSessionSnapshotIfExists(options.sessionId, options) : null;
|
|
48169
|
+
const session = sessionState?.receipt ?? null;
|
|
48170
|
+
const parentState = !session && options.parentSessionId ? readSkillSessionSnapshotIfExists(options.parentSessionId, options) : null;
|
|
48171
|
+
if (!session && options.parentSessionId && !parentState) {
|
|
48172
|
+
throw new SkillSelectionError("SESSION_PARENT_NOT_FOUND", "A child Skills session requires an existing parent receipt so its inherited pin can be bound exactly.");
|
|
48173
|
+
}
|
|
48174
|
+
const parentSession = parentState?.receipt ?? null;
|
|
48175
|
+
const sessionSnapshot = sessionState ? skillSessionSnapshotBinding(sessionState) : null;
|
|
48176
|
+
const parentSnapshot = parentState ? skillSessionSnapshotBinding(parentState) : undefined;
|
|
47946
48177
|
const project = options.projectDir ? readProjectSelection(options.projectDir) : null;
|
|
47947
48178
|
if (session && session.profile.profileId !== profileId || parentSession && parentSession.profile.profileId !== profileId || project && project.profile.profileId !== profileId) {
|
|
47948
|
-
throw new SkillSelectionError("PROFILE_LOCK_MISMATCH", "The session or project is pinned to a different Skills profile. Select
|
|
48179
|
+
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.");
|
|
47949
48180
|
}
|
|
47950
48181
|
if (options.cached) {
|
|
47951
48182
|
const receipt2 = session ?? parentSession ?? project ?? readSelectionProfile(profileId, options);
|
|
@@ -47953,7 +48184,7 @@ async function resolveSelectionContext(profileId, options = {}) {
|
|
|
47953
48184
|
throw new SkillSelectionError("CACHED_PROFILE_MISSING", "No verified Skills profile is cached; authenticate and sync it first.");
|
|
47954
48185
|
assertFreshCachedProfile(receipt2, options);
|
|
47955
48186
|
assertBinding(receipt2.profile, options);
|
|
47956
|
-
return { receipt: receipt2, session, inheritedLoaded: parentSession?.loaded };
|
|
48187
|
+
return { receipt: receipt2, session, sessionSnapshot, parentSnapshot, inheritedLoaded: parentSession?.loaded };
|
|
47957
48188
|
}
|
|
47958
48189
|
const client = options.client ?? await createProfileClient();
|
|
47959
48190
|
const current = await client.resolveProfile(profileId);
|
|
@@ -47966,7 +48197,7 @@ async function resolveSelectionContext(profileId, options = {}) {
|
|
|
47966
48197
|
throw new SkillSelectionError("PROFILE_IDENTITY_MISMATCH", "The pinned selection belongs to another Skills authority or workspace.");
|
|
47967
48198
|
}
|
|
47968
48199
|
const receipt = locked ?? { schemaVersion: 1, verifiedAt: new Date((options.now ?? Date.now)()).toISOString(), profile: current };
|
|
47969
|
-
return { receipt, session, client, inheritedLoaded: parentSession?.loaded };
|
|
48200
|
+
return { receipt, session, sessionSnapshot, parentSnapshot, client, inheritedLoaded: parentSession?.loaded };
|
|
47970
48201
|
}
|
|
47971
48202
|
function assertBinding(profile, options) {
|
|
47972
48203
|
if (options.authority !== undefined && profile.authority !== options.authority || options.workspaceId !== undefined && profile.workspaceId !== options.workspaceId) {
|
|
@@ -48005,7 +48236,7 @@ async function loadSelectedSkill(spec, profileId, options = {}) {
|
|
|
48005
48236
|
sessionId: options.sessionId,
|
|
48006
48237
|
loaded: [...new Set([...context.session?.loaded ?? [], selectionKey(selection)])]
|
|
48007
48238
|
};
|
|
48008
|
-
|
|
48239
|
+
writeSkillSession(session, { current: context.sessionSnapshot, parent: context.parentSnapshot }, options);
|
|
48009
48240
|
}
|
|
48010
48241
|
return { content, selection, receipt };
|
|
48011
48242
|
}
|
|
@@ -48049,6 +48280,14 @@ var init_skill_context = __esm(() => {
|
|
|
48049
48280
|
init_selected_document();
|
|
48050
48281
|
});
|
|
48051
48282
|
|
|
48283
|
+
// src/lib/session-reconciliation.ts
|
|
48284
|
+
var SESSION_RECONCILIATION_PLAN_TTL_MS;
|
|
48285
|
+
var init_session_reconciliation = __esm(() => {
|
|
48286
|
+
init_profile_client();
|
|
48287
|
+
init_selection_cache();
|
|
48288
|
+
SESSION_RECONCILIATION_PLAN_TTL_MS = 5 * 60 * 1000;
|
|
48289
|
+
});
|
|
48290
|
+
|
|
48052
48291
|
// src/cli/commands/context.ts
|
|
48053
48292
|
function selectedProfileId(explicit) {
|
|
48054
48293
|
return explicit ?? process.env.HASNA_SKILLS_SELECTION_PROFILE ?? readManagedSkillPolicy()?.profileId ?? "default";
|
|
@@ -48059,6 +48298,7 @@ var init_context = __esm(() => {
|
|
|
48059
48298
|
init_selection_resolver();
|
|
48060
48299
|
init_selection_cache();
|
|
48061
48300
|
init_managed_policy();
|
|
48301
|
+
init_session_reconciliation();
|
|
48062
48302
|
});
|
|
48063
48303
|
|
|
48064
48304
|
// src/lib/remote-customer-operations.ts
|
|
@@ -48070,7 +48310,7 @@ var init_remote_customer_operations = __esm(() => {
|
|
|
48070
48310
|
{ name: "list_remote_skills", title: "List Remote Skills", parameter: null, mutates: false, invoke: (client) => client.listSkills() },
|
|
48071
48311
|
{ name: "get_billing_status", title: "Get Billing Status", parameter: null, mutates: false, invoke: (client) => client.getBillingStatus() },
|
|
48072
48312
|
{ name: "list_credit_packs", title: "List Credit Packs", parameter: null, mutates: false, invoke: (client) => client.listCreditPacks() },
|
|
48073
|
-
{ name: "create_credit_checkout", title: "Create Credit Checkout", parameter: "pack_id", mutates: true, invoke: (client, value) => client.createCreditCheckout(value) },
|
|
48313
|
+
{ name: "create_credit_checkout", title: "Create Credit Checkout", parameter: "pack_id", mutates: true, invoke: (client, value, options) => client.createCreditCheckout(value, options) },
|
|
48074
48314
|
{ name: "get_billing_usage", title: "Get Billing Usage", parameter: null, mutates: false, invoke: (client) => client.getUsage() },
|
|
48075
48315
|
{ name: "list_invoices", title: "List Invoices", parameter: null, mutates: false, invoke: (client) => client.listInvoices() },
|
|
48076
48316
|
{ name: "create_billing_checkout", title: "Create Billing Checkout", parameter: null, mutates: true, invoke: (client) => client.createBillingCheckout() },
|
|
@@ -48877,14 +49117,14 @@ var init_remote_workspace_leave = __esm(() => {
|
|
|
48877
49117
|
});
|
|
48878
49118
|
|
|
48879
49119
|
// src/lib/auth-store.ts
|
|
48880
|
-
import { chmodSync, existsSync as existsSync13, mkdirSync as
|
|
48881
|
-
import { basename as
|
|
49120
|
+
import { chmodSync, existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync15, renameSync as renameSync4, statSync as statSync8, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "fs";
|
|
49121
|
+
import { basename as basename5, dirname as dirname6, join as join19 } from "path";
|
|
48882
49122
|
function getAuthFilePath(env = process.env) {
|
|
48883
49123
|
return skillsCredentialFilePath(env);
|
|
48884
49124
|
}
|
|
48885
49125
|
function getIdentityFilePath(env = process.env) {
|
|
48886
49126
|
const file2 = skillsCredentialFilePath(env);
|
|
48887
|
-
return join19(dirname6(file2),
|
|
49127
|
+
return join19(dirname6(file2), basename5(file2).replace(/^credentials/, "identity") + ".json");
|
|
48888
49128
|
}
|
|
48889
49129
|
function getApiUrl(action, env = process.env, options = {}) {
|
|
48890
49130
|
return requireSkillsApiOrigin(action, env, options);
|
|
@@ -49038,6 +49278,35 @@ var init_remote_account = __esm(() => {
|
|
|
49038
49278
|
};
|
|
49039
49279
|
});
|
|
49040
49280
|
|
|
49281
|
+
// src/lib/remote-credit-checkout.ts
|
|
49282
|
+
function creditCheckoutRequestKey(value) {
|
|
49283
|
+
if (value === undefined)
|
|
49284
|
+
return crypto.randomUUID();
|
|
49285
|
+
if (typeof value !== "string" || !creditCheckoutKeyPattern.test(value))
|
|
49286
|
+
throw new Error("Checkout idempotency key must be 8-255 URL-safe characters");
|
|
49287
|
+
return value;
|
|
49288
|
+
}
|
|
49289
|
+
function creditCheckoutFailure(value, status, key) {
|
|
49290
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
49291
|
+
return { code: "CREDIT_CHECKOUT_UNCONFIRMED" };
|
|
49292
|
+
const row = value;
|
|
49293
|
+
if (row.requestIdempotencyKey !== undefined && row.requestIdempotencyKey !== key)
|
|
49294
|
+
return { code: "CREDIT_CHECKOUT_UNCONFIRMED" };
|
|
49295
|
+
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";
|
|
49296
|
+
const delay = row.retryAfterSeconds;
|
|
49297
|
+
return { code, ...code === "CREDIT_CHECKOUT_IN_PROGRESS" || status === 503 && row.error === "credit checkout creation unresolved" ? typeof delay === "number" && Number.isSafeInteger(delay) && delay > 0 && delay <= 3600 ? { retryAfterSeconds: delay } : {} : {} };
|
|
49298
|
+
}
|
|
49299
|
+
var creditCheckoutKeyPattern, creditCheckoutMessages;
|
|
49300
|
+
var init_remote_credit_checkout = __esm(() => {
|
|
49301
|
+
creditCheckoutKeyPattern = /^[A-Za-z0-9._:-]{8,255}$/;
|
|
49302
|
+
creditCheckoutMessages = {
|
|
49303
|
+
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.",
|
|
49304
|
+
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.",
|
|
49305
|
+
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.",
|
|
49306
|
+
CREDIT_CHECKOUT_FULFILLED: "This checkout is already fulfilled. Inspect the account balance; do not create another checkout to recover this purchase."
|
|
49307
|
+
};
|
|
49308
|
+
});
|
|
49309
|
+
|
|
49041
49310
|
// src/lib/remote-profile.ts
|
|
49042
49311
|
function customerNamePatch(input2, field) {
|
|
49043
49312
|
if (!isRecord4(input2) || Object.keys(input2).length !== 1 || !Object.hasOwn(input2, field))
|
|
@@ -49083,10 +49352,10 @@ async function readQuoteUnavailableCode(response) {
|
|
|
49083
49352
|
let timer;
|
|
49084
49353
|
let deadlineExceeded = false;
|
|
49085
49354
|
const expired = Symbol("quote body deadline");
|
|
49086
|
-
const deadline = new Promise((
|
|
49355
|
+
const deadline = new Promise((resolve5) => {
|
|
49087
49356
|
timer = setTimeout(() => {
|
|
49088
49357
|
deadlineExceeded = true;
|
|
49089
|
-
|
|
49358
|
+
resolve5(expired);
|
|
49090
49359
|
reader.cancel().catch(() => {});
|
|
49091
49360
|
}, 1500);
|
|
49092
49361
|
});
|
|
@@ -49135,6 +49404,61 @@ var init_remote_quote_errors = __esm(() => {
|
|
|
49135
49404
|
});
|
|
49136
49405
|
});
|
|
49137
49406
|
|
|
49407
|
+
// src/lib/remote-permissions.ts
|
|
49408
|
+
function parseSkillsAccess(value) {
|
|
49409
|
+
if (value === undefined)
|
|
49410
|
+
return {};
|
|
49411
|
+
if (!record7(value))
|
|
49412
|
+
throw new Error("Invalid Skills permission contract");
|
|
49413
|
+
const result = {};
|
|
49414
|
+
if (value.scopes !== undefined) {
|
|
49415
|
+
if (!Array.isArray(value.scopes) || value.scopes.length > 256 || value.scopes.some((scope) => typeof scope !== "string" || scope.length > 128 || !/^(?:\*|[a-z][a-z0-9.-]*:[a-z0-9.*-]+)$/.test(scope)))
|
|
49416
|
+
throw new Error("Invalid Skills scope contract");
|
|
49417
|
+
result.scopes = [...value.scopes];
|
|
49418
|
+
}
|
|
49419
|
+
if (value.permissions !== undefined) {
|
|
49420
|
+
if (!record7(value.permissions))
|
|
49421
|
+
throw new Error("Invalid Skills permission contract");
|
|
49422
|
+
result.permissions = {};
|
|
49423
|
+
for (const name of permissionNames) {
|
|
49424
|
+
const permission = value.permissions[name];
|
|
49425
|
+
if (permission === undefined)
|
|
49426
|
+
continue;
|
|
49427
|
+
if (typeof permission !== "boolean")
|
|
49428
|
+
throw new Error("Invalid Skills permission contract");
|
|
49429
|
+
result.permissions[name] = permission;
|
|
49430
|
+
}
|
|
49431
|
+
}
|
|
49432
|
+
return result;
|
|
49433
|
+
}
|
|
49434
|
+
function assertSkillsPermission(access, permission) {
|
|
49435
|
+
if (access.permissions?.[permission] === false)
|
|
49436
|
+
throw new RemoteSkillsPermissionError(permission);
|
|
49437
|
+
}
|
|
49438
|
+
var permissionNames, record7 = (value) => value !== null && typeof value === "object" && !Array.isArray(value), RemoteSkillsPermissionError;
|
|
49439
|
+
var init_remote_permissions = __esm(() => {
|
|
49440
|
+
permissionNames = [
|
|
49441
|
+
"read",
|
|
49442
|
+
"publish",
|
|
49443
|
+
"profilesWrite",
|
|
49444
|
+
"stationStateWrite",
|
|
49445
|
+
"cloudSubmit",
|
|
49446
|
+
"executionGrantsRead",
|
|
49447
|
+
"executionGrantsWrite",
|
|
49448
|
+
"executionGrantsResolve"
|
|
49449
|
+
];
|
|
49450
|
+
RemoteSkillsPermissionError = class RemoteSkillsPermissionError extends Error {
|
|
49451
|
+
permission;
|
|
49452
|
+
code = "SKILLS_PERMISSION_DENIED";
|
|
49453
|
+
status = 403;
|
|
49454
|
+
constructor(permission) {
|
|
49455
|
+
super(`The current Skills credential cannot ${permission === "publish" ? "publish skills" : "write shared profiles"}. ` + "Workspace role does not override credential permissions. Ask the workspace administrator to authorize this credential, " + "then check skills auth whoami or skills capabilities. This write request was not sent.");
|
|
49456
|
+
this.permission = permission;
|
|
49457
|
+
this.name = "RemoteSkillsPermissionError";
|
|
49458
|
+
}
|
|
49459
|
+
};
|
|
49460
|
+
});
|
|
49461
|
+
|
|
49138
49462
|
// src/lib/remote-client.ts
|
|
49139
49463
|
var exports_remote_client = {};
|
|
49140
49464
|
__export(exports_remote_client, {
|
|
@@ -49146,6 +49470,7 @@ __export(exports_remote_client, {
|
|
|
49146
49470
|
RemoteRouteUnsupportedError: () => RemoteRouteUnsupportedError,
|
|
49147
49471
|
RemoteRequestError: () => RemoteRequestError,
|
|
49148
49472
|
RemoteQuoteUnavailableError: () => RemoteQuoteUnavailableError,
|
|
49473
|
+
RemoteCreditCheckoutError: () => RemoteCreditCheckoutError,
|
|
49149
49474
|
RemoteCapabilityUnavailableError: () => RemoteCapabilityUnavailableError
|
|
49150
49475
|
});
|
|
49151
49476
|
|
|
@@ -49253,15 +49578,23 @@ class RemoteSkillsClient {
|
|
|
49253
49578
|
}, { quoteRefusal: true });
|
|
49254
49579
|
return parseRemoteRunQuote(await response.json());
|
|
49255
49580
|
}
|
|
49256
|
-
getCapabilities() {
|
|
49257
|
-
if (!this.capabilities)
|
|
49581
|
+
getCapabilities(options = {}) {
|
|
49582
|
+
if (!this.capabilities || options.refresh)
|
|
49258
49583
|
this.capabilities = (async () => {
|
|
49259
|
-
const
|
|
49584
|
+
const response = await this.requestNewRoute("/api/v1/capabilities");
|
|
49585
|
+
let value;
|
|
49586
|
+
try {
|
|
49587
|
+
value = await response.json();
|
|
49588
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
49589
|
+
throw new Error;
|
|
49590
|
+
} catch {
|
|
49591
|
+
throw new Error("Invalid Skills capability response");
|
|
49592
|
+
}
|
|
49260
49593
|
if (value.contractVersion !== 1 || value.apiVersion !== 1 || !Array.isArray(value.capabilities) || value.capabilities.some((item) => typeof item !== "string"))
|
|
49261
49594
|
throw new Error("Unsupported Skills server capability contract");
|
|
49262
49595
|
const billing = value.billing;
|
|
49263
49596
|
const recurringConsents = parseRecurringCapability(value.recurringConsents);
|
|
49264
|
-
return { contractVersion: 1, apiVersion: 1, capabilities: value.capabilities, ...billing ? { billing } : {}, ...recurringConsents ? { recurringConsents } : {} };
|
|
49597
|
+
return { contractVersion: 1, apiVersion: 1, capabilities: value.capabilities, ...parseSkillsAccess(value), ...billing ? { billing } : {}, ...recurringConsents ? { recurringConsents } : {} };
|
|
49265
49598
|
})();
|
|
49266
49599
|
return this.capabilities;
|
|
49267
49600
|
}
|
|
@@ -49588,14 +49921,43 @@ class RemoteSkillsClient {
|
|
|
49588
49921
|
async listCreditPacks() {
|
|
49589
49922
|
return parseRemoteCreditPacks(await (await this.requestNewRoute("/api/v1/billing/credits")).json());
|
|
49590
49923
|
}
|
|
49591
|
-
async createCreditCheckout(packId) {
|
|
49924
|
+
async createCreditCheckout(packId, options = {}) {
|
|
49925
|
+
const requestIdempotencyKey = creditCheckoutRequestKey(options.idempotencyKey);
|
|
49592
49926
|
const packs = await this.listCreditPacks();
|
|
49593
49927
|
if (!packs.some((pack) => pack.id === packId))
|
|
49594
49928
|
throw new Error("Choose a credit pack returned by skills credits packs");
|
|
49595
|
-
|
|
49596
|
-
|
|
49597
|
-
|
|
49598
|
-
|
|
49929
|
+
let response;
|
|
49930
|
+
try {
|
|
49931
|
+
response = await this.request("/api/v1/billing/credits", {
|
|
49932
|
+
method: "POST",
|
|
49933
|
+
body: JSON.stringify({ packId, idempotencyKey: requestIdempotencyKey })
|
|
49934
|
+
});
|
|
49935
|
+
} catch {
|
|
49936
|
+
throw new RemoteCreditCheckoutError("CREDIT_CHECKOUT_UNCONFIRMED", 0, requestIdempotencyKey);
|
|
49937
|
+
}
|
|
49938
|
+
if (response.status === 404 || response.status === 405) {
|
|
49939
|
+
response.body?.cancel().catch(() => {});
|
|
49940
|
+
throw new RemoteRouteUnsupportedError("/api/v1/billing/credits", response.status, this.apiUrl);
|
|
49941
|
+
}
|
|
49942
|
+
let value;
|
|
49943
|
+
try {
|
|
49944
|
+
value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 4096)));
|
|
49945
|
+
} catch {
|
|
49946
|
+
throw new RemoteCreditCheckoutError("CREDIT_CHECKOUT_UNCONFIRMED", response.status, requestIdempotencyKey);
|
|
49947
|
+
}
|
|
49948
|
+
if (!response.ok) {
|
|
49949
|
+
const failure = creditCheckoutFailure(value, response.status, requestIdempotencyKey);
|
|
49950
|
+
throw new RemoteCreditCheckoutError(failure.code, response.status, requestIdempotencyKey, failure.retryAfterSeconds);
|
|
49951
|
+
}
|
|
49952
|
+
try {
|
|
49953
|
+
const checkout = parseRemoteCheckout(value);
|
|
49954
|
+
const echo = value.requestIdempotencyKey;
|
|
49955
|
+
if (echo !== undefined && echo !== requestIdempotencyKey)
|
|
49956
|
+
throw new Error("checkout request key changed");
|
|
49957
|
+
return { ...checkout, requestIdempotencyKey };
|
|
49958
|
+
} catch {
|
|
49959
|
+
throw new RemoteCreditCheckoutError("CREDIT_CHECKOUT_UNCONFIRMED", response.status, requestIdempotencyKey);
|
|
49960
|
+
}
|
|
49599
49961
|
}
|
|
49600
49962
|
async getUsage() {
|
|
49601
49963
|
return this.arrayResponse("/api/v1/billing/usage");
|
|
@@ -49728,6 +50090,12 @@ class RemoteSkillsClient {
|
|
|
49728
50090
|
}
|
|
49729
50091
|
}
|
|
49730
50092
|
async publishSkill(manifest, bundle, ifMatch) {
|
|
50093
|
+
try {
|
|
50094
|
+
assertSkillsPermission(await this.getCapabilities({ refresh: true }), "publish");
|
|
50095
|
+
} catch (error61) {
|
|
50096
|
+
if (!(error61 instanceof RemoteRouteUnsupportedError))
|
|
50097
|
+
throw error61;
|
|
50098
|
+
}
|
|
49731
50099
|
const form = new FormData;
|
|
49732
50100
|
form.set("manifest", JSON.stringify(manifest));
|
|
49733
50101
|
if (bundle) {
|
|
@@ -49822,13 +50190,13 @@ class RemoteSkillsClient {
|
|
|
49822
50190
|
return normalizeUpdatedSincePage(await response.json());
|
|
49823
50191
|
}
|
|
49824
50192
|
}
|
|
49825
|
-
function requireOptionalString(
|
|
49826
|
-
if (
|
|
50193
|
+
function requireOptionalString(record8, field) {
|
|
50194
|
+
if (record8[field] === undefined)
|
|
49827
50195
|
return;
|
|
49828
|
-
if (typeof
|
|
50196
|
+
if (typeof record8[field] !== "string") {
|
|
49829
50197
|
throw new Error(`Remote payload did not match the expected contract (${field} must be a string when present)`);
|
|
49830
50198
|
}
|
|
49831
|
-
return
|
|
50199
|
+
return record8[field];
|
|
49832
50200
|
}
|
|
49833
50201
|
function isVersionRecord(value) {
|
|
49834
50202
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
@@ -49850,19 +50218,19 @@ function normalizePin(entry) {
|
|
|
49850
50218
|
if (!entry || typeof entry !== "object") {
|
|
49851
50219
|
throw new Error("Remote pin payload did not match the expected contract (expected an object)");
|
|
49852
50220
|
}
|
|
49853
|
-
const
|
|
49854
|
-
const slug2 = typeof
|
|
50221
|
+
const record8 = entry;
|
|
50222
|
+
const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
|
|
49855
50223
|
if (!slug2) {
|
|
49856
50224
|
throw new Error("Remote pin payload did not match the expected contract (missing slug)");
|
|
49857
50225
|
}
|
|
49858
50226
|
let metadata;
|
|
49859
|
-
if (
|
|
49860
|
-
if (!
|
|
50227
|
+
if (record8.metadata !== undefined) {
|
|
50228
|
+
if (!record8.metadata || typeof record8.metadata !== "object" || Array.isArray(record8.metadata)) {
|
|
49861
50229
|
throw new Error("Remote pin payload did not match the expected contract (metadata must be a JSON object when present)");
|
|
49862
50230
|
}
|
|
49863
|
-
metadata =
|
|
50231
|
+
metadata = record8.metadata;
|
|
49864
50232
|
}
|
|
49865
|
-
const pinnedAt = requireOptionalString(
|
|
50233
|
+
const pinnedAt = requireOptionalString(record8, "pinnedAt");
|
|
49866
50234
|
return {
|
|
49867
50235
|
slug: slug2,
|
|
49868
50236
|
...pinnedAt !== undefined ? { pinnedAt } : {},
|
|
@@ -49879,16 +50247,16 @@ function normalizeSkillSummary(entry) {
|
|
|
49879
50247
|
if (!entry || typeof entry !== "object") {
|
|
49880
50248
|
throw new Error("Remote skill payload did not match the expected contract (expected an object)");
|
|
49881
50249
|
}
|
|
49882
|
-
const
|
|
49883
|
-
const slug2 = typeof
|
|
50250
|
+
const record8 = entry;
|
|
50251
|
+
const slug2 = typeof record8.slug === "string" && record8.slug.trim() ? record8.slug.trim() : undefined;
|
|
49884
50252
|
if (!slug2) {
|
|
49885
50253
|
throw new Error("Remote skill payload did not match the expected contract (missing slug)");
|
|
49886
50254
|
}
|
|
49887
50255
|
return {
|
|
49888
50256
|
slug: slug2,
|
|
49889
|
-
...requireOptionalString(
|
|
49890
|
-
...requireOptionalString(
|
|
49891
|
-
...requireOptionalString(
|
|
50257
|
+
...requireOptionalString(record8, "name") !== undefined ? { name: requireOptionalString(record8, "name") } : {},
|
|
50258
|
+
...requireOptionalString(record8, "version") !== undefined ? { version: requireOptionalString(record8, "version") } : {},
|
|
50259
|
+
...requireOptionalString(record8, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record8, "updatedAt") } : {}
|
|
49892
50260
|
};
|
|
49893
50261
|
}
|
|
49894
50262
|
function normalizeSkillSummaryList(payload) {
|
|
@@ -49941,12 +50309,12 @@ function normalizeUpdatedSincePage(payload) {
|
|
|
49941
50309
|
if (!payload || typeof payload !== "object") {
|
|
49942
50310
|
throw new Error("Updated-since payload did not match the expected contract (expected an object)");
|
|
49943
50311
|
}
|
|
49944
|
-
const
|
|
49945
|
-
if (!Array.isArray(
|
|
50312
|
+
const record8 = payload;
|
|
50313
|
+
if (!Array.isArray(record8.skills)) {
|
|
49946
50314
|
throw new Error("Updated-since payload did not match the expected contract (missing skills array)");
|
|
49947
50315
|
}
|
|
49948
|
-
const skills =
|
|
49949
|
-
const nextCursor =
|
|
50316
|
+
const skills = record8.skills.map(normalizeSkillSummary);
|
|
50317
|
+
const nextCursor = record8.nextCursor === undefined || record8.nextCursor === null ? null : record8.nextCursor;
|
|
49950
50318
|
if (nextCursor !== null && typeof nextCursor !== "string") {
|
|
49951
50319
|
throw new Error("Updated-since payload did not match the expected contract (nextCursor must be a string or absent)");
|
|
49952
50320
|
}
|
|
@@ -49959,7 +50327,7 @@ async function createRemoteSkillsClient(env = process.env) {
|
|
|
49959
50327
|
function createRemoteSkillsClientReadOnly(env = process.env) {
|
|
49960
50328
|
return createRemoteSkillsClient(env);
|
|
49961
50329
|
}
|
|
49962
|
-
var RemoteRouteUnsupportedError, RemoteRequestError, RemoteQuoteUnavailableError, RemoteWorkspaceMemberError, RemoteWorkspaceSelectionError, RemoteCapabilityUnavailableError, INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
|
|
50330
|
+
var RemoteRouteUnsupportedError, RemoteRequestError, RemoteCreditCheckoutError, RemoteQuoteUnavailableError, RemoteWorkspaceMemberError, RemoteWorkspaceSelectionError, RemoteCapabilityUnavailableError, INVALID_SKILL_VERSION_RESPONSE = "Remote skill version payload did not match the expected contract.";
|
|
49963
50331
|
var init_remote_client = __esm(() => {
|
|
49964
50332
|
init_remote_recurring();
|
|
49965
50333
|
init_remote_invitations();
|
|
@@ -49971,7 +50339,9 @@ var init_remote_client = __esm(() => {
|
|
|
49971
50339
|
init_fleet_credentials();
|
|
49972
50340
|
init_remote_account();
|
|
49973
50341
|
init_remote_files();
|
|
50342
|
+
init_remote_credit_checkout();
|
|
49974
50343
|
init_remote_quote_errors();
|
|
50344
|
+
init_remote_permissions();
|
|
49975
50345
|
RemoteRouteUnsupportedError = class RemoteRouteUnsupportedError extends Error {
|
|
49976
50346
|
path;
|
|
49977
50347
|
status;
|
|
@@ -49994,6 +50364,19 @@ var init_remote_client = __esm(() => {
|
|
|
49994
50364
|
this.name = "RemoteRequestError";
|
|
49995
50365
|
}
|
|
49996
50366
|
};
|
|
50367
|
+
RemoteCreditCheckoutError = class RemoteCreditCheckoutError extends RemoteRequestError {
|
|
50368
|
+
code;
|
|
50369
|
+
requestIdempotencyKey;
|
|
50370
|
+
retryAfterSeconds;
|
|
50371
|
+
constructor(code, status, requestIdempotencyKey, retryAfterSeconds) {
|
|
50372
|
+
super("/api/v1/billing/credits", status);
|
|
50373
|
+
this.code = code;
|
|
50374
|
+
this.requestIdempotencyKey = requestIdempotencyKey;
|
|
50375
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
50376
|
+
this.name = "RemoteCreditCheckoutError";
|
|
50377
|
+
this.message = creditCheckoutMessages[code];
|
|
50378
|
+
}
|
|
50379
|
+
};
|
|
49997
50380
|
RemoteQuoteUnavailableError = class RemoteQuoteUnavailableError extends RemoteRequestError {
|
|
49998
50381
|
code;
|
|
49999
50382
|
constructor(path, code) {
|
|
@@ -50041,7 +50424,7 @@ function invitationEmailIds(invitationId, challengeId) {
|
|
|
50041
50424
|
}
|
|
50042
50425
|
function invitationEmailInput(action, input2) {
|
|
50043
50426
|
const keys = ["invitationId", "token", "challengeId", "confirm", ...action === "accept" ? ["code"] : []];
|
|
50044
|
-
if (!
|
|
50427
|
+
if (!record8(input2) || Object.keys(input2).length !== keys.length || keys.some((key) => !Object.hasOwn(input2, key)))
|
|
50045
50428
|
throw new InvitationEmailInputError;
|
|
50046
50429
|
const value = { ...input2 };
|
|
50047
50430
|
const ids = invitationEmailIds(value.invitationId, value.challengeId);
|
|
@@ -50070,12 +50453,12 @@ async function requestInvitationEmail(origin, action, input2) {
|
|
|
50070
50453
|
signal: AbortSignal.timeout(15000)
|
|
50071
50454
|
});
|
|
50072
50455
|
const parsed = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(await readBoundedResponse(response, 4096)));
|
|
50073
|
-
if (!response.ok &&
|
|
50456
|
+
if (!response.ok && record8(parsed) && typeof parsed.code === "string" && Object.hasOwn(refusals, parsed.code)) {
|
|
50074
50457
|
const code = parsed.code;
|
|
50075
50458
|
if (response.status === refusals[code][0])
|
|
50076
50459
|
throw new RemoteInvitationEmailError(code);
|
|
50077
50460
|
}
|
|
50078
|
-
if (!
|
|
50461
|
+
if (!record8(parsed))
|
|
50079
50462
|
throw new RemoteInvitationEmailUnconfirmedError(action);
|
|
50080
50463
|
if (action === "challenge" && response.status === 202 && parsed.challengeId === value.challengeId && parsed.expiresIn === 600 && typeof parsed.message === "string" && parsed.message.length <= 256) {
|
|
50081
50464
|
return { challengeId: value.challengeId, message: "If this invitation is eligible, a verification code will arrive. Delivery is not confirmed.", expiresIn: 600 };
|
|
@@ -50094,7 +50477,7 @@ function invitationEmailCustomerError(error61) {
|
|
|
50094
50477
|
return { code: error61.code, error: error61.message };
|
|
50095
50478
|
return { code: "INVITATION_EMAIL_UNAVAILABLE", error: "Unable to prepare this recovery action. Check the explicit server and stable profile. No credential was saved." };
|
|
50096
50479
|
}
|
|
50097
|
-
var InvitationEmailInputError, refusals, RemoteInvitationEmailError, RemoteInvitationEmailUnconfirmedError,
|
|
50480
|
+
var InvitationEmailInputError, refusals, RemoteInvitationEmailError, RemoteInvitationEmailUnconfirmedError, record8 = (v) => !!v && typeof v === "object" && !Array.isArray(v), uuid11 = (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);
|
|
50098
50481
|
var init_remote_invitation_recovery = __esm(() => {
|
|
50099
50482
|
init_fleet_credentials();
|
|
50100
50483
|
init_remote_files();
|
|
@@ -50141,7 +50524,7 @@ function checkedPublicationDeclaration(value) {
|
|
|
50141
50524
|
return bad();
|
|
50142
50525
|
try {
|
|
50143
50526
|
const manifest = JSON.parse(value.manifestText);
|
|
50144
|
-
if (!
|
|
50527
|
+
if (!record9(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
|
|
50145
50528
|
return bad();
|
|
50146
50529
|
} catch {
|
|
50147
50530
|
return bad();
|
|
@@ -50199,7 +50582,7 @@ async function boundedJson(url2, init, token, mutation, budget2 = 15000, signal)
|
|
|
50199
50582
|
return invalid4();
|
|
50200
50583
|
}
|
|
50201
50584
|
if (!response.ok) {
|
|
50202
|
-
const code =
|
|
50585
|
+
const code = record9(body) && typeof body.code === "string" && Object.hasOwn(failures2, body.code) ? body.code : null;
|
|
50203
50586
|
if (code && failures2[code][0] === response.status)
|
|
50204
50587
|
throw new PrivatePublicationError(code, failures2[code][1], mutation && code === "PUBLICATION_UNCERTAIN", response.status);
|
|
50205
50588
|
throw new PrivatePublicationError("PUBLICATION_REQUEST_FAILED", "The publication request was refused. Inspect its status before retrying.", mutation && response.status >= 500, response.status);
|
|
@@ -50254,8 +50637,8 @@ class RemotePrivatePublicationsClient {
|
|
|
50254
50637
|
if (options.timeoutMs !== undefined && (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 15000))
|
|
50255
50638
|
return bad();
|
|
50256
50639
|
const response = await boundedJson(skillsApiRequestUrl(this.apiOrigin, "/api/v1/capabilities"), {}, this.#token, false, options.timeoutMs, options.signal);
|
|
50257
|
-
const p =
|
|
50258
|
-
if (!
|
|
50640
|
+
const p = record9(response) && response.privatePublishing;
|
|
50641
|
+
if (!record9(response) || response.contractVersion !== 1 || response.apiVersion !== 1 || !exact(p, ["contractVersion", "enabled", "authentication", "maxArchiveBytes", "uploadMaxTtlSeconds", "executionEnabled"]) || p.contractVersion !== 1 || typeof p.enabled !== "boolean" || p.authentication !== "interactive-session" || p.maxArchiveBytes !== PRIVATE_PUBLICATION_MAX_BYTES || p.uploadMaxTtlSeconds !== 300 || typeof p.executionEnabled !== "boolean")
|
|
50259
50642
|
throw new PrivatePublicationError("PUBLICATION_CONTRACT_UNAVAILABLE", "This server does not support the hosted private publication contract.");
|
|
50260
50643
|
return Object.freeze({ ...p });
|
|
50261
50644
|
}
|
|
@@ -50271,7 +50654,7 @@ class RemotePrivatePublicationsClient {
|
|
|
50271
50654
|
async#view(path, method, skillId, intentId, declaration, options = {}) {
|
|
50272
50655
|
const value = await boundedJson(path, { method, ...method === "GET" ? {} : { body: JSON.stringify(declaration ?? {}) } }, this.#token, method !== "GET", options.timeoutMs, options.signal);
|
|
50273
50656
|
try {
|
|
50274
|
-
if (!
|
|
50657
|
+
if (!record9(value) || !Object.keys(value).every((k) => k === "upload" || k === "changed") || value.changed !== undefined && typeof value.changed !== "boolean")
|
|
50275
50658
|
return invalid4();
|
|
50276
50659
|
return checkedPublicationView(value.upload, skillId, intentId, declaration);
|
|
50277
50660
|
} catch (error61) {
|
|
@@ -50380,12 +50763,12 @@ class RemotePrivatePublicationsClient {
|
|
|
50380
50763
|
previous = view;
|
|
50381
50764
|
if (!["queued", "verifying"].includes(view.state) || Date.now() >= until)
|
|
50382
50765
|
return view;
|
|
50383
|
-
await new Promise((
|
|
50766
|
+
await new Promise((resolve5) => {
|
|
50384
50767
|
const timer = setTimeout(done, Math.min(1000, until - Date.now()));
|
|
50385
50768
|
function done() {
|
|
50386
50769
|
clearTimeout(timer);
|
|
50387
50770
|
options.signal?.removeEventListener("abort", done);
|
|
50388
|
-
|
|
50771
|
+
resolve5();
|
|
50389
50772
|
}
|
|
50390
50773
|
options.signal?.addEventListener("abort", done, { once: true });
|
|
50391
50774
|
});
|
|
@@ -50396,7 +50779,7 @@ var PRIVATE_PUBLICATION_MAX_BYTES, failures2, PrivatePublicationError, bad = ()
|
|
|
50396
50779
|
throw new PrivatePublicationError("INVALID_PUBLICATION_INPUT", "Invalid publication input or recovery data.");
|
|
50397
50780
|
}, invalid4 = () => {
|
|
50398
50781
|
throw new PrivatePublicationError("INVALID_PUBLICATION_RESPONSE", "The server returned an invalid publication result.");
|
|
50399
|
-
}, 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),
|
|
50782
|
+
}, 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), record9 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys) => record9(v) && Object.keys(v).sort().join(",") === keys.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) => createHash7("sha256").update(bytes).digest("hex");
|
|
50400
50783
|
var init_remote_private_publications = __esm(() => {
|
|
50401
50784
|
init_fleet_credentials();
|
|
50402
50785
|
init_remote_workspace_selection();
|
|
@@ -50460,10 +50843,10 @@ async function requestAuthApi(instance, path, options) {
|
|
|
50460
50843
|
const text3 = await res.text();
|
|
50461
50844
|
const body = text3 ? parseJsonBody(text3) : {};
|
|
50462
50845
|
if (!res.ok) {
|
|
50463
|
-
const
|
|
50464
|
-
const detail = typeof
|
|
50465
|
-
const error61 = typeof
|
|
50466
|
-
const code = typeof
|
|
50846
|
+
const record10 = isRecord5(body) ? body : {};
|
|
50847
|
+
const detail = typeof record10.detail === "string" ? record10.detail : undefined;
|
|
50848
|
+
const error61 = typeof record10.error === "string" ? record10.error : undefined;
|
|
50849
|
+
const code = typeof record10.code === "string" ? record10.code : undefined;
|
|
50467
50850
|
throw new HostedApiError(detail || error61 || `${res.status} ${res.statusText}`, {
|
|
50468
50851
|
status: res.status,
|
|
50469
50852
|
code,
|
|
@@ -50673,10 +51056,10 @@ var init_remote_auth = __esm(() => {
|
|
|
50673
51056
|
});
|
|
50674
51057
|
|
|
50675
51058
|
// src/lib/workspace-profile.ts
|
|
50676
|
-
import { constants as
|
|
51059
|
+
import { constants as constants6, closeSync as closeSync9, fstatSync as fstatSync9, lstatSync as lstatSync9, mkdirSync as mkdirSync9, mkdtempSync as mkdtempSync2, openSync as openSync9, readFileSync as readFileSync16, renameSync as renameSync5, rmSync as rmSync4, writeFileSync as writeFileSync7 } from "fs";
|
|
50677
51060
|
function stat(path) {
|
|
50678
51061
|
try {
|
|
50679
|
-
return
|
|
51062
|
+
return lstatSync9(path);
|
|
50680
51063
|
} catch (error61) {
|
|
50681
51064
|
if (error61.code === "ENOENT")
|
|
50682
51065
|
return null;
|
|
@@ -50686,14 +51069,14 @@ function stat(path) {
|
|
|
50686
51069
|
function safeText(file2) {
|
|
50687
51070
|
if (stat(file2) === null)
|
|
50688
51071
|
return null;
|
|
50689
|
-
const fd =
|
|
51072
|
+
const fd = openSync9(file2, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
|
|
50690
51073
|
try {
|
|
50691
|
-
const s =
|
|
51074
|
+
const s = fstatSync9(fd);
|
|
50692
51075
|
if (!s.isFile() || s.size > 65536 || ![256, 384].includes(s.mode & 4095) || process.getuid && s.uid !== process.getuid())
|
|
50693
51076
|
return fail("The selected profile must use bounded owner-only regular files.");
|
|
50694
51077
|
return readFileSync16(fd, "utf8");
|
|
50695
51078
|
} finally {
|
|
50696
|
-
|
|
51079
|
+
closeSync9(fd);
|
|
50697
51080
|
}
|
|
50698
51081
|
}
|
|
50699
51082
|
function checkIdentityMetadata(file2, identity2) {
|
|
@@ -50905,8 +51288,8 @@ var init_recurring_customer = __esm(() => {
|
|
|
50905
51288
|
});
|
|
50906
51289
|
|
|
50907
51290
|
// src/lib/recurring-recovery.ts
|
|
50908
|
-
import { constants as
|
|
50909
|
-
import { dirname as dirname7, isAbsolute as
|
|
51291
|
+
import { constants as constants7, closeSync as closeSync10, fsyncSync as fsyncSync3, fstatSync as fstatSync10, lstatSync as lstatSync10, mkdirSync as mkdirSync10, openSync as openSync10, readSync as readSync5, realpathSync as realpathSync4, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync8 } from "fs";
|
|
51292
|
+
import { dirname as dirname7, isAbsolute as isAbsolute5, join as join20, resolve as resolve5 } from "path";
|
|
50910
51293
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
50911
51294
|
|
|
50912
51295
|
class RecoveryOwner {
|
|
@@ -50914,10 +51297,10 @@ class RecoveryOwner {
|
|
|
50914
51297
|
parents = [];
|
|
50915
51298
|
constructor(directory) {
|
|
50916
51299
|
this.directory = directory;
|
|
50917
|
-
if (!
|
|
51300
|
+
if (!isAbsolute5(directory) || resolve5(directory) !== directory || realpathSync4(directory) !== directory)
|
|
50918
51301
|
invalid5();
|
|
50919
51302
|
for (let path = directory;; path = dirname7(path)) {
|
|
50920
|
-
const stat2 =
|
|
51303
|
+
const stat2 = lstatSync10(path);
|
|
50921
51304
|
if (!stat2.isDirectory() || stat2.isSymbolicLink())
|
|
50922
51305
|
invalid5();
|
|
50923
51306
|
this.parents.push({ path, dev: stat2.dev, ino: stat2.ino });
|
|
@@ -50930,59 +51313,59 @@ class RecoveryOwner {
|
|
|
50930
51313
|
if (realpathSync4(this.directory) !== this.directory)
|
|
50931
51314
|
invalid5();
|
|
50932
51315
|
for (const prior of this.parents) {
|
|
50933
|
-
const now =
|
|
51316
|
+
const now = lstatSync10(prior.path);
|
|
50934
51317
|
if (!now.isDirectory() || now.isSymbolicLink() || now.dev !== prior.dev || now.ino !== prior.ino)
|
|
50935
51318
|
invalid5();
|
|
50936
51319
|
}
|
|
50937
|
-
const own2 =
|
|
51320
|
+
const own2 = lstatSync10(this.directory);
|
|
50938
51321
|
if ((own2.mode & 511) !== 448 || (own2.mode & 3584) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
50939
51322
|
invalid5();
|
|
50940
51323
|
}
|
|
50941
51324
|
read(name) {
|
|
50942
51325
|
this.assert();
|
|
50943
|
-
const fd =
|
|
51326
|
+
const fd = openSync10(join20(this.directory, name), constants7.O_RDONLY | constants7.O_NOFOLLOW | constants7.O_NONBLOCK);
|
|
50944
51327
|
try {
|
|
50945
|
-
const before =
|
|
51328
|
+
const before = fstatSync10(fd);
|
|
50946
51329
|
if (!before.isFile() || before.nlink !== 1 || (before.mode & 4095) !== 384 || before.size < 1 || before.size > 8192 || process.getuid && before.uid !== process.getuid())
|
|
50947
51330
|
invalid5();
|
|
50948
51331
|
const bytes = Buffer.alloc(before.size + 1);
|
|
50949
51332
|
let size = 0;
|
|
50950
51333
|
while (size < bytes.length) {
|
|
50951
|
-
const n2 =
|
|
51334
|
+
const n2 = readSync5(fd, bytes, size, bytes.length - size, size);
|
|
50952
51335
|
if (!n2)
|
|
50953
51336
|
break;
|
|
50954
51337
|
size += n2;
|
|
50955
51338
|
}
|
|
50956
|
-
const after =
|
|
51339
|
+
const after = fstatSync10(fd), path = lstatSync10(join20(this.directory, name));
|
|
50957
51340
|
if (size !== before.size || after.size !== before.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs || path.dev !== before.dev || path.ino !== before.ino || !path.isFile() || path.isSymbolicLink())
|
|
50958
51341
|
invalid5();
|
|
50959
51342
|
this.assert();
|
|
50960
51343
|
return new TextDecoder("utf-8", { fatal: true }).decode(bytes.subarray(0, size));
|
|
50961
51344
|
} finally {
|
|
50962
|
-
|
|
51345
|
+
closeSync10(fd);
|
|
50963
51346
|
}
|
|
50964
51347
|
}
|
|
50965
51348
|
write(name, value) {
|
|
50966
51349
|
this.assert();
|
|
50967
51350
|
const bytes = canonicalJson(value, 8192) + `
|
|
50968
51351
|
`;
|
|
50969
|
-
const fd =
|
|
51352
|
+
const fd = openSync10(join20(this.directory, name), constants7.O_WRONLY | constants7.O_CREAT | constants7.O_EXCL | constants7.O_NOFOLLOW, 384);
|
|
50970
51353
|
try {
|
|
50971
51354
|
writeFileSync8(fd, bytes);
|
|
50972
|
-
|
|
51355
|
+
fsyncSync3(fd);
|
|
50973
51356
|
} finally {
|
|
50974
|
-
|
|
51357
|
+
closeSync10(fd);
|
|
50975
51358
|
}
|
|
50976
51359
|
this.assert();
|
|
50977
51360
|
this.sync();
|
|
50978
51361
|
}
|
|
50979
51362
|
sync() {
|
|
50980
51363
|
this.assert();
|
|
50981
|
-
const fd =
|
|
51364
|
+
const fd = openSync10(this.directory, constants7.O_RDONLY | constants7.O_NOFOLLOW);
|
|
50982
51365
|
try {
|
|
50983
|
-
|
|
51366
|
+
fsyncSync3(fd);
|
|
50984
51367
|
} finally {
|
|
50985
|
-
|
|
51368
|
+
closeSync10(fd);
|
|
50986
51369
|
}
|
|
50987
51370
|
}
|
|
50988
51371
|
saveState(state, expected) {
|
|
@@ -50993,30 +51376,30 @@ class RecoveryOwner {
|
|
|
50993
51376
|
if (this.read("state.json") !== expected)
|
|
50994
51377
|
invalid5();
|
|
50995
51378
|
this.assert();
|
|
50996
|
-
|
|
51379
|
+
renameSync6(join20(this.directory, name), join20(this.directory, "state.json"));
|
|
50997
51380
|
this.sync();
|
|
50998
51381
|
}
|
|
50999
51382
|
async locked(action) {
|
|
51000
51383
|
this.assert();
|
|
51001
51384
|
let fd;
|
|
51002
51385
|
try {
|
|
51003
|
-
fd =
|
|
51386
|
+
fd = openSync10(join20(this.directory, "operation.lock"), constants7.O_WRONLY | constants7.O_CREAT | constants7.O_EXCL | constants7.O_NOFOLLOW, 384);
|
|
51004
51387
|
} catch {
|
|
51005
51388
|
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.");
|
|
51006
51389
|
}
|
|
51007
|
-
const owner =
|
|
51390
|
+
const owner = fstatSync10(fd);
|
|
51008
51391
|
try {
|
|
51009
51392
|
writeFileSync8(fd, JSON.stringify({ pid: process.pid }));
|
|
51010
|
-
|
|
51393
|
+
fsyncSync3(fd);
|
|
51011
51394
|
this.sync();
|
|
51012
51395
|
return await action();
|
|
51013
51396
|
} finally {
|
|
51014
|
-
|
|
51397
|
+
closeSync10(fd);
|
|
51015
51398
|
this.assert();
|
|
51016
|
-
const now =
|
|
51399
|
+
const now = lstatSync10(join20(this.directory, "operation.lock"));
|
|
51017
51400
|
if (owner.dev !== now.dev || owner.ino !== now.ino || !now.isFile() || now.isSymbolicLink())
|
|
51018
51401
|
invalid5();
|
|
51019
|
-
|
|
51402
|
+
unlinkSync5(join20(this.directory, "operation.lock"));
|
|
51020
51403
|
this.sync();
|
|
51021
51404
|
}
|
|
51022
51405
|
}
|
|
@@ -51049,9 +51432,9 @@ function base(customer, organizationId) {
|
|
|
51049
51432
|
};
|
|
51050
51433
|
}
|
|
51051
51434
|
function create(directory, intent) {
|
|
51052
|
-
if (!
|
|
51435
|
+
if (!isAbsolute5(directory) || resolve5(directory) !== directory || realpathSync4(dirname7(directory)) !== dirname7(directory))
|
|
51053
51436
|
invalid5();
|
|
51054
|
-
|
|
51437
|
+
mkdirSync10(directory, { mode: 448 });
|
|
51055
51438
|
const owner = new RecoveryOwner(directory), checked = intentSchema.parse(intent), intentSha256 = canonicalJsonSha256(checked);
|
|
51056
51439
|
owner.write(`intent-${intentSha256}.json`, checked);
|
|
51057
51440
|
owner.write("state.json", { contractVersion: 1, intentSha256, phase: "prepared", consentId: null });
|
|
@@ -51212,7 +51595,7 @@ var init_recurring_recovery = __esm(() => {
|
|
|
51212
51595
|
});
|
|
51213
51596
|
|
|
51214
51597
|
// src/lib/recurring-surface.ts
|
|
51215
|
-
import { isAbsolute as
|
|
51598
|
+
import { isAbsolute as isAbsolute6 } from "path";
|
|
51216
51599
|
function recurringMcpSchema(action) {
|
|
51217
51600
|
return action === "activate" ? recurringSurfaceSchemas.activate.extend({ code, confirm: exports_external.literal(true) }) : recurringSurfaceSchemas[action];
|
|
51218
51601
|
}
|
|
@@ -51317,7 +51700,7 @@ var init_recurring_surface = __esm(() => {
|
|
|
51317
51700
|
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}$/);
|
|
51318
51701
|
context = { userId: uuid13.optional(), membershipId: uuid13.optional() };
|
|
51319
51702
|
page2 = { limit: exports_external.number().int().min(1).max(100).optional(), cursor: exports_external.string().min(1).max(2048).optional() };
|
|
51320
|
-
directory = exports_external.string().max(4096).refine(
|
|
51703
|
+
directory = exports_external.string().max(4096).refine(isAbsolute6, "Use an absolute recovery directory");
|
|
51321
51704
|
email4 = exports_external.string().trim().toLowerCase().email().max(254);
|
|
51322
51705
|
code = exports_external.string().regex(/^\d{6}$/);
|
|
51323
51706
|
recurringSurfaceSchemas = {
|
|
@@ -52286,11 +52669,11 @@ var init_mcp_contracts = __esm(() => {
|
|
|
52286
52669
|
name: operation.name,
|
|
52287
52670
|
title: operation.title,
|
|
52288
52671
|
description: `${operation.title} on the configured server; unavailable capabilities fail explicitly.`,
|
|
52289
|
-
params: operation.parameter ? [operation.parameter] : [],
|
|
52672
|
+
params: operation.parameter ? [operation.parameter, ...operation.name === "create_credit_checkout" ? ["idempotency_key?"] : []] : [],
|
|
52290
52673
|
category: "execution",
|
|
52291
52674
|
sideEffects: operation.mutates ? "local-process-or-remote-run" : "none",
|
|
52292
52675
|
stable: true,
|
|
52293
|
-
inputSchema: objectSchema(operation.parameter ? { [operation.parameter]: stringSchema("Server resource identifier.") } : {}, operation.parameter ? [operation.parameter] : []),
|
|
52676
|
+
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] : []),
|
|
52294
52677
|
outputSchema: { oneOf: [objectSchema({}, [], "Server response.", true), { type: "array", items: objectSchema({}, [], "Server record.", true) }] }
|
|
52295
52678
|
}));
|
|
52296
52679
|
remoteCustomerContracts.push({
|
|
@@ -53147,7 +53530,7 @@ var init_credential_state = __esm(() => {
|
|
|
53147
53530
|
|
|
53148
53531
|
// src/lib/run-state.ts
|
|
53149
53532
|
import { createHash as createHash8, randomBytes } from "crypto";
|
|
53150
|
-
import { existsSync as existsSync14, mkdirSync as
|
|
53533
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync11, readFileSync as readFileSync17, readdirSync as readdirSync8, statSync as statSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
53151
53534
|
import { extname, join as join21, relative as relative5 } from "path";
|
|
53152
53535
|
function createSkillRun(params, targetDir = process.cwd()) {
|
|
53153
53536
|
const now = new Date;
|
|
@@ -53158,10 +53541,10 @@ function createSkillRun(params, targetDir = process.cwd()) {
|
|
|
53158
53541
|
const runDir = join21(root, "runs", day, id);
|
|
53159
53542
|
const logsDir = join21(runDir, "logs");
|
|
53160
53543
|
const exportDir = join21(root, "exports", skillName, id);
|
|
53161
|
-
|
|
53162
|
-
|
|
53163
|
-
|
|
53164
|
-
const
|
|
53544
|
+
mkdirSync11(logsDir, { recursive: true });
|
|
53545
|
+
mkdirSync11(exportDir, { recursive: true });
|
|
53546
|
+
mkdirSync11(join21(root, "tmp"), { recursive: true });
|
|
53547
|
+
const record10 = {
|
|
53165
53548
|
id,
|
|
53166
53549
|
skill: skillName,
|
|
53167
53550
|
status: params.status ?? "running",
|
|
@@ -53179,10 +53562,10 @@ function createSkillRun(params, targetDir = process.cwd()) {
|
|
|
53179
53562
|
logsDir: toProjectRelative(targetDir, logsDir)
|
|
53180
53563
|
}
|
|
53181
53564
|
};
|
|
53182
|
-
const context2 = { targetDir, runDir, exportDir, logsDir, record:
|
|
53565
|
+
const context2 = { targetDir, runDir, exportDir, logsDir, record: record10 };
|
|
53183
53566
|
writeRunRecord(context2);
|
|
53184
53567
|
writeArtifactsManifest(context2, []);
|
|
53185
|
-
appendRunEvent(context2, "created", { status:
|
|
53568
|
+
appendRunEvent(context2, "created", { status: record10.status });
|
|
53186
53569
|
return context2;
|
|
53187
53570
|
}
|
|
53188
53571
|
function completeSkillRun(context2, patch) {
|
|
@@ -53227,9 +53610,9 @@ function findSkillRun(runId, targetDir = process.cwd()) {
|
|
|
53227
53610
|
if (!existsSync14(runsRoot))
|
|
53228
53611
|
return null;
|
|
53229
53612
|
for (const day of readdirSync8(runsRoot)) {
|
|
53230
|
-
const
|
|
53231
|
-
if (
|
|
53232
|
-
return
|
|
53613
|
+
const record10 = readRunRecord(join21(runsRoot, day, runId));
|
|
53614
|
+
if (record10)
|
|
53615
|
+
return record10;
|
|
53233
53616
|
}
|
|
53234
53617
|
return null;
|
|
53235
53618
|
}
|
|
@@ -53378,11 +53761,11 @@ var init_run_routing = __esm(() => {
|
|
|
53378
53761
|
// node_modules/@hasna/secrets/dist/sdk.js
|
|
53379
53762
|
import { isIP as isIP2 } from "net";
|
|
53380
53763
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
53381
|
-
import { closeSync as
|
|
53764
|
+
import { closeSync as closeSync11, fstatSync as fstatSync11, openSync as openSync11, readFileSync as readFileSync18 } from "fs";
|
|
53382
53765
|
import { O_NOFOLLOW as O_NOFOLLOW3, O_NONBLOCK as O_NONBLOCK3, O_RDONLY as O_RDONLY3 } from "constants";
|
|
53383
53766
|
import { createRequire as createRequire2 } from "module";
|
|
53384
53767
|
import { hostname as osHostname2 } from "os";
|
|
53385
|
-
import { isAbsolute as
|
|
53768
|
+
import { isAbsolute as isAbsolute7, join as join22 } from "path";
|
|
53386
53769
|
import { createRequire as createRequire22 } from "module";
|
|
53387
53770
|
function envToken2(name) {
|
|
53388
53771
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -53406,7 +53789,7 @@ function homeDir2(env) {
|
|
|
53406
53789
|
}
|
|
53407
53790
|
function absoluteOverride2(env, key) {
|
|
53408
53791
|
const value = env[key]?.trim();
|
|
53409
|
-
return value &&
|
|
53792
|
+
return value && isAbsolute7(value) ? value : null;
|
|
53410
53793
|
}
|
|
53411
53794
|
function hasnaHomeDir2(env) {
|
|
53412
53795
|
const override = absoluteOverride2(env, HASNA_HOME_ENV_KEY2);
|
|
@@ -53483,7 +53866,7 @@ function readAppConfigFile2(path) {
|
|
|
53483
53866
|
};
|
|
53484
53867
|
let fd = -1;
|
|
53485
53868
|
try {
|
|
53486
|
-
fd =
|
|
53869
|
+
fd = openSync11(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
|
|
53487
53870
|
} catch (error61) {
|
|
53488
53871
|
const code2 = error61.code;
|
|
53489
53872
|
if (code2 === "ENOENT" || code2 === "ENOTDIR")
|
|
@@ -53493,7 +53876,7 @@ function readAppConfigFile2(path) {
|
|
|
53493
53876
|
unsafe(`the path could not be opened (${code2 ?? "unknown error"})`);
|
|
53494
53877
|
}
|
|
53495
53878
|
try {
|
|
53496
|
-
const before =
|
|
53879
|
+
const before = fstatSync11(fd);
|
|
53497
53880
|
if (!before.isFile())
|
|
53498
53881
|
unsafe("the path is not a regular file");
|
|
53499
53882
|
if (!configFileModeAllowed2(before.mode)) {
|
|
@@ -53505,14 +53888,14 @@ function readAppConfigFile2(path) {
|
|
|
53505
53888
|
if (before.size > MAX_CREDENTIAL_FILE_BYTES2)
|
|
53506
53889
|
unsafe("the file exceeds the size limit");
|
|
53507
53890
|
const bytes = readFileSync18(fd);
|
|
53508
|
-
const after =
|
|
53891
|
+
const after = fstatSync11(fd);
|
|
53509
53892
|
if (!configFileReadsCoherent2(before, after)) {
|
|
53510
53893
|
unsafe("the file changed while being read");
|
|
53511
53894
|
}
|
|
53512
53895
|
return parseEnvFile2(bytes.toString("utf8"));
|
|
53513
53896
|
} finally {
|
|
53514
53897
|
if (fd !== -1)
|
|
53515
|
-
|
|
53898
|
+
closeSync11(fd);
|
|
53516
53899
|
}
|
|
53517
53900
|
}
|
|
53518
53901
|
function readCredentialFile2(path, apiKeyKeys) {
|
|
@@ -54543,7 +54926,7 @@ function createSecretsClientFromEnv(env = process.env, overrides = {}) {
|
|
|
54543
54926
|
});
|
|
54544
54927
|
return new SecretsClient({ ...clientOverrides, baseUrl, apiKey });
|
|
54545
54928
|
}
|
|
54546
|
-
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((
|
|
54929
|
+
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((resolve6) => setTimeout(resolve6, 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_RE2, SQLITE_SIDECAR_FILES, LEGACY_SERVICE_FILES, init_data_dir, SecretsTestIsolationError, TEST_ENTRYPOINT_RE, init_test_isolation, init_client, ApiError;
|
|
54547
54930
|
var init_sdk = __esm(() => {
|
|
54548
54931
|
init_transport2 = __esm2(() => {
|
|
54549
54932
|
CredentialResolutionError2 = class CredentialResolutionError3 extends Error {
|
|
@@ -54678,7 +55061,7 @@ var init_sdk = __esm(() => {
|
|
|
54678
55061
|
});
|
|
54679
55062
|
|
|
54680
55063
|
// src/lib/execution-secrets.ts
|
|
54681
|
-
import { constants as
|
|
55064
|
+
import { constants as constants8, closeSync as closeSync12, fstatSync as fstatSync12, openSync as openSync12, readSync as readSync6, realpathSync as realpathSync5 } from "fs";
|
|
54682
55065
|
import { hostname as stationHostname } from "os";
|
|
54683
55066
|
function selectedSecretBindingsTemplate(scope, names, createClient = createSecretsClientFromEnv) {
|
|
54684
55067
|
let secretsAuthority;
|
|
@@ -54699,7 +55082,7 @@ function selectedSecretBindingsTemplate(scope, names, createClient = createSecre
|
|
|
54699
55082
|
function refuse(code2, message) {
|
|
54700
55083
|
throw new SkillSelectionError(code2, message);
|
|
54701
55084
|
}
|
|
54702
|
-
function
|
|
55085
|
+
function record10(value) {
|
|
54703
55086
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
54704
55087
|
}
|
|
54705
55088
|
function exactKeys(value, keys) {
|
|
@@ -54720,7 +55103,7 @@ function declaredSecretNames(value) {
|
|
|
54720
55103
|
return value;
|
|
54721
55104
|
}
|
|
54722
55105
|
function validateSelectedSecretBindings(value, scope, names) {
|
|
54723
|
-
if (!
|
|
55106
|
+
if (!record10(value) || !exactKeys(value, ["schema", "selection", "consumer", "secretsAuthority", "bindings"]) || value.schema !== "hasna.skills-secret-bindings.v1" || !record10(value.selection) || !exactKeys(value.selection, ["authority", "workspaceId", "profileId", "profileRevision", "slug", "version", "bundleDigest"]) || !record10(value.consumer) || !exactKeys(value.consumer, ["stationId", "workspaceDirectory"]) || !record10(value.bindings)) {
|
|
54724
55107
|
return refuse("INVALID_SECRET_BINDINGS", "Secret bindings do not match the hasna.skills-secret-bindings.v1 contract.");
|
|
54725
55108
|
}
|
|
54726
55109
|
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 })) {
|
|
@@ -54858,7 +55241,7 @@ var init_execution_grants = __esm(() => {
|
|
|
54858
55241
|
});
|
|
54859
55242
|
|
|
54860
55243
|
// src/lib/execution-grant-client.ts
|
|
54861
|
-
import { isDeepStrictEqual } from "util";
|
|
55244
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "util";
|
|
54862
55245
|
function id(value) {
|
|
54863
55246
|
if (!grantIdentifier(value))
|
|
54864
55247
|
throw new Error("Invalid execution grant profile or revision identifier.");
|
|
@@ -54901,7 +55284,7 @@ async function resolveExecutionGrant(input2) {
|
|
|
54901
55284
|
if (!grantRecord(value) || Object.keys(value).length !== 3 || !grantIdentifier(value.policyRevision) || !grantIdentifier(value.grantId) || !grantRecord(value.bindings)) {
|
|
54902
55285
|
throw new SkillSelectionError("INVALID_EXECUTION_GRANT", "The Skills API returned an invalid execution grant.");
|
|
54903
55286
|
}
|
|
54904
|
-
if (!
|
|
55287
|
+
if (!isDeepStrictEqual2(value.bindings.selection, snapshot.selection) || !isDeepStrictEqual2(value.bindings.consumer, snapshot.consumer)) {
|
|
54905
55288
|
throw new SkillSelectionError("EXECUTION_GRANT_SCOPE_MISMATCH", "The Skills API returned a grant for a different selection or consumer.");
|
|
54906
55289
|
}
|
|
54907
55290
|
return value;
|
|
@@ -54913,32 +55296,6 @@ var init_execution_grant_client = __esm(() => {
|
|
|
54913
55296
|
init_execution_grants();
|
|
54914
55297
|
});
|
|
54915
55298
|
|
|
54916
|
-
// src/lib/selected-manifest.ts
|
|
54917
|
-
function jsonEntry(entries, path) {
|
|
54918
|
-
const entry = entries.find((candidate) => candidate.path === path);
|
|
54919
|
-
if (!entry)
|
|
54920
|
-
return {};
|
|
54921
|
-
try {
|
|
54922
|
-
const value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(entry.bytes));
|
|
54923
|
-
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
54924
|
-
throw new Error;
|
|
54925
|
-
return value;
|
|
54926
|
-
} catch {
|
|
54927
|
-
throw new SkillSelectionError("INVALID_SKILL_MANIFEST", "The selected skill has an invalid execution manifest.");
|
|
54928
|
-
}
|
|
54929
|
-
}
|
|
54930
|
-
function describeEntries(entries) {
|
|
54931
|
-
const manifest = jsonEntry(entries, "skill.json"), packageJson = jsonEntry(entries, "package.json");
|
|
54932
|
-
const docs = entries.find((entry) => entry.path === "SKILL.md");
|
|
54933
|
-
const frontmatter = docs ? parseSkillFrontmatter(new TextDecoder().decode(docs.bytes)) : null;
|
|
54934
|
-
const kind = frontmatter?.kind === "instruction" || manifest.kind === "instruction" || packageJson.skills?.kind === "instruction" ? "instruction" : "executable";
|
|
54935
|
-
return { kind, manifest, packageJson };
|
|
54936
|
-
}
|
|
54937
|
-
var init_selected_manifest = __esm(() => {
|
|
54938
|
-
init_skill_validation();
|
|
54939
|
-
init_selection_cache();
|
|
54940
|
-
});
|
|
54941
|
-
|
|
54942
55299
|
// src/lib/selected-run.ts
|
|
54943
55300
|
var exports_selected_run = {};
|
|
54944
55301
|
__export(exports_selected_run, {
|
|
@@ -54948,8 +55305,8 @@ __export(exports_selected_run, {
|
|
|
54948
55305
|
});
|
|
54949
55306
|
import { createHash as createHash9 } from "crypto";
|
|
54950
55307
|
import { spawn } from "child_process";
|
|
54951
|
-
import { mkdirSync as
|
|
54952
|
-
import { dirname as dirname8, join as join23, resolve as
|
|
55308
|
+
import { mkdirSync as mkdirSync12, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync10, realpathSync as realpathSync6 } from "fs";
|
|
55309
|
+
import { dirname as dirname8, join as join23, resolve as resolve6 } from "path";
|
|
54953
55310
|
import { tmpdir, hostname as stationHostname2 } from "os";
|
|
54954
55311
|
async function resolveSelectedRun(spec, profileId, options = {}) {
|
|
54955
55312
|
const context2 = await resolveSelectionContext(profileId, options);
|
|
@@ -55038,11 +55395,11 @@ async function executeSelectedLocal(selected, options = {}) {
|
|
|
55038
55395
|
throw new SkillSelectionError("INVALID_BUNDLE_PATH", "The execution bundle path exceeds its limit.");
|
|
55039
55396
|
});
|
|
55040
55397
|
const destination = join23(runDirectory, entry.path);
|
|
55041
|
-
|
|
55398
|
+
mkdirSync12(dirname8(destination), { recursive: true, mode: 448 });
|
|
55042
55399
|
writeFileSync10(destination, entry.bytes, { flag: "wx", mode: entry.mode & 511 });
|
|
55043
55400
|
}
|
|
55044
55401
|
env.SKILLS_INPUT_JSON = input2;
|
|
55045
|
-
env.SKILLS_WORKSPACE_DIR =
|
|
55402
|
+
env.SKILLS_WORKSPACE_DIR = resolve6(options.cwd ?? process.cwd());
|
|
55046
55403
|
env.SKILLS_RUN_DIR = runDirectory;
|
|
55047
55404
|
if (runtime.version) {
|
|
55048
55405
|
const version2 = await subprocess([executable, ...runtimeName === "bun" ? ["--no-env-file"] : [], "--version"], runDirectory, env, "", Math.min(timeoutMs, 5000));
|
|
@@ -55946,7 +56303,7 @@ var init_operation_tools = __esm(() => {
|
|
|
55946
56303
|
});
|
|
55947
56304
|
|
|
55948
56305
|
// src/lib/feedback.ts
|
|
55949
|
-
import { appendFileSync, existsSync as existsSync16, mkdirSync as
|
|
56306
|
+
import { appendFileSync, existsSync as existsSync16, mkdirSync as mkdirSync13 } from "fs";
|
|
55950
56307
|
import { dirname as dirname9, join as join25 } from "path";
|
|
55951
56308
|
import { Database } from "bun:sqlite";
|
|
55952
56309
|
function getFeedbackDbPath() {
|
|
@@ -55956,7 +56313,7 @@ function getFeedbackDb() {
|
|
|
55956
56313
|
const dbPath = getFeedbackDbPath();
|
|
55957
56314
|
const dir = dirname9(dbPath);
|
|
55958
56315
|
if (!existsSync16(dir))
|
|
55959
|
-
|
|
56316
|
+
mkdirSync13(dir, { recursive: true });
|
|
55960
56317
|
const db = new Database(dbPath);
|
|
55961
56318
|
db.exec("PRAGMA journal_mode = WAL");
|
|
55962
56319
|
db.exec([
|
|
@@ -55985,7 +56342,7 @@ function saveFeedback(input2) {
|
|
|
55985
56342
|
const path = join25(getDataDir(), "feedback.jsonl");
|
|
55986
56343
|
const dir = dirname9(path);
|
|
55987
56344
|
if (!existsSync16(dir))
|
|
55988
|
-
|
|
56345
|
+
mkdirSync13(dir, { recursive: true });
|
|
55989
56346
|
appendFileSync(path, JSON.stringify({ message, category, email: input2.email ?? null, agent: input2.agent ?? null, version: input2.version ?? null, createdAt: new Date().toISOString() }) + `
|
|
55990
56347
|
`);
|
|
55991
56348
|
return { saved: true, category, path };
|
|
@@ -56146,7 +56503,7 @@ var init_resource_meta_tools = __esm(() => {
|
|
|
56146
56503
|
});
|
|
56147
56504
|
|
|
56148
56505
|
// src/lib/scheduler.ts
|
|
56149
|
-
import { existsSync as existsSync17, readFileSync as readFileSync19, writeFileSync as writeFileSync11, mkdirSync as
|
|
56506
|
+
import { existsSync as existsSync17, readFileSync as readFileSync19, writeFileSync as writeFileSync11, mkdirSync as mkdirSync14 } from "fs";
|
|
56150
56507
|
import { join as join26 } from "path";
|
|
56151
56508
|
function getSchedulesPath(targetDir = process.cwd()) {
|
|
56152
56509
|
return join26(targetDir, ".skills", "schedules.json");
|
|
@@ -56164,7 +56521,7 @@ function saveSchedules(data, targetDir = process.cwd()) {
|
|
|
56164
56521
|
const path = getSchedulesPath(targetDir);
|
|
56165
56522
|
const dir = join26(targetDir, ".skills");
|
|
56166
56523
|
if (!existsSync17(dir))
|
|
56167
|
-
|
|
56524
|
+
mkdirSync14(dir, { recursive: true });
|
|
56168
56525
|
writeFileSync11(path, JSON.stringify(data, null, 2));
|
|
56169
56526
|
}
|
|
56170
56527
|
function validateCronField(expr, min, max, label) {
|
|
@@ -56437,7 +56794,7 @@ var init_schedule_tools = __esm(() => {
|
|
|
56437
56794
|
import { createHash as createHash10, createHmac } from "crypto";
|
|
56438
56795
|
import {
|
|
56439
56796
|
existsSync as existsSync18,
|
|
56440
|
-
mkdirSync as
|
|
56797
|
+
mkdirSync as mkdirSync15,
|
|
56441
56798
|
readFileSync as readFileSync20,
|
|
56442
56799
|
readdirSync as readdirSync10,
|
|
56443
56800
|
statSync as statSync11,
|
|
@@ -56803,20 +57160,20 @@ var init_private_publication_customer = __esm(() => {
|
|
|
56803
57160
|
});
|
|
56804
57161
|
|
|
56805
57162
|
// src/lib/private-publication-recovery.ts
|
|
56806
|
-
import { constants as
|
|
56807
|
-
import { dirname as dirname11, isAbsolute as
|
|
57163
|
+
import { constants as constants9, closeSync as closeSync13, fsyncSync as fsyncSync4, fstatSync as fstatSync13, lstatSync as lstatSync11, mkdirSync as mkdirSync16, openSync as openSync13, readSync as readSync7, realpathSync as realpathSync7, renameSync as renameSync7, unlinkSync as unlinkSync6, writeFileSync as writeFileSync13 } from "fs";
|
|
57164
|
+
import { dirname as dirname11, isAbsolute as isAbsolute8, join as join28, resolve as resolve7 } from "path";
|
|
56808
57165
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
56809
57166
|
function safeDirectory(directory2) {
|
|
56810
|
-
if (!
|
|
57167
|
+
if (!isAbsolute8(directory2) || directory2 !== resolve7(directory2) || realpathSync7(directory2) !== directory2)
|
|
56811
57168
|
return fail2();
|
|
56812
57169
|
for (let path = directory2;; path = dirname11(path)) {
|
|
56813
|
-
const stat2 =
|
|
57170
|
+
const stat2 = lstatSync11(path);
|
|
56814
57171
|
if (!stat2.isDirectory() || stat2.isSymbolicLink())
|
|
56815
57172
|
return fail2();
|
|
56816
57173
|
if (path === dirname11(path))
|
|
56817
57174
|
break;
|
|
56818
57175
|
}
|
|
56819
|
-
const own2 =
|
|
57176
|
+
const own2 = lstatSync11(directory2);
|
|
56820
57177
|
if ((own2.mode & 63) !== 0 || process.getuid && own2.uid !== process.getuid())
|
|
56821
57178
|
return fail2();
|
|
56822
57179
|
return { dev: own2.dev, ino: own2.ino };
|
|
@@ -56828,35 +57185,35 @@ function unchangedDirectory(directory2, identity2) {
|
|
|
56828
57185
|
}
|
|
56829
57186
|
function readOwned(directory2, name, max) {
|
|
56830
57187
|
const identity2 = safeDirectory(directory2), file2 = join28(directory2, name);
|
|
56831
|
-
const fd =
|
|
57188
|
+
const fd = openSync13(file2, constants9.O_RDONLY | constants9.O_NOFOLLOW);
|
|
56832
57189
|
try {
|
|
56833
|
-
const stat2 =
|
|
57190
|
+
const stat2 = fstatSync13(fd);
|
|
56834
57191
|
if (!stat2.isFile() || stat2.nlink !== 1 || stat2.size > max || stat2.size < 1 || (stat2.mode & 63) !== 0 || process.getuid && stat2.uid !== process.getuid())
|
|
56835
57192
|
return fail2();
|
|
56836
57193
|
const buffer = Buffer.alloc(Math.min(max, stat2.size) + 1);
|
|
56837
57194
|
let length = 0;
|
|
56838
57195
|
while (length < buffer.length) {
|
|
56839
|
-
const count =
|
|
57196
|
+
const count = readSync7(fd, buffer, length, buffer.length - length, length);
|
|
56840
57197
|
if (count === 0)
|
|
56841
57198
|
break;
|
|
56842
57199
|
length += count;
|
|
56843
57200
|
}
|
|
56844
|
-
const bytes = buffer.subarray(0, length), after =
|
|
57201
|
+
const bytes = buffer.subarray(0, length), after = fstatSync13(fd);
|
|
56845
57202
|
unchangedDirectory(directory2, identity2);
|
|
56846
57203
|
if (bytes.length !== stat2.size || stat2.size !== after.size || stat2.mtimeMs !== after.mtimeMs || stat2.ctimeMs !== after.ctimeMs)
|
|
56847
57204
|
return fail2();
|
|
56848
57205
|
return bytes;
|
|
56849
57206
|
} finally {
|
|
56850
|
-
|
|
57207
|
+
closeSync13(fd);
|
|
56851
57208
|
}
|
|
56852
57209
|
}
|
|
56853
57210
|
function writeOwned(directory2, name, bytes) {
|
|
56854
|
-
const fd =
|
|
57211
|
+
const fd = openSync13(join28(directory2, name), constants9.O_WRONLY | constants9.O_CREAT | constants9.O_EXCL | constants9.O_NOFOLLOW, 384);
|
|
56855
57212
|
try {
|
|
56856
57213
|
writeFileSync13(fd, bytes);
|
|
56857
|
-
|
|
57214
|
+
fsyncSync4(fd);
|
|
56858
57215
|
} finally {
|
|
56859
|
-
|
|
57216
|
+
closeSync13(fd);
|
|
56860
57217
|
}
|
|
56861
57218
|
}
|
|
56862
57219
|
function save(directory2, value) {
|
|
@@ -56864,12 +57221,12 @@ function save(directory2, value) {
|
|
|
56864
57221
|
writeOwned(directory2, temporary, JSON.stringify(value) + `
|
|
56865
57222
|
`);
|
|
56866
57223
|
unchangedDirectory(directory2, identity2);
|
|
56867
|
-
|
|
56868
|
-
const fd =
|
|
57224
|
+
renameSync7(join28(directory2, temporary), join28(directory2, "receipt.json"));
|
|
57225
|
+
const fd = openSync13(directory2, constants9.O_RDONLY | constants9.O_NOFOLLOW);
|
|
56869
57226
|
try {
|
|
56870
|
-
|
|
57227
|
+
fsyncSync4(fd);
|
|
56871
57228
|
} finally {
|
|
56872
|
-
|
|
57229
|
+
closeSync13(fd);
|
|
56873
57230
|
}
|
|
56874
57231
|
}
|
|
56875
57232
|
function bind(client, receipt) {
|
|
@@ -56880,23 +57237,23 @@ async function locked(directory2, action) {
|
|
|
56880
57237
|
const identity2 = safeDirectory(directory2), file2 = join28(directory2, "operation.lock");
|
|
56881
57238
|
let fd;
|
|
56882
57239
|
try {
|
|
56883
|
-
fd =
|
|
57240
|
+
fd = openSync13(file2, constants9.O_WRONLY | constants9.O_CREAT | constants9.O_EXCL | constants9.O_NOFOLLOW, 384);
|
|
56884
57241
|
} catch {
|
|
56885
57242
|
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.");
|
|
56886
57243
|
}
|
|
56887
|
-
const lock =
|
|
57244
|
+
const lock = fstatSync13(fd);
|
|
56888
57245
|
try {
|
|
56889
57246
|
writeFileSync13(fd, JSON.stringify({ pid: process.pid }) + `
|
|
56890
57247
|
`);
|
|
56891
|
-
|
|
57248
|
+
fsyncSync4(fd);
|
|
56892
57249
|
return await action();
|
|
56893
57250
|
} finally {
|
|
56894
|
-
|
|
57251
|
+
closeSync13(fd);
|
|
56895
57252
|
unchangedDirectory(directory2, identity2);
|
|
56896
|
-
const now =
|
|
57253
|
+
const now = lstatSync11(file2);
|
|
56897
57254
|
if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
|
|
56898
57255
|
fail2();
|
|
56899
|
-
|
|
57256
|
+
unlinkSync6(file2);
|
|
56900
57257
|
}
|
|
56901
57258
|
}
|
|
56902
57259
|
function readPrivatePublicationRecovery(directory2) {
|
|
@@ -56945,15 +57302,15 @@ async function preparePrivatePublication(client, sourceDirectory, recoveryDirect
|
|
|
56945
57302
|
phase: "prepared",
|
|
56946
57303
|
intent: null
|
|
56947
57304
|
};
|
|
56948
|
-
if (!
|
|
57305
|
+
if (!isAbsolute8(recoveryDirectory) || resolve7(recoveryDirectory) !== recoveryDirectory || realpathSync7(dirname11(recoveryDirectory)) !== dirname11(recoveryDirectory))
|
|
56949
57306
|
return fail2();
|
|
56950
|
-
|
|
57307
|
+
mkdirSync16(recoveryDirectory, { mode: 448 });
|
|
56951
57308
|
safeDirectory(recoveryDirectory);
|
|
56952
|
-
const parent =
|
|
57309
|
+
const parent = openSync13(dirname11(recoveryDirectory), constants9.O_RDONLY | constants9.O_NOFOLLOW);
|
|
56953
57310
|
try {
|
|
56954
|
-
|
|
57311
|
+
fsyncSync4(parent);
|
|
56955
57312
|
} finally {
|
|
56956
|
-
|
|
57313
|
+
closeSync13(parent);
|
|
56957
57314
|
}
|
|
56958
57315
|
writeOwned(recoveryDirectory, "bundle.tgz", packed.bytes);
|
|
56959
57316
|
save(recoveryDirectory, receipt);
|
|
@@ -57046,10 +57403,10 @@ var init_private_publication_recovery = __esm(() => {
|
|
|
57046
57403
|
});
|
|
57047
57404
|
|
|
57048
57405
|
// src/mcp/private-publication-tools.ts
|
|
57049
|
-
import { isAbsolute as
|
|
57406
|
+
import { isAbsolute as isAbsolute9 } from "path";
|
|
57050
57407
|
function registerPrivatePublicationTools(server) {
|
|
57051
57408
|
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}$/);
|
|
57052
|
-
const directory2 = exports_external.string().max(4096).refine(
|
|
57409
|
+
const directory2 = exports_external.string().max(4096).refine(isAbsolute9, "Use an absolute local directory");
|
|
57053
57410
|
const verification2 = { email: exports_external.string().email().max(254), code: exports_external.string().regex(/^\d{6}$/), userId: uuid9, membershipId: uuid9, recoveryDirectory: directory2 };
|
|
57054
57411
|
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.";
|
|
57055
57412
|
const handler = (action) => async (value) => {
|
|
@@ -57204,6 +57561,14 @@ function registerRemoteCustomerTools(server) {
|
|
|
57204
57561
|
});
|
|
57205
57562
|
}
|
|
57206
57563
|
for (const operation of REMOTE_CUSTOMER_OPERATIONS) {
|
|
57564
|
+
if (operation.name === "create_credit_checkout") {
|
|
57565
|
+
server.registerTool(operation.name, {
|
|
57566
|
+
title: operation.title,
|
|
57567
|
+
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.",
|
|
57568
|
+
inputSchema: { pack_id: exports_external.string().min(1), idempotency_key: exports_external.string().regex(/^[A-Za-z0-9._:-]{8,255}$/).optional() }
|
|
57569
|
+
}, ({ pack_id, idempotency_key }) => callRemote((client) => operation.invoke(client, pack_id, { idempotencyKey: idempotency_key })));
|
|
57570
|
+
continue;
|
|
57571
|
+
}
|
|
57207
57572
|
const inputSchema = {};
|
|
57208
57573
|
if (operation.parameter)
|
|
57209
57574
|
inputSchema[operation.parameter] = exports_external.string().min(1);
|
|
@@ -57280,6 +57645,15 @@ async function callRemote(action) {
|
|
|
57280
57645
|
return mcpError("AUTH_REQUIRED", "Configure a Skills API and sign in with skills auth login");
|
|
57281
57646
|
return mcpJson(await action(client));
|
|
57282
57647
|
} catch (error61) {
|
|
57648
|
+
if (error61 instanceof RemoteCreditCheckoutError) {
|
|
57649
|
+
return { ...mcpJson({
|
|
57650
|
+
code: error61.code,
|
|
57651
|
+
message: error61.message,
|
|
57652
|
+
status: error61.status,
|
|
57653
|
+
requestIdempotencyKey: error61.requestIdempotencyKey,
|
|
57654
|
+
...error61.retryAfterSeconds === undefined ? {} : { retryAfterSeconds: error61.retryAfterSeconds }
|
|
57655
|
+
}), isError: true };
|
|
57656
|
+
}
|
|
57283
57657
|
if (error61 instanceof RemoteCapabilityUnavailableError) {
|
|
57284
57658
|
return { ...mcpJson({ code: error61.code, message: error61.message, status: error61.status }), isError: true };
|
|
57285
57659
|
}
|
|
@@ -57474,7 +57848,7 @@ var WSContext = class {
|
|
|
57474
57848
|
var init_websocket = () => {};
|
|
57475
57849
|
|
|
57476
57850
|
// node_modules/@hono/node-server/dist/index.mjs
|
|
57477
|
-
import { Http2ServerRequest, constants as
|
|
57851
|
+
import { Http2ServerRequest, constants as constants10 } from "http2";
|
|
57478
57852
|
import { Readable } from "stream";
|
|
57479
57853
|
async function readWithoutBlocking(readPromise) {
|
|
57480
57854
|
return Promise.race([readPromise, Promise.resolve().then(() => Promise.resolve(undefined))]);
|
|
@@ -57744,7 +58118,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
57744
58118
|
request2[bodyBufferKey] = buffered;
|
|
57745
58119
|
return Promise.resolve(buffered);
|
|
57746
58120
|
}
|
|
57747
|
-
const promise3 = new Promise((
|
|
58121
|
+
const promise3 = new Promise((resolve8, reject) => {
|
|
57748
58122
|
const chunks = [];
|
|
57749
58123
|
let settled = false;
|
|
57750
58124
|
const finish = (callback) => {
|
|
@@ -57766,7 +58140,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
57766
58140
|
reject(error61 ?? normalizeAbortError(request2, incoming));
|
|
57767
58141
|
else {
|
|
57768
58142
|
request2[bodyBufferKey] = recovered;
|
|
57769
|
-
|
|
58143
|
+
resolve8(recovered);
|
|
57770
58144
|
}
|
|
57771
58145
|
});
|
|
57772
58146
|
return true;
|
|
@@ -57778,7 +58152,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
57778
58152
|
finish(() => {
|
|
57779
58153
|
const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
|
|
57780
58154
|
request2[bodyBufferKey] = buffer;
|
|
57781
|
-
|
|
58155
|
+
resolve8(buffer);
|
|
57782
58156
|
});
|
|
57783
58157
|
};
|
|
57784
58158
|
const onError = (error61) => {
|
|
@@ -57889,7 +58263,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
57889
58263
|
incomingWithDrainState[incomingDraining] = true;
|
|
57890
58264
|
if (incoming instanceof Http2ServerRequest) {
|
|
57891
58265
|
try {
|
|
57892
|
-
incoming.stream?.close?.(
|
|
58266
|
+
incoming.stream?.close?.(constants10.NGHTTP2_NO_ERROR);
|
|
57893
58267
|
} catch {}
|
|
57894
58268
|
return;
|
|
57895
58269
|
}
|
|
@@ -58052,7 +58426,7 @@ var RequestError, nonJoinedHeaders, validHeaderName, isHttpWhitespace = (code2)
|
|
|
58052
58426
|
});
|
|
58053
58427
|
if (!chunk) {
|
|
58054
58428
|
if (i === 1) {
|
|
58055
|
-
await new Promise((
|
|
58429
|
+
await new Promise((resolve8) => setTimeout(resolve8));
|
|
58056
58430
|
maxReadCount = 3;
|
|
58057
58431
|
continue;
|
|
58058
58432
|
}
|
|
@@ -59282,9 +59656,9 @@ data:
|
|
|
59282
59656
|
const initRequest = messages.find((m) => isInitializeRequest(m));
|
|
59283
59657
|
const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
|
|
59284
59658
|
if (this._enableJsonResponse) {
|
|
59285
|
-
return new Promise((
|
|
59659
|
+
return new Promise((resolve8) => {
|
|
59286
59660
|
this._streamMapping.set(streamId, {
|
|
59287
|
-
resolveJson:
|
|
59661
|
+
resolveJson: resolve8,
|
|
59288
59662
|
cleanup: () => {
|
|
59289
59663
|
this._streamMapping.delete(streamId);
|
|
59290
59664
|
}
|
|
@@ -59653,19 +60027,19 @@ async function connectMcpForNode() {
|
|
|
59653
60027
|
return { server: server2, transport };
|
|
59654
60028
|
}
|
|
59655
60029
|
function readBody(req) {
|
|
59656
|
-
return new Promise((
|
|
60030
|
+
return new Promise((resolve8, reject) => {
|
|
59657
60031
|
const chunks = [];
|
|
59658
60032
|
req.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
59659
60033
|
req.on("end", () => {
|
|
59660
60034
|
const raw = Buffer.concat(chunks).toString("utf-8");
|
|
59661
60035
|
if (!raw.trim()) {
|
|
59662
|
-
|
|
60036
|
+
resolve8(undefined);
|
|
59663
60037
|
return;
|
|
59664
60038
|
}
|
|
59665
60039
|
try {
|
|
59666
|
-
|
|
60040
|
+
resolve8(JSON.parse(raw));
|
|
59667
60041
|
} catch {
|
|
59668
|
-
|
|
60042
|
+
resolve8(undefined);
|
|
59669
60043
|
}
|
|
59670
60044
|
});
|
|
59671
60045
|
req.on("error", reject);
|
|
@@ -59707,9 +60081,9 @@ async function startSkillsMcpHttpServer(options = {}) {
|
|
|
59707
60081
|
}
|
|
59708
60082
|
}
|
|
59709
60083
|
});
|
|
59710
|
-
await new Promise((
|
|
60084
|
+
await new Promise((resolve8, reject) => {
|
|
59711
60085
|
httpServer.once("error", reject);
|
|
59712
|
-
httpServer.listen(port, hostname3, () =>
|
|
60086
|
+
httpServer.listen(port, hostname3, () => resolve8());
|
|
59713
60087
|
});
|
|
59714
60088
|
const address = httpServer.address();
|
|
59715
60089
|
const listenPort = typeof address === "object" && address ? address.port : port;
|