@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.
Files changed (37) hide show
  1. package/README.md +103 -1
  2. package/bin/index.js +26509 -24016
  3. package/bin/mcp.js +596 -222
  4. package/bin/migrate.js +7 -5
  5. package/bin/server.js +12313 -73626
  6. package/bin/worker.js +7636 -60520
  7. package/dist/cli/commands/plugin-admission.d.ts +2 -0
  8. package/dist/index.d.ts +9 -2
  9. package/dist/index.js +23559 -21779
  10. package/dist/lib/agent-adapters.d.ts +1 -0
  11. package/dist/lib/agent-codex-trust.d.ts +42 -0
  12. package/dist/lib/agent-discovery.d.ts +4 -2
  13. package/dist/lib/claude-marketplace-registry.d.ts +17 -0
  14. package/dist/lib/codex-hook-rpc.d.ts +13 -0
  15. package/dist/lib/codex-hook-trust-files.d.ts +15 -0
  16. package/dist/lib/codex-hook-trust-identity.d.ts +16 -0
  17. package/dist/lib/codex-hook-trust-layout.d.ts +3 -0
  18. package/dist/lib/fleet-credentials.d.ts +18 -0
  19. package/dist/lib/hook-diagnostics.d.ts +7 -0
  20. package/dist/lib/plugin-admission.d.ts +101 -0
  21. package/dist/lib/plugin-discovery.d.ts +13 -0
  22. package/dist/lib/plugin-projection-store.d.ts +14 -0
  23. package/dist/lib/plugin-projection.d.ts +80 -0
  24. package/dist/lib/profile-client.d.ts +10 -0
  25. package/dist/lib/recurring-recovery.d.ts +2 -2
  26. package/dist/lib/recurring-surface.d.ts +1 -1
  27. package/dist/lib/remote-client.d.ts +14 -4
  28. package/dist/lib/remote-credit-checkout.d.ts +22 -0
  29. package/dist/lib/remote-customer-operations.d.ts +3 -4
  30. package/dist/lib/remote-permissions.d.ts +24 -0
  31. package/dist/lib/selection-cache.d.ts +32 -0
  32. package/dist/lib/selection-resolver.d.ts +3 -1
  33. package/dist/lib/session-reconciliation.d.ts +100 -0
  34. package/dist/sdk/index.d.ts +5 -2
  35. package/dist/sdk/index.js +18528 -78089
  36. package/docs/plugin-admission.md +221 -0
  37. 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.9",
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
- prepare: "bun run build:js",
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 asSkillsFleetCredentialError(error61) {
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 * 6 + 256;
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
- writeFileSync4(temporary, bytes, { flag: "wx", mode });
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 readSkillSession(sessionId, options = {}) {
39722
- const receipt = readSelectionJson(sessionReceiptPath(sessionId, options));
39723
- if (receipt) {
39724
- validateSelectionReceipt(receipt);
39725
- const keys = new Set(receipt.profile.selections.map(selectionKey));
39726
- 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))) {
39727
- throw new SkillSelectionError("INVALID_RECEIPT", "The Skills session receipt is invalid.");
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
- return receipt;
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 !== "path-bytes" || source.sha256 !== null));
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 request(path, init = {}) {
40185
+ async requestRoute(route, init = {}) {
40040
40186
  let response;
40041
40187
  try {
40042
- response = await fetch(skillsApiRequestUrl(this.origin, `/api/v1${path}`), {
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 mkdirSync6, readFileSync as readFileSync12, writeFileSync as writeFileSync5 } from "fs";
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
- mkdirSync6(dir, { recursive: true });
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 rmSync2 } from "fs";
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 session = options.sessionId ? readSkillSession(options.sessionId, options) : null;
47945
- const parentSession = !session && options.parentSessionId ? readSkillSession(options.parentSessionId, options) : null;
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 that profile or explicitly sync the new selection.");
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
- writeSelectionJson(sessionReceiptPath(options.sessionId, options), session);
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 mkdirSync7, readFileSync as readFileSync15, renameSync as renameSync3, statSync as statSync8, unlinkSync as unlinkSync3, writeFileSync as writeFileSync6 } from "fs";
48881
- import { basename as basename4, dirname as dirname6, join as join19 } from "path";
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), basename4(file2).replace(/^credentials/, "identity") + ".json");
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((resolve4) => {
49355
+ const deadline = new Promise((resolve5) => {
49087
49356
  timer = setTimeout(() => {
49088
49357
  deadlineExceeded = true;
49089
- resolve4(expired);
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 value = await (await this.requestNewRoute("/api/v1/capabilities")).json();
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
- return parseRemoteCheckout(await (await this.requestNewRoute("/api/v1/billing/credits", {
49596
- method: "POST",
49597
- body: JSON.stringify({ packId })
49598
- })).json());
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(record7, field) {
49826
- if (record7[field] === undefined)
50193
+ function requireOptionalString(record8, field) {
50194
+ if (record8[field] === undefined)
49827
50195
  return;
49828
- if (typeof record7[field] !== "string") {
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 record7[field];
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 record7 = entry;
49854
- const slug2 = typeof record7.slug === "string" && record7.slug.trim() ? record7.slug.trim() : undefined;
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 (record7.metadata !== undefined) {
49860
- if (!record7.metadata || typeof record7.metadata !== "object" || Array.isArray(record7.metadata)) {
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 = record7.metadata;
50231
+ metadata = record8.metadata;
49864
50232
  }
49865
- const pinnedAt = requireOptionalString(record7, "pinnedAt");
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 record7 = entry;
49883
- const slug2 = typeof record7.slug === "string" && record7.slug.trim() ? record7.slug.trim() : undefined;
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(record7, "name") !== undefined ? { name: requireOptionalString(record7, "name") } : {},
49890
- ...requireOptionalString(record7, "version") !== undefined ? { version: requireOptionalString(record7, "version") } : {},
49891
- ...requireOptionalString(record7, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record7, "updatedAt") } : {}
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 record7 = payload;
49945
- if (!Array.isArray(record7.skills)) {
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 = record7.skills.map(normalizeSkillSummary);
49949
- const nextCursor = record7.nextCursor === undefined || record7.nextCursor === null ? null : record7.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 (!record7(input2) || Object.keys(input2).length !== keys.length || keys.some((key) => !Object.hasOwn(input2, key)))
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 && record7(parsed) && typeof parsed.code === "string" && Object.hasOwn(refusals, parsed.code)) {
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 (!record7(parsed))
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, record7 = (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);
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 (!record8(manifest) || manifest.version !== value.version || validatePortableManifestContract(manifest, { strict: true }).length || !hash3(manifest.provenance?.content_hash))
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 = record8(body) && typeof body.code === "string" && Object.hasOwn(failures2, body.code) ? body.code : null;
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 = record8(response) && response.privatePublishing;
50258
- if (!record8(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")
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 (!record8(value) || !Object.keys(value).every((k) => k === "upload" || k === "changed") || value.changed !== undefined && typeof value.changed !== "boolean")
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((resolve4) => {
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
- resolve4();
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), record8 = (v) => !!v && typeof v === "object" && !Array.isArray(v), exact = (v, keys) => record8(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");
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 record9 = isRecord5(body) ? body : {};
50464
- const detail = typeof record9.detail === "string" ? record9.detail : undefined;
50465
- const error61 = typeof record9.error === "string" ? record9.error : undefined;
50466
- const code = typeof record9.code === "string" ? record9.code : undefined;
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 constants5, closeSync as closeSync8, fstatSync as fstatSync8, lstatSync as lstatSync8, mkdirSync as mkdirSync8, mkdtempSync as mkdtempSync2, openSync as openSync8, readFileSync as readFileSync16, renameSync as renameSync4, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "fs";
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 lstatSync8(path);
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 = openSync8(file2, constants5.O_RDONLY | constants5.O_NOFOLLOW | constants5.O_NONBLOCK);
51072
+ const fd = openSync9(file2, constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
50690
51073
  try {
50691
- const s = fstatSync8(fd);
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
- closeSync8(fd);
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 constants6, closeSync as closeSync9, fsyncSync, fstatSync as fstatSync9, lstatSync as lstatSync9, mkdirSync as mkdirSync9, openSync as openSync9, readSync as readSync4, realpathSync as realpathSync4, renameSync as renameSync5, unlinkSync as unlinkSync4, writeFileSync as writeFileSync8 } from "fs";
50909
- import { dirname as dirname7, isAbsolute as isAbsolute4, join as join20, resolve as resolve4 } from "path";
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 (!isAbsolute4(directory) || resolve4(directory) !== directory || realpathSync4(directory) !== directory)
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 = lstatSync9(path);
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 = lstatSync9(prior.path);
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 = lstatSync9(this.directory);
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 = openSync9(join20(this.directory, name), constants6.O_RDONLY | constants6.O_NOFOLLOW | constants6.O_NONBLOCK);
51326
+ const fd = openSync10(join20(this.directory, name), constants7.O_RDONLY | constants7.O_NOFOLLOW | constants7.O_NONBLOCK);
50944
51327
  try {
50945
- const before = fstatSync9(fd);
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 = readSync4(fd, bytes, size, bytes.length - size, size);
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 = fstatSync9(fd), path = lstatSync9(join20(this.directory, name));
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
- closeSync9(fd);
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 = openSync9(join20(this.directory, name), constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW, 384);
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
- fsyncSync(fd);
51355
+ fsyncSync3(fd);
50973
51356
  } finally {
50974
- closeSync9(fd);
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 = openSync9(this.directory, constants6.O_RDONLY | constants6.O_NOFOLLOW);
51364
+ const fd = openSync10(this.directory, constants7.O_RDONLY | constants7.O_NOFOLLOW);
50982
51365
  try {
50983
- fsyncSync(fd);
51366
+ fsyncSync3(fd);
50984
51367
  } finally {
50985
- closeSync9(fd);
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
- renameSync5(join20(this.directory, name), join20(this.directory, "state.json"));
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 = openSync9(join20(this.directory, "operation.lock"), constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW, 384);
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 = fstatSync9(fd);
51390
+ const owner = fstatSync10(fd);
51008
51391
  try {
51009
51392
  writeFileSync8(fd, JSON.stringify({ pid: process.pid }));
51010
- fsyncSync(fd);
51393
+ fsyncSync3(fd);
51011
51394
  this.sync();
51012
51395
  return await action();
51013
51396
  } finally {
51014
- closeSync9(fd);
51397
+ closeSync10(fd);
51015
51398
  this.assert();
51016
- const now = lstatSync9(join20(this.directory, "operation.lock"));
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
- unlinkSync4(join20(this.directory, "operation.lock"));
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 (!isAbsolute4(directory) || resolve4(directory) !== directory || realpathSync4(dirname7(directory)) !== dirname7(directory))
51435
+ if (!isAbsolute5(directory) || resolve5(directory) !== directory || realpathSync4(dirname7(directory)) !== dirname7(directory))
51053
51436
  invalid5();
51054
- mkdirSync9(directory, { mode: 448 });
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 isAbsolute5 } from "path";
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(isAbsolute5, "Use an absolute recovery directory");
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 mkdirSync10, readFileSync as readFileSync17, readdirSync as readdirSync8, statSync as statSync9, writeFileSync as writeFileSync9 } from "fs";
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
- mkdirSync10(logsDir, { recursive: true });
53162
- mkdirSync10(exportDir, { recursive: true });
53163
- mkdirSync10(join21(root, "tmp"), { recursive: true });
53164
- const record9 = {
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: record9 };
53565
+ const context2 = { targetDir, runDir, exportDir, logsDir, record: record10 };
53183
53566
  writeRunRecord(context2);
53184
53567
  writeArtifactsManifest(context2, []);
53185
- appendRunEvent(context2, "created", { status: record9.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 record9 = readRunRecord(join21(runsRoot, day, runId));
53231
- if (record9)
53232
- return record9;
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 closeSync10, fstatSync as fstatSync10, openSync as openSync10, readFileSync as readFileSync18 } from "fs";
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 isAbsolute6, join as join22 } from "path";
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 && isAbsolute6(value) ? value : null;
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 = openSync10(path, O_RDONLY3 | O_NOFOLLOW3 | O_NONBLOCK3);
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 = fstatSync10(fd);
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 = fstatSync10(fd);
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
- closeSync10(fd);
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((resolve5) => setTimeout(resolve5, 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;
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 constants7, closeSync as closeSync11, fstatSync as fstatSync11, openSync as openSync11, readSync as readSync5, realpathSync as realpathSync5 } from "fs";
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 record9(value) {
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 (!record9(value) || !exactKeys(value, ["schema", "selection", "consumer", "secretsAuthority", "bindings"]) || value.schema !== "hasna.skills-secret-bindings.v1" || !record9(value.selection) || !exactKeys(value.selection, ["authority", "workspaceId", "profileId", "profileRevision", "slug", "version", "bundleDigest"]) || !record9(value.consumer) || !exactKeys(value.consumer, ["stationId", "workspaceDirectory"]) || !record9(value.bindings)) {
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 (!isDeepStrictEqual(value.bindings.selection, snapshot.selection) || !isDeepStrictEqual(value.bindings.consumer, snapshot.consumer)) {
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 mkdirSync11, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync10, realpathSync as realpathSync6 } from "fs";
54952
- import { dirname as dirname8, join as join23, resolve as resolve5 } from "path";
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
- mkdirSync11(dirname8(destination), { recursive: true, mode: 448 });
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 = resolve5(options.cwd ?? process.cwd());
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 mkdirSync12 } from "fs";
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
- mkdirSync12(dir, { recursive: true });
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
- mkdirSync12(dir, { recursive: true });
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 mkdirSync13 } from "fs";
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
- mkdirSync13(dir, { recursive: true });
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 mkdirSync14,
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 constants8, closeSync as closeSync12, fsyncSync as fsyncSync2, fstatSync as fstatSync12, lstatSync as lstatSync10, mkdirSync as mkdirSync15, openSync as openSync12, readSync as readSync6, realpathSync as realpathSync7, renameSync as renameSync6, unlinkSync as unlinkSync5, writeFileSync as writeFileSync13 } from "fs";
56807
- import { dirname as dirname11, isAbsolute as isAbsolute7, join as join28, resolve as resolve6 } from "path";
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 (!isAbsolute7(directory2) || directory2 !== resolve6(directory2) || realpathSync7(directory2) !== directory2)
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 = lstatSync10(path);
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 = lstatSync10(directory2);
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 = openSync12(file2, constants8.O_RDONLY | constants8.O_NOFOLLOW);
57188
+ const fd = openSync13(file2, constants9.O_RDONLY | constants9.O_NOFOLLOW);
56832
57189
  try {
56833
- const stat2 = fstatSync12(fd);
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 = readSync6(fd, buffer, length, buffer.length - length, length);
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 = fstatSync12(fd);
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
- closeSync12(fd);
57207
+ closeSync13(fd);
56851
57208
  }
56852
57209
  }
56853
57210
  function writeOwned(directory2, name, bytes) {
56854
- const fd = openSync12(join28(directory2, name), constants8.O_WRONLY | constants8.O_CREAT | constants8.O_EXCL | constants8.O_NOFOLLOW, 384);
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
- fsyncSync2(fd);
57214
+ fsyncSync4(fd);
56858
57215
  } finally {
56859
- closeSync12(fd);
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
- renameSync6(join28(directory2, temporary), join28(directory2, "receipt.json"));
56868
- const fd = openSync12(directory2, constants8.O_RDONLY | constants8.O_NOFOLLOW);
57224
+ renameSync7(join28(directory2, temporary), join28(directory2, "receipt.json"));
57225
+ const fd = openSync13(directory2, constants9.O_RDONLY | constants9.O_NOFOLLOW);
56869
57226
  try {
56870
- fsyncSync2(fd);
57227
+ fsyncSync4(fd);
56871
57228
  } finally {
56872
- closeSync12(fd);
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 = openSync12(file2, constants8.O_WRONLY | constants8.O_CREAT | constants8.O_EXCL | constants8.O_NOFOLLOW, 384);
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 = fstatSync12(fd);
57244
+ const lock = fstatSync13(fd);
56888
57245
  try {
56889
57246
  writeFileSync13(fd, JSON.stringify({ pid: process.pid }) + `
56890
57247
  `);
56891
- fsyncSync2(fd);
57248
+ fsyncSync4(fd);
56892
57249
  return await action();
56893
57250
  } finally {
56894
- closeSync12(fd);
57251
+ closeSync13(fd);
56895
57252
  unchangedDirectory(directory2, identity2);
56896
- const now = lstatSync10(file2);
57253
+ const now = lstatSync11(file2);
56897
57254
  if (now.dev !== lock.dev || now.ino !== lock.ino || !now.isFile() || now.isSymbolicLink())
56898
57255
  fail2();
56899
- unlinkSync5(file2);
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 (!isAbsolute7(recoveryDirectory) || resolve6(recoveryDirectory) !== recoveryDirectory || realpathSync7(dirname11(recoveryDirectory)) !== dirname11(recoveryDirectory))
57305
+ if (!isAbsolute8(recoveryDirectory) || resolve7(recoveryDirectory) !== recoveryDirectory || realpathSync7(dirname11(recoveryDirectory)) !== dirname11(recoveryDirectory))
56949
57306
  return fail2();
56950
- mkdirSync15(recoveryDirectory, { mode: 448 });
57307
+ mkdirSync16(recoveryDirectory, { mode: 448 });
56951
57308
  safeDirectory(recoveryDirectory);
56952
- const parent = openSync12(dirname11(recoveryDirectory), constants8.O_RDONLY | constants8.O_NOFOLLOW);
57309
+ const parent = openSync13(dirname11(recoveryDirectory), constants9.O_RDONLY | constants9.O_NOFOLLOW);
56953
57310
  try {
56954
- fsyncSync2(parent);
57311
+ fsyncSync4(parent);
56955
57312
  } finally {
56956
- closeSync12(parent);
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 isAbsolute8 } from "path";
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(isAbsolute8, "Use an absolute local directory");
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 constants9 } from "http2";
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((resolve7, reject) => {
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
- resolve7(recovered);
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
- resolve7(buffer);
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?.(constants9.NGHTTP2_NO_ERROR);
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((resolve7) => setTimeout(resolve7));
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((resolve7) => {
59659
+ return new Promise((resolve8) => {
59286
59660
  this._streamMapping.set(streamId, {
59287
- resolveJson: resolve7,
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((resolve7, reject) => {
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
- resolve7(undefined);
60036
+ resolve8(undefined);
59663
60037
  return;
59664
60038
  }
59665
60039
  try {
59666
- resolve7(JSON.parse(raw));
60040
+ resolve8(JSON.parse(raw));
59667
60041
  } catch {
59668
- resolve7(undefined);
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((resolve7, reject) => {
60084
+ await new Promise((resolve8, reject) => {
59711
60085
  httpServer.once("error", reject);
59712
- httpServer.listen(port, hostname3, () => resolve7());
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;